summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xAUTHORS2
-rwxr-xr-xCMakeLists.txt126
-rwxr-xr-xLICENSE.APLv2.0201
-rwxr-xr-xNOTICE3
-rwxr-xr-xcapi-media-controller.manifest5
-rwxr-xr-xcapi-media-controller.pc.in14
-rwxr-xr-xdoc/media_controller_doc.h74
-rwxr-xr-xinclude/media_controller_client.h735
-rwxr-xr-xinclude/media_controller_db.h89
-rwxr-xr-xinclude/media_controller_private.h243
-rwxr-xr-xinclude/media_controller_server.h362
-rwxr-xr-xinclude/media_controller_type.h157
-rwxr-xr-xmedia-controller-service.manifest22
-rwxr-xr-xpackaging/capi-media-controller.spec114
-rwxr-xr-xpackaging/mediacontroller.service12
-rwxr-xr-xpackaging/mediacontroller.socket13
-rwxr-xr-xsrc/media_controller_client.c1053
-rwxr-xr-xsrc/media_controller_db.c639
-rwxr-xr-xsrc/media_controller_ipc.c424
-rwxr-xr-xsrc/media_controller_server.c691
-rwxr-xr-xsrc/media_controller_util.c152
-rwxr-xr-xsvc/CMakeLists.txt46
-rwxr-xr-xsvc/daemon/CMakeLists.txt21
-rwxr-xr-xsvc/daemon/media_controller_main.c92
-rwxr-xr-xsvc/media_controller_db_util.c238
-rwxr-xr-xsvc/media_controller_db_util.h39
-rwxr-xr-xsvc/media_controller_socket.c185
-rwxr-xr-xsvc/media_controller_socket.h75
-rwxr-xr-xsvc/media_controller_svc.c317
-rwxr-xr-xsvc/media_controller_svc.h45
-rwxr-xr-xtest/client_test/CMakeLists.txt20
-rwxr-xr-xtest/client_test/media_controller_client_test.c661
-rwxr-xr-xtest/server_test/CMakeLists.txt20
-rwxr-xr-xtest/server_test/media_controller_server_test.c557
34 files changed, 7447 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100755
index 0000000..6c44d79
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+MANOJ KUMAR KOPPARAPU <manojkumar.k at samsung dot com>
+ABHISHEK BAJAJ <abhi.bajaj at samsung dot com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755
index 0000000..06f1d39
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,126 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+SET(Services
+ "application"
+ "base"
+ "content"
+ "location"
+ "media"
+ "messaging"
+ "network"
+ "social"
+ "telephony"
+ "system"
+ )
+
+
+# project
+SET(project_prefix "capi")
+SET(prefix "/usr")
+SET(version "0.0.1")
+SET(maintainer "Haejeong Kim <backto.kim@samsung.com>")
+SET(description "A Media Controller library in Tizen Native API")
+SET(service "media")
+SET(submodule "controller")
+
+# for package file
+SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util aul bundle")
+SET(fw_name "${project_prefix}-${service}-${submodule}")
+
+PROJECT(${fw_name})
+
+SET(CMAKE_INSTALL_PREFIX ${prefix})
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(VERSION ${version})
+
+SET(INC_DIR include)
+SET(SVC_DIR svc)
+
+INCLUDE_DIRECTORIES(${INC_DIR} ${SVC_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_name} REQUIRED ${dependents})
+FOREACH(flag ${${fw_name}_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+
+IF("${ARCH}" MATCHES "^arm.*")
+ ADD_DEFINITIONS("-DTARGET")
+ENDIF("${ARCH}" MATCHES "^arm.*")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DTIZEN_DEBUG")
+ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib")
+
+aux_source_directory(src SOURCES)
+ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+
+TARGET_LINK_LIBRARIES(${fw_name} media-controller-svc ${${fw_name}_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${fw_name}
+ PROPERTIES
+ VERSION ${FULLVER}
+ SOVERSION ${MAJORVER}
+ CLEAN_DIRECT_OUTPUT 1
+)
+
+INSTALL(TARGETS ${fw_name} DESTINATION lib)
+INSTALL(
+ DIRECTORY ${INC_DIR}/ DESTINATION include/${service}
+ FILES_MATCHING
+ PATTERN "*_private.h" EXCLUDE
+ PATTERN "*_db.h" EXCLUDE
+ PATTERN "${INC_DIR}/*.h"
+ )
+
+SET(PC_NAME ${fw_name})
+SET(PC_REQUIRED ${dependents})
+SET(PC_LDFLAGS -l${fw_name})
+SET(PC_CFLAGS -I\${includedir}/${service})
+
+CONFIGURE_FILE(
+ ${fw_name}.pc.in
+ ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc
+ @ONLY
+)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION lib/pkgconfig)
+
+ADD_SUBDIRECTORY(svc)
+ADD_SUBDIRECTORY(test/client_test)
+ADD_SUBDIRECTORY(test/server_test)
+
+IF(UNIX)
+
+ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
+ADD_CUSTOM_COMMAND(
+ DEPENDS clean
+ COMMENT "distribution clean"
+ COMMAND find
+ ARGS .
+ -not -name config.cmake -and \(
+ -name tester.c -or
+ -name Testing -or
+ -name CMakeFiles -or
+ -name cmake.depends -or
+ -name cmake.check_depends -or
+ -name CMakeCache.txt -or
+ -name cmake.check_cache -or
+ -name *.cmake -or
+ -name Makefile -or
+ -name core -or
+ -name core.* -or
+ -name gmon.out -or
+ -name install_manifest.txt -or
+ -name *.pc -or
+ -name *~ \)
+ | grep -v TC | xargs rm -rf
+ TARGET distclean
+ VERBATIM
+)
+
+ENDIF(UNIX)
diff --git a/LICENSE.APLv2.0 b/LICENSE.APLv2.0
new file mode 100755
index 0000000..261eeb9
--- /dev/null
+++ b/LICENSE.APLv2.0
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/NOTICE b/NOTICE
new file mode 100755
index 0000000..ccdad52
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
diff --git a/capi-media-controller.manifest b/capi-media-controller.manifest
new file mode 100755
index 0000000..c00c25b
--- /dev/null
+++ b/capi-media-controller.manifest
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
diff --git a/capi-media-controller.pc.in b/capi-media-controller.pc.in
new file mode 100755
index 0000000..b5516cd
--- /dev/null
+++ b/capi-media-controller.pc.in
@@ -0,0 +1,14 @@
+
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=/usr/lib
+includedir=/usr/include/media
+
+Name: @PC_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @VERSION@
+Requires: @PC_REQUIRED@
+Libs: -L${libdir} @PC_LDFLAGS@
+Cflags: -I${includedir} @PC_CFLAGS@
diff --git a/doc/media_controller_doc.h b/doc/media_controller_doc.h
new file mode 100755
index 0000000..c66a94f
--- /dev/null
+++ b/doc/media_controller_doc.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_DOC_H__
+#define __TIZEN_MEDIA_CONTROLLER_DOC_H__
+
+/**
+ * @file media_controller_doc.h
+ * @brief File contains the high level documentation for the Media Controller API.
+ *
+ */
+
+/**
+ * @defgroup CAPI_MEDIA_CONTROLLER_MODULE Media Controller
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+ */
+
+/**
+ * @ingroup CAPI_MEDIA_FRAMEWORK
+ * @addtogroup CAPI_MEDIA_CONTROLLER_MODULE
+ * @brief The @ref CAPI_MEDIA_CONTROLLER_MODULE API provides functions for communication between the media controller server and the media controller client.
+ * @section CAPI_MEDIA_CONTROLLER_MODULE_HEADER Required Header
+ * \#include <media_controller_server.h>
+ * \#include <media_controller_client.h>
+ *
+ * @section CAPI_MEDIA_CONTROLLER_OVERVIEW Overview
+ * The @ref CAPI_MEDIA_CONTROLLER_MODULE API provides a set of functions to an effective communication between the server and the client for delivering the latest server information. It helps to transfer the information like playback info, shuffle mode, or the metadata of the latest server. \n
+ * To programming the interface, first, create a handler via #mc_client_create() or #mc_server_create(). And then, the client request the necessary information to the server by using #mc_client_set_server_update_cb(), or #mc_client_set_playback_update_cb(). The server provides the requested information to the client by the callback.
+ *
+ */
+
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @defgroup CAPI_MEDIA_CONTROLLER_SERVER_MODULE Media Controller Server
+* @brief The @ref CAPI_MEDIA_CONTROLLER_SERVER_MODULE API provides functions for sending the server information to the client.
+* @section CAPI_MEDIA_CONTROLLER_SERVER_MODULE_HEADER Required Header
+* \#include <media_controller_server.h>
+*
+* @section CAPI_MEDIA_CONTROLLER_SERVER_MODULE_OVERVIEW Overview
+* The @ref CAPI_MEDIA_CONTROLLER_SERVER_MODULE API allows you to send the playback info(#mc_server_set_playback_state(), #mc_server_set_playback_position), or the metadata(#mc_server_set_metadata()). and to receive the custom command(#mc_server_set_custom_command_received_cb()), to update the status information on the latest server(#mc_server_update_playback_info, #mc_server_update_metadata), or to create/destroy the handle(#mc_server_create()/#mc_server_destroy()). \n
+*
+*/
+
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @defgroup CAPI_MEDIA_CONTROLLER_CLIENT_MODULE Media Controller Client
+* @brief The @ref CAPI_MEDIA_CONTROLLER_CLIENT_MODULE API provides functions for requesting the information to the server.
+* @section CAPI_MEDIA_CONTROLLER_CLIENT_MODULE_HEADER Required Header
+* \#include <media_controller_client.h>
+*
+* @section CAPI_MEDIA_CONTROLLER_CLIENT_MODULE_OVERVIEW Overview
+* The @ref CAPI_MEDIA_CONTROLLER_CLIENT_MODULE API allows you to check the activated server status(#mc_client_set_server_update_cb()), the playback info(#mc_client_set_playback_update_cb()), or the metadata(#mc_client_set_metadata_update_cb()). to send the custom command(#mc_client_send_custom_command()), to create/destroy the handle(#mc_client_create()/#mc_client_destroy()). \n
+* If there is no the activated server, you can get the latest server information by using #mc_client_get_latest_server_info().
+*
+*/
+
+
+#endif /* __TIZEN_MEDIA_CONTROLLER_DOC_H__ */
+
+
diff --git a/include/media_controller_client.h b/include/media_controller_client.h
new file mode 100755
index 0000000..202e3b4
--- /dev/null
+++ b/include/media_controller_client.h
@@ -0,0 +1,735 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_CLIENT_H__
+#define __TIZEN_MEDIA_CONTROLLER_CLIENT_H__
+
+#include <media_controller_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file media_controller_client.h
+ * @brief This file contains the media controller client API and functions related with handling media control. \n
+ * Functions include operations to get the latest status of the media controller servers.
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_CONTROLLER_CLIENT_MODULE
+ * @{
+ */
+
+/**
+ * @brief Called when updating status of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the updated media controller server
+ * @param[in] state, The state of the updated media controller server
+ * @param[in] user_data The user data passed from the mc_client_set_server_update_cb() fuction
+ *
+ * @pre mc_client_set_server_update_cb()
+ *
+ * @see mc_client_set_server_update_cb()
+ */
+typedef void (*mc_server_state_updated_cb)(const char *server_name, mc_server_state_e state, void *user_data);
+
+/**
+ * @brief Called when updating the playback information of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the updated media controller server
+ * @param[in] playback, The playback information of the updated media controller server
+ * @param[in] user_data The user data passed from the mc_client_set_playback_update_cb() fuction
+ *
+ * @pre mc_client_set_playback_update_cb()
+ *
+ * @see mc_client_set_playback_update_cb()
+ */
+typedef void (*mc_playback_updated_cb)(const char *server_name, mc_playback_h playback, void *user_data);
+
+/**
+ * @brief Called when updating the metadata of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the updated media controller server
+ * @param[in] metadata, the metadata of the updated media controller server
+ * @param[in] user_data The user data passed from the mc_client_set_metadata_update_cb() fuction
+ *
+ * @pre mc_client_set_metadata_update_cb()
+ *
+ * @see mc_client_set_metadata_update_cb()
+ */
+typedef void (*mc_metadata_updated_cb)(const char *server_name, mc_metadata_h metadata, void *user_data);
+
+/**
+ * @brief Called when updating the shuffle mode of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the updated media controller server
+ * @param[in] mode, The shuffle mode of the updated media controller server
+ * @param[in] user_data The user data passed from the mc_client_set_shuffle_mode_update_cb() fuction
+ *
+ * @pre mc_client_set_shuffle_mode_update_cb()
+ *
+ * @see mc_client_set_shuffle_mode_update_cb()
+ */
+typedef void (*mc_shuffle_mode_changed_cb)(const char *server_name, mc_shuffle_mode_e mode, void *user_data);
+
+/**
+ * @brief Called when updating the repeat mode of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the updated media controller server
+ * @param[in] mode, The repeat mode of the updated media controller server
+ * @param[in] user_data The user data passed from the mc_client_set_repeat_mode_update_cb() fuction
+ *
+ * @pre mc_client_set_repeat_mode_update_cb()
+ *
+ * @see mc_client_set_repeat_mode_update_cb()
+ */
+typedef void (*mc_repeat_mode_changed_cb)(const char *server_name, mc_repeat_mode_e mode, void *user_data);
+
+/**
+ * @brief Called when requesting the list of activated servers.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the activated media controller server
+ * @param[in] user_data The user data passed from the mc_client_foreach_server() fuction
+ *
+ * @return @c true to continue with the next iteration of the loop,
+ * otherwise @c false to break out of the loop
+ *
+ * @pre mc_client_foreach_server()
+ *
+ * @see mc_client_foreach_server()
+ */
+typedef bool (*mc_activated_server_cb)(const char *server_name, void *user_data);
+
+/**
+ * @brief Called when receiving the command processing result from the server.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name The app_id of the updated media controller server
+ * @param[in] result_code The result code of custom command
+ * @param[in] data The extra data
+ * @param[in] user_data The user data passed from the mc_client_send_custom_command() fuction
+ *
+ * @pre mc_client_send_custom_command()
+ *
+ * @see mc_client_send_custom_command()
+ */
+typedef void (*mc_command_reply_received_cb)(const char *server_name, int result_code, bundle *data, void *user_data);
+
+/**
+ * @brief Called when requesting the list of subscribed servers.
+ * @since_tizen 2.4
+ *
+ * @param[in] server_name, The app_id of the subscribed media controller server
+ * @param[in] user_data The user data passed from the mc_client_foreach_server_subscribed() fuction
+ *
+ * @return @c true to continue with the next iteration of the loop,
+ * otherwise @c false to break out of the loop
+ *
+ * @pre mc_client_foreach_server_subscribed()
+ *
+ * @see mc_client_foreach_server_subscribed()
+ */
+typedef bool (*mc_subscribed_server_cb)(const char *server_name, void *user_data);
+
+/**
+ * @brief Creates a media controller client.
+ * @details The media controller client binds the latest media controller server when handlers are created.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks You must release @a client using mc_client_destroy().
+ *
+ * @param[out] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @see mc_client_destroy()
+ */
+int mc_client_create(mc_client_h *client);
+
+/**
+ * @brief Sets the callback for monitoring status of the media controller server.
+ * @since_tizen 2.4
+ * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers.
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] callback The callback to be invoked when the media controller server status is changed
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_server_update_cb(mc_client_h client, mc_server_state_updated_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for monitoring status of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_server_update_cb(mc_client_h client);
+
+/**
+ * @brief Sets the callback for monitoring playback status of the media controller server.
+ * @since_tizen 2.4
+ * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers. \n
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] callback The callback to be invoked when the playback status is changed
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_playback_update_cb(mc_client_h client, mc_playback_updated_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for monitoring playback status of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_playback_update_cb(mc_client_h client);
+
+/**
+ * @brief Sets the callback for monitoring metadata status of the media controller server.
+ * @since_tizen 2.4
+ * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers.
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] callback The callback to be invoked when the metadata status is changed
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_metadata_update_cb(mc_client_h client, mc_metadata_updated_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for monitoring metadata status of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_metadata_update_cb(mc_client_h client);
+
+/**
+ * @brief Sets the callback for monitoring shuffle mode of the media controller server.
+ * @since_tizen 2.4
+ * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers.
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] callback The callback to be invoked when the shuffle mode is changed
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_shuffle_mode_update_cb(mc_client_h client, mc_shuffle_mode_changed_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for monitoring shuffle mode of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_shuffle_mode_update_cb(mc_client_h client);
+
+/**
+ * @brief Sets the callback for monitoring repeat mode of the media controller server.
+ * @since_tizen 2.4
+ * @details If media controller client call this function, basically the media controller client recieve the callback from all media controller servers.
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] callback The callback to be invoked when the repeat mode is changed
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_set_repeat_mode_update_cb(mc_client_h client, mc_repeat_mode_changed_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for monitoring repeat mode of the media controller server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_destroy()
+ */
+int mc_client_unset_repeat_mode_update_cb(mc_client_h client);
+
+/**
+ * @brief Subscribes media controller server for monitoring status.
+ * @since_tizen 2.4
+ * @details If media controller client subscribe media controller server, \n
+ * the media controller client recieve callback from subscribed media controller server. \n
+ * If media controller client subscribe media controller server one or more, \n
+ * the media controller client can recieve callback from only subscribed media controller server. \n
+ * If you want to subscribe for the all media controller server again, \n
+ * unset mode update callback and set the callback for the monitoring status again. \n
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] subscription_type The subscription type
+ * @param [in] server_name The app_id of the media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media controller client handle by calling mc_client_create()
+ * @pre Set the callback for monitoring status of the media controller server
+ * @post Unsubscribe the media controller server for monitoring status by calling mc_client_unsubscribe()
+ * @see mc_client_create()
+ * @see mc_client_unsubscribe()
+ */
+int mc_client_subscribe(mc_client_h client, mc_subscription_type_e subscription_type, const char *server_name);
+
+/**
+ * @brief Unsubscribes media controller server for monitoring status.
+ * @since_tizen 2.4
+ * @details If media controller client unsubscribe media controller server, \n
+ * the media controller client don't recieve callback from unsubscribed media controller server. \n
+ * If media controller client unsubscribe all subscibed media controller server, \n
+ * the media controller client don't recieve callback from all media controller server. \n
+ * After unset and set update callback function is called again, the media controller client can recieve callback from all media controller servers. \n
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] subscription_type The subscription type
+ * @param [in] server_name The app_id of the media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media controller client handle by calling mc_client_create()
+ * @pre Subscribe the media controller server for monitoring status by calling mc_client_subscribe()
+ * @see mc_client_create()
+ * @see mc_client_subscribe()
+ */
+int mc_client_unsubscribe(mc_client_h client, mc_subscription_type_e subscription_type, const char *server_name);
+
+/**
+ * @brief Retrieves all subscribed Server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] subscription_type The subscription type
+ * @param [in] callback The callback to be invoked when the list of the subscribed media controller server.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media controller client handle by calling mc_client_create()
+ * @pre Subscribe the media controller server for monitoring status by calling mc_client_subscribe()
+ * @see mc_client_create()
+ * @see mc_client_subscribe()
+ */
+int mc_client_foreach_server_subscribed(mc_client_h client, mc_subscription_type_e subscription_type, mc_subscribed_server_cb callback, void *user_data);
+
+/**
+ * @brief Gets the playback state.
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a playback using @c mc_client_destroy_playback().
+ *
+ * @param [in] playback The handle to playback
+ * @param [out] state The state of the playback
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Sets mc_client_set_playback_update_cb() function to get the state
+ * @see mc_client_set_playback_update_cb()
+ */
+int mc_client_get_playback_state(mc_playback_h playback, mc_playback_states_e *state);
+
+/**
+ * @brief Gets the playback position.
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a playback using @c mc_client_destroy_playback().
+ *
+ * @param [in] playback The handle to playback
+ * @param [out] position The position of the playback in milliseconds
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Sets mc_client_set_playback_update_cb() function to get the position
+ * @see mc_client_set_playback_update_cb()
+ */
+int mc_client_get_playback_position(mc_playback_h playback, unsigned long long *position);
+
+/**
+ * @brief Destroys playback
+ * @since_tizen 2.4
+ *
+ * @param [in] playback The handle to playback
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Sets mc_client_set_playback_update_cb() function to create playback
+ * @see mc_client_set_playback_update_cb()
+ */
+int mc_client_destroy_playback(mc_playback_h playback);
+
+/**
+ * @brief Gets the metadata.
+ * @since_tizen 2.4
+ *
+ * @remarks You must release @a metadata using @c mc_client_destroy_metadata(). \n
+ * And also You must release @a value using free().
+ * If the attribute value of the metadata is empty, return value is NULL.
+ *
+ * @param [in] metadata The handle to metadata
+ * @param [in] attribute The key attribute name to get
+ * @param [out] value The value of the attribute
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Sets mc_client_set_metadata_update_cb() function to get the metadata
+ * @see mc_client_set_metadata_update_cb()
+ */
+int mc_client_get_metadata(mc_metadata_h metadata, mc_meta_e attribute, char **value);
+
+/**
+ * @brief Destroys metadata
+ * @since_tizen 2.4
+ *
+ * @param [in] playback The handle to metadata
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Sets mc_client_set_metadata_update_cb() function to create metadata
+ * @see mc_client_set_metadata_update_cb()
+ */
+int mc_client_destroy_metadata(mc_metadata_h metadata);
+
+/**
+ * @brief Gets the latest media controller server info.
+ * @details The media controller client will get the most recently updated information by the server.
+ *
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks If there is no activated media controller server, return value of the server name is NULL.
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [out] server_name The app_id of the latest media controller server
+ * @param [out] server_state The state of the latest media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ */
+int mc_client_get_latest_server_info(mc_client_h client, char **server_name, mc_server_state_e *server_state);
+
+/**
+ * @brief Gets the latest playback info.
+ * @details The media controller client will get the most recently updated information from @a server_name.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks You must release @a playback using @c mc_client_destroy_playback(). \n
+ * If there is no playback info, return value of the playback is NULL.
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] server_name The app_id of the server to requesting
+ * @param [out] playback The handle to playback
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ */
+int mc_client_get_server_playback_info(mc_client_h client, const char *server_name, mc_playback_h *playback);
+
+/**
+ * @brief Gets the latest metadata.
+ * @details The media controller client will get the most recently updated information from @a server_name.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks You must release @a metadata using @c mc_client_destroy_metadata(). \n
+ * If there is no metadata, return value of the metadata is NULL.
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] server_name The app_id of the server to requesting
+ * @param [out] metadata The handle to metadata
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ */
+int mc_client_get_server_metadata(mc_client_h client, const char *server_name, mc_metadata_h *metadata);
+
+/**
+ * @brief Gets the latest shuffle mode.
+ * @details The media controller client will get the most recently updated information from @a server_name.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks If there is no shuffle mode info, return value is MC_SHUFFLE_MODE_OFF.
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] server_name The app_id of the server to requesting
+ * @param [out] mode The info of the latest shuffle mode
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ */
+int mc_client_get_server_shuffle_mode(mc_client_h client, const char *server_name, mc_shuffle_mode_e *mode);
+
+/**
+ * @brief Gets the latest repeat mode.
+ * @details The media controller client will get the most recently updated information from @a server_name.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @remarks If there is no repeat mode info, return value is MC_REPEAT_MODE_OFF.
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] server_name The app_id of the server to requesting
+ * @param [out] mode The info of the latest shuffle mode
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ */
+int mc_client_get_server_repeat_mode(mc_client_h client, const char *server_name, mc_repeat_mode_e *mode);
+
+/**
+ * @brief Retrieves all activated Server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] callback The callback to be invoked when the list of the registered media controller server created completely.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ */
+int mc_client_foreach_server(mc_client_h client, mc_activated_server_cb callback, void *user_data);
+
+/**
+ * @brief Sends the playback state command to server.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] server_name The app_id of the media controller server
+ * @param [in] state The playback state command to send media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ * @see mc_client_get_server_playback_info()
+ */
+int mc_client_send_playback_state_command(mc_client_h client, const char *server_name, mc_playback_states_e state);
+
+/**
+ * @brief Sends the custom command to server.
+ * @since_tizen 2.4
+ * @details If there is the result for comand from server, the media controller client will get the result of the custom command by mc_command_reply_received_cb() callback.
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.client
+ *
+ * @param [in] client The handle to the media controller client
+ * @param [in] server_name The app_id of the media controller server
+ * @param [in] command The command to be sent
+ * @param [in] data The extra data
+ * @param [in] callback The callback to be invoked when the custom command execute completely.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ */
+int mc_client_send_custom_command(mc_client_h client, const char *server_name, const char *command, bundle *data, mc_command_reply_received_cb callback, void *user_data);
+
+/**
+ * @brief Destroys client.
+ * @since_tizen 2.4
+ * @param [in] client The handle to the media controller client
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #METADATA_EXTRACTOR_ERROR_NONE Successful
+ * @retval #METADATA_EXTRACTOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media controller client handle by calling mc_client_create().
+ * @see mc_client_create()
+ */
+int mc_client_destroy(mc_client_h client); //deregistered internally
+
+
+/**
+* @}
+*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIA_CONTROLLER_CLIENT_H__ */
diff --git a/include/media_controller_db.h b/include/media_controller_db.h
new file mode 100755
index 0000000..c6cc3c9
--- /dev/null
+++ b/include/media_controller_db.h
@@ -0,0 +1,89 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_DB_H__
+#define __TIZEN_MEDIA_CONTROLLER_DB_H__
+
+#include <db-util.h>
+#include <sqlite3.h>
+
+#define MC_DB_NAME "/opt/usr/dbspace/.media_controller.db"
+
+#define MC_DB_TABLE_SERVER_LIST "server_list"
+#define MC_DB_TABLE_LATEST_SERVER "latest_server"
+
+#define DB_DELETE_ALL_FROM_TABLE "DELETE FROM '%q';"
+#define DB_SELECT_META_FROM_TABLE "SELECT * FROM '%q';"
+#define DB_SELECT_SERVER_INFO_FROM_TABLE "SELECT '%q' FROM '%q' WHERE '%q' = '%q';"
+#define DB_SELECT_SERVER_STATE_FROM_TABLE "SELECT server_state FROM '%q';"
+#define DB_SELECT_PLAYBACK_STATE_FROM_DB "SELECT playback_state FROM '%q';"
+#define DB_SELECT_PLAYBACK_POSITION_FROM_DB "SELECT playback_position FROM '%q';"
+#define DB_SELECT_METADATA_FROM_DB "SELECT * FROM '%q';"
+#define DB_SELECT_SHUFFLE_MODE_FROM_DB "SELECT shuffle_mode FROM '%q';"
+#define DB_SELECT_REPEAT_MODE_FROM_DB "SELECT repeat_mode FROM '%q';"
+#define DB_SELECT_VALUE_OF_KEY "SELECT %s FROM '%q';"
+
+#define DB_UPDATE_PLAYBACK_INFO_INTO_SERVER_TABLE "UPDATE '%q' SET playback_state=%d, playback_position=%llu;"
+#define DB_UPDATE_METADATA_INTO_SERVER_TABLE "UPDATE '%q' SET %s='%q';"
+#define DB_UPDATE_SHUFFLE_MODE_INTO_SERVER_TABLE "UPDATE '%q' SET shuffle_mode=%d;"
+#define DB_UPDATE_REPEAT_MODE_INTO_SERVER_TABLE "UPDATE '%q' SET repeat_mode=%d;"
+#define DB_UPDATE_METADATA_INFO_INFO_SERVER_TABLE "UPDATE '%q' SET title=%Q, artist=%Q, album=%Q, author=%Q, genre=%Q, duration=%Q, date=%Q, copyright=%Q, description=%Q, track_num=%Q, picture=%Q"
+
+#define DB_INSERT_INTO_SERVER_TABLE "INSERT INTO '%q' (server_name) VALUES ('%q');"
+#define DB_DELETE_FROM_SERVER_TABLE "DELETE FROM %q WHERE server_name = '%q';"
+#define DB_UPDATE_VALUE_SERVER_TABLE "UPDATE '%q' set '%q'='%q' where server_name='%q';"
+
+#define DB_SELECT_LATEST_SERVER_NAME "SELECT server_name FROM "MC_DB_TABLE_LATEST_SERVER";"
+#define DB_SELECT_ALL_SERVER_LIST "SELECT server_name FROM "MC_DB_TABLE_SERVER_LIST";"
+
+
+#define DB_COLUMN_SERVER_NAME "server_name"
+#define DB_COLUMN_SERVER_STATE "server_state"
+#define DB_COLUMN_PLAYBACK_STATE "playback_state"
+#define DB_COLUMN_PLAYBACK_POSITION "playback_position"
+
+#define SQLITE3_SAFE_FREE(sql_string) {if(sql_string) { sqlite3_free(sql_string); sql_string = NULL;}}
+#define SQLITE3_FINALIZE(x) {if(x != NULL) {sqlite3_finalize(x);}}
+
+int mc_db_connect(void **db_handle);
+int mc_db_disconnect(void *db_handle);
+int mc_db_create_server_table(void *handle, const char *server_name);
+int mc_db_delete_server_table(void *handle, const char *server_name);
+int mc_db_check_server_table_exist(void *handle, const char *server_name, bool *exist);
+
+int mc_db_update_playback_info(void *handle, const char *table_name, int playback_state, unsigned long long playback_position);
+int mc_db_update_whole_metadata(void *handle, const char *server_name,
+ const char *title, const char *artist, const char *album, const char *author, const char *genre, const char *duration, const char *date,
+ const char *copyright, const char *description, const char *track_num, const char *picture);
+int mc_db_update_shuffle_mode(void *handle, const char *table_name, int shuffle_mode);
+int mc_db_update_repeat_mode(void *handle, const char *table_name, int repeat_mode);
+
+int mc_db_get_latest_server_name(void *handle, char **latest_server_name);
+int mc_db_get_server_state(void *handle, const char *server_name, mc_server_state_e *state);
+int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h *playback);
+int mc_db_get_metadata_info(void *handle, const char *server_name, mc_metadata_h *metadata);
+int mc_db_get_shuffle_mode(void *handle, const char *server_name, mc_shuffle_mode_e *mode);
+int mc_db_get_repeat_mode(void *handle, const char *server_name, mc_repeat_mode_e *mode);
+
+int mc_db_insert_server_address_into_table(void *db_handle, const char *table_name, char *address);
+int mc_db_delete_server_address_from_table(void *db_handle, const char *table_name, char *address);
+
+int mc_db_foreach_server_list(void *handle, mc_activated_server_cb callback, void *user_data);
+int mc_db_update_server_state(void *handle, const char *server_name, mc_server_state_e server_state);
+int mc_db_update_latest_server_table(void *handle, const char *server_name);
+
+
+#endif /*__MEDIA_CONTROL_DB_H__*/
diff --git a/include/media_controller_private.h b/include/media_controller_private.h
new file mode 100755
index 0000000..1eb3dfc
--- /dev/null
+++ b/include/media_controller_private.h
@@ -0,0 +1,243 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_PRIVATE_H__
+#define __TIZEN_MEDIA_CONTROLLER_PRIVATE_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <dlog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gio/gio.h>
+#include "media_controller_server.h"
+#include "media_controller_client.h"
+#include "media_controller_socket.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "CAPI_MEDIA_CONTROLLER"
+
+#define FONT_COLOR_RESET "\033[0m"
+#define FONT_COLOR_RED "\033[31m"
+#define FONT_COLOR_GREEN "\033[32m"
+#define FONT_COLOR_YELLOW "\033[33m"
+#define FONT_COLOR_BLUE "\033[34m"
+#define FONT_COLOR_PURPLE "\033[35m"
+#define FONT_COLOR_CYAN "\033[36m"
+#define FONT_COLOR_GRAY "\033[37m"
+
+#define mc_debug(fmt, arg...) do { \
+ LOGD(FONT_COLOR_RESET""fmt"", ##arg); \
+ } while (0)
+
+#define mc_info(fmt, arg...) do { \
+ LOGI(FONT_COLOR_GREEN""fmt"", ##arg); \
+ } while (0)
+
+#define mc_error(fmt, arg...) do { \
+ LOGE(FONT_COLOR_RED""fmt"", ##arg); \
+ } while (0)
+
+#define mc_debug_fenter() do { \
+ LOGD(FONT_COLOR_RESET"<Enter>"); \
+ } while (0)
+
+#define mc_debug_fleave() do { \
+ LOGD(FONT_COLOR_RESET"<Leave>"); \
+ } while (0)
+
+#define mc_retm_if(expr, fmt, arg...) do { \
+ if(expr) { \
+ LOGE(FONT_COLOR_RED""fmt"", ##arg); \
+ return; \
+ } \
+ } while (0)
+
+#define mc_retvm_if(expr, val, fmt, arg...) do { \
+ if(expr) { \
+ LOGE(FONT_COLOR_RED""fmt"", ##arg); \
+ return (val); \
+ } \
+ } while (0)
+
+#define ERR_BUF_LENGHT 256
+#define mc_stderror(fmt) do { \
+ char mc_stderror_buf[ERR_BUF_LENGHT] = {0, }; \
+ strerror_r(errno, mc_stderror_buf, ERR_BUF_LENGHT); \
+ LOGE(fmt" : standard error= [%s]", mc_stderror_buf); \
+ } while (0)
+
+#define MC_SAFE_FREE(src) {if(src) {free(src); src = NULL;}}
+#define MC_STRING_VALID(str) ((str != NULL && strlen(str) > 0) ? TRUE : FALSE)
+#define MC_STRING_DELIMITER "VAL_SEP"
+
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @brief DBus path for media controller.
+* @since_tizen 2.4
+*/
+#define MC_DBUS_PATH "/org/tizen/mediacontroller/dbus/notify"
+
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @brief DBus interface to update from server to client.
+* @since_tizen 2.4
+*/
+#define MC_DBUS_UPDATE_INTERFACE "org.tizen.mediacontroller.update"
+
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @brief DBus interface prefix name.
+* @since_tizen 2.4
+*/
+#define MC_DBUS_INTERFACE_PREFIX "org.tizen"
+
+/**
+* @ingroup CAPI_MEDIA_CONTROLLER_MODULE
+* @brief DBus interface type name.
+* @since_tizen 2.4
+*/
+#define MC_CLIENT "mediacontroller.client"
+#define MC_SERVER "mediacontroller.server"
+
+#define MC_DBUS_SIGNAL_NAME_SERVER_STATE "server_state"
+#define MC_DBUS_SIGNAL_NAME_PLAY_BACK "playback"
+#define MC_DBUS_SIGNAL_NAME_METADATA "metadata"
+#define MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE "playback_shuffle"
+#define MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT "playback_repeat"
+#define MC_DBUS_SIGNAL_NAME_PLAYBACK_STATE_CMD "playback_state_command"
+#define MC_DBUS_SIGNAL_NAME_CUSTOM_CMD "custom_command"
+#define MC_DBUS_SIGNAL_NAME_CMD_REPLY "command_reply"
+
+#define MC_COMMAND_PLAYBACKSTATE "_playback_command_"
+#define MC_COMMAND_CUSTOM "_custom_command_"
+
+#define MC_MILLISEC_SLEEP(msec) \
+ do { \
+ if(msec) { \
+ unsigned long sec_t = 0; \
+ unsigned long nsec_t = 0; \
+ unsigned long cal_time = msec * 1000000; \
+ sec_t = cal_time / 1000000000; \
+ nsec_t = cal_time % 1000000000; \
+ struct timespec reqtime; \
+ reqtime.tv_sec = sec_t; \
+ reqtime.tv_nsec = nsec_t; \
+ nanosleep(&reqtime, NULL); \
+ } \
+ } while (0)
+
+typedef struct {
+ void *callback;
+ void *user_data;
+ GList *filter_list;
+}media_controller_receiver_s;
+
+typedef struct {
+ mc_playback_states_e state;
+ unsigned long long position;
+}media_controller_playback_s;
+
+typedef struct {
+ char *title;
+ char *artist;
+ char *album;
+ char *author;
+ char *genre;
+ char *duration;
+ char *date;
+ char *copyright;
+ char *description;
+ char *track_num;
+ char *picture;
+}media_controller_metadata_s;
+
+typedef struct {
+ char *server_name;
+ void* db_handle;
+
+ GDBusConnection* dconn;
+ int dref_count;
+
+ GList *listeners;
+
+ mc_server_state_e state;
+ media_controller_playback_s playback;
+ media_controller_metadata_s *metadata;
+
+ media_controller_receiver_s playback_state_reciever;
+ media_controller_receiver_s custom_cmd_reciever;
+}media_controller_server_s;
+
+typedef struct {
+ char *client_name;
+ void *db_handle;
+
+ GDBusConnection *dconn;
+ int dref_count;
+
+ GList *listeners;
+
+ media_controller_receiver_s playback_cb;
+ media_controller_receiver_s metadata_cb;
+ media_controller_receiver_s server_state_cb;
+ media_controller_receiver_s shuffle_cb;
+ media_controller_receiver_s repeat_cb;
+ media_controller_receiver_s reply_cb;
+}media_controller_client_s;
+
+/* formal callback to receive signal */
+typedef void(*mc_signal_received_cb)(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data);
+typedef struct {
+ GDBusConnection *dbus_conn;
+ char *interface_name;
+ char *signal_name;
+ mc_signal_received_cb callback;
+ char *user_data;
+ guint handler;
+ char *key;
+} mc_ipc_listener_s;
+
+
+/* util */
+int mc_util_get_own_name(char **name);
+char* mc_util_get_interface_name(const char *type, const char *name);
+int mc_util_make_filter_interface_name(const char *prefix, const char *filter, char **interface_name);
+int mc_util_set_command_availabe(const char *name, const char *command_type, const char *command);
+int mc_util_get_command_availabe(const char *name, const char *command_type, const char *command);
+
+/* for d-bus IPC */
+int mc_ipc_get_dbus_connection(GDBusConnection **conn, int *dref_count);
+int mc_ipc_unref_dbus_connection(GDBusConnection *conn, int *dref_count);
+int mc_ipc_register_listener(GList *manage_list, GDBusConnection *connection, const char *interface_name, const char *signal_name, mc_signal_received_cb callback, void *user_data);
+int mc_ipc_unregister_listener(GList *manage_list, GDBusConnection *connection, const char *interface_name, const char *signal_name);
+int mc_ipc_unregister_all_listener(GList *manage_list, GDBusConnection *connection);
+int mc_ipc_send_message(GDBusConnection *connection, const char *dbus_name, const char *interface_name, const char* signal_name, const char* message, int flags);
+int mc_ipc_send_message_to_server(mc_msg_type_e msg_type, const char *request_msg);
+int mc_ipc_service_connect(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIA_CONTROLLER_PRIVATE_H__ */
diff --git a/include/media_controller_server.h b/include/media_controller_server.h
new file mode 100755
index 0000000..c8f3375
--- /dev/null
+++ b/include/media_controller_server.h
@@ -0,0 +1,362 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_SERVER_H__
+#define __TIZEN_MEDIA_CONTROLLER_SERVER_H__
+
+#include <media_controller_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file media_controller_server.h
+ * @brief This file contains the media controller server API and functions related with handling media controller server. \n
+ * Functions include operations to send the latest status of the server to client.
+ */
+
+/**
+ * @addtogroup CAPI_MEDIA_CONTROLLER_SERVER_MODULE
+ * @{
+ */
+
+/**
+ * @brief Called when the Server received playback state command from the client.
+ * @since_tizen 2.4
+ *
+ * @details This callback is called when server received playback state recommand from client.
+ *
+ * @param[in] client_name The app_id of the media controller client
+ * @param[in] state The received playback state
+ * @param[in] user_data The user data passed from the mc_server_set_playback_state_command_received_cb() fuction
+ *
+ * @pre mc_server_set_playback_state_command_received_cb()
+ *
+ * @see mc_server_set_playback_state_command_received_cb()
+ */
+typedef void (*mc_server_playback_state_command_received_cb)(const char* client_name, mc_playback_states_e state, void *user_data);
+
+/**
+ * @brief Called when the Server received custom command from the client.
+ * @since_tizen 2.4
+ *
+ * @details This callback is called when server received custom recommand from client.
+ * If there is reply for command, call mc_server_send_command_reply() function.
+ *
+ * @param[in] client_name The app_id of the media controller client
+ * @param[in] command The received command
+ * @param[in] data The extra data
+ * @param[in] user_data The user data passed from the mc_server_set_custom_command_received_cb() fuction
+ *
+ * @pre mc_server_set_custom_command_received_cb()
+ *
+ * @see mc_server_set_custom_command_received_cb()
+ */
+typedef void (*mc_server_custom_command_received_cb)(const char* client_name, const char *command, bundle *data, void *user_data);
+
+/**
+ * @brief Creates a media controller server.
+ * @since_tizen 2.4
+ * @remarks You must release @a server using mc_server_destroy().
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param[out] server The handle to media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY Not enough memory is available
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @see mc_server_destroy()
+ */
+int mc_server_create(mc_server_h *server);
+
+/**
+ * @brief Sets the playback state to update the latest state info
+ * @since_tizen 2.4
+ * @param [in] server The handle to media controller server
+ * @param [in] state The state to set
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @post Apply the updated playback information by calling mc_server_update_playback_info().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ * @see mc_server_update_playback_info()
+ */
+int mc_server_set_playback_state(mc_server_h server, mc_playback_states_e state);
+
+/**
+ * @brief Sets the playback position to update the latest playback info
+ * @since_tizen 2.4
+ * @param [in] server The handle to media controller server
+ * @param [in] position The position to set in milliseconds
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @post Apply the updated playback information by calling mc_server_update_playback_info().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ * @see mc_server_update_playback_info()
+ */
+int mc_server_set_playback_position(mc_server_h server, unsigned long long position);
+
+/**
+ * @brief Update the modified playback info
+ * @details If this API is called, the updated playback information will be sent to the controller.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_update_playback_info(mc_server_h server);
+
+/**
+ * @brief Sets the metadata to update the latest metadata info
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @param [in] attribute The key attribute name to set
+ * @param [in] value The value of the attribute
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @post Apply the updated metadata information by calling mc_server_update_metadata().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ * @see mc_server_update_metadata()
+ */
+int mc_server_set_metadata(mc_server_h server, mc_meta_e attribute, const char *value);
+
+/**
+ * @brief Update the modified metadata info.
+ * @details If this API is called, the updated metadata will be sent to all controllers.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_update_metadata(mc_server_h server);
+
+/**
+ * @brief Update the modified shuffle mode
+ * @details If this API is called, the updated mode information will be sent to all controllers.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @param [in] mode The shuffle mode to update the latest status
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_update_shuffle_mode(mc_server_h server, mc_shuffle_mode_e mode);
+
+/**
+ * @brief Updates the modified repeat mode
+ * @details If this API is called, the updated mode information will be sent to all controllers.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @param [in] mode The repeat mode to update the latest status
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY File does not exist
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_update_repeat_mode(mc_server_h server, mc_repeat_mode_e mode);
+
+/**
+ * @brief Sets the callback for receiving playback state command from client.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @param [in] callback The callback to be invoked when media controller server receives playback command from client.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_set_playback_state_command_received_cb(mc_server_h server, mc_server_playback_state_command_received_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for receiving playback state command from client.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_unset_playback_state_command_received_cb(mc_server_h server);
+
+/**
+ * @brief Sets the callback for receiving custom command from client.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @param [in] callback The callback to be invoked when media controller server receives custom command from client.
+ * @param [in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_set_custom_command_received_cb(mc_server_h server, mc_server_custom_command_received_cb callback, void *user_data);
+
+/**
+ * @brief Unsets the callback for receiving custom command from client.
+ * @since_tizen 2.4
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_unset_custom_command_received_cb(mc_server_h server);
+
+/**
+ * @brief Sends a reply for the requested command to the client.
+ * @since_tizen 2.4
+ * @remarks When server recieve command, this API can be called by mc_server_custom_command_received_cb().
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/mediacontroller.server
+ *
+ * @param [in] server The handle to media controller server
+ * @param [in] client_name The app_id of the media controller client
+ * @param [in] result_code The result code of custom command
+ * @param [in] data The extra data
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #MEDIA_CONTROLLER_ERROR_NONE Successful
+ * @retval #MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED Permission denied
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @pre mc_server_set_custom_command_received_cb()
+ * @see mc_server_create()
+ * @see mc_server_destroy()
+ */
+int mc_server_send_command_reply(mc_server_h server, const char *client_name, int result_code, bundle *data);
+
+/**
+ * @brief Destroys media controller server.
+ * @since_tizen 2.4
+ * @param [in] server The handle to media controller server
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #METADATA_EXTRACTOR_ERROR_NONE Successful
+ * @retval #METADATA_EXTRACTOR_ERROR_INVALID_PARAMETER Invalid parameter
+ * @pre Create a media controller server handle by calling mc_server_create().
+ * @see mc_server_create()
+ */
+int mc_server_destroy(mc_server_h server); //deregistered internally
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIA_CONTROLLER_SERVER_H__ */
diff --git a/include/media_controller_type.h b/include/media_controller_type.h
new file mode 100755
index 0000000..93001d9
--- /dev/null
+++ b/include/media_controller_type.h
@@ -0,0 +1,157 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_TYPE_H__
+#define __TIZEN_MEDIA_CONTROLLER_TYPE_H__
+
+#include <tizen.h>
+#include <bundle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file media_controller_type.h
+ * @brief This file contains API related to media controller enumerations and types. \n
+ * Listed APIs are called when client send and receive event. \n
+ */
+
+/**
+* @addtogroup CAPI_MEDIA_CONTROLLER_MODULE
+ * @{
+ */
+
+/**
+ * @brief The structure type for the media server handle.
+ * @since_tizen 2.4
+ */
+typedef void *mc_server_h;
+
+/**
+ * @brief The structure type for the media client handle.
+ * @since_tizen 2.4
+ */
+typedef void *mc_client_h;
+
+/**
+ * @brief The structure type for the media controller playback handle.
+ * @since_tizen 2.4
+ */
+typedef void *mc_playback_h;
+
+/**
+ * @brief The structure type for the media controller metadata handle.
+ * @since_tizen 2.4
+ */
+typedef void *mc_metadata_h;
+
+/**
+ * @brief Enumeration for the media controller error.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MEDIA_CONTROLLER_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+ MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ MEDIA_CONTROLLER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid Operation */
+ MEDIA_CONTROLLER_ERROR_FILE_NO_SPACE_ON_DEVICE = TIZEN_ERROR_FILE_NO_SPACE_ON_DEVICE, /**< No space left on device */
+ MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+} mc_error_e;
+
+/**
+ * @brief Enumeration for the media controller server state.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MC_SERVER_STATE_NONE = 0, /**< None state*/
+ MC_SERVER_STATE_ACTIVATE, /**< Activate state*/
+ MC_SERVER_STATE_DEACTIVATE, /**< Deactivate state*/
+} mc_server_state_e;
+
+/**
+ * @brief Enumeration for the media meta info.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MC_META_MEDIA_TITLE = 0, /**< Title */
+ MC_META_MEDIA_ARTIST, /**< Artist */
+ MC_META_MEDIA_ALBUM, /**< Album */
+ MC_META_MEDIA_AUTHOR, /**< Author */
+ MC_META_MEDIA_GENRE, /**< Genre */
+ MC_META_MEDIA_DURATION, /**< Duration */
+ MC_META_MEDIA_DATE, /**< Date */
+ MC_META_MEDIA_COPYRIGHT, /**< Copyright */
+ MC_META_MEDIA_DESCRIPTION, /**< Description */
+ MC_META_MEDIA_TRACK_NUM, /**< Track Number */
+ MC_META_MEDIA_PICTURE, /**< Picture. Album Art */
+} mc_meta_e;
+
+/**
+ * @brief Enumeration for the media playback state.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MC_PLAYBACK_STATE_NONE = 0, /**< None */
+ MC_PLAYBACK_STATE_PLAYING, /**< Play */
+ MC_PLAYBACK_STATE_PAUSED, /**< Pause */
+ MC_PLAYBACK_STATE_STOPPED, /**< Stop */
+ MC_PLAYBACK_STATE_NEXT_FILE, /**< Next file */
+ MC_PLAYBACK_STATE_PREV_FILE, /**< Previous file */
+ MC_PLAYBACK_STATE_FAST_FORWARD, /**< Fast forward */
+ MC_PLAYBACK_STATE_REWIND, /**< Rewind */
+} mc_playback_states_e;
+
+/**
+ * @brief Enumeration for the shuffle mode.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MC_SHUFFLE_MODE_ON = 0, /**< Shuffle mode on */
+ MC_SHUFFLE_MODE_OFF, /**< Shuffle mode off */
+} mc_shuffle_mode_e;
+
+/**
+ * @brief Enumeration for the repeat mode.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MC_REPEAT_MODE_ON = 0, /**< Repeat mode on */
+ MC_REPEAT_MODE_OFF, /**< Repeat mode off */
+} mc_repeat_mode_e;
+
+/**
+ * @brief Enumeration for the subscription type.
+ * @since_tizen 2.4
+ */
+typedef enum {
+ MC_SUBSCRIPTION_TYPE_SERVER_STATE = 0, /**< Server state */
+ MC_SUBSCRIPTION_TYPE_PLAYBACK, /**< Playback */
+ MC_SUBSCRIPTION_TYPE_METADATA, /**< Metadata */
+ MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE, /**< Shuffle mode */
+ MC_SUBSCRIPTION_TYPE_REPEAT_MODE, /**< Repeat mode */
+} mc_subscription_type_e;
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIA_CONTROLLER_TYPE_H__ */
diff --git a/media-controller-service.manifest b/media-controller-service.manifest
new file mode 100755
index 0000000..bd5a727
--- /dev/null
+++ b/media-controller-service.manifest
@@ -0,0 +1,22 @@
+<manifest>
+ <define>
+ <domain name="mediacontroller"/>
+ <provide>
+ <label name="mediacontroller::svc"/>
+ <label name="mediacontroller::db"/>
+ </provide>
+ <request>
+ <smack request="security-server::api-privilege-by-pid" type="w"/>
+ <smack request="mediacontroller::db" type="rw"/>
+ <smack request="device::app_logging" type="w"/>
+ <smack request="device::sys_logging" type="w"/>
+ </request>
+ </define>
+ <request>
+ <domain name="_"/>
+ </request>
+ <assign>
+ <filesystem path="/usr/bin/mediacontroller" label="mediacontroller" exec_label="mediacontroller" />
+ </assign>
+</manifest>
+
diff --git a/packaging/capi-media-controller.spec b/packaging/capi-media-controller.spec
new file mode 100755
index 0000000..b0e6c9c
--- /dev/null
+++ b/packaging/capi-media-controller.spec
@@ -0,0 +1,114 @@
+Name: capi-media-controller
+Summary: Multimedia Controller for player application
+Version: 0.0.16
+Release: 1
+Group: System/Libraries
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source1: mediacontroller.service
+Source2: mediacontroller.socket
+BuildRequires: cmake
+BuildRequires: sqlite
+BuildRequires: pkgconfig(capi-base-common)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(db-util)
+BuildRequires: pkgconfig(aul)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(security-server)
+BuildRequires: pkgconfig(libsystemd-daemon)
+
+%description
+A media controller library in SLP C API
+
+%package -n mediacontroller
+Summary: media Controller service server
+
+%description -n mediacontroller
+A media controller library in SLP C API
+
+%package devel
+Summary: Multimedia Controller for player Library (DEV)
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+A media controller library in SLP C API
+
+%prep
+%setup -q
+
+%build
+export CFLAGS+=" -Wextra -Wno-array-bounds"
+export CFLAGS+=" -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow"
+export CFLAGS+=" -Wwrite-strings -Wswitch-default"
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+export CFLAGS+=" -DGST_EXT_TIME_ANALYSIS -include stdint.h"
+
+%if 0%{?sec_build_binary_debug_enable}
+export CFLAGS+=" -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS+=" -DDTIZEN_DEBUG_ENABLE"
+export FFLAGS+=" -DTIZEN_DEBUG_ENABLE"
+%endif
+
+cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+# Daemon & socket activation
+mkdir -p %{buildroot}%{_libdir}/systemd/system
+mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants
+install -m 644 %{SOURCE1} %{buildroot}/usr/lib/systemd/system/mediacontroller.service
+install -m 644 %{SOURCE2} %{buildroot}%{_libdir}/systemd/system/mediacontroller.socket
+ln -s ../mediacontroller.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/mediacontroller.socket
+
+#Create DB
+mkdir -p %{buildroot}/opt/usr/dbspace
+sqlite3 %{buildroot}/opt/usr/dbspace/.media_controller.db 'PRAGMA journal_mode = PERSIST; PRAGMA user_version=1;'
+
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE.APLv2.0 %{buildroot}/usr/share/license/%{name}
+
+%post
+# DB permission & SMACK
+chmod 644 /opt/usr/dbspace/.media_controller.db
+chmod 644 /opt/usr/dbspace/.media_controller.db-journal
+
+chown 200:5000 /opt/usr/dbspace/.media_controller.db*
+
+if [ -f /opt/usr/dbspace/.media_controller.db ]
+then
+ chsmack -a 'mediacontroller::db' /opt/usr/dbspace/.media_controller.db*
+fi
+
+%files
+%defattr(-,root,root,-)
+%{_libdir}/*.so.*
+#%{_bindir}/* //disable tests
+%manifest capi-media-controller.manifest
+%attr(660,system,app) /opt/usr/dbspace/.media_controller.db
+%attr(660,system,app) /opt/usr/dbspace/.media_controller.db-journal
+%config(noreplace) /opt/usr/dbspace/.media_controller.db
+%config(noreplace) /opt/usr/dbspace/.media_controller.db-journal
+/usr/share/license/%{name}
+
+%files -n mediacontroller
+%defattr(-,system,system,-)
+%{_bindir}/mediacontroller
+%manifest media-controller-service.manifest
+%{_libdir}/systemd/system/mediacontroller.service
+%{_libdir}/systemd/system/mediacontroller.socket
+%{_libdir}/systemd/system/sockets.target.wants/mediacontroller.socket
+/usr/share/license/%{name}
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/*.so
+%{_includedir}/media/*.h
+%{_libdir}/pkgconfig/capi-media-controller.pc
diff --git a/packaging/mediacontroller.service b/packaging/mediacontroller.service
new file mode 100755
index 0000000..035f1a7
--- /dev/null
+++ b/packaging/mediacontroller.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Media controller
+
+[Service]
+User=system
+Group=system
+SmackProcessLabel=mediacontroller
+ExecStart=/usr/bin/mediacontroller
+Type=simple
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packaging/mediacontroller.socket b/packaging/mediacontroller.socket
new file mode 100755
index 0000000..c0261f6
--- /dev/null
+++ b/packaging/mediacontroller.socket
@@ -0,0 +1,13 @@
+[Unit]
+Description=MediaController Service socket
+
+[Socket]
+SocketUser=system
+SocketGroup=system
+ListenStream=/tmp/.media_sa_controller
+SmackLabelIPIn=mediacontroller
+SmackLabelIPOut=mediacontroller
+Service=mediacontroller.service
+
+[Install]
+WantedBy=sockets.target
diff --git a/src/media_controller_client.c b/src/media_controller_client.c
new file mode 100755
index 0000000..5959506
--- /dev/null
+++ b/src/media_controller_client.c
@@ -0,0 +1,1053 @@
+/*
+* Copyright (c) 2011 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 "media_controller_client.h"
+#include "media_controller_private.h"
+#include "media_controller_db.h"
+
+
+static void __client_server_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
+ mc_server_state_updated_cb callback = (mc_server_state_updated_cb)reciever->callback;
+
+ mc_retm_if(reciever == NULL, "reciever is NULL");
+ mc_retm_if(reciever->callback == NULL, "server_state_cb is NULL");
+ mc_retm_if(message == NULL, "message is NULL");
+
+ mc_debug("__client_server_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid server data");
+
+ callback(params[0], (mc_server_state_e)atoi(params[1]), reciever->user_data);
+
+ g_strfreev(params);
+}
+
+static void __client_playback_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
+ mc_playback_updated_cb callback = (mc_playback_updated_cb)reciever->callback;
+ media_controller_playback_s *playback = NULL;
+
+ mc_retm_if(reciever == NULL, "reciever is NULL");
+ mc_retm_if(reciever->callback == NULL, "playback_cb is NULL");
+ mc_retm_if(message == NULL, "message is NULL");
+
+ mc_debug("__client_playback_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ playback = (media_controller_playback_s *)g_malloc(sizeof(media_controller_playback_s));
+ mc_retm_if(playback == NULL, "Error allocation memory");
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid playback data");
+
+ playback->state = atoi(params[1]);
+ playback->position = atol(params[2]);
+
+ callback(params[0], (mc_playback_h) playback, reciever->user_data);
+
+ g_strfreev(params);
+}
+
+static void __client_metadata_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ mc_metadata_h metadata = NULL;
+ media_controller_client_s *mc_client = (media_controller_client_s *)user_data;
+ mc_metadata_updated_cb callback = (mc_metadata_updated_cb)mc_client->metadata_cb.callback;
+
+ mc_retm_if(mc_client == NULL, "mc_client is NULL");
+ mc_retm_if(mc_client->metadata_cb.callback == NULL, "metadata_cb is NULL");
+ mc_retm_if(message == NULL, "message is NULL");
+
+ mc_debug("__client_metadata_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ ret = mc_db_get_metadata_info(mc_client->db_handle, message, &metadata);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("Fail to mc_db_get_metadata_info");
+
+ callback(message, metadata, mc_client->metadata_cb.user_data);
+
+ mc_client_destroy_metadata(metadata);
+}
+
+static void __client_shuffle_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
+ mc_shuffle_mode_changed_cb callback = (mc_shuffle_mode_changed_cb)reciever->callback;
+
+ mc_retm_if(reciever == NULL, "reciever is NULL");
+ mc_retm_if(reciever->callback == NULL, "shuffle_cb is NULL");
+
+ mc_debug("__client_shuffle_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid shuffle mode data");
+
+ callback(params[0], (mc_shuffle_mode_e)atoi(params[1]), reciever->user_data);
+
+ g_strfreev(params);
+}
+
+static void __client_repeat_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
+ mc_repeat_mode_changed_cb callback = (mc_repeat_mode_changed_cb)reciever->callback;
+
+ mc_retm_if(reciever == NULL, "reciever is NULL");
+ mc_retm_if(reciever->callback == NULL, "repeat_cb is NULL");
+
+ mc_debug("__client_repeat_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid repeat mode data");
+
+ callback(params[0], (mc_repeat_mode_e)atoi(params[1]), reciever->user_data);
+
+ g_strfreev(params);
+}
+
+static void __client_reply_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ int enc_size = 0;
+ bundle *bundle_data = NULL;
+
+ media_controller_receiver_s *reciever = (media_controller_receiver_s *)user_data;
+ mc_retm_if(reciever == NULL, "reciever is NULL");
+
+ mc_command_reply_received_cb callback = (mc_command_reply_received_cb)reciever->callback;
+ mc_retm_if(reciever->callback == NULL, "reply_cb is NULL");
+
+ mc_debug("__client_reply_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid custom data");
+
+ enc_size = atoi(params[2]);
+ if (enc_size > 0)
+ bundle_data = bundle_decode((bundle_raw *)params[3], enc_size);
+
+ callback(params[0], atoi(params[1]), bundle_data, reciever->user_data);
+
+ g_strfreev(params);
+}
+
+static int __mc_client_create(media_controller_client_s **mc_client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *_client = NULL;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ _client = (media_controller_client_s *)calloc(1, sizeof(media_controller_client_s));
+ mc_retvm_if(_client == NULL, MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY, "Error allocation memory");
+
+ ret = mc_util_get_own_name(&(_client->client_name));
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Filed to get client name %d", ret);
+ goto Error;
+ }
+
+ ret = mc_ipc_get_dbus_connection(&(_client->dconn), &(_client->dref_count));
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("error in client init %d", ret);
+ goto Error;
+ }
+
+ ret = mc_db_connect(&_client->db_handle);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("error in connecting to DB %d", ret);
+ goto Error;
+ }
+
+ _client->listeners = g_list_alloc();
+ if (_client->listeners == NULL) {
+ ret = MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ mc_error("Error allocation list %d", ret);
+ goto Error;
+ }
+
+ *mc_client = _client;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+Error:
+ if (_client->dconn)
+ mc_ipc_unref_dbus_connection(_client->dconn, &_client->dref_count);
+
+ if (_client->db_handle)
+ mc_db_disconnect(_client->db_handle);
+
+ if (_client->listeners)
+ g_list_free(_client->listeners);
+
+ MC_SAFE_FREE(_client->client_name);
+ MC_SAFE_FREE(_client);
+
+ return ret;
+}
+
+static int __mc_client_destroy(media_controller_client_s *mc_client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ if (mc_client->dconn) {
+ ret = mc_ipc_unref_dbus_connection(mc_client->dconn, &mc_client->dref_count);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail to mc_ipc_unref_dbus_connection");
+ }
+
+ if (mc_client->db_handle) {
+ ret = mc_db_disconnect(mc_client->db_handle);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail to mc_db_disconnect");
+ }
+
+ if (mc_client->listeners != NULL) {
+ g_list_free(mc_client->listeners);
+ }
+
+ MC_SAFE_FREE(mc_client->client_name);
+ MC_SAFE_FREE(mc_client);
+
+ return ret;
+}
+
+static int __mc_client_register_filter_listener(media_controller_client_s *mc_client, GList **filter_list, const char *server_name, const char *signal_name, mc_signal_received_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *filter_interface_name = NULL;
+
+ mc_debug("signal = [%s]", signal_name);
+
+ ret = mc_util_make_filter_interface_name(MC_DBUS_UPDATE_INTERFACE, server_name, &filter_interface_name);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Fail mc_util_make_filter_interface_name");
+
+ ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, filter_interface_name, signal_name, callback, user_data);
+ if (ret == MEDIA_CONTROLLER_ERROR_NONE)
+ *filter_list = g_list_append(*filter_list, strdup(filter_interface_name));
+
+ MC_SAFE_FREE(filter_interface_name);
+
+ return ret;
+}
+
+static int __mc_client_unregister_filter_listener(media_controller_client_s *mc_client, GList **filter_list, const char *server_name, const char *signal_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int idx = 0;
+ int filter_cnt = 0;
+
+ mc_retvm_if(filter_list == NULL, MEDIA_CONTROLLER_ERROR_NONE, "[No-Error] No filter list to unset");
+ mc_retvm_if(!MC_STRING_VALID(signal_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid signal_name");
+
+ filter_cnt = g_list_length(*filter_list);
+
+ mc_debug("signal [%s] cnt [%d]", signal_name, filter_cnt);
+
+ if (MC_STRING_VALID(server_name)) {
+
+ char *filter_interface_name = NULL;
+
+ ret = mc_util_make_filter_interface_name(MC_DBUS_UPDATE_INTERFACE, server_name, &filter_interface_name);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "Fail mc_util_make_filter_interface_name");
+ if (!MC_STRING_VALID(filter_interface_name)) {
+ mc_error("filter_interface_name is NULL");
+ MC_SAFE_FREE(filter_interface_name);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /*Unregister listener*/
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, filter_interface_name, signal_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ MC_SAFE_FREE(filter_interface_name);
+ return ret;
+ }
+
+ /*Remove from filter_list*/
+ for(idx = 0; idx < filter_cnt; idx++) {
+ char * interface_name = NULL;
+ interface_name = g_list_nth_data(*filter_list, idx);
+
+ if (MC_STRING_VALID(interface_name)) {
+ if (strcmp(interface_name, filter_interface_name) == 0) {
+ mc_debug("Unset subscriber [%d][%s]", idx, interface_name);
+ *filter_list = g_list_remove(*filter_list, interface_name);
+ MC_SAFE_FREE(interface_name);
+ }
+ }
+ }
+
+ MC_SAFE_FREE(filter_interface_name);
+ } else {
+
+ /*Remove All filter listener*/
+ for(idx = 0; idx < filter_cnt; idx++) {
+ char * interface_name = NULL;
+ interface_name = g_list_nth_data(*filter_list, idx);
+
+ if (MC_STRING_VALID(interface_name)) {
+ mc_debug("[%d][%s]", idx, interface_name);
+
+ /*Unregister listener*/
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, interface_name, signal_name);
+ if(ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("Fail mc_ipc_unregister_listener");
+
+ /*Remove from filter_list*/
+ *filter_list = g_list_remove(*filter_list, interface_name);
+ MC_SAFE_FREE(interface_name);
+ }
+ }
+
+ g_list_free(*filter_list);
+ }
+
+ return ret;
+}
+
+static int __mc_parse_server_name(const char *interface_name, char **server_name)
+{
+ mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "interface_name is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "server_name is NULL");
+
+ *server_name = strdup(interface_name + strlen(MC_DBUS_UPDATE_INTERFACE) + 1);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_create(mc_client_h *client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = NULL;
+
+ mc_debug_fenter();
+
+ mc_retvm_if(client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ /*Try Socket Activation by systemd*/
+ ret = mc_ipc_service_connect();
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to get mc_ipc_service_connect [%d]", ret);
+ return ret;
+ }
+
+ ret = __mc_client_create(&mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed __mc_server_create [%d]", ret);
+ return ret;
+ }
+
+ *client = (mc_client_h)mc_client;
+
+ mc_debug_fleave();
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_set_server_update_cb(mc_client_h client, mc_server_state_updated_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+ mc_retvm_if(mc_client->server_state_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+ mc_client->server_state_cb.callback = callback;
+ mc_client->server_state_cb.user_data = user_data;
+
+ ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE,
+ __client_server_cb, (void *)&(mc_client->server_state_cb));
+
+ return ret;
+}
+
+int mc_client_unset_server_update_cb(mc_client_h client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE);
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_SERVER_STATE);
+
+ mc_client->server_state_cb.callback = NULL;
+ mc_client->server_state_cb.user_data = NULL;
+ mc_client->server_state_cb.filter_list = NULL;
+
+ return ret;
+}
+
+int mc_client_set_playback_update_cb(mc_client_h client, mc_playback_updated_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+ mc_retvm_if(mc_client->playback_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+ mc_client->playback_cb.callback = callback;
+ mc_client->playback_cb.user_data = user_data;
+
+ ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK,
+ __client_playback_cb, (void *)&(mc_client->playback_cb));
+
+ return ret;
+}
+
+int mc_client_unset_playback_update_cb(mc_client_h client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK);
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playback_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAY_BACK);
+
+ mc_client->playback_cb.callback = NULL;
+ mc_client->playback_cb.user_data = NULL;
+ mc_client->playback_cb.filter_list = NULL;
+
+ return ret;
+}
+
+int mc_client_set_metadata_update_cb(mc_client_h client, mc_metadata_updated_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+ mc_retvm_if(mc_client->metadata_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+ mc_client->metadata_cb.callback = callback;
+ mc_client->metadata_cb.user_data = user_data;
+
+ ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA,
+ __client_metadata_cb, (void *)(mc_client));
+
+ return ret;
+}
+
+int mc_client_unset_metadata_update_cb(mc_client_h client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA);
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_METADATA);
+
+ mc_client->metadata_cb.callback = NULL;
+ mc_client->metadata_cb.user_data = NULL;
+ mc_client->metadata_cb.filter_list = NULL;
+
+ return ret;
+}
+
+int mc_client_set_shuffle_mode_update_cb(mc_client_h client, mc_shuffle_mode_changed_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+ mc_retvm_if(mc_client->shuffle_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+ mc_client->shuffle_cb.callback = callback;
+ mc_client->shuffle_cb.user_data = user_data;
+
+ ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE,
+ __client_shuffle_cb, (void *)&(mc_client->shuffle_cb));
+
+ return ret;
+}
+
+int mc_client_unset_shuffle_mode_update_cb(mc_client_h client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE);
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE);
+
+ mc_client->shuffle_cb.callback = NULL;
+ mc_client->shuffle_cb.user_data = NULL;
+ mc_client->shuffle_cb.filter_list = NULL;
+
+
+ return ret;
+}
+
+int mc_client_set_repeat_mode_update_cb(mc_client_h client, mc_repeat_mode_changed_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+ mc_retvm_if(mc_client->repeat_cb.callback != NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is already set");
+
+ mc_client->repeat_cb.callback = callback;
+ mc_client->repeat_cb.user_data = user_data;
+
+ ret = mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT,
+ __client_repeat_cb, (void *)&(mc_client->repeat_cb));
+
+ return ret;
+}
+
+int mc_client_unset_repeat_mode_update_cb(mc_client_h client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
+
+ mc_client->repeat_cb.callback = NULL;
+ mc_client->repeat_cb.user_data = NULL;
+ mc_client->repeat_cb.filter_list = NULL;
+
+ return ret;
+}
+
+int mc_client_subscribe(mc_client_h client, const mc_subscription_type_e subscription_type, const char *server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+
+ switch(subscription_type) {
+ case MC_SUBSCRIPTION_TYPE_SERVER_STATE:
+ mc_retvm_if(mc_client->server_state_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE);
+ ret = __mc_client_register_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_SERVER_STATE,
+ __client_server_cb, (void *)&(mc_client->server_state_cb));
+ break;
+ case MC_SUBSCRIPTION_TYPE_PLAYBACK:
+ mc_retvm_if(mc_client->playback_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK);
+ ret = __mc_client_register_filter_listener(mc_client, &mc_client->playback_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAY_BACK,
+ __client_playback_cb, (void *)&(mc_client->playback_cb));
+ break;
+ case MC_SUBSCRIPTION_TYPE_METADATA:
+ mc_retvm_if(mc_client->metadata_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA);
+ ret = __mc_client_register_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_METADATA,
+ __client_metadata_cb, (void *)(mc_client));
+ break;
+ case MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE:
+ mc_retvm_if(mc_client->shuffle_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE);
+ ret = __mc_client_register_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE,
+ __client_shuffle_cb, (void *)&(mc_client->shuffle_cb));
+ break;
+ case MC_SUBSCRIPTION_TYPE_REPEAT_MODE:
+ mc_retvm_if(mc_client->repeat_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback");
+
+ ret = mc_ipc_unregister_listener(mc_client->listeners, mc_client->dconn, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
+ ret = __mc_client_register_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT,
+ __client_repeat_cb, (void *)&(mc_client->repeat_cb));
+ break;
+ default:
+ mc_error("Invalid subscription_type [%d]", subscription_type);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ return ret;
+}
+
+int mc_client_unsubscribe(mc_client_h client, const mc_subscription_type_e subscription_type, const char *server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+
+ switch(subscription_type) {
+ case MC_SUBSCRIPTION_TYPE_SERVER_STATE:
+ mc_retvm_if(mc_client->server_state_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe");
+ mc_retvm_if(mc_client->server_state_cb.filter_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid filter_list. No list to unsubscribe");
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_SERVER_STATE);
+ break;
+ case MC_SUBSCRIPTION_TYPE_PLAYBACK:
+ mc_retvm_if(mc_client->playback_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe");
+ mc_retvm_if(mc_client->playback_cb.filter_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid filter_list. No list to unsubscribe");
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playback_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAY_BACK);
+ break;
+ case MC_SUBSCRIPTION_TYPE_METADATA:
+ mc_retvm_if(mc_client->metadata_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe");
+ mc_retvm_if(mc_client->metadata_cb.filter_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid filter_list. No list to unsubscribe");
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_METADATA);
+ break;
+ case MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE:
+ mc_retvm_if(mc_client->shuffle_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe");
+ mc_retvm_if(mc_client->shuffle_cb.filter_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid filter_list. No list to unsubscribe");
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE);
+ break;
+ case MC_SUBSCRIPTION_TYPE_REPEAT_MODE:
+ mc_retvm_if(mc_client->repeat_cb.callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid callback. No list to unsubscribe");
+ mc_retvm_if(mc_client->repeat_cb.filter_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid filter_list. No list to unsubscribe");
+
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, server_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
+ break;
+ default:
+ mc_error("Invalid subscription_type [%d]", subscription_type);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ return ret;
+}
+
+int mc_client_foreach_server_subscribed(mc_client_h client, const mc_subscription_type_e subscription_type, mc_subscribed_server_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+ int idx = 0;
+ char *server_name = NULL;
+ GList *filter_list = NULL;
+ char *filter_data = NULL;
+ int filter_cnt = 0;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ switch(subscription_type) {
+ case MC_SUBSCRIPTION_TYPE_SERVER_STATE:
+ filter_list = mc_client->server_state_cb.filter_list;
+ break;
+ case MC_SUBSCRIPTION_TYPE_PLAYBACK:
+ filter_list = mc_client->playback_cb.filter_list;
+ break;
+ case MC_SUBSCRIPTION_TYPE_METADATA:
+ filter_list = mc_client->metadata_cb.filter_list;
+ break;
+ case MC_SUBSCRIPTION_TYPE_SHUFFLE_MODE:
+ filter_list = mc_client->shuffle_cb.filter_list;
+ break;
+ case MC_SUBSCRIPTION_TYPE_REPEAT_MODE:
+ filter_list = mc_client->repeat_cb.filter_list;
+ break;
+ default:
+ mc_error("Invalid subscription_type [%d]", subscription_type);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ if (filter_list == NULL) {
+ mc_debug("No filter list for the subscription_type [%d]", subscription_type);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ }
+
+ filter_cnt = g_list_length(filter_list);
+
+ for(idx = 0; idx < filter_cnt; idx++) {
+ filter_data = (char*)g_list_nth_data(filter_list, idx);
+ ret = __mc_parse_server_name(filter_data, &server_name);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail __mc_parse_server_name");
+
+ if (MC_STRING_VALID(server_name)) {
+ if (callback(server_name, user_data) == false) {
+ MC_SAFE_FREE(server_name);
+ break;
+ }
+ }
+
+ MC_SAFE_FREE(server_name);
+ }
+
+ return ret;
+}
+
+int mc_client_get_playback_state(mc_playback_h playback, mc_playback_states_e *state)
+{
+ media_controller_playback_s *mc_playback = (media_controller_playback_s *)playback;
+
+ mc_retvm_if(mc_playback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(state == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is NULL");
+
+ *state = mc_playback->state;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_get_playback_position(mc_playback_h playback, unsigned long long *position)
+{
+ media_controller_playback_s *mc_playback = (media_controller_playback_s *)playback;
+
+ mc_retvm_if(mc_playback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(position == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "position is NULL");
+
+ *position = mc_playback->position;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_get_metadata(mc_metadata_h metadata, mc_meta_e attribute, char **value)
+{
+ char *meta_val = NULL;
+ media_controller_metadata_s *mc_metadata = (media_controller_metadata_s *)metadata;
+
+ mc_retvm_if(mc_metadata == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(value == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "value is NULL");
+
+ *value = NULL;
+
+ mc_debug("attribute[%d]", attribute);
+
+ switch (attribute) {
+ case MC_META_MEDIA_TITLE:
+ if (mc_metadata->title != NULL)
+ meta_val = strdup(mc_metadata->title);
+ break;
+ case MC_META_MEDIA_ARTIST:
+ if (mc_metadata->artist != NULL)
+ meta_val = strdup(mc_metadata->artist);
+ break;
+ case MC_META_MEDIA_ALBUM:
+ if (mc_metadata->album != NULL)
+ meta_val = strdup(mc_metadata->album);
+ break;
+ case MC_META_MEDIA_AUTHOR:
+ if (mc_metadata->author != NULL)
+ meta_val = strdup(mc_metadata->author);
+ break;
+ case MC_META_MEDIA_GENRE:
+ if (mc_metadata->genre != NULL)
+ meta_val = strdup(mc_metadata->genre);
+ break;
+ case MC_META_MEDIA_DURATION:
+ if (mc_metadata->duration != NULL)
+ meta_val = strdup(mc_metadata->duration);
+ break;
+ case MC_META_MEDIA_DATE:
+ if (mc_metadata->date != NULL)
+ meta_val = strdup(mc_metadata->date);
+ break;
+ case MC_META_MEDIA_COPYRIGHT:
+ if (mc_metadata->copyright != NULL)
+ meta_val = strdup(mc_metadata->copyright);
+ break;
+ case MC_META_MEDIA_DESCRIPTION:
+ if (mc_metadata->description != NULL)
+ meta_val = strdup(mc_metadata->description);
+ break;
+ case MC_META_MEDIA_TRACK_NUM:
+ if (mc_metadata->track_num != NULL)
+ meta_val = strdup(mc_metadata->track_num);
+ break;
+ case MC_META_MEDIA_PICTURE:
+ if (mc_metadata->picture != NULL)
+ meta_val = strdup(mc_metadata->picture);
+ break;
+ default:
+ mc_error("Invalid Parameter [%d]", attribute);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ *value = meta_val;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_destroy_playback(mc_playback_h playback)
+{
+ media_controller_playback_s *mc_playback = (media_controller_playback_s *)playback;
+
+ mc_retvm_if(mc_playback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ MC_SAFE_FREE(mc_playback);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_destroy_metadata(mc_metadata_h metadata)
+{
+ media_controller_metadata_s *mc_metadata = (media_controller_metadata_s *)metadata;
+
+ mc_retvm_if(mc_metadata == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ MC_SAFE_FREE(mc_metadata->title);
+ MC_SAFE_FREE(mc_metadata->artist);
+ MC_SAFE_FREE(mc_metadata->album);
+ MC_SAFE_FREE(mc_metadata->author);
+ MC_SAFE_FREE(mc_metadata->genre);
+ MC_SAFE_FREE(mc_metadata->duration);
+ MC_SAFE_FREE(mc_metadata->date);
+ MC_SAFE_FREE(mc_metadata->copyright);
+ MC_SAFE_FREE(mc_metadata->description);
+ MC_SAFE_FREE(mc_metadata->track_num);
+ MC_SAFE_FREE(mc_metadata->picture);
+
+ MC_SAFE_FREE(mc_metadata);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_client_get_latest_server_info(mc_client_h client, char **server_name, mc_server_state_e *server_state)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *latest_server_name = NULL;
+ mc_server_state_e latest_server_state = MC_SERVER_STATE_NONE;
+
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+ mc_retvm_if(server_state == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_state is NULL");
+
+ ret = mc_db_get_latest_server_name(mc_client->db_handle, &latest_server_name);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail mc_db_get_latest_server_name [%d]", ret);
+
+ if (latest_server_name != NULL) {
+ ret = mc_db_get_server_state(mc_client->db_handle, latest_server_name, &latest_server_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("error in getting latest server state %d", ret);
+ MC_SAFE_FREE(latest_server_name);
+ return ret;
+ }
+
+ *server_name = latest_server_name;
+ *server_state = latest_server_state;
+ } else {
+ *server_name = NULL;
+ *server_state = MC_SERVER_STATE_NONE;
+ }
+
+ return ret;
+}
+
+int mc_client_get_server_playback_info(mc_client_h client, const char *server_name, mc_playback_h *playback)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+ mc_retvm_if(playback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "playback Handle is NULL");
+
+ ret = mc_db_get_playback_info(mc_client->db_handle, server_name, playback);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail mc_db_get_playback_info [%d]", ret);
+
+ return ret;
+}
+
+int mc_client_get_server_metadata(mc_client_h client, const char *server_name, mc_metadata_h *metadata)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+ mc_retvm_if(metadata == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "metadata Handle is NULL");
+
+ ret = mc_db_get_metadata_info(mc_client->db_handle, server_name, metadata);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail mc_db_get_metadata_info [%d]", ret);
+
+ return ret;
+}
+
+int mc_client_get_server_shuffle_mode(mc_client_h client, const char *server_name, mc_shuffle_mode_e *mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+ mc_retvm_if(mode == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "mode is NULL");
+
+ ret = mc_db_get_shuffle_mode(mc_client->db_handle, server_name, mode);
+
+ return ret;
+}
+
+int mc_client_get_server_repeat_mode(mc_client_h client, const char *server_name, mc_repeat_mode_e *mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+ mc_retvm_if(mode == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "mode is NULL");
+
+ ret = mc_db_get_repeat_mode(mc_client->db_handle, server_name, mode);
+
+ return ret;
+}
+
+int mc_client_foreach_server(mc_client_h client, mc_activated_server_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ ret = mc_db_foreach_server_list(mc_client->db_handle, callback, user_data);
+
+ return ret;
+}
+
+int mc_client_send_playback_state_command(mc_client_h client, const char *server_name, mc_playback_states_e state)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *message = NULL;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+ mc_retvm_if(((state < MC_PLAYBACK_STATE_PLAYING) || (state > MC_PLAYBACK_STATE_REWIND)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is invalid");
+
+ message = g_strdup_printf("%s%s%d", mc_client->client_name, MC_STRING_DELIMITER, state);
+ mc_retvm_if(message == NULL, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "fail making message [%d]", ret);
+
+ ret = mc_util_set_command_availabe(mc_client->client_name, MC_COMMAND_PLAYBACKSTATE, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_util_set_command_availabe [%d]", ret);
+ return ret;
+ }
+
+ char *interface_name = mc_util_get_interface_name(MC_SERVER, server_name);
+ ret = mc_ipc_send_message(mc_client->dconn, NULL, interface_name, MC_DBUS_SIGNAL_NAME_PLAYBACK_STATE_CMD, message, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_ipc_send_message [%d]", ret);
+ }
+
+ MC_SAFE_FREE(message);
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_client_send_custom_command(mc_client_h client, const char *server_name, const char *command, bundle *data, mc_command_reply_received_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *message = NULL;
+ int size_r = 0;
+ bundle_raw *raw_data = NULL;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(server_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name");
+
+ ret = mc_util_set_command_availabe(mc_client->client_name, MC_COMMAND_CUSTOM, command);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_util_set_command_availabe [%d]", ret);
+ return ret;
+ }
+
+ if (callback) {
+ char *interface_name_for_reply = mc_util_get_interface_name(MC_CLIENT, mc_client->client_name);
+ mc_client->reply_cb.callback = callback;
+ mc_client->reply_cb.user_data = user_data;
+ mc_ipc_register_listener(mc_client->listeners, mc_client->dconn, interface_name_for_reply,
+ MC_DBUS_SIGNAL_NAME_CMD_REPLY, __client_reply_cb, (void *)&(mc_client->reply_cb));
+ MC_SAFE_FREE(interface_name_for_reply);
+ }
+
+ if (data) {
+ ret = bundle_encode(data, &raw_data, &size_r);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail while encoding bundle [%d]", ret);
+ }
+
+ if ((size_r == 0) || (raw_data == NULL)) {
+ message = g_strdup_printf("%s%s%s%s%d", mc_client->client_name, MC_STRING_DELIMITER, command, MC_STRING_DELIMITER, size_r);
+ } else {
+ message = g_strdup_printf("%s%s%s%s%d%s%s", mc_client->client_name, MC_STRING_DELIMITER, command, MC_STRING_DELIMITER, size_r, MC_STRING_DELIMITER, (unsigned char *)raw_data);
+ }
+ if (message == NULL) {
+ mc_error("Error when making message");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ char *interface_name = mc_util_get_interface_name(MC_SERVER, server_name);
+ ret = mc_ipc_send_message(mc_client->dconn, NULL, interface_name, MC_DBUS_SIGNAL_NAME_CUSTOM_CMD, message, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("Error mc_ipc_send_message [%d]", ret);
+
+ MC_SAFE_FREE(message);
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_client_destroy(mc_client_h client)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_client_s *mc_client = (media_controller_client_s *)client;
+
+ mc_debug_fenter();
+
+ mc_retvm_if(mc_client == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ /*Unregister all filter listener*/
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->server_state_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_SERVER_STATE);
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->playback_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAY_BACK);
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->metadata_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_METADATA);
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->shuffle_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE);
+ ret = __mc_client_unregister_filter_listener(mc_client, &mc_client->repeat_cb.filter_list, NULL, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT);
+
+ /*Unregister all listener*/
+ ret = mc_ipc_unregister_all_listener(mc_client->listeners, mc_client->dconn);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_ipc_unregister_all_listener [%d]", ret);
+ }
+
+ /*Send Disconnection Msg to Server*/
+ ret = mc_ipc_send_message_to_server(MC_MSG_SERVER_DISCONNECTION, MC_SERVER_DISCONNECTION_MSG);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to mc_ipc_send_message_to_server [%d]", ret);
+ }
+
+ ret = __mc_client_destroy(mc_client);
+
+ mc_debug_fleave();
+
+ return ret;
+}
diff --git a/src/media_controller_db.c b/src/media_controller_db.c
new file mode 100755
index 0000000..3bd58ed
--- /dev/null
+++ b/src/media_controller_db.c
@@ -0,0 +1,639 @@
+/*
+* Copyright (c) 2011 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 "media_controller_private.h"
+#include "media_controller_db.h"
+#include "media_controller_socket.h"
+
+typedef enum {
+ MC_SERVER_FIELD_SERVER_NAME = 0,
+ MC_SERVER_FIELD_SERVER_STATE,
+ MC_SERVER_FIELD_PLAYBACK_STATE,
+ MC_SERVER_FIELD_PLAYBACK_POSITION,
+ MC_SERVER_FIELD_TITLE,
+ MC_SERVER_FIELD_ARTIST,
+ MC_SERVER_FIELD_ALBUM,
+ MC_SERVER_FIELD_AUTHOR,
+ MC_SERVER_FIELD_GENRE,
+ MC_SERVER_FIELD_DURATION,
+ MC_SERVER_FIELD_DATE,
+ MC_SERVER_FIELD_COPYRIGHT,
+ MC_SERVER_FIELD_DESCRIPTION,
+ MC_SERVER_FIELD_TRACK_NUM,
+ MC_SERVER_FIELD_PICTURE,
+ MC_SERVER_FIELD_SHUFFLE_MODE,
+ MC_SERVER_FIELD_REPEAT_MODE,
+} server_table_field_e;
+
+static int __mc_db_busy_handler(void *pData, int count)
+{
+ MC_MILLISEC_SLEEP(50);
+
+ mc_debug("mc_db_busy_handler called : %d", count);
+
+ return 100 - count;
+}
+
+static int __mc_db_update_db(void *handle, const char *sql_str)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ mc_retvm_if(!MC_STRING_VALID(sql_str), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid Query");
+
+ ret = mc_ipc_send_message_to_server(MC_MSG_DB_UPDATE, sql_str);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_ipc_send_message_to_server failed : %d", ret);
+ }
+
+ return ret;
+}
+
+static int __mc_db_get_int_value_of_key(void *handle, const char *server_name, const char *key, int *value)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+ mc_retvm_if(key == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "key is NULL");
+
+ sql_str = sqlite3_mprintf(DB_SELECT_VALUE_OF_KEY, key, server_name);
+
+ ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (SQLITE_ROW != ret) {
+ mc_error("end of row [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ while (SQLITE_ROW == ret) {
+ *value = sqlite3_column_int(stmt, 0);
+ ret = sqlite3_step(stmt);
+ }
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+static int __mc_db_get_ulong_value_of_key(void *handle, const char *server_name, const char *key, unsigned long long *value)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+ mc_retvm_if(key == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "key is NULL");
+
+ sql_str = sqlite3_mprintf(DB_SELECT_VALUE_OF_KEY, key, server_name);
+
+ ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (SQLITE_ROW != ret) {
+ mc_error("end of row [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ while (SQLITE_ROW == ret) {
+ *value = (unsigned long long)sqlite3_column_int64(stmt, 0);
+ ret = sqlite3_step(stmt);
+ }
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_connect(void **handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = NULL;
+
+ mc_debug("mc_db_connect");
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ /*Connect DB*/
+ ret = db_util_open(MC_DB_NAME, &db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
+ if (SQLITE_OK != ret) {
+ mc_error("error when db open");
+ *handle = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ if (db_handle == NULL) {
+ mc_error("*db_handle is NULL");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /*Register busy handler*/
+ ret = sqlite3_busy_handler(db_handle, __mc_db_busy_handler, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("error when register busy handler %s\n", sqlite3_errmsg(db_handle));
+ db_util_close(db_handle);
+ *handle = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ *handle = db_handle;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_update_playback_info(void *handle, const char *server_name, int playback_state, unsigned long long playback_position)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf(DB_UPDATE_PLAYBACK_INFO_INTO_SERVER_TABLE, server_name, playback_state, playback_position);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_update_whole_metadata(void *handle, const char *server_name,
+ const char *title, const char *artist, const char *album, const char *author, const char *genre, const char *duration, const char *date,
+ const char *copyright, const char *description, const char *track_num, const char *picture)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf(DB_UPDATE_METADATA_INFO_INFO_SERVER_TABLE, server_name,
+ title, artist, album, author, genre, duration, date, copyright, description, track_num, picture);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_update_shuffle_mode(void *handle, const char *server_name, int shuffle_mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf(DB_UPDATE_SHUFFLE_MODE_INTO_SERVER_TABLE, server_name, shuffle_mode);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_update_repeat_mode(void *handle, const char *server_name, int repeat_mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf(DB_UPDATE_REPEAT_MODE_INTO_SERVER_TABLE, server_name, repeat_mode);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_get_latest_server_name(void *handle, char **latest_server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+ char *server_name = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ *latest_server_name = NULL;
+
+ sql_str = sqlite3_mprintf(DB_SELECT_LATEST_SERVER_NAME);
+
+ ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (SQLITE_ROW != ret) {
+ mc_error("end of row [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_NONE; /*There is no activated server yet. */
+ }
+
+ while (SQLITE_ROW == ret) {
+ MC_SAFE_FREE(server_name);
+ server_name = strdup((char *)sqlite3_column_text(stmt, 0));
+ ret = sqlite3_step(stmt);
+ }
+
+ if (server_name)
+ *latest_server_name = server_name;
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_get_playback_info(void *handle, const char *server_name, mc_playback_h *playback)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ mc_playback_states_e playback_state = MC_PLAYBACK_STATE_PLAYING;
+ unsigned long long position = 0;
+ media_controller_playback_s *_playback = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ ret = __mc_db_get_int_value_of_key(handle, server_name, "playback_state", (int *)&playback_state);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "Fail to get playback_state");
+
+ ret = __mc_db_get_ulong_value_of_key(handle, server_name, "playback_position", &position);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "Fail to get position");
+
+ _playback = (media_controller_playback_s *)calloc(1, sizeof(media_controller_playback_s));
+ mc_retvm_if(_playback == NULL, MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+
+ _playback->state = playback_state;
+ _playback->position = position;
+
+ *playback = (mc_playback_h)_playback;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_get_metadata_info(void *handle, const char *server_name, mc_metadata_h *metadata)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+ media_controller_metadata_s *_metadata = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf(DB_SELECT_METADATA_FROM_DB, server_name);
+
+ ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ ret = sqlite3_step(stmt);
+ if (SQLITE_ROW != ret) {
+ mc_error("end of row [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ } else {
+ _metadata = (media_controller_metadata_s *)calloc(1, sizeof(media_controller_metadata_s));
+ mc_retvm_if(_metadata == NULL, MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TITLE)))
+ _metadata->title = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TITLE));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ARTIST)))
+ _metadata->artist = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ARTIST));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ALBUM)))
+ _metadata->album = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_ALBUM));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_AUTHOR)))
+ _metadata->author = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_AUTHOR));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_GENRE)))
+ _metadata->genre = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_GENRE));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DURATION)))
+ _metadata->duration = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DURATION));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DATE)))
+ _metadata->date = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DATE));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_COPYRIGHT)))
+ _metadata->copyright = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_COPYRIGHT));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DESCRIPTION)))
+ _metadata->description = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_DESCRIPTION));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TRACK_NUM)))
+ _metadata->track_num = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_TRACK_NUM));
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_PICTURE)))
+ _metadata->picture = strdup((const char *)sqlite3_column_text(stmt, MC_SERVER_FIELD_PICTURE));
+ }
+
+ *metadata = (mc_metadata_h)_metadata;
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_get_server_state(void *handle, const char *server_name, mc_server_state_e *state)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ ret = __mc_db_get_int_value_of_key(handle, server_name, "server_state", (int *)state);
+
+ return ret;
+}
+
+int mc_db_get_shuffle_mode(void *handle, const char *server_name, mc_shuffle_mode_e *mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ ret = __mc_db_get_int_value_of_key(handle, server_name, "shuffle_mode", (int *)mode);
+
+ return ret;
+}
+
+int mc_db_get_repeat_mode(void *handle, const char *server_name, mc_repeat_mode_e *mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ ret = __mc_db_get_int_value_of_key(handle, server_name, "repeat_mode", (int *)mode);
+
+ return ret;
+}
+
+int mc_db_insert_server_address_into_table(void *handle, const char *table_name, char *address)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ sql_str = sqlite3_mprintf(DB_INSERT_INTO_SERVER_TABLE, table_name, address);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_delete_server_address_from_table(void *handle, const char *table_name, char *address)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ sql_str = sqlite3_mprintf(DB_DELETE_FROM_SERVER_TABLE, table_name, address);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_disconnect(void *handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+
+ mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = db_util_close(db_handle);
+ if (SQLITE_OK != ret) {
+ mc_error("error when db close");
+ mc_error("Error : %s", sqlite3_errmsg(db_handle));
+ db_handle = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_create_server_table(void *handle, const char *server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS '%q' (\
+ server_name TEXT PRIMARY KEY, \
+ server_state INTEGER DEFAULT 1, \
+ playback_state INTEGER DEFAULT 0, \
+ playback_position INTEGER DEFAULT 0, \
+ title TEXT, \
+ artist TEXT, \
+ album TEXT, \
+ author TEXT, \
+ genre TEXT, \
+ duration INTEGER DEFAULT 0, \
+ date TEXT, \
+ copyright TEXT, \
+ description TEXT, \
+ track_num TEXT, \
+ picture TEXT, \
+ shuffle_mode INTEGER DEFAULT 1, \
+ repeat_mode INTEGER DEFAULT 1 \
+ );",
+ server_name);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_delete_server_table(void *handle, const char *server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf("DROP TABLE IF EXISTS '%q'", server_name);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+int mc_db_check_server_table_exist(void *handle, const char *server_name, bool *exist)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+ int count = 0;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf("SELECT COUNT(*) FROM SQLITE_MASTER WHERE type='table' and name='%q'", server_name);
+
+ ret = sqlite3_prepare_v2(handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (SQLITE_ROW != ret) {
+ mc_error("end of row [%s]\n", sqlite3_errmsg(handle));
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ count = sqlite3_column_int(stmt, 0);
+
+ mc_debug("table count [%d]", count);
+
+ if (count > 0)
+ *exist = TRUE;
+ else
+ *exist = FALSE;
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_foreach_server_list(void *handle, mc_activated_server_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ sql_str = sqlite3_mprintf(DB_SELECT_ALL_SERVER_LIST);
+ ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (SQLITE_ROW != ret) {
+ mc_error("end of row [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ }
+
+ while (SQLITE_ROW == ret) {
+ char *server_name = NULL;
+ server_name = strdup((char *)sqlite3_column_text(stmt, 0));
+ if (callback(server_name, user_data) == false) {
+ MC_SAFE_FREE(server_name);
+ break;
+ }
+ MC_SAFE_FREE(server_name);
+
+ ret = sqlite3_step(stmt);
+ }
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_update_server_state(void *handle, const char *server_name, mc_server_state_e server_state)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf("UPDATE '%q' SET server_state=%d;", server_name, server_state);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+
+int mc_db_update_latest_server_table(void *handle, const char *server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf("DELETE FROM '%q'; INSERT INTO '%q' (server_name) VALUES ('%q');", MC_DB_TABLE_LATEST_SERVER, MC_DB_TABLE_LATEST_SERVER, server_name);
+
+ ret = __mc_db_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
diff --git a/src/media_controller_ipc.c b/src/media_controller_ipc.c
new file mode 100755
index 0000000..9c8beb0
--- /dev/null
+++ b/src/media_controller_ipc.c
@@ -0,0 +1,424 @@
+/*
+* Copyright (c) 2011 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 <stdio.h>
+#include <glib.h>
+#include "media_controller_private.h"
+
+#define MAX_RETRY_COUNT 3
+#define MAX_WAIT_COUNT 100
+#define MC_SVC_NAME "mediacontroller"
+
+/* This checks if service daemon is running */
+static gboolean __is_service_activated()
+{
+ gboolean ret = FALSE;
+ ret = mc_ipc_send_message_to_server(MC_MSG_SERVER_CONNECTION, MC_SERVER_CONNECTION_MSG);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to mc_ipc_send_message_to_server [%d]", ret);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static char *__make_key_for_map(const char *main_key, const char *sub_key)
+{
+ return g_strdup_printf("%s.%s", main_key, sub_key);
+}
+
+static void __mc_ipc_signal_cb(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ char *key = __make_key_for_map(interface_name, signal_name);
+ GList *listener_list = (GList *)user_data;
+ unsigned int i = 0;
+
+ mc_debug("__mc_ipc_signal_cb Received : ");
+
+ for (i = 0; i < g_list_length(listener_list); i++) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data(listener_list, i);
+ if (listener && !strcmp(listener->key, key)) {
+ gchar *message = NULL;
+ int internal_flags = 0;
+ g_variant_get(parameters, "(i&s)", &internal_flags, &message);
+ if (!message) {
+ mc_error("g_variant_get() fail");
+ break;
+ }
+ mc_debug("Received : [%s] (flags = %x) from %s.%s", message, internal_flags, listener->interface_name, listener->signal_name);
+ listener->callback(listener->interface_name, listener->signal_name, message, 0, listener->user_data);
+ }
+ }
+}
+
+static gboolean _mc_ipc_is_listener_duplicated(GList *listener_list, const char *key)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < g_list_length(listener_list); i++) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data((listener_list), i);
+ mc_retvm_if(listener && !strcmp(listener->key, key), TRUE, "listener[%s] is duplicated ", key);
+ }
+
+ return FALSE;
+}
+
+static guint _mc_ipc_signal_subscribe(GDBusConnection *connection, const char *interface_name, const char *signal_name, void *user_data)
+{
+ guint ret = g_dbus_connection_signal_subscribe(
+ connection,
+ NULL,
+ interface_name,
+ signal_name,
+ MC_DBUS_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __mc_ipc_signal_cb,
+ user_data,
+ NULL);
+
+ return ret;
+}
+
+static void _mc_ipc_signal_unsubscribe(GDBusConnection *connection, guint handler)
+{
+ g_dbus_connection_signal_unsubscribe(connection, handler);
+}
+
+int mc_ipc_get_dbus_connection(GDBusConnection **connection, int *dref_count)
+{
+ GError *error = NULL;
+ GDBusConnection *_connection = NULL;
+
+ if (*dref_count > 0) {
+ mc_retvm_if(!(*connection), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "__dbus_conn is null");
+
+ mc_error("Reference count : %d", *dref_count);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ _connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!_connection) {
+ mc_error("g_bus_get_sync failed : %s", error ? error->message : "none");
+ if (error) g_error_free(error);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ (*connection) = _connection;
+ (*dref_count)++;
+
+ mc_debug("Reference count : %d", *dref_count);
+
+ if (error) g_error_free(error);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_unref_dbus_connection(GDBusConnection *connection, int *dref_count)
+{
+ if (*dref_count > 1) {
+ mc_retvm_if(!connection, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "__dbus_conn is null");
+ (*dref_count)--;
+ mc_debug("Reference count : %d", dref_count);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ } else if (*dref_count == 1) {
+ mc_retvm_if(!connection, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "__dbus_conn is null");
+ (*dref_count)--;
+ mc_debug("Reference count : %d", *dref_count);
+ } else {
+ mc_retvm_if(connection, MEDIA_CONTROLLER_ERROR_NONE, "__dbus_conn is not null");
+ mc_debug("Reference count : %d", *dref_count);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ }
+
+ g_object_unref(connection);
+ connection = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_register_listener(GList *listener_list, GDBusConnection *connection, const char *interface_name, const char *signal_name, mc_signal_received_cb callback, void *user_data)
+{
+ char *key = NULL;
+ guint handler = 0;
+
+ mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "interface_name is NULL");
+ mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ key = __make_key_for_map(interface_name, signal_name);
+
+ if (_mc_ipc_is_listener_duplicated(listener_list, key)) {
+ mc_error("listener is duplicated");
+
+ MC_SAFE_FREE(key);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_malloc(sizeof(mc_ipc_listener_s));
+ if (listener == NULL) {
+ mc_error("Error memroy allocation");
+ MC_SAFE_FREE(key);
+ return MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ }
+
+ handler = _mc_ipc_signal_subscribe(connection, interface_name, signal_name, listener_list);
+
+ listener->dbus_conn = connection;
+ listener->interface_name = g_strdup(interface_name);
+ listener->signal_name = g_strdup(signal_name);
+ listener->callback = callback;
+ listener->user_data = user_data;
+ listener->handler = handler;
+ listener->key = key;
+
+ (listener_list) = g_list_append((listener_list), listener);
+
+ mc_debug("listener[%s.%s] is registered", interface_name, signal_name);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_unregister_listener(GList *listener_list, GDBusConnection *connection, const char *interface_name, const char *signal_name)
+{
+ int i = 0;
+ char *key = NULL;
+
+ mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "interface_name is NULL");
+ mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL");
+
+ key = __make_key_for_map(interface_name, signal_name);
+ if (key == NULL) {
+ mc_error("fail to get key");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ for (i = g_list_length(listener_list) - 1; i >= 0; i--) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data(listener_list, i);
+ if (listener && !strcmp(listener->key, key)) {
+ _mc_ipc_signal_unsubscribe(connection, listener->handler);
+ MC_SAFE_FREE(listener->interface_name);
+ MC_SAFE_FREE(listener->signal_name);
+ MC_SAFE_FREE(listener->key);
+ (listener_list) = g_list_remove(listener_list, listener);
+ MC_SAFE_FREE(listener);
+ mc_debug("listener[%s.%s] is unregistered", interface_name, signal_name);
+ }
+ }
+
+ MC_SAFE_FREE(key);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_unregister_all_listener(GList *listener_list, GDBusConnection *connection)
+{
+ int i = 0;
+
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(listener_list == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "listener_list is NULL");
+
+ for (i = g_list_length(listener_list) - 1; i >= 0; i--) {
+ mc_ipc_listener_s *listener = (mc_ipc_listener_s *)g_list_nth_data(listener_list, i);
+ if (listener) {
+ _mc_ipc_signal_unsubscribe(connection, listener->handler);
+ MC_SAFE_FREE(listener->interface_name);
+ MC_SAFE_FREE(listener->signal_name);
+ MC_SAFE_FREE(listener->key);
+ (listener_list) = g_list_remove(listener_list, listener);
+ MC_SAFE_FREE(listener);
+ }
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_send_message(GDBusConnection *connection, const char *dbus_name, const char *interface_name, const char *signal_name, const char *message, int flags)
+{
+ GError *error = NULL;
+
+ mc_retvm_if(connection == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "connection is NULL");
+ mc_retvm_if(!MC_STRING_VALID(signal_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid signal_name");
+ mc_retvm_if(!MC_STRING_VALID(message), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid message");
+
+ mc_debug("emit signal - interface_name [%s], signal_name [%s]", interface_name, signal_name);
+
+ gboolean emmiting = g_dbus_connection_emit_signal(
+ connection,
+ dbus_name,
+ MC_DBUS_PATH,
+ interface_name,
+ signal_name,
+ g_variant_new("(is)", 0, message),
+ &error);
+ if (!emmiting) {
+ mc_error("g_dbus_connection_emit_signal failed : %s", error ? error->message : "none");
+ if (error) {
+ mc_error("Error in g_dbus_connection_emit_signal");
+ g_error_free(error);
+ }
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_send_message_to_server(mc_msg_type_e msg_type, const char *request_msg)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int request_msg_size = 0;
+ int sockfd = -1;
+ mc_sock_info_s sock_info;
+ struct sockaddr_un serv_addr;
+ int retry_count = 0;
+
+ if (!MC_STRING_VALID(request_msg)) {
+ mc_error("invalid query");
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ request_msg_size = strlen(request_msg);
+ if (request_msg_size >= MAX_MSG_SIZE) {
+ mc_error("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ mc_comm_msg_s send_msg;
+ memset((void *)&send_msg, 0, sizeof(mc_comm_msg_s));
+
+ send_msg.msg_type = msg_type;
+ send_msg.pid = getpid();
+ send_msg.msg_size = request_msg_size;
+ strncpy(send_msg.msg, request_msg, sizeof(send_msg.msg) - 1);
+
+ /*Create Socket*/
+ ret = mc_ipc_create_client_socket(MC_TIMEOUT_SEC_5, &sock_info);
+ sockfd = sock_info.sock_fd;
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "socket is not created properly");
+
+ /*Set server Address*/
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sun_family = AF_UNIX;
+ strncpy(serv_addr.sun_path, MC_IPC_PATH, sizeof(serv_addr.sun_path) - 1);
+
+ /* Connecting to the media db server */
+ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ mc_stderror("connect error");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /* Send request */
+ if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
+ mc_stderror("send failed");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /*Receive Response*/
+ int recv_msg_size = -1;
+ int recv_msg = -1;
+RETRY:
+ if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) {
+ mc_error("recv failed : [%d]", sockfd);
+ mc_stderror("recv failed");
+
+ if (errno == EINTR) {
+ mc_stderror("catch interrupt");
+ goto RETRY;
+ }
+
+ if (errno == EWOULDBLOCK) {
+ if (retry_count < MAX_RETRY_COUNT) {
+ mc_error("TIME OUT[%d]", retry_count);
+ retry_count++;
+ goto RETRY;
+ }
+
+ mc_ipc_delete_client_socket(&sock_info);
+ mc_error("Timeout. Can't try any more");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ } else {
+ mc_stderror("recv failed");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ }
+
+ mc_debug("RECEIVE OK [%d]", recv_msg);
+ ret = recv_msg;
+
+ mc_ipc_delete_client_socket(&sock_info);
+
+ return ret;
+}
+
+int mc_ipc_service_connect(void)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int sockfd = -1;
+ mc_sock_info_s sock_info;
+ struct sockaddr_un serv_addr;
+ unsigned int retrycount = 0;
+
+ if (__is_service_activated() == TRUE) {
+ mc_debug("service is already running!");
+ return MEDIA_CONTROLLER_ERROR_NONE;
+ }
+
+ /*Create Socket*/
+ ret = mc_ipc_create_client_socket(MC_TIMEOUT_SEC_5, &sock_info);
+ sockfd = sock_info.sock_fd;
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "socket is not created properly");
+
+ /*Set server Address*/
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sun_family = AF_UNIX;
+ strncpy(serv_addr.sun_path, MC_SOCK_ACTIVATION_PATH, sizeof(serv_addr.sun_path) - 1);
+
+ /* Connecting to the media db server */
+ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ mc_stderror("connect error");
+ mc_ipc_delete_client_socket(&sock_info);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ mc_ipc_delete_client_socket(&sock_info);
+
+ while((__is_service_activated() == FALSE) && (retrycount++ < MAX_WAIT_COUNT)) {
+ MC_MILLISEC_SLEEP(200);
+ mc_error("[No-Error] retry count [%d]", retrycount);
+ }
+
+ if (retrycount < MAX_WAIT_COUNT) {
+ mc_debug("CONNECT OK");
+ ret = MEDIA_CONTROLLER_ERROR_NONE;
+ } else {
+ mc_error("CONNECT FAIL");
+ ret = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return ret;
+}
diff --git a/src/media_controller_server.c b/src/media_controller_server.c
new file mode 100755
index 0000000..eb94375
--- /dev/null
+++ b/src/media_controller_server.c
@@ -0,0 +1,691 @@
+/*
+* Copyright (c) 2011 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 "media_controller_private.h"
+#include "media_controller_db.h"
+
+static int __mc_server_create(media_controller_server_s **mc_server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *_server = NULL;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ _server = (media_controller_server_s *)calloc(1, sizeof(media_controller_server_s));
+ mc_retvm_if(_server == NULL, MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY, "Error allocation memory");
+
+ ret = mc_util_get_own_name(&(_server->server_name));
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to get server_name [%d]", ret);
+ goto ERROR;
+ }
+
+ _server->metadata = (media_controller_metadata_s *)calloc(1, sizeof(media_controller_metadata_s));
+ if (_server->metadata == NULL) {
+ mc_error("Error allocation memory");
+ ret = MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ goto ERROR;
+ }
+
+ ret = mc_ipc_get_dbus_connection(&(_server->dconn), &(_server->dref_count));
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error allocation memory");
+ goto ERROR;
+ }
+
+ ret = mc_db_connect(&(_server->db_handle));
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_connect [%d]", ret);
+ goto ERROR;
+ }
+
+ _server->listeners = g_list_alloc();
+ if (_server->listeners == NULL) {
+ ret = MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ mc_error("Error allocation list %d", ret);
+ goto ERROR;
+ }
+
+ *mc_server = _server;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+
+ERROR:
+ if (_server->dconn)
+ mc_ipc_unref_dbus_connection(_server->dconn, &_server->dref_count);
+
+ if (_server->db_handle)
+ mc_db_disconnect(_server->db_handle);
+
+ if (_server->listeners)
+ g_list_free(_server->listeners);
+
+ MC_SAFE_FREE(_server->server_name);
+ MC_SAFE_FREE(_server->metadata);
+ MC_SAFE_FREE(_server);
+
+ return ret;
+}
+
+static int __mc_server_destoy(media_controller_server_s *mc_server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ if (mc_server->dconn) {
+ ret = mc_ipc_unref_dbus_connection(mc_server->dconn, &mc_server->dref_count);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail to mc_ipc_unref_dbus_connection");
+ }
+
+ if (mc_server->db_handle) {
+ ret = mc_db_disconnect(mc_server->db_handle);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail to mc_db_disconnect");
+ }
+
+ if (mc_server->listeners != NULL) {
+ g_list_free(mc_server->listeners);
+ }
+
+ MC_SAFE_FREE(mc_server->server_name);
+
+ if (mc_server->metadata) {
+ MC_SAFE_FREE(mc_server->metadata->title);
+ MC_SAFE_FREE(mc_server->metadata->artist);
+ MC_SAFE_FREE(mc_server->metadata->album);
+ MC_SAFE_FREE(mc_server->metadata->author);
+ MC_SAFE_FREE(mc_server->metadata->genre);
+ MC_SAFE_FREE(mc_server->metadata->duration);
+ MC_SAFE_FREE(mc_server->metadata->date);
+ MC_SAFE_FREE(mc_server->metadata->copyright);
+ MC_SAFE_FREE(mc_server->metadata->description);
+ MC_SAFE_FREE(mc_server->metadata->track_num);
+ MC_SAFE_FREE(mc_server->metadata->picture);
+ MC_SAFE_FREE(mc_server->metadata);
+ }
+
+ MC_SAFE_FREE(mc_server);
+
+ return ret;
+}
+
+static void __server_playback_state_command_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ media_controller_receiver_s *receiver = (media_controller_receiver_s *)user_data;
+ mc_retm_if(receiver == NULL, "reciever is NULL");
+ mc_retm_if(message == NULL, "message is NULL");
+
+ mc_server_playback_state_command_received_cb callback = receiver->callback;
+ mc_retm_if(receiver->callback == NULL, "playback_state_command_received_cb is NULL");
+
+ mc_debug("__server_playback_state_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid playback state command");
+
+ if (mc_util_get_command_availabe(params[0], MC_COMMAND_PLAYBACKSTATE, NULL) != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error permission denied");
+ return ;
+ }
+
+ callback(params[0], (mc_playback_states_e)atoi(params[1]), receiver->user_data);
+
+ g_strfreev(params);
+}
+
+static void __server_custom_command_cb(const char *interface_name, const char *signal_name, const char *message, int size, void *user_data)
+{
+ gchar **params = NULL;
+ int enc_size = 0;
+ char *sender = NULL;
+ char *command = NULL;
+ bundle *bundle_data = NULL;
+
+ media_controller_receiver_s *receiver = (media_controller_receiver_s *)user_data;
+ mc_retm_if(receiver == NULL, "reciever is NULL");
+
+ mc_server_custom_command_received_cb callback = receiver->callback;
+ mc_retm_if(receiver->callback == NULL, "custom_command_received_cb is NULL");
+
+ mc_debug("__server_custom_cb(%s, %s, %s, %d, %p)", interface_name, signal_name, message, size, user_data);
+
+ params = g_strsplit(message, MC_STRING_DELIMITER, 0);
+ mc_retm_if(params == NULL, "invalid custom data");
+
+ if(params[0])
+ sender = strdup(params[0]);
+
+ if (mc_util_get_command_availabe(sender, MC_COMMAND_CUSTOM, params[1]) != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error permission denied");
+ MC_SAFE_FREE(sender);
+ g_strfreev(params);
+ return;
+ }
+
+ command = strdup(params[1]);
+ enc_size = atoi(params[2]);
+ if (enc_size > 0)
+ bundle_data = bundle_decode((bundle_raw *)params[3], enc_size);
+
+ callback(sender, command, bundle_data, receiver->user_data);
+
+ g_strfreev(params);
+}
+
+static int __mc_server_current_is_latest(media_controller_server_s *mc_server, bool *is_latest)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *latest_server_name = NULL;
+
+ *is_latest = FALSE;
+
+ ret = mc_db_get_latest_server_name(mc_server->db_handle, &latest_server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_get_latest_server_name [%d]", ret);
+ return ret;
+ }
+
+ if ((latest_server_name != NULL) && (mc_server->server_name != NULL)) {
+ if (!strcmp(latest_server_name, mc_server->server_name))
+ *is_latest = TRUE;
+ }
+
+ MC_SAFE_FREE(latest_server_name);
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+static int __mc_server_send_message(media_controller_server_s *mc_server, const char *interface_name, const char *signal_name, int param1, unsigned long long param2)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *message = NULL;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(interface_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "interface_name is NULL");
+ mc_retvm_if(signal_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "signal_name is NULL");
+
+ if (!strcmp(MC_DBUS_SIGNAL_NAME_PLAY_BACK, signal_name)) {
+ message = g_strdup_printf("%s%s%d%s%llu", mc_server->server_name, MC_STRING_DELIMITER, param1, MC_STRING_DELIMITER, param2);
+ } else if (!strcmp(MC_DBUS_SIGNAL_NAME_METADATA, signal_name)) {
+ message = g_strdup_printf("%s", mc_server->server_name);
+ } else {
+ message = g_strdup_printf("%s%s%d", mc_server->server_name, MC_STRING_DELIMITER, param1);
+ }
+
+ if (message == NULL) {
+ mc_error("Error when making message");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = mc_ipc_send_message(mc_server->dconn, NULL, interface_name, signal_name, message, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_ipc_send_message [%d]", ret);
+ }
+
+ mc_debug("interface_name[%s] signal_name[%s] message[%s]", interface_name, signal_name, message);
+
+ /*Send again for the subscriber which receive filtered msg with server_name*/
+ char *filter_interface_name = NULL;
+ ret = mc_util_make_filter_interface_name(interface_name, mc_server->server_name, &filter_interface_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_util_make_interface_name [%d]", ret);
+ } else {
+ ret = mc_ipc_send_message(mc_server->dconn, NULL, filter_interface_name, signal_name, message, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error mc_ipc_send_message [%d]", ret);
+ }
+ }
+
+ MC_SAFE_FREE(filter_interface_name);
+ MC_SAFE_FREE(message);
+
+ return ret;
+}
+
+int mc_server_set_playback_state(mc_server_h server, mc_playback_states_e state)
+{
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(((state < MC_PLAYBACK_STATE_PLAYING) || (state > MC_PLAYBACK_STATE_REWIND)), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "state is invalid");
+
+ mc_debug("playback state update [%d]", state);
+
+ mc_server->playback.state = state;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_server_set_playback_position(mc_server_h server, unsigned long long position)
+{
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ mc_debug("playback position update [%llu]", position);
+
+ mc_server->playback.position = position;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_server_update_playback_info(mc_server_h server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ mc_debug("playback info update: state [%d], position [%llu]", mc_server->playback.state, mc_server->playback.position);
+
+ ret = mc_db_update_playback_info(mc_server->db_handle, mc_server->server_name, (int)mc_server->playback.state, mc_server->playback.position);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_update_playback_info [%d]", ret);
+ return ret;
+ }
+
+ ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAY_BACK, mc_server->playback.state, mc_server->playback.position);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error __mc_server_send_message [%d]", ret);
+ }
+
+ if (mc_server->playback.state == MC_PLAYBACK_STATE_PLAYING) {
+ ret = mc_db_update_latest_server_table(mc_server->db_handle, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_update_playback_info [%d]", ret);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+int mc_server_update_shuffle_mode(mc_server_h server, mc_shuffle_mode_e mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ if ((mode != MC_SHUFFLE_MODE_ON) && (mode != MC_SHUFFLE_MODE_OFF)) {
+ mc_error("Invalid shuffle mode [%d]", mode);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ mc_debug("shuffle mode %d", mode);
+
+ ret = mc_db_update_shuffle_mode(mc_server->db_handle, mc_server->server_name, mode);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_shuffle_mode");
+
+ ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_SHUFFLE, mode, 0);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
+
+ return ret;
+}
+
+int mc_server_update_repeat_mode(mc_server_h server, mc_repeat_mode_e mode)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ if ((mode != MC_REPEAT_MODE_ON) && (mode != MC_REPEAT_MODE_OFF)) {
+ mc_error("Invalid repeat mode [%d]", mode);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ mc_debug("repeat mode %d", mode);
+
+ ret = mc_db_update_repeat_mode(mc_server->db_handle, mc_server->server_name, mode);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_repeat_mode");
+
+ ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_PLAYBACK_REPEAT, mode, 0);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
+
+ return ret;
+}
+
+int mc_server_set_metadata(mc_server_h server, mc_meta_e attribute, const char *value)
+{
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ mc_debug("meta data set attribute [%d] value [%s]", attribute, value);
+
+ switch (attribute) {
+ case MC_META_MEDIA_TITLE:
+ MC_SAFE_FREE(mc_server->metadata->title);
+ if (value != NULL)
+ mc_server->metadata->title = strdup(value);
+ break;
+ case MC_META_MEDIA_ARTIST:
+ MC_SAFE_FREE(mc_server->metadata->artist);
+ if (value != NULL)
+ mc_server->metadata->artist = strdup(value);
+ break;
+ case MC_META_MEDIA_ALBUM:
+ MC_SAFE_FREE(mc_server->metadata->album);
+ if (value != NULL)
+ mc_server->metadata->album = strdup(value);
+ break;
+ case MC_META_MEDIA_AUTHOR:
+ MC_SAFE_FREE(mc_server->metadata->author);
+ if (value != NULL)
+ mc_server->metadata->author = strdup(value);
+ break;
+ case MC_META_MEDIA_GENRE:
+ MC_SAFE_FREE(mc_server->metadata->genre);
+ if (value != NULL)
+ mc_server->metadata->genre = strdup(value);
+ break;
+ case MC_META_MEDIA_DURATION:
+ MC_SAFE_FREE(mc_server->metadata->duration);
+ if (value != NULL)
+ mc_server->metadata->duration = strdup(value);
+ break;
+ case MC_META_MEDIA_DATE:
+ MC_SAFE_FREE(mc_server->metadata->date);
+ if (value != NULL)
+ mc_server->metadata->date = strdup(value);
+ break;
+ case MC_META_MEDIA_COPYRIGHT:
+ MC_SAFE_FREE(mc_server->metadata->copyright);
+ if (value != NULL)
+ mc_server->metadata->copyright = strdup(value);
+ break;
+ case MC_META_MEDIA_DESCRIPTION:
+ MC_SAFE_FREE(mc_server->metadata->description);
+ if (value != NULL)
+ mc_server->metadata->description = strdup(value);
+ break;
+ case MC_META_MEDIA_TRACK_NUM:
+ MC_SAFE_FREE(mc_server->metadata->track_num);
+ if (value != NULL)
+ mc_server->metadata->track_num = strdup(value);
+ break;
+ case MC_META_MEDIA_PICTURE:
+ MC_SAFE_FREE(mc_server->metadata->picture);
+ if (value != NULL)
+ mc_server->metadata->picture = strdup(value);
+ break;
+ default:
+ mc_error("Invalid Parameter [%d]", attribute);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_server_update_metadata(mc_server_h server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_db_update_whole_metadata(mc_server->db_handle, mc_server->server_name,
+ mc_server->metadata->title, mc_server->metadata->artist, mc_server->metadata->album, mc_server->metadata->author,
+ mc_server->metadata->genre, mc_server->metadata->duration, mc_server->metadata->date, mc_server->metadata->copyright,
+ mc_server->metadata->description, mc_server->metadata->track_num, mc_server->metadata->picture);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to mc_db_update_whole_metadata");
+
+ ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_METADATA, 0, 0);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "fail to __mc_server_send_message");
+
+ return ret;
+}
+
+int mc_server_set_playback_state_command_received_cb(mc_server_h server, mc_server_playback_state_command_received_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ mc_server->playback_state_reciever.callback = callback;
+ mc_server->playback_state_reciever.user_data = user_data;
+
+ char *interface_name = mc_util_get_interface_name(MC_SERVER, mc_server->server_name);
+ ret = mc_ipc_register_listener(mc_server->listeners, mc_server->dconn, interface_name,
+ MC_DBUS_SIGNAL_NAME_PLAYBACK_STATE_CMD, __server_playback_state_command_cb, (void *)&(mc_server->playback_state_reciever));
+
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_server_unset_playback_state_command_received_cb(mc_server_h server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ char *interface_name = mc_util_get_interface_name(MC_SERVER, mc_server->server_name);
+ ret = mc_ipc_unregister_listener(mc_server->listeners, mc_server->dconn, interface_name,
+ MC_DBUS_SIGNAL_NAME_PLAYBACK_STATE_CMD);
+
+ mc_server->playback_state_reciever.callback = NULL;
+ mc_server->playback_state_reciever.user_data = NULL;
+
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_server_set_custom_command_received_cb(mc_server_h server, mc_server_custom_command_received_cb callback, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(callback == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "callback is NULL");
+
+ mc_server->custom_cmd_reciever.callback = callback;
+ mc_server->custom_cmd_reciever.user_data = user_data;
+
+ char *interface_name = mc_util_get_interface_name(MC_SERVER, mc_server->server_name);
+ ret = mc_ipc_register_listener(mc_server->listeners, mc_server->dconn, interface_name,
+ MC_DBUS_SIGNAL_NAME_CUSTOM_CMD, __server_custom_command_cb, (void *)&(mc_server->custom_cmd_reciever));
+
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_server_unset_custom_command_received_cb(mc_server_h server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ char *interface_name = mc_util_get_interface_name(MC_SERVER, mc_server->server_name);
+ ret = mc_ipc_unregister_listener(mc_server->listeners, mc_server->dconn, interface_name, MC_DBUS_SIGNAL_NAME_CUSTOM_CMD);
+
+ mc_server->custom_cmd_reciever.callback = NULL;
+ mc_server->custom_cmd_reciever.user_data = NULL;
+
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_server_send_command_reply(mc_server_h server, const char *client_name, int result_code, bundle *data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *message = NULL;
+ int size_r = 0;
+ bundle_raw *raw_data = NULL;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(!MC_STRING_VALID(client_name), MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "client_name is NULL");
+
+ if (data) {
+ ret = bundle_encode(data, &raw_data, &size_r);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error while encoding bundle [%d]", ret);
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ message = g_strdup_printf("%s%s%d%s%d%s%s", mc_server->server_name, MC_STRING_DELIMITER, result_code, MC_STRING_DELIMITER, size_r, MC_STRING_DELIMITER, (unsigned char *)raw_data);
+
+ char *interface_name = mc_util_get_interface_name(MC_CLIENT, client_name);
+ ret = mc_ipc_send_message(mc_server->dconn, NULL, interface_name, MC_DBUS_SIGNAL_NAME_CMD_REPLY, message, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail mc_ipc_send_message [%d]", ret);
+
+ MC_SAFE_FREE(message);
+ MC_SAFE_FREE(interface_name);
+
+ return ret;
+}
+
+int mc_server_create(mc_server_h *server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = NULL;
+ bool table_exist = FALSE;
+
+ mc_debug_fenter();
+
+ mc_retvm_if(server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is null");
+
+ /*Try Socket Activation by systemd*/
+ ret = mc_ipc_service_connect();
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to get mc_ipc_service_connect [%d]", ret);
+ return ret;
+ }
+
+ ret = __mc_server_create(&mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail __mc_server_create [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+
+ ret = mc_db_check_server_table_exist(mc_server->db_handle, mc_server->server_name, &table_exist);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_db_check_server_table_exist failed [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+
+ if (table_exist) {
+ ret = mc_db_delete_server_table(mc_server->db_handle, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_db_delete_server_table failed [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+ ret = mc_db_delete_server_address_from_table(mc_server->db_handle, MC_DB_TABLE_SERVER_LIST, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_db_delete_server_address_from_table failed [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+ }
+
+ ret = mc_db_create_server_table(mc_server->db_handle, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_clear_table [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+
+ ret = mc_db_insert_server_address_into_table(mc_server->db_handle, mc_server->server_name, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_insert_server_address_into_table [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+
+ ret = mc_db_insert_server_address_into_table(mc_server->db_handle, MC_DB_TABLE_SERVER_LIST, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_db_insert_server_address_into_table [%d]", ret);
+ __mc_server_destoy(mc_server);
+ return ret;
+ }
+
+ ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE, MC_SERVER_STATE_ACTIVATE, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error __mc_server_send_message [%d]", ret);
+ }
+
+ *server = (mc_server_h)mc_server;
+
+ mc_debug_fleave();
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_server_destroy(mc_server_h server)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ bool is_latest = FALSE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)server;
+
+ mc_debug_fenter();
+
+ mc_retvm_if(mc_server == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = mc_ipc_unregister_all_listener(mc_server->listeners, mc_server->dconn);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("fail mc_ipc_unregister_all_listener [%d]", ret);
+ }
+
+ ret = mc_db_delete_server_address_from_table(mc_server->db_handle, MC_DB_TABLE_SERVER_LIST, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail mc_db_delete_server_address_from_table [%d]", ret);
+
+ ret = __mc_server_current_is_latest(mc_server, &is_latest);
+ if (is_latest) {
+ ret = mc_db_update_server_state(mc_server->db_handle, mc_server->server_name, MC_SERVER_STATE_DEACTIVATE);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail mc_db_delete_server_table [%d]", ret);
+ } else {
+ ret = mc_db_delete_server_table(mc_server->db_handle, mc_server->server_name);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail mc_db_delete_server_table [%d]", ret);
+ }
+
+ ret = __mc_server_send_message(mc_server, MC_DBUS_UPDATE_INTERFACE, MC_DBUS_SIGNAL_NAME_SERVER_STATE, MC_SERVER_STATE_DEACTIVATE, 0);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error __mc_server_send_message [%d]", ret);
+ }
+
+ /*Send Disconnection Msg to Server*/
+ ret = mc_ipc_send_message_to_server(MC_MSG_SERVER_DISCONNECTION, MC_SERVER_DISCONNECTION_MSG);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to mc_ipc_send_message_to_server [%d]", ret);
+ }
+
+ ret = __mc_server_destoy(mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("fail __mc_server_destoy [%d]", ret);
+
+ mc_debug_fleave();
+
+ return ret;
+}
diff --git a/src/media_controller_util.c b/src/media_controller_util.c
new file mode 100755
index 0000000..f55f7bd
--- /dev/null
+++ b/src/media_controller_util.c
@@ -0,0 +1,152 @@
+/*
+* Copyright (c) 2011 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 <aul.h>
+#include "media_controller_private.h"
+
+#define MAX_NAME_LENGTH 255
+
+static void _mc_util_check_valid_name(const char *name, char **new_name)
+{
+ char old_word[MAX_NAME_LENGTH] = {0, };
+ char new_word[MAX_NAME_LENGTH] = {0, };
+ unsigned int i = 0;
+
+ mc_retm_if(name == NULL, "Invalid parameter.");
+
+ memset(old_word, 0, MAX_NAME_LENGTH);
+ memset(new_word, 0, MAX_NAME_LENGTH);
+
+ if (strlen(name) > MAX_NAME_LENGTH) {
+ memcpy(old_word, name, MAX_NAME_LENGTH);
+ } else {
+ memcpy(old_word, name, strlen(name));
+ }
+
+ /* only 0~9, a~z, A~Z, '.', '_' will be used */
+ for (i = 0; i < strlen(old_word); i++) {
+ if ((old_word[i] >= '0' && old_word[i] <= '9') ||
+ (old_word[i] >= 'a' && old_word[i] <= 'z') ||
+ (old_word[i] >= 'A' && old_word[i] <= 'Z') ||
+ (old_word[i] == '.' && i != 0)) {
+ new_word[i] = old_word[i];
+ } else {
+ new_word[i] = 'x';
+ }
+ }
+
+ (*new_name) = strdup(new_word);
+
+ mc_retm_if((*new_name) == NULL, "Error allocation memory.");
+}
+
+int mc_util_get_own_name(char **name)
+{
+ char temp[MAX_NAME_LENGTH] = {0, };
+ int pid = -1;
+
+ memset(temp, 0, MAX_NAME_LENGTH);
+
+ pid = getpid();
+ if (pid == -1) {
+ mc_error("Error failed to get pid!");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ if (AUL_R_OK != aul_app_get_appid_bypid(pid, temp, sizeof(temp))) {
+ mc_error("Error failed to get appid!");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ _mc_util_check_valid_name(temp, name);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+char *mc_util_get_interface_name(const char *type, const char *name)
+{
+ char *temp = NULL;
+ char *interface_name = NULL;
+
+ mc_retvm_if(type == NULL, NULL, "type is NULL");
+ mc_retvm_if(name == NULL, NULL, "name is NULL");
+
+ temp = g_strdup_printf("%s.%s.%s", MC_DBUS_INTERFACE_PREFIX, type, name);
+
+ _mc_util_check_valid_name(temp, &interface_name);
+ MC_SAFE_FREE(temp);
+ return interface_name;
+}
+
+int mc_util_make_filter_interface_name(const char *prefix, const char *filter, char **interface_name)
+{
+ char *temp = NULL;
+
+ mc_retvm_if(prefix == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "prefix is NULL");
+ mc_retvm_if(filter == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "filter is NULL");
+
+ temp = g_strdup_printf("%s.%s", prefix, filter);
+
+ if (temp == NULL) {
+ mc_error("Fail to make interface_name");
+ return MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ }
+
+ _mc_util_check_valid_name(temp, interface_name);
+
+ MC_SAFE_FREE(temp);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_util_set_command_availabe(const char *name, const char *command_type, const char *command)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *message = NULL;
+
+ if (!MC_STRING_VALID(name) || !MC_STRING_VALID(command_type)) {
+ mc_error("invalid query");
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ if (command == NULL)
+ message = g_strdup_printf("%s%s", name, command_type);
+ else
+ message = g_strdup_printf("%s%s%s", name, command_type, command);
+
+ ret = mc_ipc_send_message_to_server(MC_MSG_CLIENT_SET, message);
+
+ return ret;
+}
+
+int mc_util_get_command_availabe(const char *name, const char *command_type, const char *command)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *message = NULL;
+
+ if (!MC_STRING_VALID(name) || !MC_STRING_VALID(command_type)) {
+ mc_error("invalid query");
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+ }
+
+ if (command == NULL)
+ message = g_strdup_printf("%s%s", name, command_type);
+ else
+ message = g_strdup_printf("%s%s%s", name, command_type, command);
+
+ ret = mc_ipc_send_message_to_server(MC_MSG_CLIENT_GET, message);
+
+ return ret;
+}
diff --git a/svc/CMakeLists.txt b/svc/CMakeLists.txt
new file mode 100755
index 0000000..baa51f2
--- /dev/null
+++ b/svc/CMakeLists.txt
@@ -0,0 +1,46 @@
+# for package file
+SET(dependents "capi-base-common glib-2.0 gio-2.0 dlog sqlite3 db-util security-server libsystemd-daemon")
+SET(fw_svc "media-controller-svc")
+
+PROJECT(${fw_svc})
+
+SET(CMAKE_INSTALL_PREFIX ${prefix})
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(VERSION ${version})
+
+SET(INC_DIR include)
+INCLUDE_DIRECTORIES(${INC_DIR})
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_svc} REQUIRED ${dependents})
+FOREACH(flag ${${fw_svc}_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+
+IF("${ARCH}" MATCHES "^arm.*")
+ ADD_DEFINITIONS("-DTARGET")
+ENDIF("${ARCH}" MATCHES "^arm.*")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DTIZEN_DEBUG")
+ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib")
+
+aux_source_directory(. SOURCES_SVC)
+ADD_LIBRARY(${fw_svc} SHARED ${SOURCES_SVC})
+
+TARGET_LINK_LIBRARIES(${fw_svc} ${${fw_svc}_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${fw_svc}
+ PROPERTIES
+ VERSION ${FULLVER}
+ SOVERSION ${MAJORVER}
+ CLEAN_DIRECT_OUTPUT 1
+)
+
+INSTALL(TARGETS ${fw_svc} DESTINATION lib)
+ADD_SUBDIRECTORY(daemon)
diff --git a/svc/daemon/CMakeLists.txt b/svc/daemon/CMakeLists.txt
new file mode 100755
index 0000000..9140113
--- /dev/null
+++ b/svc/daemon/CMakeLists.txt
@@ -0,0 +1,21 @@
+SET(fw_daemon "mediacontroller")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_daemon} REQUIRED glib-2.0 security-server)
+
+FOREACH(flag ${${fw_daemon}_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE -Wall")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both -pie")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+ GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+ MESSAGE("${src_name}")
+ ADD_EXECUTABLE(${fw_daemon} ${src})
+ TARGET_LINK_LIBRARIES(${fw_daemon} media-controller-svc ${${fw_daemon}_LDFLAGS})
+ENDFOREACH()
+
+INSTALL(TARGETS ${fw_daemon} DESTINATION bin)
diff --git a/svc/daemon/media_controller_main.c b/svc/daemon/media_controller_main.c
new file mode 100755
index 0000000..63aa550
--- /dev/null
+++ b/svc/daemon/media_controller_main.c
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2011 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 "media_controller_private.h"
+#include "../media_controller_socket.h"
+#include "../media_controller_svc.h"
+
+GMainLoop *g_mc_mainloop = NULL;
+static int g_mc_timer_id = 0;
+
+#define MC_MAIN_TIMEOUT_SEC_60 60
+
+
+void __mc_main_create_timer(int timer_id);
+
+gboolean __mc_main_check_connection(gpointer user_data)
+{
+ int connection_cnt = 0;
+ connection_cnt = mc_svc_get_connection_cnt();
+ if ((connection_cnt == -1) || (connection_cnt > 0)) {
+ mc_error("[No-error] Timer is Called but there is working Process");
+
+ __mc_main_create_timer(g_mc_timer_id);
+ } else {
+ mc_error("[No-error] Timer is Called. Now Killing mediacontroller process");
+ g_mc_timer_id = 0;
+
+ /*Quit Controller Thread*/
+ GMainLoop *mc_svc_mainloop = mc_svc_get_main_loop();
+ if (mc_svc_mainloop && g_main_is_running(mc_svc_mainloop)) {
+ g_main_loop_quit(mc_svc_mainloop);
+ }
+
+ g_main_loop_quit(g_mc_mainloop);
+ }
+
+ return FALSE;
+}
+
+void __mc_main_create_timer(int timer_id)
+{
+ if (timer_id > 0)
+ g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), timer_id));
+
+ GSource *timer_src = g_timeout_source_new_seconds(MC_MAIN_TIMEOUT_SEC_60);
+ g_source_set_callback (timer_src, __mc_main_check_connection, NULL, NULL);
+ g_mc_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default());
+}
+
+int main(int argc, char **argv)
+{
+ GThread *svc_thread = NULL;
+ int fd = -1;
+
+ /*Init main loop*/
+ g_mc_mainloop = g_main_loop_new(NULL, FALSE);
+
+ fd = mc_create_socket_activation();
+ if (fd < 0) {
+ mc_error("Failed to socekt creation");
+ }
+
+ /*create each threads*/
+ svc_thread = g_thread_new("mc_svc_thread", (GThreadFunc)mc_svc_thread, NULL);
+
+ /* Create Timer */
+ __mc_main_create_timer(g_mc_timer_id);
+
+ mc_debug("*** Media Controller Daemon is running ***");
+
+ g_main_loop_run(g_mc_mainloop);
+
+ g_thread_join(svc_thread);
+ g_main_loop_unref(g_mc_mainloop);
+
+ mc_debug("*** Media Controller Daemon is stopped ***");
+
+ return 0;
+}
diff --git a/svc/media_controller_db_util.c b/svc/media_controller_db_util.c
new file mode 100755
index 0000000..9d67aa8
--- /dev/null
+++ b/svc/media_controller_db_util.c
@@ -0,0 +1,238 @@
+/*
+* Copyright (c) 2011 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 "media_controller_db_util.h"
+#include "media_controller_private.h"
+
+static int __mc_db_util_busy_handler(void *pData, int count)
+{
+ MC_MILLISEC_SLEEP(50);
+
+ mc_debug("mc_db_busy_handler called : %d", count);
+
+ return 100 - count;
+}
+
+static int __mc_foreach_table_list(void *handle, GList **list)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+ char *sql_str = NULL;
+ sqlite3_stmt *stmt = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ sql_str = sqlite3_mprintf(DB_SELECT_ALL_SERVER_LIST_EXCEPT_LATEST, MC_DB_TABLE_LATEST_SERVER);
+
+ ret = sqlite3_prepare_v2(db_handle, sql_str, strlen(sql_str), &stmt, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("prepare error [%s]\n", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(sql_str);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = sqlite3_step(stmt);
+ while (SQLITE_ROW == ret) {
+ char *table_name = NULL;
+
+ if (MC_STRING_VALID((const char *)sqlite3_column_text(stmt, 0))) {
+ table_name = strdup((const char *)sqlite3_column_text(stmt, 0));
+ mc_debug("table_name: %s", table_name);
+
+ if (MC_STRING_VALID(table_name)) {
+ (*list) = g_list_append((*list), table_name);
+ }
+ }
+
+ ret = sqlite3_step(stmt);
+ }
+
+ SQLITE3_FINALIZE(stmt);
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+static int __mc_db_util_delete_server_table(void *handle, const char *server_name)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(server_name == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "server_name is NULL");
+
+ sql_str = sqlite3_mprintf("DROP TABLE IF EXISTS '%q'", server_name);
+
+ ret = mc_db_util_update_db(handle, sql_str);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ mc_error("Error mc_db_util_update_db %d", ret);
+ }
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+static int __mc_create_latest_server_table(sqlite3 *handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (server_name TEXT PRIMARY KEY);", MC_DB_TABLE_LATEST_SERVER);
+
+ ret = mc_db_util_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+
+ return ret;
+}
+
+static int __mc_create_server_list_table(sqlite3 *handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *sql_str = NULL;
+
+ sql_str = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %s (\
+ server_name TEXT PRIMARY KEY);",
+ MC_DB_TABLE_SERVER_LIST);
+
+ ret = mc_db_util_update_db(handle, sql_str);
+
+ SQLITE3_SAFE_FREE(sql_str);
+ return ret;
+}
+
+int mc_db_util_connect(void **handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = NULL;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ /*Connect DB*/
+ ret = db_util_open(MC_DB_NAME, &db_handle, DB_UTIL_REGISTER_HOOK_METHOD);
+ if (SQLITE_OK != ret) {
+ mc_error("error when db open");
+ *handle = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ if (db_handle == NULL) {
+ mc_error("*db_handle is NULL");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ /*Register busy handler*/
+ ret = sqlite3_busy_handler(db_handle, __mc_db_util_busy_handler, NULL);
+ if (SQLITE_OK != ret) {
+ mc_error("error when register busy handler %s\n", sqlite3_errmsg(db_handle));
+ db_util_close(db_handle);
+ *handle = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ *handle = db_handle;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_util_disconnect(void *handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+
+ mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = db_util_close(db_handle);
+ if (SQLITE_OK != ret) {
+ mc_error("error when db close");
+ mc_error("Error : %s", sqlite3_errmsg(db_handle));
+ db_handle = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_util_create_tables(void *handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+
+ mc_retvm_if(db_handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = __mc_create_latest_server_table(db_handle);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create latest_server table failed!err= [%d]", ret);
+
+ ret = __mc_create_server_list_table(db_handle);
+ mc_retvm_if(ret != MEDIA_CONTROLLER_ERROR_NONE, ret, "create server_list table failed!err= [%d]", ret);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_util_update_db(void *handle, const char *sql_str)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *err_msg = NULL;
+ sqlite3 *db_handle = (sqlite3 *)handle;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+ mc_retvm_if(sql_str == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "sql_str is NULL");
+
+ mc_debug("Update query [%s]", sql_str);
+
+ ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &err_msg);
+ if (SQLITE_OK != ret) {
+ mc_error("failed to update db[%s]", sqlite3_errmsg(db_handle));
+ SQLITE3_SAFE_FREE(err_msg);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_db_util_delete_whole_server_tables(void *handle)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ GList *table_list = NULL;
+ unsigned int idx = 0;
+
+ mc_retvm_if(handle == NULL, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Handle is NULL");
+
+ ret = __mc_foreach_table_list(handle, &table_list);
+ if ( ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Error __mc_foreach_table_list %d", ret);
+ return ret;
+ }
+
+ if (table_list == NULL) {
+ mc_debug("No server list to delete");
+ return ret;
+ }
+
+ for (idx = 0; idx < g_list_length(table_list); idx++) {
+ char *table_name = g_list_nth_data(table_list, idx);
+ __mc_db_util_delete_server_table(handle, table_name);
+ MC_SAFE_FREE(table_name);
+ }
+
+ g_list_free(table_list);
+
+ return ret;
+}
diff --git a/svc/media_controller_db_util.h b/svc/media_controller_db_util.h
new file mode 100755
index 0000000..7436008
--- /dev/null
+++ b/svc/media_controller_db_util.h
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_DB_UTIL_H__
+#define __TIZEN_MEDIA_CONTROLLER_DB_UTIL_H__
+
+#include <db-util.h>
+#include <sqlite3.h>
+
+#define MC_DB_NAME "/opt/usr/dbspace/.media_controller.db"
+
+#define MC_DB_TABLE_SERVER_LIST "server_list"
+#define MC_DB_TABLE_LATEST_SERVER "latest_server"
+
+#define DB_SELECT_ALL_SERVER_LIST_EXCEPT_LATEST "SELECT name FROM SQLITE_MASTER WHERE type='table' AND (name != '%q') AND (name NOT IN (SELECT server_name FROM "MC_DB_TABLE_LATEST_SERVER"))"
+
+#define SQLITE3_SAFE_FREE(sql_string) {if(sql_string) { sqlite3_free(sql_string); sql_string = NULL;}}
+#define SQLITE3_FINALIZE(x) {if(x != NULL) {sqlite3_finalize(x);}}
+
+int mc_db_util_connect(void **handle);
+int mc_db_util_disconnect(void *handle);
+int mc_db_util_create_tables(void *handle);
+int mc_db_util_update_db(void *handle, const char *sql_str);
+int mc_db_util_delete_whole_server_tables(void *handle);
+
+#endif /*__TIZEN_MEDIA_CONTROLLER_DB_UTIL_H__*/
diff --git a/svc/media_controller_socket.c b/svc/media_controller_socket.c
new file mode 100755
index 0000000..0a2bf13
--- /dev/null
+++ b/svc/media_controller_socket.c
@@ -0,0 +1,185 @@
+/*
+* Copyright (c) 2011 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 <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "media_controller_private.h"
+#include "media_controller_db_util.h"
+#include "media_controller_socket.h"
+
+#define MC_SOCK_PATH_PRFX "/tmp/.media_ipc_mc_client"
+#define MC_SOCK_PATH_TEMPLATE "XXXXXX"
+#define MC_SOCK_PATH MC_SOCK_PATH_PRFX MC_SOCK_PATH_TEMPLATE
+#define MC_SOCK_UDP_BLOCK_SIZE 512
+
+int mc_ipc_create_client_socket(int timeout_sec, mc_sock_info_s *sock_info)
+{
+ int sock = -1;
+
+ struct timeval tv_timeout = { timeout_sec, 0 };
+
+ /*Create TCP Socket*/
+ if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
+ mc_stderror("socket failed");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ if (timeout_sec > 0) {
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) {
+ mc_stderror("setsockopt failed");
+ close(sock);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ }
+
+ sock_info->sock_fd = sock;
+ sock_info->sock_path = NULL;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_delete_client_socket(mc_sock_info_s *sock_info)
+{
+ int ret = 0;
+
+ close(sock_info->sock_fd);
+ mc_debug("sockfd %d close", sock_info->sock_fd);
+ if (sock_info->sock_path != NULL) {
+ ret = unlink(sock_info->sock_path);
+ if (ret < 0) {
+ mc_stderror("unlink failed");
+ }
+ free(sock_info->sock_path);
+ }
+
+ return ret;
+}
+
+int mc_ipc_create_server_socket(mc_msg_port_type_e port, int *sock_fd)
+{
+ int i = 0;
+ bool bind_success = false;
+ int sock = -1;
+ struct sockaddr_un serv_addr;
+
+ /* Create a TCP socket */
+ if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
+ mc_stderror("socket failed");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+
+ serv_addr.sun_family = AF_UNIX;
+ unlink(MC_IPC_PATH);
+ strncpy(serv_addr.sun_path, MC_IPC_PATH, sizeof(serv_addr.sun_path) - 1);
+
+ /* Bind to the local address */
+ for (i = 0; i < 20; i++) {
+ if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
+ bind_success = true;
+ break;
+ }
+ mc_debug("%d", i);
+ MC_MILLISEC_SLEEP(250);
+ }
+
+ if (bind_success == false) {
+ mc_stderror("bind failed");
+ close(sock);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ mc_debug("bind success");
+
+ /* Listening */
+ if (listen(sock, SOMAXCONN) < 0) {
+ mc_stderror("listen failed");
+ close(sock);
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ mc_debug("Listening...");
+
+ /*change permission of sock file*/
+ if (chmod(MC_IPC_PATH, 0660) < 0)
+ mc_stderror("chmod failed");
+ if (chown(MC_IPC_PATH, 200, 5000) < 0)
+ mc_stderror("chown failed");
+
+ *sock_fd = sock;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+
+}
+
+int mc_ipc_send_msg_to_client_tcp(int sockfd, mc_comm_msg_s *send_msg, struct sockaddr_un *client_addr)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ if (write(sockfd, send_msg, sizeof(*(send_msg))) != sizeof(*(send_msg))) {
+ mc_stderror("sendto failed");
+ ret = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ } else {
+ mc_debug("sent result [%d]", send_msg->result);
+ mc_debug("result message [%s]", send_msg->msg);
+ }
+
+ return ret;
+}
+
+int mc_ipc_receive_message_tcp(int client_sock, mc_comm_msg_s *recv_msg)
+{
+ int recv_msg_size = 0;
+
+ if ((recv_msg_size = read(client_sock, recv_msg, sizeof(mc_comm_msg_s))) < 0) {
+ if (errno == EWOULDBLOCK) {
+ mc_error("Timeout. Can't try any more");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ } else {
+ mc_stderror("recv failed");
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ }
+
+ mc_debug("receive msg from [%d] %d, %s", recv_msg->pid, recv_msg->msg_type, recv_msg->msg);
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int mc_ipc_accept_client_tcp(int serv_sock, int *client_sock)
+{
+ int sockfd = -1;
+ struct sockaddr_un client_addr;
+ socklen_t client_addr_len;
+
+ if (client_sock == NULL)
+ return MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER;
+
+ client_addr_len = sizeof(client_addr);
+ if ((sockfd = accept(serv_sock, (struct sockaddr *)&client_addr, &client_addr_len)) < 0) {
+ mc_stderror("accept failed");
+ *client_sock = -1;
+ return MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ *client_sock = sockfd;
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
diff --git a/svc/media_controller_socket.h b/svc/media_controller_socket.h
new file mode 100755
index 0000000..fb9b247
--- /dev/null
+++ b/svc/media_controller_socket.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef __TIZEN_MEDIA_CONTROLLER_SOCKET_H__
+#define __TIZEN_MEDIA_CONTROLLER_SOCKET_H__
+
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define SERVER_IP "127.0.0.1"
+#define MC_TIMEOUT_SEC_5 5 /**< Response from Server time out */
+#define MAX_MSG_SIZE 4096*2
+#define MC_SOCK_NOT_ALLOCATE -1
+#define MC_SOCK_ACTIVATION_PATH "/tmp/.media_sa_controller"
+#define MC_IPC_PATH "/tmp/.media_ipc_controller"
+#define MC_SERVER_CONNECTION_MSG "Connect"
+#define MC_SERVER_DISCONNECTION_MSG "Disonnect"
+
+typedef enum{
+ MC_DB_UPDATE_PORT, /**< Media Controller DB Update */
+ MC_PORT_MAX,
+} mc_msg_port_type_e;
+
+typedef enum{
+ MC_MSG_DB_UPDATE, /**< Media Controller DB Update */
+ MC_MSG_CLIENT_SET,
+ MC_MSG_CLIENT_GET,
+ MC_MSG_SERVER_CONNECTION,
+ MC_MSG_SERVER_DISCONNECTION,
+ MC_MSG_MAX,
+} mc_msg_type_e;
+
+typedef struct {
+ int sock_fd;
+ char *sock_path;
+}mc_sock_info_s;
+
+typedef struct {
+ mc_msg_type_e msg_type;
+ int pid;
+ int result;
+ size_t msg_size; /*this is size of message below and this does not include the terminationg null byte ('\0'). */
+ char msg[MAX_MSG_SIZE];
+}mc_comm_msg_s;
+
+int mc_ipc_create_client_socket(int timeout_sec, mc_sock_info_s* sock_info);
+int mc_ipc_delete_client_socket(mc_sock_info_s* sock_info);
+int mc_ipc_create_server_socket(mc_msg_port_type_e port, int *sock_fd);
+int mc_ipc_send_msg_to_client_tcp(int sockfd, mc_comm_msg_s *send_msg, struct sockaddr_un *client_addr);
+int mc_ipc_receive_message_tcp(int client_sock, mc_comm_msg_s *recv_msg);
+int mc_ipc_accept_client_tcp(int serv_sock, int* client_sock);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TIZEN_MEDIA_CONTROLLER_SERVER_H__ */
diff --git a/svc/media_controller_svc.c b/svc/media_controller_svc.c
new file mode 100755
index 0000000..e943ccf
--- /dev/null
+++ b/svc/media_controller_svc.c
@@ -0,0 +1,317 @@
+/*
+* Copyright (c) 2011 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 <string.h>
+#include <security-server.h>
+#include <sys/stat.h>
+#include <systemd/sd-daemon.h>
+
+#include "media_controller_svc.h"
+#include "media_controller_private.h"
+#include "media_controller_socket.h"
+#include "media_controller_db_util.h"
+
+static GMainLoop *g_mc_svc_mainloop = NULL;
+static int g_connection_cnt = -1;
+
+static int __mc_privilege_ask(int client_sockfd, const char *type, const char *privilege_object)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ ret = security_server_check_privilege_by_sockfd(client_sockfd, type, privilege_object);
+ if (ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
+ mc_error("You do not have permission for this operation.");
+ ret = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED;
+ } else {
+ mc_debug("PERMISSION OK");
+ }
+
+ return ret;
+}
+
+static int __create_socket_activation(void)
+{
+ int fd = -1;
+ int listen_fds;
+
+ listen_fds = sd_listen_fds(0);
+ if (listen_fds == 1) {
+ fd = SD_LISTEN_FDS_START;
+ return fd;
+ } else if (listen_fds > 1) {
+ mc_error("Too many file descriptors received.");
+ return -1;
+ } else {
+ mc_error("There is no socket stream");
+ return -1;
+ }
+}
+
+gboolean _mc_read_service_request_tcp_socket(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+ int sock = -1;
+ int client_sock = -1;
+ char *sql_query = NULL;
+ mc_comm_msg_s recv_msg;
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int send_msg = MEDIA_CONTROLLER_ERROR_NONE;
+ int i = 0;
+ mc_svc_data_t *mc_svc_data = (mc_svc_data_t*)data;
+
+ mc_debug("mc_read_service_request_tcp_socket is called!!!!!");
+
+ sock = g_io_channel_unix_get_fd(src);
+ if (sock < 0) {
+ mc_error("sock fd is invalid!");
+ return TRUE;
+ }
+
+ /* get client socket fd */
+ ret = mc_ipc_accept_client_tcp(sock, &client_sock);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ return TRUE;
+ }
+
+ ret = mc_ipc_receive_message_tcp(client_sock, &recv_msg);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_ipc_receive_message_tcp failed [%d]", ret);
+ send_msg = ret;
+ goto ERROR;
+ }
+
+ if (recv_msg.msg_type == MC_MSG_DB_UPDATE) {
+ sql_query = strndup(recv_msg.msg, recv_msg.msg_size);
+ if (sql_query != NULL) {
+ ret = mc_db_util_update_db(mc_svc_data->db_handle, sql_query);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("media_db_update_db error : %d", ret);
+
+ send_msg = ret;
+ MC_SAFE_FREE(sql_query);
+ } else {
+ send_msg = MEDIA_CONTROLLER_ERROR_OUT_OF_MEMORY;
+ }
+ } else if (recv_msg.msg_type == MC_MSG_CLIENT_SET) {
+ /* check privileage */
+ ret = __mc_privilege_ask(client_sock, "mediacontroller::svc", "w");
+ if (ret == MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED) {
+ mc_error("permission is denied!");
+ send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED;
+ goto ERROR;
+ }
+
+ mc_svc_list_t *set_data = (mc_svc_list_t *)malloc(sizeof(mc_svc_list_t));
+ set_data->pid = recv_msg.pid;
+ set_data->data = strdup(recv_msg.msg);
+ mc_svc_data->mc_svc_list = g_list_append(mc_svc_data->mc_svc_list, set_data);
+ } else if (recv_msg.msg_type == MC_MSG_CLIENT_GET) {
+ send_msg = MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED;
+
+ /* check privileage */
+ ret = __mc_privilege_ask(client_sock, "mediacontroller::svc", "r");
+ if (ret == MEDIA_CONTROLLER_ERROR_PERMISSION_DENIED) {
+ mc_error("permission is denied!");
+ goto ERROR;
+ }
+
+ mc_svc_list_t *set_data = NULL;
+ for (i = 0; i < (int)g_list_length(mc_svc_data->mc_svc_list); i++) {
+ set_data = (mc_svc_list_t *)g_list_nth_data(mc_svc_data->mc_svc_list, i);
+ if (set_data != NULL && set_data->data != NULL && strcmp(set_data->data, recv_msg.msg) == 0) {
+ mc_svc_data->mc_svc_list = g_list_remove(mc_svc_data->mc_svc_list, set_data);
+ MC_SAFE_FREE(set_data->data);
+ MC_SAFE_FREE(set_data);
+ send_msg = MEDIA_CONTROLLER_ERROR_NONE;
+ break;
+ }
+ }
+ } else if (recv_msg.msg_type == MC_MSG_SERVER_CONNECTION) {
+ if((recv_msg.msg_size > 0) && (recv_msg.msg != NULL)) {
+ if (strncmp(recv_msg.msg, MC_SERVER_CONNECTION_MSG, recv_msg.msg_size) == 0) {
+ if(g_connection_cnt == -1)
+ g_connection_cnt = 1;
+ else
+ g_connection_cnt++;
+
+ mc_error("[No-error] increased connection count [%d]", g_connection_cnt);
+
+ send_msg = MEDIA_CONTROLLER_ERROR_NONE;
+ } else {
+ mc_error("Wrong message!");
+ send_msg = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ mc_error("Wrong message!");
+ send_msg = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ } else if (recv_msg.msg_type == MC_MSG_SERVER_DISCONNECTION) {
+ if((recv_msg.msg_size > 0) && (recv_msg.msg != NULL)) {
+ if (strncmp(recv_msg.msg, MC_SERVER_DISCONNECTION_MSG, recv_msg.msg_size) == 0) {
+ g_connection_cnt--;
+ mc_error("[No-error] decreased connection count [%d]", g_connection_cnt);
+
+ // remove resource for disconnected process
+ mc_svc_list_t *set_data = NULL;
+ for (i = (int)(g_list_length(mc_svc_data->mc_svc_list)) - 1; i >= 0; i--) {
+ set_data = (mc_svc_list_t *)g_list_nth_data(mc_svc_data->mc_svc_list, i);
+ if ((set_data != NULL) && (set_data->pid == recv_msg.pid)) {
+ mc_svc_data->mc_svc_list = g_list_remove(mc_svc_data->mc_svc_list, set_data);
+ MC_SAFE_FREE(set_data->data);
+ MC_SAFE_FREE(set_data);
+ }
+ }
+
+ send_msg = MEDIA_CONTROLLER_ERROR_NONE;
+ } else {
+ mc_error("Wrong message!");
+ send_msg = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ mc_error("Wrong message!");
+ send_msg = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ mc_error("Wrong message type!");
+ send_msg = MEDIA_CONTROLLER_ERROR_INVALID_OPERATION;
+ }
+
+ERROR:
+ if (write(client_sock, &send_msg, sizeof(send_msg)) != sizeof(send_msg)) {
+ mc_stderror("send failed");
+ } else {
+ mc_debug("Sent successfully");
+ }
+
+ if (close(client_sock) < 0) {
+ mc_stderror("close failed");
+ }
+
+ return TRUE;
+}
+
+int mc_create_socket_activation(void)
+{
+ return __create_socket_activation();
+}
+
+gboolean mc_svc_thread(void *data)
+{
+ int sockfd = -1;
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ GSource *source = NULL;
+ GIOChannel *channel = NULL;
+ GMainContext *context = NULL;
+ mc_svc_data_t *mc_svc_data = NULL;
+
+ mc_svc_data = (mc_svc_data_t *)g_malloc(sizeof(mc_svc_data_t));
+ if (mc_svc_data == NULL) {
+ mc_error("Failed to allocate svc data");
+ return FALSE;
+ }
+ memset(mc_svc_data, 0, sizeof(mc_svc_data_t));
+
+ /* Create TCP Socket*/
+ ret = mc_ipc_create_server_socket(MC_DB_UPDATE_PORT, &sockfd);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ /* Disconnect DB*/
+ mc_error("Failed to create socket");
+ return FALSE;
+ }
+
+ /* Connect Media DB*/
+ if (mc_db_util_connect(&(mc_svc_data->db_handle)) != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("Failed to connect DB");
+ close(sockfd);
+ return FALSE;
+ }
+
+ /* Destroy tables */
+ if (mc_db_util_delete_whole_server_tables(mc_svc_data->db_handle) != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_db_util_delete_whole_server_tables failed [%d]", ret);
+ }
+
+ /* Create tables */
+ if (mc_db_util_create_tables(mc_svc_data->db_handle) != MEDIA_CONTROLLER_ERROR_NONE) {
+ mc_error("mc_db_util_create_tables failed [%d]", ret);
+ return FALSE;
+ }
+
+ context = g_main_context_new();
+ if (context == NULL) {
+ mc_error("g_main_context_new failed");
+ } else {
+ mc_debug("g_main_context_new success");
+ }
+
+ /*Init main loop*/
+ g_mc_svc_mainloop = g_main_loop_new(context, FALSE);
+
+ /* Create new channel to watch UDP socket */
+ channel = g_io_channel_unix_new(sockfd);
+ source = g_io_create_watch(channel, G_IO_IN);
+
+ /* Set callback to be called when socket is readable */
+ g_source_set_callback(source, (GSourceFunc)_mc_read_service_request_tcp_socket, mc_svc_data, NULL);
+ g_source_attach(source, context);
+
+ g_main_context_push_thread_default(context);
+
+ mc_debug("*******************************************");
+ mc_debug("*** Media Controller Service thread is running ***");
+ mc_debug("*******************************************");
+
+ g_main_loop_run(g_mc_svc_mainloop);
+
+ mc_debug("*** Media Controller Service thread will be closed ***");
+
+ g_io_channel_shutdown(channel, FALSE, NULL);
+ g_io_channel_unref(channel);
+
+ /* Disconnect DB*/
+ mc_db_util_disconnect(mc_svc_data->db_handle);
+
+ if (mc_svc_data->mc_svc_list != NULL) {
+ unsigned int idx = 0;
+
+ for (idx = 0; idx < g_list_length(mc_svc_data->mc_svc_list); idx++) {
+ mc_svc_list_t *set_data = NULL;
+ set_data = (mc_svc_list_t *)g_list_nth_data(mc_svc_data->mc_svc_list, idx);
+ MC_SAFE_FREE(set_data->data);
+ MC_SAFE_FREE(set_data);
+ }
+
+ g_list_free(mc_svc_data->mc_svc_list);
+ }
+
+ MC_SAFE_FREE(mc_svc_data);
+
+ /*close socket*/
+ close(sockfd);
+
+ g_main_loop_unref(g_mc_svc_mainloop);
+
+ return FALSE;
+}
+
+GMainLoop *mc_svc_get_main_loop(void)
+{
+ return g_mc_svc_mainloop;
+}
+
+int mc_svc_get_connection_cnt(void)
+{
+ return g_connection_cnt;
+}
diff --git a/svc/media_controller_svc.h b/svc/media_controller_svc.h
new file mode 100755
index 0000000..709c206
--- /dev/null
+++ b/svc/media_controller_svc.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2011 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.
+*/
+
+#ifndef _MEDIA_CONTROLLER_SVC_H_
+#define _MEDIA_CONTROLLER_SVC_H_
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct {
+ int pid;
+ char *data;
+} mc_svc_list_t;
+
+typedef struct {
+ void *db_handle;
+ void *mc_svc_list;
+} mc_svc_data_t;
+
+int mc_create_socket_activation(void);
+gboolean mc_svc_thread(void *data);
+GMainLoop *mc_svc_get_main_loop(void);
+int mc_svc_get_connection_cnt(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif/* _MEDIA_CONTROLLER_SVC_H_ */
diff --git a/test/client_test/CMakeLists.txt b/test/client_test/CMakeLists.txt
new file mode 100755
index 0000000..938cd60
--- /dev/null
+++ b/test/client_test/CMakeLists.txt
@@ -0,0 +1,20 @@
+SET(fw_test "media-controller-client-test")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_test} REQUIRED glib-2.0)
+
+FOREACH(flag ${${fw_test}_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+ GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+ MESSAGE("${src_name}")
+ ADD_EXECUTABLE(${fw_test} ${src})
+ TARGET_LINK_LIBRARIES(${fw_test} ${fw_name} ${${fw_test}_LDFLAGS})
+ENDFOREACH()
+
+#INSTALL(TARGETS ${fw_test} DESTINATION bin)
diff --git a/test/client_test/media_controller_client_test.c b/test/client_test/media_controller_client_test.c
new file mode 100755
index 0000000..c4a4646
--- /dev/null
+++ b/test/client_test/media_controller_client_test.c
@@ -0,0 +1,661 @@
+/*
+* Copyright (c) 2011 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include <media_controller_client.h>
+#include "media_controller_private.h"
+
+
+#define PACKAGE "media_controller_client_test"
+
+/*===========================================================================================
+| |
+| LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
+| |
+========================================================================================== */
+/*---------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS: |
+---------------------------------------------------------------------------*/
+
+static mc_client_h g_mc_client;
+static char *g_server_name;
+
+static mc_playback_states_e g_playback_state;
+
+GMainLoop *mainloop = NULL;
+
+#define MAX_STRING_LEN 2048
+
+/*---------------------------------------------------------------------------
+| LOCAL CONSTANT DEFINITIONS: |
+---------------------------------------------------------------------------*/
+#define DEFAULT_SERVICE "com.samsung.mcontroller_service"
+
+enum {
+ CURRENT_STATE_MAIN_MENU,
+ CURRENT_STATE_INFORMATION_GET_MENU,
+};
+
+enum {
+ CURRENT_STATE_INFORMATION_GET_MODE,
+ CURRENT_STATE_INFORMATION_GET_METADATA,
+};
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS: |
+---------------------------------------------------------------------------*/
+int g_menu_state = CURRENT_STATE_MAIN_MENU;
+int g_menu_information_state = CURRENT_STATE_INFORMATION_GET_MODE;
+
+/*---------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------*/
+
+void _mc_server_state_updated_cb(const char *server_name, mc_server_state_e state, void *user_data)
+{
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+ mc_debug("[Client:%s] Server state(%d) updated from server[%s]", _client->client_name, state, server_name);
+}
+
+void _mc_playback_updated_cb(const char *server_name, mc_playback_h playback, void *user_data)
+{
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+ unsigned long long position = 0;
+ mc_playback_states_e playback_state = MC_PLAYBACK_STATE_NONE;
+
+ mc_client_get_playback_position(playback, &position);
+ mc_client_get_playback_state(playback, &playback_state);
+
+ mc_debug("[Client:%s] Playback updated from server[%s] playback_state[%d] position[%lld]", _client->client_name, server_name, playback_state, position);
+}
+
+void _mc_metadata_updated_cb(const char *server_name, mc_metadata_h metadata, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int idx = 0;
+ char *str_val = NULL;
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+ mc_debug("[Client:%s] Metadata updated from server[%s] ", _client->client_name, server_name);
+
+ for (idx = 0; idx <= MC_META_MEDIA_PICTURE; idx++) {
+ ret = mc_client_get_metadata(metadata, idx, &str_val);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("Fail to mc_client_get_metadata");
+ mc_debug("metadata [%d] val [%s]\n", idx, str_val);
+
+ if (str_val)
+ g_free(str_val);
+ }
+}
+
+void _mc_shuffle_mode_updated_cb(const char *server_name, mc_shuffle_mode_e mode, void *user_data)
+{
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+ mc_debug("[Client:%s] Shuffle mode(%d) updated from server[%s]", _client->client_name, mode, server_name);
+}
+
+void _mc_repeat_mode_updated_cb(const char *server_name, mc_repeat_mode_e mode, void *user_data)
+{
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+ mc_debug("[Client:%s] Repeat mode(%d) updated from server[%s]", _client->client_name, mode, server_name);
+}
+
+bool _mc_activated_server_cb(const char *server_name, void *user_data)
+{
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+ mc_debug("[Client:%s] Activated server_name: %s", _client->client_name, server_name);
+ return TRUE;
+}
+
+void _mc_command_reply_received_cb(const char *server_name, int result_code, bundle *data, void *user_data)
+{
+ char *value = NULL;
+ media_controller_client_s *_client = (media_controller_client_s *)g_mc_client;
+
+ if (data)
+ bundle_get_str(data, "key1", &value);
+
+ mc_debug("[Client:%s] Command Reply (key1: %s)received from server[%s] result code[%d]", _client->client_name, value, server_name, result_code);
+}
+
+static gboolean _create()
+{
+ g_print("== create \n");
+ int ret;
+
+ ret = mc_client_create(&g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to create media contoller client");
+ return FALSE;
+ }
+ g_print("== success create \n");
+
+ return TRUE;
+}
+
+static gboolean _foreach()
+{
+ g_print("== create \n");
+ int ret;
+
+ ret = mc_client_foreach_server(g_mc_client, _mc_activated_server_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to foreach media contoller client");
+ return FALSE;
+ }
+ g_print("== success create \n");
+
+ return TRUE;
+}
+
+static gboolean _set()
+{
+ g_print("== set default callback \n");
+ int ret = TRUE;
+
+ ret = mc_client_set_server_update_cb(g_mc_client, _mc_server_state_updated_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set param and initialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_set_playback_update_cb(g_mc_client, _mc_playback_updated_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set param and initialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_set_metadata_update_cb(g_mc_client, _mc_metadata_updated_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set param and initialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_set_shuffle_mode_update_cb(g_mc_client, _mc_shuffle_mode_updated_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set param and initialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_set_repeat_mode_update_cb(g_mc_client, _mc_repeat_mode_updated_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set param and initialize %d", ret);
+ return FALSE;
+ }
+
+ g_print("==\n");
+
+ return ret;
+}
+
+static gboolean _unset()
+{
+ g_print("== unset callback \n");
+ int ret;
+
+ ret = mc_client_unset_server_update_cb(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to deinitialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_unset_playback_update_cb(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to deinitialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_unset_metadata_update_cb(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to deinitialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_unset_shuffle_mode_update_cb(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to deinitialize %d", ret);
+ return FALSE;
+ }
+
+ ret = mc_client_unset_repeat_mode_update_cb(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to deinitialize %d", ret);
+ return FALSE;
+ }
+
+ g_print("== success destroy \n");
+
+ return TRUE;
+}
+
+static gboolean _get_info(int type)
+{
+ g_print("== get information \n");
+ int ret;
+ mc_server_state_e server_state;
+ mc_playback_h playback;
+ mc_playback_states_e playback_state;
+ unsigned long long playback_position;
+ mc_metadata_h metadata;
+ char *metadata_value;
+ mc_shuffle_mode_e shuffle_mode;
+ mc_repeat_mode_e repeate_mode;
+
+ switch (type) {
+ case 1:
+ ret = mc_client_get_latest_server_info(g_mc_client, &g_server_name, &server_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get latest server info");
+ return FALSE;
+ }
+ g_print("get server name: %s, state: %d", g_server_name, server_state);
+ break;
+ case 2:
+ ret = mc_client_get_server_playback_info(g_mc_client, g_server_name, &playback);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get playback info");
+ return FALSE;
+ }
+ ret = mc_client_get_playback_state(playback, &playback_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get playback state");
+ }
+ ret = mc_client_get_playback_position(playback, &playback_position);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get playback position");
+ }
+ g_print("playback state: %d, position: %lld", playback_state, playback_position);
+
+ ret = mc_client_destroy_playback(playback);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to destroy playback");
+ return FALSE;
+ }
+ break;
+ case 3:
+ ret = mc_client_get_server_metadata(g_mc_client, g_server_name, &metadata);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get metadata");
+ return FALSE;
+ }
+ ret = mc_client_get_metadata(metadata, MC_META_MEDIA_TITLE, &metadata_value);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get infot");
+ }
+ g_print("metadata title: %s", metadata_value);
+
+ ret = mc_client_destroy_metadata(metadata);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to destroy metadata");
+ return FALSE;
+ }
+ free(metadata_value);
+ break;
+ case 4:
+ ret = mc_client_get_server_shuffle_mode(g_mc_client, g_server_name, &shuffle_mode);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get infot");
+ return FALSE;
+ }
+ g_print("shuffle mode: %d", shuffle_mode);
+ break;
+ case 5:
+ ret = mc_client_get_server_repeat_mode(g_mc_client, g_server_name, &repeate_mode);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to get infot");
+ return FALSE;
+ }
+ g_print("repeate mode: %d", repeate_mode);
+ break;
+ default:
+ g_print("== unknown type!\n");
+ return TRUE;
+ }
+
+ g_print("== success get information \n");
+
+ return TRUE;
+}
+
+static gboolean _send()
+{
+ g_print("== send command to latest server \n");
+ int ret;
+
+ if (g_playback_state == MC_PLAYBACK_STATE_PLAYING)
+ g_playback_state = MC_PLAYBACK_STATE_STOPPED;
+ else
+ g_playback_state = MC_PLAYBACK_STATE_PLAYING;
+ ret = mc_client_send_playback_state_command(g_mc_client, g_server_name, g_playback_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to send playback state command %d", ret);
+ return FALSE;
+ }
+
+ struct timespec reqtime;
+ reqtime.tv_sec = 0;
+ reqtime.tv_nsec = 500000000;
+ nanosleep(&reqtime, NULL);
+
+ bundle *bundle_data = bundle_create();
+ bundle_add_str(bundle_data, "key1", "val1");
+ bundle_add_str(bundle_data, "key2", "val2");
+ bundle_add_str(bundle_data, "key3", "val3");
+ bundle_add_str(bundle_data, "key4", "val4");
+
+ ret = mc_client_send_custom_command(g_mc_client, g_server_name, "Custom Command", bundle_data, _mc_command_reply_received_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ bundle_free(bundle_data);
+ mc_error("Fail to send custom command %d", ret);
+ return FALSE;
+ }
+ bundle_free(bundle_data);
+
+ g_print("== success send command \n");
+
+ return TRUE;
+}
+
+static gboolean _destroy()
+{
+ g_print("== destroy \n");
+ int ret;
+
+ ret = mc_client_destroy(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to destroy media contoller client");
+ return FALSE;
+ }
+
+ g_print("== success destroy \n");
+ g_mc_client = NULL;
+ return TRUE;
+}
+
+
+/***************************************************************/
+/** Testsuite */
+/***************************************************************/
+void quit(void)
+{
+ if (g_mc_client != NULL)
+ _destroy();
+
+ g_main_loop_quit(mainloop);
+}
+
+void reset_current_information_menu_state()
+{
+ g_menu_information_state = CURRENT_STATE_INFORMATION_GET_MODE;
+ return;
+}
+
+void reset_current_menu_state()
+{
+ g_menu_state = CURRENT_STATE_MAIN_MENU;
+ return;
+}
+
+static void display_information_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media controller test(client): Get info menu\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. get latest server info \n");
+ g_print("2. get latest server playback \n");
+ g_print("3. get latest server metadata \n");
+ g_print("4. get latest server shuffle mode \n");
+ g_print("5. get latest server repeate moder \n");
+ g_print("0. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+
+}
+
+static void display_main_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media controller test(client): Main menu v0.1\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. create media controller client \n");
+ g_print("2. foreach server list \n");
+ g_print("3. set default callback \n");
+ g_print("4. unset default callback \n");
+ g_print("5. get information from server \n");
+ g_print("6. send command \n");
+ g_print("9. destroy media controller client \n");
+ g_print("0. quit \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+
+}
+
+static void display_menu(void)
+{
+ if (g_menu_state == CURRENT_STATE_MAIN_MENU) {
+ display_main_menu();
+ } else if (g_menu_state == CURRENT_STATE_INFORMATION_GET_MENU) {
+ display_information_menu();
+ } else {
+ g_print("*** Unknown status.\n");
+ }
+}
+
+void _interpret_information_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if (len == 1) {
+ if (!strncmp(cmd, "1", len)) {
+ _get_info(1);
+ } else if (!strncmp(cmd, "2", len)) {
+ _get_info(2);
+ } else if (!strncmp(cmd, "3", len)) {
+ _get_info(3);
+ } else if (!strncmp(cmd, "4", len)) {
+ _get_info(4);
+ } else if (!strncmp(cmd, "5", len)) {
+ _get_info(5);
+ } else if (!strncmp(cmd, "0", len)) {
+ reset_current_menu_state();
+ }
+ } else {
+ g_print("wrong command\n");
+ }
+}
+
+void _interpret_main_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if (len == 1) {
+ if (!strncmp(cmd, "1", len)) {
+ _create();
+ } else if (!strncmp(cmd, "2", len)) {
+ _foreach();
+ } else if (!strncmp(cmd, "3", len)) {
+ _set();
+ } else if (!strncmp(cmd, "4", len)) {
+ _unset();
+ } else if (!strncmp(cmd, "5", len)) {
+ g_menu_state = CURRENT_STATE_INFORMATION_GET_MENU;
+ } else if (!strncmp(cmd, "6", len)) {
+ _send();
+ } else if (!strncmp(cmd, "9", len)) {
+ _destroy();
+ } else if (!strncmp(cmd, "0", len)) {
+ quit();
+ }
+ } else {
+ g_print("wrong command\n");
+ }
+}
+
+static void interpret_cmd(char *cmd)
+{
+ switch (g_menu_state) {
+ case CURRENT_STATE_MAIN_MENU:
+ _interpret_main_menu(cmd);
+ display_menu();
+ break;
+ case CURRENT_STATE_INFORMATION_GET_MENU:
+ _interpret_information_menu(cmd);
+ display_menu();
+ break;
+ default:
+ g_print("Invalid command\n");
+ }
+}
+
+gboolean input(GIOChannel *channel)
+{
+ gchar buf[MAX_STRING_LEN];
+ gsize read;
+ GError *error = NULL;
+
+ g_io_channel_read_chars(channel, buf, MAX_STRING_LEN, &read, &error);
+
+ buf[read] = '\0';
+ g_strstrip(buf);
+ interpret_cmd(buf);
+
+ return TRUE;
+
+}
+
+int client_sequential_test(void)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ char *server_name = NULL;
+ mc_server_state_e server_state = MC_SERVER_STATE_NONE;
+ mc_shuffle_mode_e shuffle_mode = MC_SHUFFLE_MODE_OFF;
+ mc_repeat_mode_e repeat_mode = MC_REPEAT_MODE_OFF;
+ mc_metadata_h metadata = NULL;
+ mc_playback_h playback = NULL;
+ char *str_val = NULL;
+ int idx = 0;
+ mc_playback_states_e playback_state = MC_PLAYBACK_STATE_REWIND;
+ unsigned long long playback_position = 0;
+
+ /*Create Client*/
+ ret = mc_client_create(&g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_client_create");
+ return ret;
+ }
+
+ /*Get Latest Server Info*/
+ ret = mc_client_get_latest_server_info(g_mc_client, &server_name, &server_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_client_create");
+ return ret;
+ }
+
+ g_print("latest server name[%s] server_state[%d]\n", server_name, server_state);
+
+ if (server_name == NULL)
+ return MEDIA_CONTROLLER_ERROR_NONE;
+
+ /*Get Foreach server*/
+ ret = mc_client_foreach_server(g_mc_client, _mc_activated_server_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_foreach_server\n");
+
+ /*Get Playback Info*/
+ ret = mc_client_get_server_playback_info(g_mc_client, server_name, &playback);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_server_playback_info\n");
+
+ ret = mc_client_get_playback_state(playback, &playback_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_playback_state\n");
+
+ ret = mc_client_get_playback_position(playback, &playback_position);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_server_playback_info\n");
+
+ g_print("playback_state[%d] playback_position[%lld]\n", playback_state, playback_position);
+
+ ret = mc_client_destroy_playback(playback);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_destroy_playback\n");
+
+ /*Get Metadata*/
+ ret = mc_client_get_server_metadata(g_mc_client, server_name, &metadata);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_server_metadata\n");
+
+ for (idx = 0; idx <= MC_META_MEDIA_PICTURE; idx++) {
+ ret = mc_client_get_metadata(metadata, idx, &str_val);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_metadata\n");
+ g_print("metadata [%d] val [%s]\n", idx, str_val);
+ if (str_val)
+ g_free(str_val);
+ }
+
+ ret = mc_client_destroy_metadata(metadata);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_destroy_metadata\n");
+
+ /*Get Shuffle / Repeat mode*/
+ ret = mc_client_get_server_shuffle_mode(g_mc_client, server_name, &shuffle_mode);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_server_shuffle_mode\n");
+
+ ret = mc_client_get_server_repeat_mode(g_mc_client, server_name, &repeat_mode);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ g_print("Fail to mc_client_get_server_repeat_mode\n");
+
+ g_print("shuffle_mode[%d] repeat_mode[%d]\n", shuffle_mode, repeat_mode);
+
+ g_free(server_name);
+
+ ret = mc_client_destroy(g_mc_client);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_client_create\n");
+ return ret;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int main(int argc, char **argv)
+{
+ GIOChannel *stdin_channel = NULL;
+ stdin_channel = g_io_channel_unix_new(0);
+ g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, NULL);
+
+ g_playback_state = MC_PLAYBACK_STATE_PLAYING;
+
+ mainloop = g_main_loop_new(NULL, FALSE);
+
+ display_menu();
+
+ g_main_loop_run(mainloop);
+ g_main_loop_unref(mainloop);
+
+ return 0;
+}
diff --git a/test/server_test/CMakeLists.txt b/test/server_test/CMakeLists.txt
new file mode 100755
index 0000000..47b9f34
--- /dev/null
+++ b/test/server_test/CMakeLists.txt
@@ -0,0 +1,20 @@
+SET(fw_test "media-controller-server-test")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_test} REQUIRED glib-2.0)
+
+FOREACH(flag ${${fw_test}_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+ GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+ MESSAGE("${src_name}")
+ ADD_EXECUTABLE(${fw_test} ${src})
+ TARGET_LINK_LIBRARIES(${fw_test} ${fw_name} ${${fw_test}_LDFLAGS})
+ENDFOREACH()
+
+#INSTALL(TARGETS ${fw_test} DESTINATION bin)
diff --git a/test/server_test/media_controller_server_test.c b/test/server_test/media_controller_server_test.c
new file mode 100755
index 0000000..083cd5d
--- /dev/null
+++ b/test/server_test/media_controller_server_test.c
@@ -0,0 +1,557 @@
+/*
+* Copyright (c) 2011 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include <media_controller_client.h>
+#include "media_controller_private.h"
+
+
+#define PACKAGE "media_controller_client_test"
+
+/*===========================================================================================
+| |
+| LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE |
+| |
+========================================================================================== */
+/*---------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS: |
+---------------------------------------------------------------------------*/
+
+static mc_client_h g_mc_server;
+static int g_metadata_type;
+static mc_shuffle_mode_e g_shuffle_mode;
+static mc_repeat_mode_e g_repeat_mode;
+
+GMainLoop *mainloop = NULL;
+
+#define MAX_STRING_LEN 2048
+
+/*---------------------------------------------------------------------------
+| LOCAL CONSTANT DEFINITIONS: |
+---------------------------------------------------------------------------*/
+/*#define DEFAULT_SERVICE "com.samsung.mcontroller_service" */
+
+enum {
+ CURRENT_STATE_MAIN_MENU,
+ CURRENT_STATE_INFORMATION_SET_MENU,
+ CURRENT_STATE_INFORMATION_UPDATE_MENU,
+};
+
+enum {
+ CURRENT_STATE_SET_MODE_NONE,
+ CURRENT_STATE_SET_PLAYBACK_STATE,
+ CURRENT_STATE_SET_PLAYBACK_POSITION,
+ CURRENT_STATE_SET_METADATA_NAME,
+ CURRENT_STATE_SET_METADATA_VALUE,
+};
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS: |
+---------------------------------------------------------------------------*/
+int g_menu_state = CURRENT_STATE_MAIN_MENU;
+int g_menu_set_state = CURRENT_STATE_SET_MODE_NONE;
+
+/*---------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------*/
+
+void __playback_state_command_received_cb(const char *client_name, mc_playback_states_e state, void *user_data)
+{
+ media_controller_server_s *mc_server = (media_controller_server_s *)g_mc_server;
+ mc_debug("[%s] recieved playback state:[%d] from [%s]", mc_server->server_name, state, client_name);
+}
+
+void __custom_command_received_cb(const char *client_name, const char *command, bundle *data, void *user_data)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ media_controller_server_s *mc_server = (media_controller_server_s *)g_mc_server;
+
+ char *bundle_data = NULL;
+ char *get_value1 = NULL;
+ char *get_value2 = NULL;
+ char *get_value3 = NULL;
+ char *get_value4 = NULL;
+
+ if (data) {
+ bundle_get_str(data, "key1", &get_value1);
+ bundle_get_str(data, "key2", &get_value2);
+ bundle_get_str(data, "key3", &get_value3);
+ bundle_get_str(data, "key4", &get_value4);
+
+ bundle_data = g_strdup_printf("%s, %s, %s, %s", get_value1, get_value2, get_value3, get_value4);
+ }
+
+ mc_debug("[%s] recieved command:[%s] from [%s]", mc_server->server_name, command, client_name);
+ mc_debug("[%s] recieved bundle:[%s] from [%s]", mc_server->server_name, bundle_data, client_name);
+
+ bundle *bundle_reply = bundle_create();
+ bundle_add_str(bundle_reply, "key1", "result1");
+ bundle_add_str(bundle_reply, "key2", "result2");
+ bundle_add_str(bundle_reply, "key3", "result3");
+ bundle_add_str(bundle_reply, "key4", "result4");
+
+ ret = mc_server_send_command_reply(g_mc_server, client_name, 0, bundle_reply);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE)
+ mc_error("Fail to mc_server_send_command_reply");
+
+ bundle_free(bundle_reply);
+}
+
+static gboolean _create()
+{
+ g_print("== create \n");
+ int ret;
+
+ ret = mc_server_create(&g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to create media contoller server");
+ return FALSE;
+ }
+ g_print("== success create \n");
+
+ return TRUE;
+}
+
+static gboolean _set_cb()
+{
+ g_print("== set default callback for commands \n");
+ int ret;
+
+ ret = mc_server_set_playback_state_command_received_cb(g_mc_server, __playback_state_command_received_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to create media contoller server");
+ return FALSE;
+ }
+
+ ret = mc_server_set_custom_command_received_cb(g_mc_server, __custom_command_received_cb, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to create media contoller server");
+ return FALSE;
+ }
+
+ g_print("== success set default callback \n");
+
+ return TRUE;
+}
+
+static gboolean _set_info(int type, char *cmd)
+{
+ g_print("== get information \n");
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+ int playback_state = 0;
+ unsigned long long playback_position;
+ char *metadata = NULL;
+
+ switch (type) {
+ case CURRENT_STATE_SET_PLAYBACK_STATE:
+ playback_state = atoi(cmd);
+ ret = mc_server_set_playback_state(g_mc_server, playback_state);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set playback state");
+ return FALSE;
+ }
+ g_print("set state: %d", playback_state);
+ break;
+ case CURRENT_STATE_SET_PLAYBACK_POSITION:
+ playback_position = atoi(cmd);
+ ret = mc_server_set_playback_position(g_mc_server, playback_position);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set playback position");
+ return FALSE;
+ }
+ g_print("set position: %lld", playback_position);
+ break;
+ case CURRENT_STATE_SET_METADATA_NAME:
+ g_metadata_type = atoi(cmd);
+ g_print("set metadata name: %d", g_metadata_type);
+ break;
+ case CURRENT_STATE_SET_METADATA_VALUE:
+ metadata = strdup(cmd);
+ ret = mc_server_set_metadata(g_mc_server, g_metadata_type, metadata);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to set metadata");
+ if(metadata != NULL)
+ free(metadata);
+ return FALSE;
+ }
+ g_print("set metadata value: %s", metadata);
+ if(metadata != NULL)
+ free(metadata);
+ break;
+ default:
+ g_print(" == unknown type!\n");
+ return TRUE;
+ }
+
+ g_print(" == success get information \n");
+
+ return TRUE;
+}
+
+static gboolean _update_info(int type)
+{
+ g_print(" == update information \n");
+ int ret;
+
+ switch (type) {
+ case 1:
+ ret = mc_server_update_playback_info(g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to update playback info err=%d", ret);
+ return FALSE;
+ }
+ break;
+ case 2:
+ ret = mc_server_update_metadata(g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to update metadata err=%d", ret);
+ return FALSE;
+ }
+ break;
+ case 3:
+ if (g_shuffle_mode == MC_SHUFFLE_MODE_OFF)
+ g_shuffle_mode = MC_SHUFFLE_MODE_ON;
+ else
+ g_shuffle_mode = MC_SHUFFLE_MODE_OFF;
+ ret = mc_server_update_shuffle_mode(g_mc_server, g_shuffle_mode);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to update shuffle mode err=%d", ret);
+ return FALSE;
+ }
+ break;
+ case 4:
+ if (g_repeat_mode == MC_REPEAT_MODE_OFF)
+ g_repeat_mode = MC_REPEAT_MODE_ON;
+ else
+ g_repeat_mode = MC_REPEAT_MODE_OFF;
+ ret = mc_server_update_repeat_mode(g_mc_server, g_repeat_mode);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to update repeat mode err=%d", ret);
+ return FALSE;
+ }
+ break;
+ default:
+ g_print(" == unknown type!\n");
+ return TRUE;
+ }
+
+ g_print(" == success update information \n");
+
+ return TRUE;
+}
+
+static gboolean _destroy()
+{
+ g_print("== destroy \n");
+ int ret;
+
+ ret = mc_server_destroy(g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to destroy media contoller server");
+ return FALSE;
+ }
+
+ g_print("== success destroy \n");
+ g_mc_server = NULL;
+ return TRUE;
+}
+
+
+/***************************************************************/
+/** Testsuite */
+/***************************************************************/
+void quit(void)
+{
+ if (g_mc_server != NULL)
+ _destroy();
+
+ g_main_loop_quit(mainloop);
+}
+
+void reset_current_set_menu_state()
+{
+ g_menu_set_state = CURRENT_STATE_SET_MODE_NONE;
+ return;
+}
+
+void reset_current_menu_state()
+{
+ g_menu_state = CURRENT_STATE_MAIN_MENU;
+ return;
+}
+
+static void display_update_info_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media controller test(server): Update info menu\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. update server playback \n");
+ g_print("2. update server metadata \n");
+ g_print("3. update server shuffle mode \n");
+ g_print("4. update server repeate moder \n");
+ g_print("0. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+
+}
+
+static void display_set_info_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media controller test(server): Set info menu\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. set server playback state\n");
+ g_print("2. set server playback position \n");
+ g_print("3. set server metadata name\n");
+ g_print("4. set server metadata value\n");
+ g_print("0. back \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+
+}
+
+static void display_main_menu(void)
+{
+ g_print("\n");
+ g_print("====================================================\n");
+ g_print(" media controller test(server): Main menu v0.1\n");
+ g_print("----------------------------------------------------\n");
+ g_print("1. create media controller server \n");
+ g_print("2. set default command callback \n");
+ g_print("3. set information to client \n");
+ g_print("4. update information to client \n");
+ g_print("9. destroy media controller server \n");
+ g_print("0. quit \n");
+ g_print("----------------------------------------------------\n");
+ g_print("====================================================\n");
+
+}
+
+static void display_menu(void)
+{
+ if (g_menu_state == CURRENT_STATE_MAIN_MENU) {
+ display_main_menu();
+ } else if (g_menu_state == CURRENT_STATE_INFORMATION_SET_MENU) {
+ display_set_info_menu();
+ } else if (g_menu_state == CURRENT_STATE_INFORMATION_UPDATE_MENU) {
+ display_update_info_menu();
+ } else {
+ g_print("*** Unknown status.\n");
+ }
+}
+
+void _interpret_update_info_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if (len == 1) {
+ if (!strncmp(cmd, "1", len)) {
+ _update_info(1);
+ } else if (!strncmp(cmd, "2", len)) {
+ _update_info(2);
+ } else if (!strncmp(cmd, "3", len)) {
+ _update_info(3);
+ } else if (!strncmp(cmd, "4", len)) {
+ _update_info(4);
+ } else if (!strncmp(cmd, "0", len)) {
+ reset_current_menu_state();
+ }
+ } else {
+ g_print("wrong command\n");
+ }
+}
+
+void _interpret_set_info_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if (len == 1) {
+ if (!strncmp(cmd, "1", len)) {
+ g_menu_set_state = CURRENT_STATE_SET_PLAYBACK_STATE;
+ } else if (!strncmp(cmd, "2", len)) {
+ g_menu_set_state = CURRENT_STATE_SET_PLAYBACK_POSITION;
+ } else if (!strncmp(cmd, "3", len)) {
+ g_menu_set_state = CURRENT_STATE_SET_METADATA_NAME;
+ } else if (!strncmp(cmd, "4", len)) {
+ g_menu_set_state = CURRENT_STATE_SET_METADATA_VALUE;
+ } else if (!strncmp(cmd, "0", len)) {
+ reset_current_menu_state();
+ display_menu();
+ }
+ } else {
+ g_print("wrong command\n");
+ }
+}
+
+void _interpret_main_menu(char *cmd)
+{
+ int len = strlen(cmd);
+
+ if (len == 1) {
+ if (!strncmp(cmd, "1", len)) {
+ _create();
+ } else if (!strncmp(cmd, "2", len)) {
+ _set_cb();
+ } else if (!strncmp(cmd, "3", len)) {
+ g_menu_state = CURRENT_STATE_INFORMATION_SET_MENU;
+ } else if (!strncmp(cmd, "4", len)) {
+ g_menu_state = CURRENT_STATE_INFORMATION_UPDATE_MENU;
+ } else if (!strncmp(cmd, "9", len)) {
+ _destroy();
+ } else if (!strncmp(cmd, "0", len)) {
+ quit();
+ }
+ } else {
+ g_print("wrong command\n");
+ }
+}
+
+static void interpret_cmd(char *cmd)
+{
+ switch (g_menu_state) {
+ case CURRENT_STATE_MAIN_MENU:
+ _interpret_main_menu(cmd);
+ display_menu();
+ break;
+ case CURRENT_STATE_INFORMATION_SET_MENU:
+ switch (g_menu_set_state) {
+ case CURRENT_STATE_SET_MODE_NONE:
+ _interpret_set_info_menu(cmd);
+ break;
+ case CURRENT_STATE_SET_PLAYBACK_STATE:
+ case CURRENT_STATE_SET_PLAYBACK_POSITION:
+ case CURRENT_STATE_SET_METADATA_NAME:
+ case CURRENT_STATE_SET_METADATA_VALUE:
+ _set_info(g_menu_set_state, cmd);
+ reset_current_set_menu_state();
+ display_menu();
+ default:
+ break;
+ }
+ break;
+ case CURRENT_STATE_INFORMATION_UPDATE_MENU:
+ _interpret_update_info_menu(cmd);
+ display_menu();
+ break;
+ default:
+ g_print("Invalid command\n");
+ }
+}
+
+gboolean input(GIOChannel *channel)
+{
+ gchar buf[MAX_STRING_LEN];
+ gsize read;
+ GError *error = NULL;
+
+ g_io_channel_read_chars(channel, buf, MAX_STRING_LEN, &read, &error);
+
+ buf[read] = '\0';
+ g_strstrip(buf);
+ interpret_cmd(buf);
+
+ return TRUE;
+
+}
+
+int server_sequential_test(void)
+{
+ int ret = MEDIA_CONTROLLER_ERROR_NONE;
+
+ ret = mc_server_create(&g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_create\n");
+ return ret;
+ }
+
+ ret = mc_server_set_playback_state(g_mc_server, MC_PLAYBACK_STATE_PLAYING);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_set_playback_state\n");
+ return ret;
+ }
+
+ ret = mc_server_set_playback_position(g_mc_server, 10000);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_set_playback_state\n");
+ return ret;
+ }
+
+ ret = mc_server_update_playback_info(g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_update_playback_info\n");
+ /*return ret; */
+ }
+
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_TITLE, "media_title");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_ARTIST, "media_artist");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_ALBUM, "media_album");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_AUTHOR, "media_author");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_GENRE, "media_genre");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_DURATION, "200");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_DATE, "media_date");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_COPYRIGHT, "media_copyright");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_DESCRIPTION, "media_description");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_TRACK_NUM, "media_track_num 3/10");
+ ret = mc_server_set_metadata(g_mc_server, MC_META_MEDIA_PICTURE, "media_picture_path");
+ ret = mc_server_update_metadata(g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_update_metadata\n");
+ /*return ret; */
+ }
+
+ ret = mc_server_update_shuffle_mode(g_mc_server, MC_SHUFFLE_MODE_ON);
+ ret = mc_server_update_repeat_mode(g_mc_server, MC_REPEAT_MODE_ON);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_update_repeat_mode\n");
+ return ret;
+ }
+
+ ret = mc_server_destroy(g_mc_server);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ g_print("Fail to mc_server_destroy");
+ return ret;
+ }
+
+ return MEDIA_CONTROLLER_ERROR_NONE;
+}
+
+int main(int argc, char **argv)
+{
+ GIOChannel *stdin_channel;
+ stdin_channel = g_io_channel_unix_new(0);
+ g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, NULL);
+
+ g_shuffle_mode = MC_SHUFFLE_MODE_OFF;
+ g_repeat_mode = MC_REPEAT_MODE_OFF;
+
+ mainloop = g_main_loop_new(NULL, FALSE);
+
+ display_menu();
+
+ g_main_loop_run(mainloop);
+ g_main_loop_unref(mainloop);
+
+ return 0;
+}