Add media plugin
authorJinWang An <jinwang.an@samsung.com>
Tue, 24 Sep 2019 05:07:01 +0000 (14:07 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 19 Mar 2020 04:30:37 +0000 (13:30 +0900)
12 files changed:
CMakeLists.txt
media/CMakeLists.txt [new file with mode: 0644]
media/MediaAction.h [new file with mode: 0644]
media/MediaFactory.cpp [new file with mode: 0644]
media/MediaFactory.h [new file with mode: 0644]
media/MediaPlayer.cpp [new file with mode: 0644]
media/MediaPlayer.h [new file with mode: 0644]
media/MediaPlugin.cpp [new file with mode: 0644]
media/tizen_media_rule.xml [new file with mode: 0644]
packaging/modes-plugins.spec
unittests/CMakeLists.txt
unittests/mdsp_test_media.cpp [new file with mode: 0644]

index 6f39fb7bd740441c7b04e494169c6bd7de10824a..2080283b7194edba6f49bbb1d2072ae00c232b06 100644 (file)
@@ -20,4 +20,5 @@ ADD_SUBDIRECTORY(vconf)
 ADD_SUBDIRECTORY(app)
 ADD_SUBDIRECTORY(pkg)
 ADD_SUBDIRECTORY(bluetooth)
+ADD_SUBDIRECTORY(media)
 ADD_SUBDIRECTORY(unittests)
diff --git a/media/CMakeLists.txt b/media/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c66fad9
--- /dev/null
@@ -0,0 +1,13 @@
+SET(MEDIA_PLUGIN "modes-plugin-media")
+
+FILE(GLOB PKG_SRCS *.cpp)
+
+PKG_CHECK_MODULES(MEDIA_pkgs REQUIRED modes dlog capi-base-common capi-media-sound-manager capi-media-player)
+INCLUDE_DIRECTORIES(${MEDIA_pkgs_INCLUDE_DIRS})
+LINK_DIRECTORIES(${MEDIA_pkgs_LIBRARY_DIRS})
+
+ADD_LIBRARY(${MEDIA_PLUGIN} SHARED ${PKG_SRCS})
+TARGET_LINK_LIBRARIES(${MEDIA_PLUGIN} ${MEDIA_pkgs_LIBRARIES})
+SET_TARGET_PROPERTIES(${MEDIA_PLUGIN} PROPERTIES NO_SONAME 1 )
+INSTALL(TARGETS ${MEDIA_PLUGIN} DESTINATION ${MODES_PLUGIN_DEFAULT_DIR})
+INSTALL(FILES tizen_media_rule.xml DESTINATION ${MODES_ACTIONRULE_DEFAULT_DIR})
diff --git a/media/MediaAction.h b/media/MediaAction.h
new file mode 100644 (file)
index 0000000..d0bf7d7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <string>
+#include <PluginAction.h>
+#include "plugin-def.h"
+
+MODES_NAMESPACE_BEGIN
+
+class MediaAction : public PluginAction {
+public:
+       MediaAction() = default;
+       virtual ~MediaAction() = default;
+
+       virtual int set(std::string val)
+       {
+               return MODES_ERROR_NOT_SUPPORTED;
+       }
+};
+
+MODES_NAMESPACE_END
+
diff --git a/media/MediaFactory.cpp b/media/MediaFactory.cpp
new file mode 100644 (file)
index 0000000..7402c78
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "MediaFactory.h"
+#include "plugin-log.h"
+#include "MediaPlayer.h"
+
+MODES_NAMESPACE_USE;
+
+MediaFactory::MediaFactory()
+{
+       actionMap[MediaPlayer::NAME] = PLAYER;
+}
+
+MediaAction* MediaFactory::createAction(const std::string &key)
+{
+       auto search = actionMap.find(key);
+       if (search == actionMap.end()) {
+               ERR("No MediaAction(%s)", key.c_str());
+               return nullptr;
+       }
+
+       MediaAction *action;
+       switch (search->second) {
+       case PLAYER:
+               action = new MediaPlayer();
+               break;
+       default:
+               action = nullptr;
+               break;
+       }
+
+       return action;
+}
+
+void MediaFactory::destroyAction(MediaAction *action)
+{
+       delete action;
+}
diff --git a/media/MediaFactory.h b/media/MediaFactory.h
new file mode 100644 (file)
index 0000000..6d94487
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <map>
+#include <string>
+#include "MediaAction.h"
+
+MODES_NAMESPACE_BEGIN
+
+class MediaFactory {
+public:
+       MediaFactory();
+       ~MediaFactory() = default;
+
+       MediaAction* createAction(const std::string &key);
+       void destroyAction(MediaAction *action);
+private:
+       enum actionKey{
+               PLAYER
+       };
+
+       std::map<std::string, enum actionKey> actionMap;
+};
+
+MODES_NAMESPACE_END
diff --git a/media/MediaPlayer.cpp b/media/MediaPlayer.cpp
new file mode 100644 (file)
index 0000000..0b9cea7
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "MediaPlayer.h"
+#include <string>
+#include <modes_errors.h>
+#include <player.h>
+#include "plugin-log.h"
+
+MODES_NAMESPACE_USE;
+
+const std::string MediaPlayer::NAME = "player";
+
+
+void MediaPlayer::playerCompletedCb(void *data)
+{
+       RET_IF(NULL == data);
+
+       MediaPlayer *h = (MediaPlayer *)data;
+       h->destroyPlayer();
+}
+
+MediaPlayer::MediaPlayer()
+:player(NULL), stream_info(NULL)
+{
+       setName(NAME);
+}
+
+MediaPlayer::~MediaPlayer()
+{
+}
+
+int MediaPlayer::createPlayer()
+{
+       int ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
+       if (SOUND_MANAGER_ERROR_NONE != ret) {
+               ERR("sound_manager_create_stream_information() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+
+       ret = player_create(&player);
+       if (PLAYER_ERROR_NONE != ret) {
+               ERR("player_create() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+
+       ret = player_set_sound_stream_info(player, stream_info);
+       if (PLAYER_ERROR_NONE != ret) {
+               ERR("player_set_sound_stream_info() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+       return MODES_ERROR_NONE;
+}
+
+int MediaPlayer::destroyPlayer()
+{
+       if (stream_info) {
+               sound_manager_destroy_stream_information(stream_info);
+               stream_info = NULL;
+       }
+
+       if (player) {
+               player_state_e state;
+               player_get_state(player, &state);
+               if (PLAYER_STATE_PLAYING == state || PLAYER_STATE_PAUSED == state)
+                       player_stop(player);
+               player_unprepare(player);
+               player_destroy(player);
+               player = NULL;
+       }
+
+       return MODES_ERROR_NONE;
+}
+
+int MediaPlayer::set(std::string val)
+{
+       int ret = createPlayer();
+       if (MODES_ERROR_SYSTEM == ret) {
+               ERR("createPlayer() Fail(%d)", ret);
+               return MODES_ERROR_SYSTEM;
+       }
+
+       ret = player_set_uri(player, val.c_str());
+       if (PLAYER_ERROR_NONE != ret) {
+               ERR("player_set_uri() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+
+       ret = player_prepare(player);
+       if (PLAYER_ERROR_NONE != ret) {
+               ERR("player_prepare() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+
+       ret = player_set_completed_cb(player, playerCompletedCb, this);
+       if (PLAYER_ERROR_NONE != ret) {
+               ERR("player_set_completed_cb() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+
+       ret = player_start(player);
+       if (PLAYER_ERROR_NONE != ret) {
+               ERR("player_start() Fail(%s)", get_error_message(ret));
+               return MODES_ERROR_SYSTEM;
+       }
+
+       return MODES_ERROR_NONE;
+}
+
+int MediaPlayer::undo()
+{
+       return destroyPlayer();
+}
diff --git a/media/MediaPlayer.h b/media/MediaPlayer.h
new file mode 100644 (file)
index 0000000..fd0c9b1
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <player.h>
+#include <sound_manager.h>
+#include "plugin-def.h"
+#include "MediaAction.h"
+
+MODES_NAMESPACE_BEGIN
+
+class MediaPlayer : public MediaAction {
+public:
+       MediaPlayer();
+       ~MediaPlayer();
+
+       virtual int set(std::string val);
+       virtual int undo();
+
+       static const std::string NAME;
+
+private:
+       int createPlayer();
+       int destroyPlayer();
+       static void playerCompletedCb(void *data);
+
+       player_h player;
+       sound_stream_info_h stream_info;
+};
+
+MODES_NAMESPACE_END
diff --git a/media/MediaPlugin.cpp b/media/MediaPlugin.cpp
new file mode 100644 (file)
index 0000000..9b3e087
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by pkglicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string>
+#include <modes_errors.h>
+#include <Plugin.h>
+#include "plugin-log.h"
+#include "plugin-def.h"
+#include "MediaFactory.h"
+#include "MediaAction.h"
+
+MODES_NAMESPACE_USE;
+
+class MediaPlugin : public Plugin {
+public:
+       MediaPlugin();
+       ~MediaPlugin();
+
+       int set(const std::string &key, const std::string &val, PluginAction **pluginAction) override;
+
+private:
+       MediaFactory pkgFactory;
+};
+
+extern "C" API Plugin *objectCreate(void)
+{
+       return new MediaPlugin;
+}
+
+extern "C" API void objectDelete(Plugin *plugin)
+{
+       delete plugin;
+}
+
+MediaPlugin::MediaPlugin()
+{
+       setName("media");
+}
+
+MediaPlugin::~MediaPlugin()
+{
+}
+
+int MediaPlugin::set(const std::string &key, const std::string &val, PluginAction **pluginAction)
+{
+       MediaAction *action = pkgFactory.createAction(key);
+       RETVM_IF(nullptr == action, MODES_ERROR_INVALID_PARAMETER, "action(%s) is null", key.c_str());
+
+       DBG("Action(%s) set(%s)", key.c_str(), val.c_str());
+
+       int ret = action->set(val);
+       if ((ret == MODES_ERROR_NONE) && pluginAction)
+               *pluginAction = action;
+       else
+               pkgFactory.destroyAction(action);
+       return ret;
+}
diff --git a/media/tizen_media_rule.xml b/media/tizen_media_rule.xml
new file mode 100644 (file)
index 0000000..de3c3ce
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tizenModes xmlns="http://www.tizen.org" version="5.5">
+  <actionRule>
+    <rule name="media.player" type="string" since="5.5" plugin="media">
+      <desc>Audio/Video player</desc>
+      <domain>Multimedia</domain>
+    </rule>
+  </actionRule>
+</tizenModes>
index 9a7eddcb933c8bbdf94185debbeff0d59e8105ad..eeeb6818bfd44db59c266b4733941909b25b1c2e 100644 (file)
@@ -15,6 +15,8 @@ BuildRequires: modes-plugin-devel
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(capi-appfw-application)
 BuildRequires: pkgconfig(capi-appfw-app-manager)
+BuildRequires: pkgconfig(capi-media-sound-manager)
+BuildRequires: pkgconfig(capi-media-player)
 BuildRequires: pkgconfig(capi-base-common)
 BuildRequires: pkgconfig(libxml-2.0)
 BuildRequires: pkgconfig(capi-network-wifi-manager)
@@ -73,8 +75,10 @@ xmllint --noout --schema %{modes_data_dir}/schema/tizen_action_rule.xsd %{buildr
 systemctl restart modes.service
 
 %post unittests
+export XDG_RUNTIME_DIR=/run
 %{modes_plugin_test_dir}/modes-gtest-pkg
 %{modes_plugin_test_dir}/modes-gtest-vconf
+%{modes_plugin_test_dir}/modes-gtest-media
 
 %postun -p /sbin/ldconfig
 
index 70120937412acc99f2be09e8c581b76822c7b6c6..79b59c2222db01efa6f691a31078f598a324d84d 100644 (file)
@@ -4,6 +4,7 @@ ADD_DEFINITIONS("-DMDS_TEST")
 
 PKG_CHECK_MODULES(test_pkgs REQUIRED modes dlog gmock capi-network-wifi-manager capi-network-bluetooth vconf
        capi-appfw-application capi-appfw-app-manager aul
+       capi-media-sound-manager capi-media-player
        pkgmgr pkgmgr-info)
 INCLUDE_DIRECTORIES(${test_pkgs_INCLUDE_DIRS})
 LINK_DIRECTORIES(${test_pkgs_LIBRARY_DIRS})
@@ -50,3 +51,12 @@ SET(VCONF_SRCS ${VCONF_SRCS} "mdsp_test_vconf.cpp")
 ADD_EXECUTABLE(${VCONF_PLUGIN_TEST} ${VCONF_SRCS})
 TARGET_LINK_LIBRARIES(${VCONF_PLUGIN_TEST} ${test_pkgs_LIBRARIES})
 INSTALL(TARGETS ${VCONF_PLUGIN_TEST} DESTINATION ${TEST_INSTALL_DIR})
+#===================================================================#
+SET(MEDIA_SRC_DIR "${CMAKE_SOURCE_DIR}/media" )
+SET(MEDIA_PLUGIN_TEST "modes-gtest-media")
+FILE(GLOB MEDIA_SRCS ${MEDIA_SRC_DIR}/*.cpp)
+SET(MEDIA_SRCS ${MEDIA_SRCS} "mdsp_test_media.cpp")
+
+ADD_EXECUTABLE(${MEDIA_PLUGIN_TEST} ${MEDIA_SRCS})
+TARGET_LINK_LIBRARIES(${MEDIA_PLUGIN_TEST} ${test_pkgs_LIBRARIES})
+INSTALL(TARGETS ${MEDIA_PLUGIN_TEST} DESTINATION ${TEST_INSTALL_DIR})
diff --git a/unittests/mdsp_test_media.cpp b/unittests/mdsp_test_media.cpp
new file mode 100644 (file)
index 0000000..8e2c129
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by medialicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <glib.h>
+#include <string>
+#include <gtest/gtest.h>
+#include <Plugin.h>
+#include <modes_errors.h>
+#include "plugin-def.h"
+
+MODES_NAMESPACE_USE;
+
+extern "C" API Plugin *objectCreate(void);
+extern "C" API void objectDelete(Plugin *plugin);
+
+class PluginTest : public ::testing::Test {
+protected:
+       void SetUp() override
+       {
+               loop = g_main_loop_new(NULL, FALSE);
+               plugin = objectCreate();
+       }
+
+       void TearDown() override
+       {
+               g_main_loop_unref(loop);
+               loop = NULL;
+               objectDelete(plugin);
+               plugin = NULL;
+       }
+
+       static gboolean mediaPluginSetUndoTimeout(gpointer data)
+       {
+               PluginAction *action = (PluginAction*)data;
+               result = plugin->undo(action);
+               EXPECT_EQ(MODES_ERROR_NONE, result);
+               g_main_loop_quit(loop);
+               return false;
+       }
+
+       static gboolean mediaPluginSetUndoIdler(gpointer data)
+       {
+               PluginAction *action;
+               result = plugin->set("player", std::string("/opt/usr/data/settings/Previews/Media_preview_Over_the_horizon_B2.ogg"), &action);
+               EXPECT_EQ(MODES_ERROR_NONE, result);
+
+               g_timeout_add(1000, mediaPluginSetUndoTimeout, action);
+               return G_SOURCE_REMOVE;
+       }
+
+       static int result;
+       static GMainLoop *loop;
+       static Plugin *plugin;
+};
+
+int PluginTest::result = 0;
+Plugin *PluginTest::plugin = NULL;
+GMainLoop *PluginTest::loop = NULL;
+
+TEST_F(PluginTest, setUndoPluginmedia)
+{
+       g_idle_add(mediaPluginSetUndoIdler, plugin);
+       g_main_loop_run(loop);
+}
+
+int main(int argc, char **argv) {
+       testing::InitGoogleTest(&argc, argv);
+       return RUN_ALL_TESTS();
+}