var privUtils_ = xwalk.utils;
var validator_ = privUtils_.validator;
var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+var AbortError = new WebAPIException('AbortError', 'An unknown error occurred');
// TensorRawData
* limitations under the License.
*/
-//PipelineManager::createPipeline() begin
+var kPipelineStateChangeListenerNamePrefix = 'MLPipelineStateChangeListener';
+//PipelineManager::createPipeline() begin
+var nextPipelineId = 1;
+function NextPipelineId() {
+ return nextPipelineId++;
+}
+
+var ValidPipelineManagerCreatePipelineExceptions = [
+ 'InvalidValuesError',
+ 'TypeMismatchError',
+ 'NotSupportedError',
+ 'SecurityError',
+ 'AbortError'
+];
+
+var CreatePipeline = function() {
+ privUtils_.log('Entered PipelineManager.createPipeline()');
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'definition',
+ type: validator_.Types.STRING
+ },
+ {
+ name: 'listener',
+ type: validator_.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ if (!args.has.definition) {
+ throw new WebAPIException(
+ WebAPIException.INVALID_VALUES_ERR,
+ 'Invalid parameter: pipeline definition is mandatory'
+ );
+ }
+
+ var pipeline = new Pipeline(NextPipelineId());
+ var nativeArgs = {
+ id: pipeline._id,
+ definition: args.definition
+ };
+
+ if (args.listener) {
+ nativeArgs.listenerName = kPipelineStateChangeListenerNamePrefix + pipeline._id;
+ var stateChangeListener = function(stateObject) {
+ args.listener(stateObject.state);
+ };
+ native_.addListener(nativeArgs.listenerName, stateChangeListener);
+ }
+
+ var result = native_.callSync('MLPipelineManagerCreatePipeline', nativeArgs);
+
+ if (native_.isFailure(result)) {
+ if (nativeArgs.listenerName) {
+ native_.removeListener(nativeArgs.listenerName);
+ }
+ throw native_.getErrorObjectAndValidate(
+ result,
+ ValidPipelineManagerCreatePipelineExceptions,
+ AbortError
+ );
+ }
+
+ return pipeline;
+};
//PipelineManager::createPipeline() end
//Pipeline::state begin
-
+var ValidPipelineStateExceptions = ['NotSupportedError', 'AbortError'];
+var Pipeline = function(id) {
+ Object.defineProperties(this, {
+ state: {
+ enumerable: true,
+ get: function() {
+ var result = native_.callSync('MLPipelineGetState', {
+ id: id
+ });
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObjectAndValidate(
+ result,
+ ValidPipelineStateExceptions,
+ AbortError
+ );
+ }
+
+ return result.state;
+ }
+ },
+ _id: {
+ value: id
+ }
+ });
+};
//Pipeline::state end
//Pipeline::start() begin
//Valve::setOpen() begin
//Valve::setOpen() end
-
var MachineLearningPipeline = function() {};
+MachineLearningPipeline.prototype.createPipeline = CreatePipeline;
+
// ML Pipeline API
using namespace common;
-MlInstance::MlInstance() {
+MlInstance::MlInstance() : pipeline_manager_{this} {
ScopeLogger();
using namespace std::placeholders;
#define REGISTER_METHOD(M) RegisterSyncHandler(#M, std::bind(&MlInstance::M, this, _1, _2))
-// Common ML API begin
+ // Common ML API begin
-// Common ML API end
+ // Common ML API end
-// Single API begin
+ // Single API begin
-// Single API end
+ // Single API end
-// Pipeline API begin
+ // Pipeline API begin
+ REGISTER_METHOD(MLPipelineManagerCreatePipeline);
// Pipeline API end
// Single API end
// Pipeline API begin
+
+namespace {
+
+const std::string kId = "id";
+const std::string kDefinition = "definition";
+const std::string kPipelineStateChangeListenerName = "listenerName";
+
+} // namespace
+
// PipelineManager::createPipeline() begin
+namespace {
+
+bool CreatePipelineArgumentsAreInvalid(const picojson::value& args) {
+ ScopeLogger();
+ auto arguments_valid = args.get(kId).is<double>();
+ arguments_valid &= args.get(kDefinition).is<std::string>();
+ arguments_valid &= (args.get(kPipelineStateChangeListenerName).is<std::string>() ||
+ args.get(kPipelineStateChangeListenerName).is<picojson::null>());
+ LoggerD("CreatePipeline arguments are %s", arguments_valid ? "valid" : "invalid");
+
+ return !arguments_valid;
+}
+
+}; // namespace
+
+void MlInstance::MLPipelineManagerCreatePipeline(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger("args: %s", args.serialize().c_str());
+
+ if (CreatePipelineArgumentsAreInvalid(args)) {
+ ReportError(PlatformResult{ErrorCode::ABORT_ERR, "Could not create pipeline"}, &out);
+ return;
+ }
+
+ auto id = static_cast<int>(args.get(kId).get<double>());
+ auto definition = args.get(kDefinition).get<std::string>();
+ auto state_change_listener_name =
+ args.get(kPipelineStateChangeListenerName).is<std::string>()
+ ? args.get(kPipelineStateChangeListenerName).get<std::string>()
+ : "";
+
+ auto ret = pipeline_manager_.CreatePipeline(id, definition, state_change_listener_name);
+
+ if (!ret) {
+ ReportError(ret, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
// PipelineManager::createPipeline() end
// Pipeline::state begin
// Valve::setOpen() begin
// Valve::setOpen() end
+
// Pipeline API end
} // namespace ml
#include "common/extension.h"
+#include "ml/ml_pipeline_manager.h"
#include "nnstreamer/nnstreamer-single.h"
#include "nnstreamer/nnstreamer.h"
// Single API end
// Pipeline API begin
+ PipelineManager pipeline_manager_;
// PipelineManager::createPipeline() begin
-
+ void MLPipelineManagerCreatePipeline(const picojson::value& args, picojson::object& out);
// PipelineManager::createPipeline() end
// Pipeline::state begin
// Valve::setOpen() begin
// Valve::setOpen() end
-
// Pipeline API end
};
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <tizen.h>
+
+#include "common/logger.h"
+#include "common/picojson.h"
#include "ml_pipeline.h"
+#include "ml_utils.h"
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+namespace {
+
+const std::string kListenerId = "listenerId";
+const std::string kState = "state";
+
+std::string StateToString(ml_pipeline_state_e state) {
+ ScopeLogger("state: [%d]", state);
+
+ std::string state_str;
+ switch (state) {
+ case ML_PIPELINE_STATE_UNKNOWN:
+ state_str = "UNKNOWN";
+ break;
+ case ML_PIPELINE_STATE_NULL:
+ state_str = "NULL";
+ break;
+ case ML_PIPELINE_STATE_READY:
+ state_str = "READY";
+ break;
+ case ML_PIPELINE_STATE_PAUSED:
+ state_str = "PAUSED";
+ break;
+ case ML_PIPELINE_STATE_PLAYING:
+ state_str = "PLAYING";
+ break;
+ default:
+ LoggerE("Illegal ml_pipeline_state_e value: [%d]", state);
+ state_str = "UNKNOWN";
+ }
+
+ LoggerD("state_str: [%s]", state_str.c_str());
+ return state_str;
+}
+
+} // namespace
+
+namespace extension {
+namespace ml {
+
+Pipeline::Pipeline(int id, const std::string& state_change_listener_name,
+ common::Instance* instance_ptr)
+ : id_{id},
+ pipeline_{nullptr}, // this will be set to a proper pointer in CreatePipeline()
+ state_change_listener_name_{state_change_listener_name},
+ instance_ptr_{instance_ptr} {
+ ScopeLogger("id: [%d], state_change_listener_name: [%s]", id, state_change_listener_name.c_str());
+}
// PipelineManager::createPipeline() begin
-
+PlatformResult Pipeline::CreatePipeline(int id, const std::string& definition,
+ const std::string& state_change_listener_name,
+ common::Instance* instance_ptr,
+ std::unique_ptr<Pipeline>* out) {
+ ScopeLogger("id: [%d], definition: [%s], state_change_listener_name: [%s]", id,
+ definition.c_str(), state_change_listener_name.c_str());
+
+ /* We need to create the Pipeline object before setting its pipeline_ member,
+ * because Pipeline is the user data for the listener registered by
+ * ml_pipeline_construct().
+ */
+ std::unique_ptr<Pipeline> pipeline_ptr{
+ new (std::nothrow) Pipeline{id, state_change_listener_name, instance_ptr}};
+ if (!pipeline_ptr) {
+ return LogAndCreateResult(ErrorCode::ABORT_ERR, "An unknown occurred.",
+ ("Could not allocate memory for Pipeline"));
+ }
+
+ int ret = ML_ERROR_UNKNOWN;
+ if (state_change_listener_name == "") {
+ ret = ml_pipeline_construct(definition.c_str(), nullptr, nullptr, &pipeline_ptr->pipeline_);
+ } else {
+ ret = ml_pipeline_construct(definition.c_str(), PipelineStateChangeListener,
+ static_cast<void*>(pipeline_ptr.get()), &pipeline_ptr->pipeline_);
+ }
+
+ if (ML_ERROR_NONE != ret) {
+ LoggerE("ml_pipeline_construct() failed: [%d] (%s)", ret, get_error_message(ret));
+ return util::ToPlatformResult(ret, "Could not create a pipeline");
+ }
+ LoggerD("ml_pipeline_construct() succeeded");
+
+ *out = std::move(pipeline_ptr);
+ return PlatformResult{};
+}
// PipelineManager::createPipeline() end
+Pipeline::~Pipeline() {
+ ScopeLogger("Destroying pipeline: [%d]", id_);
+
+ auto ret = ml_pipeline_destroy(pipeline_);
+ if (ML_ERROR_NONE != ret) {
+ LoggerE("ml_pipeline_destroy() failed: [%d] (%s)", ret, get_error_message(ret));
+ }
+ LoggerD("ml_pipeline_destroy() succeeded");
+}
+
+void Pipeline::PipelineStateChangeListener(ml_pipeline_state_e state, void* user_data) {
+ ScopeLogger("state: [%s]", StateToString(state).c_str());
+
+ Pipeline* pipeline = static_cast<Pipeline*>(user_data);
+
+ picojson::value response{picojson::object{}};
+ response.get<picojson::object>()[kListenerId] =
+ picojson::value{pipeline->state_change_listener_name_};
+ response.get<picojson::object>()[kState] = picojson::value{StateToString(state)};
+
+ common::Instance::PostMessage(pipeline->instance_ptr_, response);
+}
+
// Pipeline::state begin
// Pipeline::state end
// Valve::setOpen() begin
-// Valve::setOpen() end
\ No newline at end of file
+// Valve::setOpen() end
+
+} // namespace extension
+} // namespace ml
#ifndef ML_ML_PIPELINE_H_
#define ML_ML_PIPELINE_H_
+#include <map>
+#include <string>
+
+#include <nnstreamer/nnstreamer.h>
+
+#include "common/extension.h"
#include "common/picojson.h"
#include "common/platform_result.h"
+using common::PlatformResult;
+
namespace extension {
namespace ml {
class Pipeline {
public:
// PipelineManager::createPipeline() begin
-
+ /*
+ * We use a static function to create Pipeline objects, instead of
+ * a typical constructor, to be able to return an error without
+ * throwing a C++ exception.
+ */
+ static PlatformResult CreatePipeline(int id, const std::string& definition,
+ const std::string& state_change_listener_name,
+ common::Instance* instance_ptr,
+ std::unique_ptr<Pipeline>* out);
// PipelineManager::createPipeline() end
+ Pipeline() = delete;
+ Pipeline(const Pipeline&) = delete;
+ Pipeline& operator=(const Pipeline&) = delete;
+
+ ~Pipeline();
+
// Pipeline::state begin
// Pipeline::state end
// Valve::setOpen() end
private:
+ Pipeline(int id, const std::string& state_change_listener_name, common::Instance* instance_ptr);
+
+ const int id_;
+ ml_pipeline_h pipeline_;
+ const std::string state_change_listener_name_;
+ common::Instance* instance_ptr_;
+
+ static void PipelineStateChangeListener(ml_pipeline_state_e state, void* user_data);
};
} // namespace ml
*/
#include "ml_pipeline_manager.h"
+#include "common/tools.h"
-// PipelineManager::createPipeline() begin
+using common::PlatformResult;
+using common::ErrorCode;
+using common::tools::ReportError;
+using common::tools::ReportSuccess;
+
+namespace extension {
+namespace ml {
+
+PipelineManager::PipelineManager(common::Instance* instance_ptr) : instance_ptr_{instance_ptr} {
+ ScopeLogger();
+}
+PipelineManager::~PipelineManager() {
+ ScopeLogger();
+}
+
+// PipelineManager::createPipeline() begin
+PlatformResult PipelineManager::CreatePipeline(int id, const std::string& definition,
+ const std::string& state_change_listener_name) {
+ ScopeLogger("id: [%d], definition: [%s], state_change_listener_name: [%s]", id,
+ definition.c_str(), state_change_listener_name.c_str());
+
+ if (pipelines_.count(id)) {
+ LoggerD("The pipeline already exists: [%d]", id);
+ return PlatformResult{ErrorCode::ABORT_ERR, "Could not create pipeline"};
+ }
+
+ std::unique_ptr<Pipeline> pipeline_ptr;
+ auto ret = Pipeline::CreatePipeline(id, definition, state_change_listener_name, instance_ptr_,
+ &pipeline_ptr);
+ if (!ret) {
+ return ret;
+ }
+
+ pipelines_.insert({id, std::move(pipeline_ptr)});
+
+ return PlatformResult{};
+}
// PipelineManager::createPipeline() end
// Pipeline::state begin
// Valve::setOpen() begin
-// Valve::setOpen() end
\ No newline at end of file
+// Valve::setOpen() end
+
+} // namespace ml
+} // namespace extension
#ifndef ML_ML_PIPELINE_MANAGER_H_
#define ML_ML_PIPELINE_MANAGER_H_
+#include "common/extension.h"
#include "common/picojson.h"
#include "common/platform_result.h"
+#include "ml_pipeline.h"
+
+using common::PlatformResult;
+
namespace extension {
namespace ml {
class PipelineManager {
public:
- // PipelineManager::createPipeline() begin
+ PipelineManager(common::Instance* instance_ptr);
+ ~PipelineManager();
+
+ PipelineManager() = delete;
+ PipelineManager(const PipelineManager&) = delete;
+ PipelineManager& operator=(const PipelineManager&) = delete;
+
+ // PipelineManager::createPipeline() begin
+ PlatformResult CreatePipeline(int id, const std::string& definition,
+ const std::string& state_change_listener_name);
// PipelineManager::createPipeline() end
// Pipeline::state begin
// Valve::setOpen() end
private:
+ common::Instance* instance_ptr_;
+ std::map<int, std::unique_ptr<Pipeline>> pipelines_;
};
} // namespace ml