--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+# project
+SET(prefix "/usr")
+SET(version "0.0.1")
+SET(submodule "resource-center-api")
+
+# for package file
+SET(dependents dlog gio-2.0 glib-2.0 resource-manager resource-information)
+
+SET(fw_name "${submodule}")
+
+PROJECT(${fw_name})
+
+SET(CMAKE_INSTALL_PREFIX ${prefix})
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(VERSION ${version})
+
+SET(INC_DIR include)
+SET(INTERNAL_INT_DIR include_internal)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${fw_name} REQUIRED ${dependents})
+FOREACH(flag ${${fw_name}_CXXFLAGS})
+ SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+INCLUDE_DIRECTORIES(${INC_DIR})
+INCLUDE_DIRECTORIES(${INTERNAL_INT_DIR})
+INCLUDE_DIRECTORIES(${${fw_name}_INCLUDE_DIRS})
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -fPIC -Wall -Werror")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+
+IF("${ARCH}" STREQUAL "arm")
+ ADD_DEFINITIONS("-DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DTIZEN_DEBUG")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/${LIB_DIR}")
+
+aux_source_directory(src SOURCES)
+ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+
+TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS})
+
+SET_TARGET_PROPERTIES(${fw_name}
+ PROPERTIES
+ VERSION ${FULLVER}
+ SOVERSION ${MAJORVER}
+ CLEAN_DIRECT_OUTPUT 1
+)
+
+INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_DIR})
+INSTALL(
+ DIRECTORY ${INC_DIR}/ DESTINATION include
+ FILES_MATCHING
+ PATTERN "*_private.h" EXCLUDE
+ PATTERN "${INC_DIR}/*.h"
+ PATTERN "${INTERNAL_INT_DIR}/*.h"
+ )
+
+SET(PC_NAME ${fw_name})
+SET(PC_LDFLAGS -l${fw_name})
+
+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_DIR}/pkgconfig)
+
+ADD_SUBDIRECTORY(test)
+
+IF(TOMATO STREQUAL "y")
+ ADD_SUBDIRECTORY(ut)
+ENDIF(TOMATO STREQUAL "y")
+
+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)
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.\r
+\r
+ Apache License\r
+ Version 2.0, January 2004\r
+ http://www.apache.org/licenses/\r
+\r
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+ 1. Definitions.\r
+\r
+ "License" shall mean the terms and conditions for use, reproduction,\r
+ and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+ "Licensor" shall mean the copyright owner or entity authorized by\r
+ the copyright owner that is granting the License.\r
+\r
+ "Legal Entity" shall mean the union of the acting entity and all\r
+ other entities that control, are controlled by, or are under common\r
+ control with that entity. For the purposes of this definition,\r
+ "control" means (i) the power, direct or indirect, to cause the\r
+ direction or management of such entity, whether by contract or\r
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+ outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+ "You" (or "Your") shall mean an individual or Legal Entity\r
+ exercising permissions granted by this License.\r
+\r
+ "Source" form shall mean the preferred form for making modifications,\r
+ including but not limited to software source code, documentation\r
+ source, and configuration files.\r
+\r
+ "Object" form shall mean any form resulting from mechanical\r
+ transformation or translation of a Source form, including but\r
+ not limited to compiled object code, generated documentation,\r
+ and conversions to other media types.\r
+\r
+ "Work" shall mean the work of authorship, whether in Source or\r
+ Object form, made available under the License, as indicated by a\r
+ copyright notice that is included in or attached to the work\r
+ (an example is provided in the Appendix below).\r
+\r
+ "Derivative Works" shall mean any work, whether in Source or Object\r
+ form, that is based on (or derived from) the Work and for which the\r
+ editorial revisions, annotations, elaborations, or other modifications\r
+ represent, as a whole, an original work of authorship. For the purposes\r
+ of this License, Derivative Works shall not include works that remain\r
+ separable from, or merely link (or bind by name) to the interfaces of,\r
+ the Work and Derivative Works thereof.\r
+\r
+ "Contribution" shall mean any work of authorship, including\r
+ the original version of the Work and any modifications or additions\r
+ to that Work or Derivative Works thereof, that is intentionally\r
+ submitted to Licensor for inclusion in the Work by the copyright owner\r
+ or by an individual or Legal Entity authorized to submit on behalf of\r
+ the copyright owner. For the purposes of this definition, "submitted"\r
+ means any form of electronic, verbal, or written communication sent\r
+ to the Licensor or its representatives, including but not limited to\r
+ communication on electronic mailing lists, source code control systems,\r
+ and issue tracking systems that are managed by, or on behalf of, the\r
+ Licensor for the purpose of discussing and improving the Work, but\r
+ excluding communication that is conspicuously marked or otherwise\r
+ designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+ "Contributor" shall mean Licensor and any individual or Legal Entity\r
+ on behalf of whom a Contribution has been received by Licensor and\r
+ subsequently incorporated within the Work.\r
+\r
+ 2. Grant of Copyright License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ copyright license to reproduce, prepare Derivative Works of,\r
+ publicly display, publicly perform, sublicense, and distribute the\r
+ Work and such Derivative Works in Source or Object form.\r
+\r
+ 3. Grant of Patent License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ (except as stated in this section) patent license to make, have made,\r
+ use, offer to sell, sell, import, and otherwise transfer the Work,\r
+ where such license applies only to those patent claims licensable\r
+ by such Contributor that are necessarily infringed by their\r
+ Contribution(s) alone or by combination of their Contribution(s)\r
+ with the Work to which such Contribution(s) was submitted. If You\r
+ institute patent litigation against any entity (including a\r
+ cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+ or a Contribution incorporated within the Work constitutes direct\r
+ or contributory patent infringement, then any patent licenses\r
+ granted to You under this License for that Work shall terminate\r
+ as of the date such litigation is filed.\r
+\r
+ 4. Redistribution. You may reproduce and distribute copies of the\r
+ Work or Derivative Works thereof in any medium, with or without\r
+ modifications, and in Source or Object form, provided that You\r
+ meet the following conditions:\r
+\r
+ (a) You must give any other recipients of the Work or\r
+ Derivative Works a copy of this License; and\r
+\r
+ (b) You must cause any modified files to carry prominent notices\r
+ stating that You changed the files; and\r
+\r
+ (c) You must retain, in the Source form of any Derivative Works\r
+ that You distribute, all copyright, patent, trademark, and\r
+ attribution notices from the Source form of the Work,\r
+ excluding those notices that do not pertain to any part of\r
+ the Derivative Works; and\r
+\r
+ (d) If the Work includes a "NOTICE" text file as part of its\r
+ distribution, then any Derivative Works that You distribute must\r
+ include a readable copy of the attribution notices contained\r
+ within such NOTICE file, excluding those notices that do not\r
+ pertain to any part of the Derivative Works, in at least one\r
+ of the following places: within a NOTICE text file distributed\r
+ as part of the Derivative Works; within the Source form or\r
+ documentation, if provided along with the Derivative Works; or,\r
+ within a display generated by the Derivative Works, if and\r
+ wherever such third-party notices normally appear. The contents\r
+ of the NOTICE file are for informational purposes only and\r
+ do not modify the License. You may add Your own attribution\r
+ notices within Derivative Works that You distribute, alongside\r
+ or as an addendum to the NOTICE text from the Work, provided\r
+ that such additional attribution notices cannot be construed\r
+ as modifying the License.\r
+\r
+ You may add Your own copyright statement to Your modifications and\r
+ may provide additional or different license terms and conditions\r
+ for use, reproduction, or distribution of Your modifications, or\r
+ for any such Derivative Works as a whole, provided Your use,\r
+ reproduction, and distribution of the Work otherwise complies with\r
+ the conditions stated in this License.\r
+\r
+ 5. Submission of Contributions. Unless You explicitly state otherwise,\r
+ any Contribution intentionally submitted for inclusion in the Work\r
+ by You to the Licensor shall be under the terms and conditions of\r
+ this License, without any additional terms or conditions.\r
+ Notwithstanding the above, nothing herein shall supersede or modify\r
+ the terms of any separate license agreement you may have executed\r
+ with Licensor regarding such Contributions.\r
+\r
+ 6. Trademarks. This License does not grant permission to use the trade\r
+ names, trademarks, service marks, or product names of the Licensor,\r
+ except as required for reasonable and customary use in describing the\r
+ origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+ 7. Disclaimer of Warranty. Unless required by applicable law or\r
+ agreed to in writing, Licensor provides the Work (and each\r
+ Contributor provides its Contributions) on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+ implied, including, without limitation, any warranties or conditions\r
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+ PARTICULAR PURPOSE. You are solely responsible for determining the\r
+ appropriateness of using or redistributing the Work and assume any\r
+ risks associated with Your exercise of permissions under this License.\r
+\r
+ 8. Limitation of Liability. In no event and under no legal theory,\r
+ whether in tort (including negligence), contract, or otherwise,\r
+ unless required by applicable law (such as deliberate and grossly\r
+ negligent acts) or agreed to in writing, shall any Contributor be\r
+ liable to You for damages, including any direct, indirect, special,\r
+ incidental, or consequential damages of any character arising as a\r
+ result of this License or out of the use or inability to use the\r
+ Work (including but not limited to damages for loss of goodwill,\r
+ work stoppage, computer failure or malfunction, or any and all\r
+ other commercial damages or losses), even if such Contributor\r
+ has been advised of the possibility of such damages.\r
+\r
+ 9. Accepting Warranty or Additional Liability. While redistributing\r
+ the Work or Derivative Works thereof, You may choose to offer,\r
+ and charge a fee for, acceptance of support, warranty, indemnity,\r
+ or other liability obligations and/or rights consistent with this\r
+ License. However, in accepting such obligations, You may act only\r
+ on Your own behalf and on Your sole responsibility, not on behalf\r
+ of any other Contributor, and only if You agree to indemnify,\r
+ defend, and hold each Contributor harmless for any liability\r
+ incurred by, or claims asserted against, such Contributor by reason\r
+ of your accepting any such warranty or additional liability.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\r
+ APPENDIX: How to apply the Apache License to your work.\r
+\r
+ To apply the Apache License to your work, attach the following\r
+ boilerplate notice, with the fields enclosed by brackets "[]"\r
+ replaced with your own identifying information. (Don't include\r
+ the brackets!) The text should be enclosed in the appropriate\r
+ comment syntax for the file format. We also recommend that a\r
+ file or class name and description of purpose be included on the\r
+ same "printed page" as the copyright notice for easier\r
+ identification within third-party archives.\r
+\r
+ Copyright [yyyy] [name of copyright owner]\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+\r
+\r
--- /dev/null
+/*
+ * Copyright (c) 2024 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_RESOURCE_CENTER_H__
+#define __TIZEN_RESOURCE_CENTER_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+* @brief resource policy
+*/
+typedef enum{
+ RC_RSC_POLICY_NORMAL = 0, /**< normal policy */
+ RC_RSC_POLICY_N_DECODING_MV,/**< N decoding policy in multiview */
+} rc_rsc_policy_e;
+
+/**
+* @brief video resolution
+*/
+typedef enum {
+ RC_RESOLUTION_FHD = 0, /**< Full HD, up to (1920 * 1088) */
+ RC_RESOLUTION_UHD, /**< UHD, up to (4096 * 2160) */
+ RC_RESOLUTION_8K /**< 8K, up to (7680 * 4320) */
+} rc_resolution_e;
+
+/**
+* @brief video framerate
+*/
+typedef enum {
+ RC_FRAMERATE_30P = 0, /**< 30 fps */
+ RC_FRAMERATE_60P, /**< 60 fps */
+ RC_FRAMERATE_120P /**< 120 fps */
+} rc_framerate_e;
+
+/**
+* @brief player's audio out
+*/
+typedef enum {
+ RC_PLAYER_AUDIO_OUT_NONE = 0, /**< audio out none */
+ RC_PLAYER_AUDIO_OUT_MAIN, /**< audio out main */
+ RC_PLAYER_AUDIO_OUT_SUB /**< audio out sub */
+} rc_player_audio_out_e;
+
+/**
+* @brief layout state
+*/
+typedef enum {
+ RC_LAYOUT_STATE_CHANGE_START = 0, /**< layout change start */
+ RC_LAYOUT_STATE_CHANGE_DONE /**< layout change done */
+} rc_layout_state_e;
+
+/**
+ * @brief Called when resource center request audio control.
+ * @param[in] player_id target player's id
+ * @param[in] data The user data passed from the callback registration function
+ * @see rc_register_player_audio_stop_request_callback()
+ * @see rc_register_player_audio_start_request_callback()
+ */
+typedef void (*rc_player_audio_request_cb)(int player_id, void* data);
+
+/**
+ * @brief Called when audio focus is changed.
+ * @param[in] zone_id id of focused zone
+ * @param[in] data The user data passed from the callback registration function
+ * @see rc_register_audio_focus_changed_callback()
+ * @see rc_unregister_audio_focus_changed_callback()
+ */
+typedef void (*rc_audio_focus_changed_cb)(int zone_id, void* data);
+
+
+/**
+ * @brief Called when best quality zone is switched.
+ * @param[in] prev_zone_id previous zone id had best quality
+ * @param[in] cur_zone_id current zone id having best quality
+ * @param[in] result switching result (0 on success, otherwise negative value)
+ * @param[in] data The user data passed from the callback registration function
+ * @see rc_register_best_quality_zone_switched_callback()
+ * @see rc_unregister_best_quality_zone_switched_callback()
+ */
+typedef void (*rc_best_quality_zone_switched_cb)(int prev_zone_id, int cur_zone_id, int result, void* data);
+
+struct rc_zone;
+
+/**
+ * @brief zone list handle.
+ */
+typedef void* rc_zone_list_h;
+
+/**
+ * @brief zone handle.
+ */
+typedef struct rc_zone* rc_zone_h;
+
+/**
+ * @brief Set resource policy.
+ * @param[in] policy resource policy to set.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_set_resource_policy(rc_rsc_policy_e policy);
+
+/**
+ * @brief Get a capable resource category which is dedicated to the application
+ * @param[in] handle player handle which is returned by rm_register()
+ * @param[in] app_id application id
+ * @param[in] category resource category id
+ * @return @c positive value which represents resource category on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @remark
+ * This function returns a resource category id which is dedicated to the application based on current resource policy.
+ * app_id shall be a valid application id. If not, RI_CATEGORY_NOT_PERMITTED will be returned
+ */
+int rc_get_capable_category_id(int handle, const char* app_id, int category);
+
+/**
+ * @brief Set audio focus.
+ * @param[in] zone_id id of focused zone to set.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_set_audio_focus(int zone_id);
+
+/**
+ * @brief Get audio focus.
+ * @param[out] zone_id id of focused zone.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_audio_focus(int* zone_id);
+
+/**
+ * @brief Get last audio focus.
+ * @remarks This API is working only after exit multiview.
+ * @param[out] zone_id id of last focused zone.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_last_audio_focus(int* zone_id);
+
+/**
+ * @brief Register changed callback for audio focus.
+ * @param[in] callback Callback function to be called when audio focus is changed.
+ * @param[in] data The user data passed from the callback
+ * @return Callback handle value if function finished succesful, 0 if failed.
+ * @pre None
+ * @post None
+ * @exception None
+ */
+unsigned int rc_register_audio_focus_changed_callback(rc_audio_focus_changed_cb callback, void* data);
+
+/**
+ * @brief Unregister changed callback for audio focus.
+ * @param[in] id Id of handler received from rc_register_audio_focus_changed_callback() function.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @return None
+ */
+int rc_unregister_audio_focus_changed_callback(const unsigned int id);
+
+/**
+ * @brief Get max video resolution the application can use in current resource policy
+ * @param[in] app_id application id
+ * @param[out] width max width (in pixel)
+ * @param[out] height max height (in pixel)
+ * @param[out] framerate max framerate (in fps)
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_max_video_resolution(const char* app_id, int *width, int *height, int *framerate);
+
+/**
+ * @brief Called when max video resolution to the application is changed
+ * @param[in] app_id The application id
+ * @param[in] width max width (in pixel)
+ * @param[in] height max height (in pixel)
+ * @param[in] framerate max framerate (in pixel)
+ * @param[in] data user data
+ * @pre None
+ * @post None
+ * @remarks
+ */
+typedef void (*max_resolution_change_cb)(const char* app_id, int width, int height, int framerate, void *data);
+
+/**
+ * @brief Register a callback to receive max video resolution change event
+ * @details Once max video resolution to the application is changed, the registered callback will be invoked.
+ * @param[in] app_id the application id id to observe
+ * @param[in] cb The callback function to register
+ * @param[in] data The user data to be passed to the callback function
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_register_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb, void* data);
+
+/**
+ * @brief Unregister a callback which had been added to observe max video resolution change event
+ * @param[in] app_id the application id to stop to observe
+ * @param[in] cb The callback function to unregister
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_unregister_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb);
+
+/**
+ * @brief Register changed callback for resource center's request.
+ * @param[in] callback Callback function to be called when resource center request audio stop.
+ * @param[in] data The user data passed from the callback
+ * @return Callback handle value if function finished succesful, 0 if failed.
+ * @pre None
+ * @post None
+ * @exception None
+ */
+unsigned int rc_register_player_audio_stop_request_callback(rc_player_audio_request_cb callback, void* data);
+
+/**
+ * @brief Register changed callback for resource center's request.
+ * @param[in] callback Callback function to be called when resource center request audio start.
+ * @param[in] data The user data passed from the callback
+ * @return Callback handle value if function finished succesful, 0 if failed.
+ * @pre None
+ * @post None
+ * @exception None
+ */
+unsigned int rc_register_player_audio_start_request_callback(rc_player_audio_request_cb callback, void* data);
+
+/**
+ * @brief Register changed callback for resource center's request.
+ * @param[in] callback Callback function to be called when resource center request audio resync.
+ * @param[in] data The user data passed from the callback
+ * @return Callback handle value if function finished succesful, 0 if failed.
+ * @pre None
+ * @post None
+ * @exception None
+ */
+unsigned int rc_register_player_audio_resync_request_callback(rc_player_audio_request_cb callback, void* data);
+
+/**
+ * @brief Unregister changed callback for resource center's request.
+ * @param[in] id Id of handler received from rc_register_player_audio_stop_request_callback() function.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @return None
+ */
+int rc_unregister_player_audio_stop_request_callback(const unsigned int id);
+
+/**
+ * @brief Unregister changed callback for resource center's request.
+ * @param[in] id Id of handler received from rc_register_player_audio_start_request_callback() function.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @return None
+ */
+int rc_unregister_player_audio_start_request_callback(const unsigned int id);
+
+/**
+ * @brief Unregister changed callback for resource center's request.
+ * @param[in] id Id of handler received from rc_register_player_audio_resync_request_callback() function.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @return None
+ */
+int rc_unregister_player_audio_resync_request_callback(const unsigned int id);
+
+/**
+ * @brief Get zone list
+ * @remarks @a zone_list should be freed using rc_free_zone_list().\n
+ * Use rc_get_next_zone() to get the first node of the list.
+ * @param[out] zone_list list of zones.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_zone_list(rc_zone_list_h* zone_list);
+
+/**
+ * @brief Gets the next zone of the zone list.
+ * @param[in] zone_list list of zones.
+ * @param[out] zone The zone item
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_next_zone(rc_zone_list_h zone_list, rc_zone_h *zone);
+
+/**
+ * @brief Gets the prev zone of the zone list.
+ * @param[in] zone_list list of zones.
+ * @param[out] zone The zone item
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_prev_zone(rc_zone_list_h zone_list, rc_zone_h *zone);
+
+/**
+ * @brief Gets the prev zone of the zone list.
+ * @param[in] zone The zone item
+ * @param[out] zone_id id of zone.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_zone_id(rc_zone_h zone, int* zone_id);
+
+/**
+ * @brief Free zone list
+ * @param[in] zone_list list of zones.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_free_zone_list(rc_zone_list_h zone_list);
+
+/**
+ * @brief Set application's zone info
+ * @remarks This API is only for control app
+ * @param[in] app_id application id
+ * @param[in] zone_id id of zone
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_set_app_zone_info(const char* app_id, int zone_id);
+
+/**
+ * @brief Set application's zone info which pre assigned
+ * @remarks This API is only for control app
+ * @param[in] app_id application id
+ * @param[in] zone_id id of zone
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_set_pre_assigned_app_zone_info(const char* app_id, int zone_id);
+
+/**
+ * @brief Notify that player's audio start is done
+ * @param[in] player_id player id
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_player_audio_start_done(int player_id);
+
+/**
+ * @brief Notify that player's audio stop is done
+ * @param[in] player_id player id
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_player_audio_stop_done(int player_id);
+
+/**
+ * @brief Set zone id which requires best quality video resource
+ * @remarks This API is only for control app
+ * @param[in] app_id application id
+ * @param[in] zone_id id of zone
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_set_best_quality_zone_info(const char* app_id, int zone_id);
+
+/**
+ * @brief Switch zones which require best quality video resource
+ * @remarks This API is only for control app
+ * @param[in] cur_zone_id current zone id having best quality video resource
+ * @param[in] next_zone_id next zone id which will have best quality video resource
+ * @return @c a zone id which is selected as best quality zone on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_switch_best_quality_zone(int cur_zone_id, int next_zone_id);
+
+/**
+ * @brief Restore best quality zone
+ * @remarks This API is only for control app
+ * @return @c 0 in case restore performed, otherwise a negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_restore_best_quality_zone(void);
+
+/**
+ * @brief Register callback for best quality zone switching
+ * @remarks This API is only for control app
+ * @param[in] cb Callback function to be called when best quality zone is switched
+ * @param[in] data The user data passed from the callback
+ * @return 0 on success, otherwise negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_register_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb, void *data);
+
+/**
+ * @brief Unregister callback for best quality zone switching
+ * @remarks This API is only for control app
+ * @param[in] cb Callback function to unregister
+ * @return 0 on success, otherwise negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_unregister_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb);
+
+/**
+ * @brief Check application has audio focus or not
+ * @remarks This API return 0, if application is not assigned specific zone yet.
+ * @param[in] app_id application id
+ * @return @c 0 and positive value on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_is_audio_focused(const char* app_id);
+
+/**
+ * @brief Get focused zone handle
+ * @param[in] zone zone handle
+ * @return @c 0 and positive value on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @remarks
+ * \li The returned zone must be freed by rc_zone_free() after use
+ * \li zone id will be 0 in case it's not in multiview mode. The valid zone id starts from 1.
+ * \li The data of zone information can be accessed by the following APIs
+ * \li rc_zone_get_id()
+ * \li rc_zone_get_app_id()
+ * \li rc_zone_get_scaler_id()
+ */
+int rc_get_focused_zone(rc_zone_h *zone);
+
+/**
+ * @brief Get zone id
+ * @param[in] zone zone handle
+ * @return positive zone id value on success, otherwise a negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_zone_get_id(rc_zone_h zone);
+
+/**
+ * @brief Get application id allocated to the zone
+ * @param[in] zone zone handle
+ * @return application id on success, otherwise NULL
+ * @pre None
+ * @post None
+ * @exception None
+ * @remarks
+ * \li The returned pointer will be valid until rc_zone_free() is called.
+ */
+const char* rc_zone_get_app_id(rc_zone_h zone);
+
+/**
+ * @brief Get scaler id allocated to the zone
+ * @param[in] zone zone handle
+ * @return positive hw scaler id value on success, otherwise a negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_zone_get_scaler_id(rc_zone_h zone);
+
+/**
+ * @brief Free zone handle
+ * @param[in] zone zone handle
+ * @return None
+ * @pre None
+ * @post None
+ * @exception None
+ */
+void rc_zone_free(rc_zone_h zone);
+
+struct rc_resource;
+
+/**
+ * @brief resource handle.
+ */
+typedef struct rc_resource* rc_resource_h;
+
+/**
+ * @brief Get whether max resolution has been changed
+ * @param[in] rsc resource handle
+ * @return true in case rc_resource_change_cb() was invoked by max resolution change, otherwise false
+ * @pre None
+ * @post None
+ * @exception None
+ */
+bool rc_rsc_max_resolution_changed(rc_resource_h rsc);
+
+/**
+ * @brief Get max video resolution allowed to the application.
+ * @param[in] rsc resource handle
+ * @param[out] width max width
+ * @param[out] height max height
+ * @param[out] framerate max framerate
+ * @return 0 on success, otherwise negative value
+ * @pre None
+ * @post None
+ * @exception None
+ * @remarks
+ * \li The values are valid only in case rc_rsc_max_resolution_changed() is true.
+ */
+int rc_rsc_get_video_max_resolution(rc_resource_h rsc, int *width, int *height, int *framerate);
+
+/**
+ * @brief Get whether audio resource shall be changed
+ * @param[in] rsc resource handle
+ * @return true in case rc_resource_change_cb() was invoked by audio resource change, otherwise false
+ * @pre None
+ * @post None
+ * @exception None
+ */
+bool rc_rsc_audio_out_changed(rc_resource_h rsc);
+
+/**
+ * @brief Called when max resolution of application is changed or audio resource shall be reallocated
+ * @param[in] app_id application id of which max resolution was changed or audio resource shall be reallocated
+ * @param[in] rsc resource handle
+ * @param[in] data The user data passed from the callback registration function
+ * @see rc_register_resource_change_callback()
+ * @see rc_unregister_resource_change_callback()
+ * @remarks
+ * \li The passed resource handle can be accessed by below APIs
+ * \li rc_rsc_max_resolution_changed()
+ * \li rc_rsc_audio_out_changed()
+ * \li rc_rsc_get_video_max_resolution()
+ */
+typedef void (*rc_resource_change_cb)(const char* app_id, rc_resource_h rsc, void *data);
+
+/**
+ * @brief Register callback for resource change event
+ * @param[in] app_id application id
+ * @param[in] cb Callback function to be called when max resolution of application is changed or audio resource shall be reallocated
+ * @param[in] data The user data passed from the callback
+ * @return 0 on success, otherwise negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_register_resource_change_callback(const char* app_id, rc_resource_change_cb cb, void* data);
+
+/**
+ * @brief Unregister callback for resource change event
+ * @param[in] app_id application id
+ * @param[in] cb Callback function to unregister
+ * @return 0 on success, otherwise negative value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_unregister_resource_change_callback(const char* app_id, rc_resource_change_cb cb);
+
+/**
+ * @brief Get player's audio out
+ * @param[in] player_id player id
+ * @param[out] audio_out player's audio out
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_get_player_audio_out(int player_id, rc_player_audio_out_e* audio_out);
+
+/**
+ * @brief Called when resource center request video control.
+ * @param[in] player_id target player's id
+ * @param[in] data The user data passed from the callback registration function
+ * @see rc_register_player_video_stop_request_callback()
+ * @see rc_register_player_video_start_request_callback()
+ */
+typedef void (*rc_player_video_request_cb)(int player_id, void* data);
+
+/**
+ * @brief Register changed callback for resource center's request.
+ * @param[in] callback Callback function to be called when resource center request video stop.
+ * @param[in] data The user data passed from the callback
+ * @return Callback handle value if function finished succesful, 0 if failed.
+ * @pre None
+ * @post None
+ * @exception None
+ */
+unsigned int rc_register_player_video_stop_request_callback(rc_player_video_request_cb callback, void* data);
+
+/**
+ * @brief Register changed callback for resource center's request.
+ * @param[in] callback Callback function to be called when resource center request video start.
+ * @param[in] data The user data passed from the callback
+ * @return Callback handle value if function finished succesful, 0 if failed.
+ * @pre None
+ * @post None
+ * @exception None
+ */
+unsigned int rc_register_player_video_start_request_callback(rc_player_video_request_cb callback, void* data);
+
+/**
+ * @brief Unregister changed callback for resource center's request.
+ * @param[in] id Id of handler received from rc_register_player_video_stop_request_callback() function.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @return None
+ */
+int rc_unregister_player_video_stop_request_callback(const unsigned int id);
+
+/**
+ * @brief Unregister changed callback for resource center's request.
+ * @param[in] id Id of handler received from rc_register_player_video_start_request_callback() function.
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ * @return None
+ */
+int rc_unregister_player_video_start_request_callback(const unsigned int id);
+
+/**
+ * @brief Notify that player's video start is done
+ * @param[in] player_id player id
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_player_video_start_done(int player_id);
+
+/**
+ * @brief Notify that player's video stop is done
+ * @param[in] player_id player id
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_player_video_stop_done(int player_id);
+
+/**
+ * @brief Notify current layout state
+ * @param[in] state layout state
+ * @return @c 0 on success, otherwise a negative error value
+ * @pre None
+ * @post None
+ * @exception None
+ */
+int rc_notify_layout_state(rc_layout_state_e state);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_RESOURCE_CENTER_H__ */
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __TIZEN_RESOURCE_CENTER_INTERNAL_H__\r
+#define __TIZEN_RESOURCE_CENTER_INTERNAL_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+typedef enum {\r
+ RC_AUDIO_OUT_MAIN = 1, /**< audio out main */\r
+ RC_AUDIO_OUT_SUB /**< audio out sub */\r
+} rc_audio_out_e;\r
+\r
+/**\r
+ * @brief Register player\r
+ * @param[in] player_id player id\r
+ * @param[in] resource_id window resource id\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_player_register(int player_id, int resource_id);\r
+\r
+/**\r
+ * @brief Request play\r
+ * @param[in] player_id player id\r
+ * @param[out] audio_out player's audio out\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_player_request_play(int player_id, rc_audio_out_e* audio_out);\r
+\r
+/**\r
+ * @brief Request stop\r
+ * @param[in] player_id player id\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_player_request_stop(int player_id);\r
+\r
+/**\r
+ * @brief Unregister player\r
+ * @param[in] player_id player id\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_player_unregister(int player_id);\r
+\r
+/**\r
+ * @brief Register external speaker info\r
+ * @param[in] info external speaker info\r
+ * @param[in] zone_id zone id\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_extspk_info_register(const char* info, int zone_id);\r
+\r
+/**\r
+ * @brief Unegister external speaker info\r
+ * @param[in] info external speaker info\r
+ * @param[in] zone_id zone id\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_extspk_info_unregister(const char* info, int zone_id);\r
+\r
+/**\r
+ * @brief Register external speaker info\r
+ * @param[in] info external speaker info\r
+ * @param[out] audio_out audio out of external speaker\r
+ * @return @c 0 on success, otherwise a negative error value\r
+ * @pre None\r
+ * @post None\r
+ * @exception None\r
+ */\r
+int rc_get_extspk_info_audio_out(const char* info, int* audio_out);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __TIZEN_RESOURCE_CENTER_INTERNAL_H__ */\r
--- /dev/null
+/*
+ * Copyright (c) 2024 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_RESOURCE_CENTER_PRIVATE_H__
+#define __TIZEN_RESOURCE_CENTER_PRIVATE_H__
+
+#include <dlog.h>
+#include <resource_center.h>
+#include <resource_center_internal.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RSC_CENTER_API"
+
+#ifndef RC_LOG_ERR
+#define RC_LOG_ERR(fmt, args...)SLOGE(fmt, ##args)
+#endif
+
+#ifndef RC_LOG_WARN
+#define RC_LOG_WARN(fmt, args...)SLOGW(fmt, ##args)
+#endif
+
+#ifndef RC_LOG_DBG
+#define RC_LOG_DBG(fmt, args...)SLOGD(fmt, ##args)
+#endif
+
+#ifndef RC_LOG_INFO
+#define RC_LOG_INFO(fmt, args...)SLOGI(fmt, ##args)
+#endif
+
+typedef struct {
+ max_resolution_change_cb cb;
+ void* data;
+} rez_change_cb;
+
+typedef struct {
+ rc_resource_change_cb cb;
+ void* data;
+} rsc_change_cb;
+
+struct rc_zone {
+ int id;
+ int scaler_id;
+ char* app_id;
+};
+
+struct rc_resource
+{
+ int max_rsz_changed;
+ int audio_out_changed;
+ int height;
+ int width;
+ int framerate;
+};
+
+int _rc_set_resource_policy(int policy);
+int _rc_get_capable_category_id(const char* app_id, int category);
+int _rc_set_audio_focus(int zone_id);
+int _rc_get_audio_focus(int* zone_id);
+int _rc_get_last_audio_focus(int* zone_id);
+unsigned int _rc_register_audio_focus_changed_callback(rc_audio_focus_changed_cb callback, void* data);
+int _rc_unregister_audio_focus_changed_callback(const unsigned int id);
+int _rc_get_max_video_resolution(const char* app_id, int *width, int *height, int *framerate);
+int _rc_player_register(int player_id, int resource_id);
+int _rc_player_request_play(int player_id, rc_audio_out_e* audio_out);
+int _rc_player_request_stop(int player_id);
+int _rc_player_unregister(int player_id);
+int _rc_extspk_info_register(const char* info, int zone_id);
+int _rc_extspk_info_unregister(const char* info, int zone_id);
+int _rc_get_extspk_info_audio_out(const char* info);
+int _rc_register_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb, void* data);
+int _rc_unregister_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb);
+unsigned int _rc_register_player_audio_stop_request_callback(rc_player_audio_request_cb callback, gpointer data);
+unsigned int _rc_register_player_audio_start_request_callback(rc_player_audio_request_cb callback, gpointer data);
+unsigned int _rc_register_player_audio_resync_request_callback(rc_player_audio_request_cb callback, gpointer data);
+int _rc_unregister_player_audio_stop_request_callback(const unsigned int id);
+int _rc_unregister_player_audio_start_request_callback(const unsigned int id);
+int _rc_unregister_player_audio_resync_request_callback(const unsigned int id);
+unsigned int _rc_register_player_video_stop_request_callback(rc_player_video_request_cb callback, gpointer data);
+unsigned int _rc_register_player_video_start_request_callback(rc_player_video_request_cb callback, gpointer data);
+int _rc_unregister_player_video_stop_request_callback(const unsigned int id);
+int _rc_unregister_player_video_start_request_callback(const unsigned int id);
+int _rc_get_zone_list(rc_zone_list_h* zone_list);
+int _rc_get_next_zone(rc_zone_list_h zone_list, rc_zone_h *zone);
+int _rc_get_prev_zone(rc_zone_list_h zone_list, rc_zone_h *zone);
+int _rc_get_zone_id(rc_zone_h zone, int* zone_id);
+int _rc_free_zone_list(rc_zone_list_h zone_list);
+int _rc_set_app_zone_info(const char* app_id, int zone_id);
+int _rc_set_pre_assigned_app_zone_info(const char* app_id, int zone_id);
+bool _rc_is_supported_category(int category);
+int _rc_player_audio_start_done(int player_id);
+int _rc_player_audio_stop_done(int player_id);
+int _rc_player_video_start_done(int player_id);
+int _rc_player_video_stop_done(int player_id);
+int _rc_switch_best_quality_zone_info(int cur_zone_id, int next_zone_id);
+int _rc_register_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb, void *data);
+int _rc_unregister_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb);
+bool _rc_is_normal_mode(void);
+int _rc_is_audio_focused(const char* app_id);
+int _rc_restore_best_quality_zone(void);
+int _rc_get_focused_zone(rc_zone_h *zone);
+int _rc_register_resource_change_callback(const char* app_id, rc_resource_change_cb cb, void *data);
+int _rc_unregister_resource_change_callback(const char* app_id, rc_resource_change_cb cb);
+int _rc_get_player_audio_out(int player_id, rc_player_audio_out_e* audio_out);
+int _rc_notify_layout_state(rc_layout_state_e state);
+
+#endif /* __TIZEN_RESOURCE_CENTER_PRIVATE_H__ */
--- /dev/null
+Name: resource-center-api
+Summary: resource center library
+Version: 0.1
+Release: 0
+Group: Multimedia/Libraries
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+BuildRequires: cmake
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(resource-manager)
+BuildRequires: pkgconfig(resource-information)
+
+%define _install_prefix /usr
+
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description
+Resource center library in Tizen
+
+%package devel
+Summary: resource center library (Development)
+Group: TO_BE/FILLED_IN
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Resource center library in Tizen (DEV)
+
+%if ("%{_vd_cfg_licensing}" == "y")
+%{?!TOMATO: %define TOMATO n}
+%else
+%{?!TOMATO: %define TOMATO y}
+%endif
+
+%prep
+%setup -q
+
+%build
+%if (%{TOMATO} == "y")
+export CXXFLAGS="$CXXFLAGS %{?__vd_cxxflags} -Wno-error"
+%endif
+
+MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
+cmake . \
+ -DFULLVER=%{version} \
+ -DMAJORVER=${MAJORVER} \
+ -DLIB_DIR=%{_libdir} \
+ -DCMAKE_INSTALL_PREFIX=%{_install_prefix} \
+ -DTOMATO_BIN=%{_tomatobin}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%if (%{TOMATO} == "y")
+mkdir -p %{buildroot}%{_tomatodir}
+mkdir -p %{buildroot}%{_tomatodir}/tc
+cp -rf ut/tc/* %{buildroot}%{_tomatodir}/tc
+%endif
+
+%make_install
+
+%clean
+
+%post
+/sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%{_libdir}/libresource-center-api.so.*
+%manifest resource-center-api.manifest
+%license LICENSE.APLv2
+%{_bindir}/resource_center_test
+
+%files devel
+%{_includedir}/resource_center.h
+%{_includedir}/resource_center_internal.h
+%{_libdir}/pkgconfig/*.pc
+%{_libdir}/*.so
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=/usr/@LIB_DIR@
+includedir=/usr/include
+
+Name: @PC_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @VERSION@
+Requires: @PC_REQUIRED@
+Libs: -L${libdir} @PC_LDFLAGS@
+Cflags: -I${includedir}
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+ </manifest>
--- /dev/null
+/*
+ * Copyright (c) 2024 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 <stdlib.h>
+#include <assert.h>
+#include <ri-module-api.h>
+#include "resource_center.h"
+#include "resource_center_private.h"
+
+int rc_set_resource_policy(rc_rsc_policy_e policy)
+{
+ RC_LOG_INFO(">>");
+
+ return _rc_set_resource_policy(policy);
+}
+
+int rc_get_capable_category_id(int handle, const char* app_id, int category)
+{
+ RC_LOG_INFO("app_id(%s), category(%d)", (app_id) ? app_id : "null", category);
+
+ if (!app_id || (category == RI_CATEGORY_NONE)) {
+ bool is_normal_mode = _rc_is_normal_mode();
+ RC_LOG_ERR("invalid param (%d:%d)", is_normal_mode, category);
+ return is_normal_mode? category:RI_CATEGORY_NOT_PERMITTED;
+ }
+
+ return (_rc_is_supported_category(category)) ? _rc_get_capable_category_id(app_id, category) : category;
+}
+
+int rc_set_audio_focus(int zone_id)
+{
+ RC_LOG_INFO(">>");
+
+ return _rc_set_audio_focus(zone_id);
+}
+
+int rc_get_audio_focus(int* zone_id)
+{
+ RC_LOG_INFO(">>");
+
+ if (!zone_id) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_get_audio_focus(zone_id);
+}
+
+int rc_get_last_audio_focus(int* zone_id)
+{
+ RC_LOG_INFO(">>");
+
+ if (!zone_id) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_get_last_audio_focus(zone_id);
+}
+
+unsigned int rc_register_audio_focus_changed_callback(rc_audio_focus_changed_cb callback, void* data)
+{
+ if (!callback) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_register_audio_focus_changed_callback(callback, data);
+}
+
+int rc_unregister_audio_focus_changed_callback(const unsigned int id)
+{
+ if (!id) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_unregister_audio_focus_changed_callback(id);
+}
+
+int rc_get_max_video_resolution(const char* app_id, int *width, int *height, int *framerate)
+{
+ if (!app_id || !width || !height || !framerate) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_get_max_video_resolution(app_id, width, height, framerate);
+}
+
+int rc_register_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb, void* data)
+{
+ if (!app_id || !cb) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_register_max_video_resolution_changed_callback(app_id, cb, data);
+}
+
+int rc_unregister_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb)
+{
+ if (!app_id || !cb) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_unregister_max_video_resolution_changed_callback(app_id, cb);
+}
+
+unsigned int rc_register_player_audio_stop_request_callback(rc_player_audio_request_cb callback, void* data)
+{
+ if (!callback) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_register_player_audio_stop_request_callback(callback, data);
+}
+
+unsigned int rc_register_player_audio_start_request_callback(rc_player_audio_request_cb callback, void* data)
+{
+ if (!callback) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_register_player_audio_start_request_callback(callback, data);
+}
+
+unsigned int rc_register_player_audio_resync_request_callback(rc_player_audio_request_cb callback, void* data)
+{
+ if (!callback) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_register_player_audio_resync_request_callback(callback, data);
+}
+
+int rc_unregister_player_audio_stop_request_callback(const unsigned int id)
+{
+ if (!id) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_unregister_player_audio_stop_request_callback(id);
+}
+
+int rc_unregister_player_audio_start_request_callback(const unsigned int id)
+{
+ if (!id) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_unregister_player_audio_start_request_callback(id);
+}
+
+int rc_unregister_player_audio_resync_request_callback(const unsigned int id)
+{
+ if (!id) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_unregister_player_audio_resync_request_callback(id);
+}
+
+int rc_get_zone_list(rc_zone_list_h* zone_list)
+{
+ if (!zone_list) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">>");
+
+ return _rc_get_zone_list(zone_list);
+}
+
+int rc_get_next_zone(rc_zone_list_h zone_list, rc_zone_h *zone)
+{
+ if (!zone_list || !zone) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">>");
+
+ return _rc_get_next_zone(zone_list, zone);
+}
+
+int rc_get_prev_zone(rc_zone_list_h zone_list, rc_zone_h *zone)
+{
+ if (!zone_list || !zone) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">>");
+
+ return _rc_get_prev_zone(zone_list, zone);
+}
+
+int rc_get_zone_id(rc_zone_h zone, int* zone_id)
+{
+ if (!zone || !zone_id) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">>");
+
+ return _rc_get_zone_id(zone, zone_id);
+}
+
+int rc_free_zone_list(rc_zone_list_h zone_list)
+{
+ if (!zone_list) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">>");
+
+ return _rc_free_zone_list(zone_list);
+}
+
+int rc_set_app_zone_info(const char* app_id, int zone_id)
+{
+ if (!app_id) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">> (%s:%d)", app_id, zone_id);
+
+ return _rc_set_app_zone_info(app_id, zone_id);
+}
+
+int rc_set_pre_assigned_app_zone_info(const char* app_id, int zone_id)
+{
+ if (!app_id) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">>");
+
+ return _rc_set_pre_assigned_app_zone_info(app_id, zone_id);
+}
+
+int rc_player_audio_start_done(int player_id)
+{
+ RC_LOG_INFO(">>");
+
+ return _rc_player_audio_start_done(player_id);
+}
+
+int rc_player_audio_stop_done(int player_id)
+{
+ RC_LOG_INFO(">>");
+
+ return _rc_player_audio_stop_done(player_id);
+}
+
+int rc_set_best_quality_zone_info(const char* app_id, int zone_id)
+{
+ //deprecated
+ return 0;
+}
+
+int rc_switch_best_quality_zone(int cur_zone_id, int next_zone_id)
+{
+ if (cur_zone_id < 0 || next_zone_id < 0) {
+ RC_LOG_ERR("invalid param (%d:%d)", cur_zone_id, next_zone_id);
+ return -1;
+ }
+
+ RC_LOG_INFO(">> (%d:%d)", cur_zone_id, next_zone_id);
+
+ return _rc_switch_best_quality_zone_info(cur_zone_id, next_zone_id);
+}
+
+int rc_register_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb, void *data)
+{
+ RC_LOG_INFO(">>");
+ return _rc_register_best_quality_zone_switched_callback(cb, data);
+}
+
+int rc_unregister_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb)
+{
+ RC_LOG_INFO(">>");
+ return _rc_unregister_best_quality_zone_switched_callback(cb);
+}
+
+int rc_is_audio_focused(const char* app_id)
+{
+ if (!app_id) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ RC_LOG_INFO(">> (%s)", app_id);
+
+ return _rc_is_audio_focused(app_id);
+}
+
+int rc_restore_best_quality_zone(void)
+{
+ return _rc_restore_best_quality_zone();
+}
+
+int rc_get_focused_zone(rc_zone_h *zone)
+{
+ if (!zone) {
+ RC_LOG_ERR("invalid zone");
+ return -1;
+ }
+
+ return _rc_get_focused_zone(zone);
+}
+
+int rc_zone_get_id(rc_zone_h zone)
+{
+ if (!zone) {
+ RC_LOG_ERR("invalid zone");
+ return -1;
+ }
+
+ return zone->id;
+}
+
+const char* rc_zone_get_app_id(rc_zone_h zone)
+{
+ if (!zone) {
+ RC_LOG_ERR("invalid zone");
+ return NULL;
+ }
+
+ RC_LOG_INFO("(%s)", zone->app_id? zone->app_id:"empty");
+ return zone->app_id;
+}
+
+int rc_zone_get_scaler_id(rc_zone_h zone)
+{
+ if (!zone) {
+ RC_LOG_ERR("invalid zone");
+ return -1;
+ }
+
+ return zone->scaler_id;
+}
+
+void rc_zone_free(rc_zone_h zone)
+{
+ if (!zone) {
+ RC_LOG_ERR("invalid zone");
+ return;
+ }
+
+ if (zone->app_id) {
+ free(zone->app_id);
+ zone->app_id = NULL;
+ }
+
+ free(zone);
+ zone = NULL;
+}
+
+int rc_register_resource_change_callback(const char* app_id, rc_resource_change_cb cb, void* data)
+{
+ if (!app_id || !cb) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_register_resource_change_callback(app_id, cb, data);
+}
+
+int rc_unregister_resource_change_callback(const char* app_id, rc_resource_change_cb cb)
+{
+ if (!app_id || !cb) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_unregister_resource_change_callback(app_id, cb);
+}
+
+bool rc_rsc_max_resolution_changed(rc_resource_h rsc)
+{
+ if (!rsc) {
+ RC_LOG_ERR("invalid param");
+ return false;
+ }
+
+ return rsc->max_rsz_changed;
+}
+
+bool rc_rsc_audio_out_changed(rc_resource_h rsc)
+{
+ if (!rsc) {
+ RC_LOG_ERR("invalid param");
+ return false;
+ }
+
+ return rsc->audio_out_changed;
+}
+
+int rc_rsc_get_video_max_resolution(rc_resource_h rsc, int *width, int *height, int *framerate)
+{
+ if (!rsc || !width || !height || !framerate) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ *width = rsc->width;
+ *height = rsc->height;
+ *framerate = rsc->framerate;
+ return 0;
+}
+
+int rc_get_player_audio_out(int player_id, rc_player_audio_out_e* audio_out)
+{
+ if (!audio_out) {
+ RC_LOG_ERR("invalid param");
+ return -1;
+ }
+
+ return _rc_get_player_audio_out(player_id, audio_out);
+}
+
+unsigned int rc_register_player_video_stop_request_callback(rc_player_video_request_cb callback, void* data)
+{
+ if (!callback) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_register_player_video_stop_request_callback(callback, data);
+}
+
+unsigned int rc_register_player_video_start_request_callback(rc_player_video_request_cb callback, void* data)
+{
+ if (!callback) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_register_player_video_start_request_callback(callback, data);
+}
+
+int rc_unregister_player_video_stop_request_callback(const unsigned int id)
+{
+ if (!id) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_unregister_player_video_stop_request_callback(id);
+}
+
+int rc_unregister_player_video_start_request_callback(const unsigned int id)
+{
+ if (!id) {
+ RC_LOG_ERR("invalid param");
+ return 0;
+ }
+
+ return _rc_unregister_player_video_start_request_callback(id);
+}
+
+int rc_player_video_start_done(int player_id)
+{
+ RC_LOG_INFO(">>");
+
+ return _rc_player_video_start_done(player_id);
+}
+
+int rc_player_video_stop_done(int player_id)
+{
+ RC_LOG_INFO(">>");
+
+ return _rc_player_video_stop_done(player_id);
+}
+
+int rc_notify_layout_state(rc_layout_state_e state)
+{
+ return _rc_notify_layout_state(state);
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include <stdlib.h>\r
+#include "resource_center_internal.h"\r
+#include "resource_center_private.h"\r
+\r
+int rc_player_register(int player_id, int resource_id)\r
+{\r
+ RC_LOG_INFO(">>");\r
+\r
+ return _rc_player_register(player_id, resource_id);\r
+}\r
+\r
+int rc_player_request_play(int player_id, rc_audio_out_e* audio_out)\r
+{\r
+ RC_LOG_INFO(">>");\r
+\r
+ return _rc_player_request_play(player_id, audio_out);\r
+}\r
+\r
+int rc_player_request_stop(int player_id)\r
+{\r
+ RC_LOG_INFO(">>");\r
+\r
+ return _rc_player_request_stop(player_id);\r
+}\r
+\r
+int rc_player_unregister(int player_id)\r
+{\r
+ RC_LOG_INFO(">>");\r
+\r
+ return _rc_player_unregister(player_id);\r
+}\r
+\r
+int rc_extspk_info_register(const char* info, int zone_id)\r
+{\r
+ RC_LOG_INFO(">>");\r
+\r
+ return _rc_extspk_info_register(info, zone_id);\r
+}\r
+\r
+int rc_extspk_info_unregister(const char* info, int zone_id)\r
+{\r
+ RC_LOG_INFO(">>");\r
+\r
+ return _rc_extspk_info_unregister(info, zone_id);\r
+}\r
+\r
+int rc_get_extspk_info_audio_out(const char* info, int* audio_out)\r
+{\r
+ int ret;\r
+ RC_LOG_INFO(">>");\r
+\r
+ ret = _rc_get_extspk_info_audio_out(info);\r
+\r
+ if (ret < 0)\r
+ return ret;\r
+\r
+ *audio_out = ret;\r
+ return 0;\r
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2024 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 <list>
+#include <map>
+#include <glib.h>
+#include <gio/gio.h>
+#include <assert.h>
+
+#include <rm_module_api.h>
+#include <ri-module-api.h>
+#include "resource_center_private.h"
+#include "resource_center.h"
+
+#define RC_DBUS_BUS_NAME "org.tizen.tv.system.resource"
+#define RC_DBUS_OBJ_PATH "/Org/Tizen/TV/System/Resource"
+#define RC_DBUS_INTERFACE_NAME RC_DBUS_BUS_NAME
+#define RC_DBUS_METHOD_NAME_SET_RESOURCE_POLICY "SetResourcePolicy"
+#define RC_DBUS_METHOD_NAME_GET_CAPABLE_CATEGORY_ID "GetCapableCatId"
+#define RC_DBUS_METHOD_NAME_SET_AUDIO_FOCUS "SetAudioFocus"
+#define RC_DBUS_METHOD_NAME_GET_AUDIO_FOCUS "GetAudioFocus"
+#define RC_DBUS_METHOD_NAME_GET_LAST_AUDIO_FOCUS "GetLastAudioFocus"
+#define RC_DBUS_METHOD_NAME_GET_MAX_VIDEO "GetMaxVideo"
+#define RC_DBUS_METHOD_NAME_PLAYER_REGISTER "PlayerRegister"
+#define RC_DBUS_METHOD_NAME_PLAYER_REQUEST_PLAY "PlayerRequestPlay"
+#define RC_DBUS_METHOD_NAME_PLAYER_REQUEST_STOP "PlayerRequestStop"
+#define RC_DBUS_METHOD_NAME_PLAYER_UNREGISTER "PlayerUnregister"
+#define RC_DBUS_METHOD_NAME_EXTSPKINFO_REGISTER "RegisterExtSpkInfo"
+#define RC_DBUS_METHOD_NAME_EXTSPKINFO_UNREGISTER "UnregisterExtSpkInfo"
+#define RC_DBUS_METHOD_NAME_GET_EXTSPKINFO_AUDIO_OUT "GetExtSpkInfoAudioOut"
+#define RC_DBUS_METHOD_NAME_GET_ZONE_LIST "GetMultiviewZoneIds"
+#define RC_DBUS_METHOD_NAME_SET_APP_ZONE_INFO "SetAppToZone"
+#define RC_DBUS_METHOD_NAME_SET_PRE_ASSIGNED_APP_ZONE_INFO "SetPreAssignedAppToZone"
+#define RC_DBUS_METHOD_NAME_MAX_REZ_REG_APP_ID "MaxVideoRegId"
+#define RC_DBUS_METHOD_NAME_MAX_REZ_UNREG_APP_ID "MaxVideoUnRegId"
+#define RC_DBUS_METHOD_NAME_SWITCH_BEST_QUALITY_ZONE "SwitchBestQaulityZone"
+#define RC_DBUS_METHOD_NAME_IS_AUDIO_FOCUSED "IsAudioFocused"
+#define RC_DBUS_METHOD_NAME_RESTORE_BEST_QUALITY_ZONE "RestoreBestQualityZone"
+#define RC_DBUS_METHOD_NAME_GET_FOCUSED_ZONE "GetFocusedZone"
+#define RC_DBUS_METHOD_NAME_RSC_CHANGE_REG_APP_ID "RscChangeRegId"
+#define RC_DBUS_METHOD_NAME_RSC_CHANGE_UNREG_APP_ID "RscChangeUnRegId"
+#define RC_DBUS_METHOD_NAME_GET_PLAYER_AUDIO_OUT "GetPlayerAudioOut"
+#define RC_DBUS_METHOD_NAME_NOTIFY_LAYOUT_STATE "NotifyLayoutState"
+
+#define RC_DBUS_SIGNAL_NAME_PLAYER_STOP_AUDIO "PlayerAudioStop"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_START_AUDIO "PlayerAudioStart"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_RESYNC_AUDIO "PlayerAudioResync"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_STOP_DONE "PlayerAudioStopDone"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_START_DONE "PlayerAudioStartDone"
+#define RC_DBUS_SIGNAL_NAME_AUDIO_FOCUS_CHANGED "AudioFocusChanged"
+
+#define RC_DBUS_SIGNAL_NAME_PLAYER_STOP_VIDEO "PlayerVideoStop"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_START_VIDEO "PlayerVideoStart"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_STOP_DONE "PlayerVideoStopDone"
+#define RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_START_DONE "PlayerVideoStartDone"
+
+typedef struct rc_player_audio_callback {
+ rc_player_audio_request_cb user_cb;
+ void* user_data;
+} rc_player_audio_callback_t;
+
+typedef struct rc_audio_focus_callback {
+ rc_audio_focus_changed_cb user_cb;
+ void* user_data;
+} rc_audio_focus_callback_t;
+
+typedef struct rc_best_quality_switched_callback {
+ rc_best_quality_zone_switched_cb user_cb;
+ void* user_data;
+} rc_best_quality_switched_callback_t;
+
+typedef struct rc_player_video_callback {
+ rc_player_video_request_cb user_cb;
+ void* user_data;
+} rc_player_video_callback_t;
+
+typedef struct rc_zone_list {
+ int count;
+ GList *list;
+ GList *iter;
+} rc_zone_list_t;
+
+static GDBusConnection* __dbus_get_connection()
+{
+ static GDBusConnection *conn = NULL;
+ GError *err = NULL;
+
+ if (conn)
+ return conn;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn) {
+ RC_LOG_ERR("g_bus_get_sync() error (%s)", err->message);
+ g_error_free(err);
+ return NULL;
+ }
+
+ return conn;
+}
+
+static int __dbus_method_call(const char *method, GVariant *args, GVariant **result)
+{
+ GError *err = NULL;
+ GVariant *reply = NULL;
+ GDBusConnection *conn = NULL;
+
+ RC_LOG_INFO("Method call '%s'", method);
+
+ if (!method) {
+ RC_LOG_ERR("Invalid Argument");
+ g_variant_unref(args);
+ return -1;
+ }
+
+ conn = __dbus_get_connection();
+
+ if (!conn) {
+ g_variant_unref(args);
+ return -1;
+ }
+
+ reply = g_dbus_connection_call_sync(conn, RC_DBUS_BUS_NAME, RC_DBUS_OBJ_PATH, RC_DBUS_INTERFACE_NAME,
+ method, args, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+
+ if (!reply) {
+ RC_LOG_ERR("Method Call '%s' Failed (%s)", method, err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ if (result)
+ *result = reply;
+
+ return 0;
+}
+
+static int __dbus_method_call_async_with_no_reply(const char *method, GVariant *args)
+{
+ GDBusConnection *conn = NULL;
+
+ RC_LOG_INFO("Method call '%s'", method);
+
+ if (!method) {
+ RC_LOG_ERR("Invalid Argument");
+ g_variant_unref(args);
+ return -1;
+ }
+
+ conn = __dbus_get_connection();
+
+ if (!conn) {
+ g_variant_unref(args);
+ return -1;
+ }
+
+ g_dbus_connection_call(conn, RC_DBUS_BUS_NAME, RC_DBUS_OBJ_PATH, RC_DBUS_INTERFACE_NAME,
+ method, args, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+
+ return 0;
+}
+
+static int _dbus_subscribe_signal(const char *signal_name, GDBusSignalCallback signal_cb, guint *subscribe_id,
+ void *userdata, GDestroyNotify freefunc)
+{
+ guint subs_id = 0;
+ GDBusConnection *conn = NULL;
+
+ if (!signal_name || !signal_cb) {
+ RC_LOG_ERR("Invalid Argument");
+ return -1;
+ }
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ RC_LOG_INFO("Dbus subscirbe signal %s", signal_name);
+
+ subs_id = g_dbus_connection_signal_subscribe(conn, NULL, RC_DBUS_INTERFACE_NAME, signal_name, RC_DBUS_OBJ_PATH,
+ NULL, G_DBUS_SIGNAL_FLAGS_NONE , signal_cb, userdata, freefunc);
+
+ if (!subs_id) {
+ RC_LOG_ERR("g_dbus_connection_signal_subscribe() failed ");
+ return -1;
+ }
+ if (subscribe_id)
+ *subscribe_id = subs_id;
+
+ return 0;
+}
+
+static int __get_command_id(void)
+{
+ static int pid = -1, count = 0;
+ if (pid == -1)
+ pid = getpid();
+
+ return (pid << 16) | count++;
+}
+
+int _rc_set_resource_policy(int policy)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ int command_id = __get_command_id();
+ GVariant *result = NULL;
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_SET_RESOURCE_POLICY,
+ g_variant_new("(iui)", command_id, policy, getpid()),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for SET_RESOURCE_POLICY is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+ if (dbus_ret)
+ ret = -1;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+bool _rc_is_supported_category(int category)
+{
+ int category_id = rm_unmask_category_options(category);
+
+ if (ri_is_video_decoder_category(category_id))
+ return true;
+ if (ri_is_audio_decoder_category(category_id))
+ return true;
+ if (ri_is_audio_out_category(category_id))
+ return true;
+ if (ri_is_video_scaler_category(category_id))
+ return true;
+ if (ri_is_mjpeg_decoder_category(category_id))
+ return true;
+
+ RC_LOG_INFO("[%d] is not supported category", category);
+
+ return false;
+}
+
+bool _rc_is_normal_mode(void)
+{
+ const char* rsc_event_name = "/tmp/.rsc_policy_activated";
+ //return (LwipcWaitEvent(rsc_event_name, 0) == 0)? false:true;
+
+ return access(rsc_event_name, F_OK) == 0;
+}
+
+static bool _rc_is_resource_center_ready(void)
+{
+ const char* rsc_event_name = "/tmp/.rsc_center_ready";
+ return access(rsc_event_name, F_OK) == 0;
+}
+
+static bool _rc_need_interlaced_capability_check(int category)
+{
+ int unmasked_id = rm_unmask_category_options(category);
+ if (unmasked_id != RM_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P && unmasked_id != RM_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P)
+ return false;
+
+ return ri_is_h264_interlaced_limited_model();
+}
+
+int _rc_get_capable_category_id(const char* app_id, int category)
+{
+ int ret = 0;
+ int category_id = -1;
+ GVariant *result = NULL;
+ pid_t pid = getpid();
+ int command_id = __get_command_id();
+
+ if (!_rc_is_resource_center_ready())
+ return category;
+ if (_rc_is_normal_mode() && !_rc_need_interlaced_capability_check(category))
+ return category;
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_CAPABLE_CATEGORY_ID,
+ g_variant_new("(isii)", command_id, app_id, category, pid),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for GET_CAPABLE_CATEGORY_ID is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &category_id);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, category_id);
+
+ g_variant_unref(result);
+
+ RC_LOG_INFO("category id %d", category_id);
+
+ return category_id;
+}
+
+int _rc_set_audio_focus(int zone_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_SET_AUDIO_FOCUS,
+ g_variant_new("(ii)", command_id, zone_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for SET_AUDIO_FOCUS is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+ if (dbus_ret)
+ ret = -1;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_get_audio_focus(int* zone_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_AUDIO_FOCUS,
+ g_variant_new("(i)", command_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for GET_AUDIO_FOCUS is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+ if (!dbus_ret)
+ ret = -1;
+
+ if (dbus_ret)
+ *zone_id = dbus_ret;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_get_last_audio_focus(int* zone_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_LAST_AUDIO_FOCUS,
+ g_variant_new("(i)", command_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for GET_LAST_AUDIO_FOCUS is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+ if (!dbus_ret)
+ ret = -1;
+
+ if (dbus_ret)
+ *zone_id = dbus_ret;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+static void audio_focus_cb_data_free_func(gpointer data)
+{
+ rc_audio_focus_callback_t *cb_data = (rc_audio_focus_callback_t *)data;
+
+ g_free(cb_data);
+}
+
+static void _dbus_audio_focus_signal_callback(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path,
+ const gchar *interface_name, const gchar *signal_name, GVariant *params, gpointer userdata)
+{
+ int zone_id;
+ int command_id;
+ rc_audio_focus_callback_t *cb_data = (rc_audio_focus_callback_t *)userdata;
+
+ g_variant_get(params, "(ii)", &command_id, &zone_id);
+
+ RC_LOG_INFO("[%08X] Signal(%s.%s) Received(%d)", command_id, interface_name, signal_name, zone_id);
+
+ (cb_data->user_cb)(zone_id, cb_data->user_data);
+}
+
+unsigned int _rc_register_audio_focus_changed_callback(rc_player_audio_request_cb callback, void* data)
+{
+ int ret = 0;
+ guint id = 0;
+ rc_audio_focus_callback_t *cb_data = (rc_audio_focus_callback_t*)g_malloc0(sizeof(rc_audio_focus_callback_t));
+
+ assert(cb_data);
+
+ cb_data->user_cb = callback;
+ cb_data->user_data = data;
+
+ ret = _dbus_subscribe_signal(RC_DBUS_SIGNAL_NAME_AUDIO_FOCUS_CHANGED, _dbus_audio_focus_signal_callback, &id, cb_data, audio_focus_cb_data_free_func);
+
+ if (ret) {
+ RC_LOG_ERR("(%s) failed", RC_DBUS_SIGNAL_NAME_AUDIO_FOCUS_CHANGED);
+ return -1;
+ }
+
+ RC_LOG_INFO("(%s) success :: (%lu)", RC_DBUS_SIGNAL_NAME_AUDIO_FOCUS_CHANGED, (unsigned long int)id);
+
+ return (unsigned int)id;
+}
+
+int _rc_unregister_audio_focus_changed_callback(const unsigned int id)
+{
+ GDBusConnection *conn = NULL;
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ g_dbus_connection_signal_unsubscribe(conn, id);
+
+ return 0;
+}
+
+int _rc_get_max_video_resolution(const char* app_id, int *width, int *height, int *framerate)
+{
+ int ret = 0;
+ int w = 0;
+ int h = 0;
+ int frame = -1;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_MAX_VIDEO,
+ g_variant_new("(is)", command_id, app_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_GET_MAX_VIDEO);
+ return -1;
+ }
+
+ g_variant_get(result, "(iii)", &w, &h, &frame);
+ RC_LOG_INFO("[%08X] (%s) success (%d*%d)-(%d)", command_id, RC_DBUS_METHOD_NAME_GET_MAX_VIDEO, w, h, frame);
+
+ *width = w;
+ *height = h;
+ *framerate = frame;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_player_register(int player_id, int resource_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_PLAYER_REGISTER,
+ g_variant_new("(iii)", command_id, player_id, resource_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_PLAYER_REGISTER);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_PLAYER_REGISTER, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_player_request_play(int player_id, rc_audio_out_e* audio_out)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_PLAYER_REQUEST_PLAY,
+ g_variant_new("(ii)", command_id, player_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_PLAYER_REQUEST_PLAY);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+
+ if (ret < 0) {
+ RC_LOG_ERR("[%08X] (%s) failed %d", command_id, RC_DBUS_METHOD_NAME_PLAYER_REQUEST_PLAY, ret);
+ return -1;
+ }
+
+ *audio_out = (rc_audio_out_e)ret;
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_PLAYER_REQUEST_PLAY, ret);
+
+ g_variant_unref(result);
+ return 0;
+}
+
+int _rc_player_request_stop(int player_id)
+{
+ int ret = 0;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call_async_with_no_reply(RC_DBUS_METHOD_NAME_PLAYER_REQUEST_STOP,
+ g_variant_new("(ii)", command_id, player_id));
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_PLAYER_REQUEST_STOP);
+ return -1;
+ }
+
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_PLAYER_REQUEST_STOP, ret);
+
+ return ret;
+}
+
+int _rc_player_unregister(int player_id)
+{
+ int ret = 0;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call_async_with_no_reply(RC_DBUS_METHOD_NAME_PLAYER_UNREGISTER,
+ g_variant_new("(ii)", command_id, player_id));
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_PLAYER_UNREGISTER);
+ return -1;
+ }
+
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_PLAYER_UNREGISTER, ret);
+
+ return ret;
+}
+
+int _rc_extspk_info_register(const char* info, int zone_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_EXTSPKINFO_REGISTER,
+ g_variant_new("(isi)", command_id, info, zone_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_EXTSPKINFO_REGISTER);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_EXTSPKINFO_REGISTER, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_extspk_info_unregister(const char* info, int zone_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_EXTSPKINFO_UNREGISTER,
+ g_variant_new("(isi)", command_id, info, zone_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_EXTSPKINFO_UNREGISTER);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_EXTSPKINFO_UNREGISTER, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_get_extspk_info_audio_out(const char* info)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_EXTSPKINFO_AUDIO_OUT,
+ g_variant_new("(is)", command_id, info),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_GET_EXTSPKINFO_AUDIO_OUT);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_GET_EXTSPKINFO_AUDIO_OUT, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+static unsigned int rez_change_signal_id = 0;
+std::map<std::string, rez_change_cb*> rez_change_cbs;
+
+static int _rc_add_max_video_resolution_cb(const char* app_id, max_resolution_change_cb cb, void * data)
+{
+ std::string appid(app_id);
+
+ auto it = rez_change_cbs.find(appid);
+ if (it != rez_change_cbs.end()) {
+ RC_LOG_ERR("already registered (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+ return -1;
+ }
+
+ rez_change_cb *cb_item = (rez_change_cb*) calloc(1, sizeof(rez_change_cb));
+ assert(cb_item);
+ cb_item->cb = cb;
+ cb_item->data = data;
+
+ rez_change_cbs.insert(std::pair<std::string, rez_change_cb*>(appid, cb_item));
+
+ RC_LOG_INFO("cb added (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+ return 0;
+}
+
+static int _rc_remove_max_video_resolution_cb(const char* app_id, max_resolution_change_cb cb)
+{
+ std::string appid(app_id);
+
+ auto it = rez_change_cbs.find(appid);
+ if (it == rez_change_cbs.end()) {
+ RC_LOG_ERR("not registered (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+ return -1;
+ }
+
+ rez_change_cb* cb_item = it->second;
+ rez_change_cbs.erase(it);
+
+ if (cb_item) {
+ free(cb_item);
+ cb_item = NULL;
+ }
+
+ RC_LOG_INFO("cb removed (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+
+ return rez_change_cbs.size();
+}
+
+static void onMaxRezChanged(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *object,
+ const gchar *interface,
+ const gchar *signal,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ char* app_id;
+ int width;
+ int height;
+ int framerate;
+
+ g_variant_get(parameters, "(&siii)", &app_id, &width, &height, &framerate);
+ RC_LOG_INFO("signal (%s) received - (%s:%d:%d:%d)", signal, app_id, width, height, framerate);
+
+ if (rez_change_cbs.size() == 0) {
+ RC_LOG_ERR("empty list");
+ return;
+ }
+
+ std::map<std::string, rez_change_cb*> cb_list;
+ std::copy(rez_change_cbs.begin(), rez_change_cbs.end(), std::inserter(cb_list, cb_list.begin()));
+
+ auto it = cb_list.find(std::string(app_id));
+ if (it == cb_list.end())
+ return;
+
+ rez_change_cb *change_cb = (rez_change_cb *) it->second;
+
+ RC_LOG_INFO("call cb(0x%08lX)", (unsigned long int) change_cb->cb);
+ change_cb->cb(app_id, width, height, framerate, change_cb->data);
+}
+
+int _rc_register_max_video_resolution_changed_callback_app_id(const char* app_id, void *func)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_MAX_REZ_REG_APP_ID,
+ g_variant_new("(islu)", command_id, app_id, (unsigned long int) func),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_MAX_REZ_REG_APP_ID);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_MAX_REZ_REG_APP_ID, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_unregister_max_video_resolution_changed_callback_app_id(const char* app_id, void *func)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_MAX_REZ_UNREG_APP_ID,
+ g_variant_new("(islu)", command_id, app_id, (unsigned long int) func),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_MAX_REZ_UNREG_APP_ID);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_MAX_REZ_UNREG_APP_ID, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_register_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb, void* data)
+{
+ if (_rc_add_max_video_resolution_cb(app_id, cb, data) < 0)
+ return -1;
+
+ if (_rc_register_max_video_resolution_changed_callback_app_id(app_id, (void*) cb) < 0) {
+ RC_LOG_ERR("failed to register app id(%s:%lu)", app_id, (unsigned long int) cb);
+ _rc_remove_max_video_resolution_cb(app_id, cb);
+ return -1;
+ }
+
+ if (rez_change_signal_id)
+ return 0;
+
+ GError *error = NULL;
+ GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!conn) {
+ RC_LOG_ERR("failed to get connection (%s)", (error)? error->message:"unknown");
+ _rc_remove_max_video_resolution_cb(app_id, cb);
+ return -1;
+ }
+
+ rez_change_signal_id = g_dbus_connection_signal_subscribe(conn,
+ NULL,
+ RC_DBUS_INTERFACE_NAME,
+ "MaxRezChanged",
+ RC_DBUS_OBJ_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ onMaxRezChanged,
+ NULL,
+ NULL);
+
+ if (rez_change_signal_id == 0) {
+ if (error) {
+ RC_LOG_ERR("dbus connection close error: %s", error->message);
+ g_clear_error(&error);
+ }
+ _rc_remove_max_video_resolution_cb(app_id, cb);
+ return -1;
+ }
+
+ RC_LOG_INFO("subscribe max resolution change (%d)", rez_change_signal_id);
+
+ return 0;
+}
+
+int _rc_unregister_max_video_resolution_changed_callback(const char* app_id, max_resolution_change_cb cb)
+{
+ int remain = _rc_remove_max_video_resolution_cb(app_id, cb);
+
+ if (remain < 0)
+ return -1;
+
+ if (_rc_unregister_max_video_resolution_changed_callback_app_id(app_id, (void*) cb) < 0) {
+ RC_LOG_ERR("failed to unregister app id(%s:%lu)", app_id, (unsigned long int) cb);
+ }
+
+ if (remain > 0)
+ return 0;
+
+ GError *error = NULL;
+ GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!conn) {
+ RC_LOG_ERR("failed to get connection (%s)", (error)? error->message:"unknown");
+ return -1;
+ }
+
+ RC_LOG_INFO("unsubscribe max resolution change(%d)", rez_change_signal_id);
+ g_dbus_connection_signal_unsubscribe(conn, rez_change_signal_id);
+ rez_change_signal_id = 0;
+
+ return 0;
+}
+
+static void player_audio_cb_data_free_func(gpointer data)
+{
+ rc_player_audio_callback_t *cb_data = (rc_player_audio_callback_t *)data;
+
+ g_free(cb_data);
+}
+
+static void _dbus_player_audio_signal_callback(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path,
+ const gchar *interface_name, const gchar *signal_name, GVariant *params, gpointer userdata)
+{
+ int command_id;
+ int player_id;
+ rc_player_audio_callback_t *cb_data = (rc_player_audio_callback_t *)userdata;
+
+ g_variant_get(params, "(ii)", &command_id, &player_id);
+
+ RC_LOG_INFO("[%08X] Signal(%s.%s) Received(%d)", command_id, interface_name, signal_name, player_id);
+
+ (cb_data->user_cb)(player_id, cb_data->user_data);
+}
+
+unsigned int _rc_register_player_audio_stop_request_callback(rc_player_audio_request_cb callback, void* data)
+{
+ int ret = 0;
+ guint id = 0;
+
+ rc_player_audio_callback_t *cb_data = (rc_player_audio_callback_t*)g_malloc0(sizeof(rc_player_audio_callback_t));
+ assert(cb_data);
+ cb_data->user_cb = callback;
+ cb_data->user_data = data;
+
+ ret = _dbus_subscribe_signal(RC_DBUS_SIGNAL_NAME_PLAYER_STOP_AUDIO, _dbus_player_audio_signal_callback, &id, cb_data, player_audio_cb_data_free_func);
+
+ if (ret) {
+ RC_LOG_ERR("(%s) failed", RC_DBUS_SIGNAL_NAME_PLAYER_STOP_AUDIO);
+ return -1;
+ }
+
+ RC_LOG_INFO("(%s) success :: (%lu)", RC_DBUS_SIGNAL_NAME_PLAYER_STOP_AUDIO, (unsigned long int)id);
+
+ return (unsigned int)id;
+}
+
+unsigned int _rc_register_player_audio_start_request_callback(rc_player_audio_request_cb callback, void* data)
+{
+ int ret = 0;
+ guint id = 0;
+
+ rc_player_audio_callback_t *cb_data = (rc_player_audio_callback_t*)g_malloc0(sizeof(rc_player_audio_callback_t));
+ assert(cb_data);
+ cb_data->user_cb = callback;
+ cb_data->user_data = data;
+
+ ret = _dbus_subscribe_signal(RC_DBUS_SIGNAL_NAME_PLAYER_START_AUDIO, _dbus_player_audio_signal_callback, &id, cb_data, player_audio_cb_data_free_func);
+
+ if (ret) {
+ RC_LOG_ERR("(%s) failed", RC_DBUS_SIGNAL_NAME_PLAYER_START_AUDIO);
+ return -1;
+ }
+
+ RC_LOG_INFO("(%s) success :: (%lu)", RC_DBUS_SIGNAL_NAME_PLAYER_START_AUDIO, (unsigned long int)id);
+
+ return (unsigned int)id;
+}
+
+unsigned int _rc_register_player_audio_resync_request_callback(rc_player_audio_request_cb callback, void* data)
+{
+ int ret = 0;
+ guint id = 0;
+
+ rc_player_audio_callback_t *cb_data = (rc_player_audio_callback_t*)g_malloc0(sizeof(rc_player_audio_callback_t));
+ assert(cb_data);
+ cb_data->user_cb = callback;
+ cb_data->user_data = data;
+
+ ret = _dbus_subscribe_signal(RC_DBUS_SIGNAL_NAME_PLAYER_RESYNC_AUDIO, _dbus_player_audio_signal_callback, &id, cb_data, player_audio_cb_data_free_func);
+
+ if (ret) {
+ RC_LOG_ERR("(%s) failed", RC_DBUS_SIGNAL_NAME_PLAYER_RESYNC_AUDIO);
+ return -1;
+ }
+
+ RC_LOG_INFO("(%s) success :: (%lx)", RC_DBUS_SIGNAL_NAME_PLAYER_RESYNC_AUDIO, (unsigned long int)id);
+
+ return (unsigned int)id;
+}
+
+int _rc_unregister_player_audio_stop_request_callback(const unsigned int id)
+{
+ GDBusConnection *conn = NULL;
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ g_dbus_connection_signal_unsubscribe(conn, id);
+
+ return 0;
+}
+
+int _rc_unregister_player_audio_start_request_callback(const unsigned int id)
+{
+ GDBusConnection *conn = NULL;
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ g_dbus_connection_signal_unsubscribe(conn, id);
+
+ return 0;
+}
+
+int _rc_unregister_player_audio_resync_request_callback(const unsigned int id)
+{
+ GDBusConnection *conn = NULL;
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ g_dbus_connection_signal_unsubscribe(conn, id);
+
+ return 0;
+}
+
+static void _rc_zone_free(gpointer data)
+{
+ rc_zone *zone = (rc_zone*) data;
+
+ if (!zone)
+ return;
+
+ if (zone->app_id) {
+ free(zone->app_id);
+ zone->app_id = NULL;
+ }
+
+ free(zone);
+ zone = NULL;
+}
+
+int _rc_get_zone_list(rc_zone_list_h* zone_list)
+{
+ int ret = 0;
+ int zone_id;
+ gchar *app_id;
+ GVariant* result = nullptr;
+ GVariantIter* iter;
+ rc_zone_list_t* _zone_list = nullptr;
+ rc_zone *zone = nullptr;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_ZONE_LIST,
+ g_variant_new("(i)", command_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for GET_ZONE_LIST is failed", command_id);
+ return -1;
+ }
+
+ _zone_list = (rc_zone_list_t*)g_malloc0(sizeof(rc_zone_list_t));
+ assert(_zone_list);
+ g_variant_get(result, "(a(is))", &iter);
+
+ if (!iter) {
+ RC_LOG_ERR("[%08X] iter is null", command_id);
+ return -1;
+ }
+
+ while (g_variant_iter_loop(iter, "(is)", &zone_id, &app_id)) {
+ zone = (rc_zone*) calloc(1, sizeof(rc_zone));
+ assert(zone);
+ zone->id = zone_id;
+ zone->app_id = (app_id)? strndup(app_id, strlen(app_id)):nullptr;
+ _zone_list->count++;
+ _zone_list->list = g_list_append(_zone_list->list, zone);
+ RC_LOG_INFO("[%08X] zone %d(%s) is added", command_id, zone->id, (zone->app_id)? zone->app_id:"");
+ }
+ g_variant_iter_free(iter);
+
+ if (!_zone_list->count) {
+ RC_LOG_INFO("[%08X] There is no zones", command_id);
+ g_list_free_full(g_list_first(_zone_list->list), _rc_zone_free);
+ g_free(_zone_list);
+ return -1;
+ }
+
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, _zone_list->count);
+ *zone_list = (rc_zone_list_h)_zone_list;
+ _zone_list->iter = NULL;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_get_next_zone(rc_zone_list_h zone_list, rc_zone_h *zone)
+{
+ rc_zone_list_t* _zone_list = NULL;
+ GList* node = NULL;
+
+ _zone_list = (rc_zone_list_t*)zone_list;
+
+ if (!_zone_list->iter)
+ node = g_list_first(_zone_list->list);
+ else
+ node = g_list_next(_zone_list->iter);
+
+ if (!node) {
+ RC_LOG_INFO("no next zone");
+ return -1;
+ }
+
+ _zone_list->iter = node;
+ *zone = (rc_zone_h) node->data;
+
+ return 0;
+}
+
+int _rc_get_prev_zone(rc_zone_list_h zone_list, rc_zone_h *zone)
+{
+ rc_zone_list_t* _zone_list = NULL;
+ GList* node = NULL;
+
+ _zone_list = (rc_zone_list_t*)zone_list;
+
+ if (!_zone_list->iter) {
+ RC_LOG_INFO("no prev zone");
+ return -1;
+ }
+
+ node = g_list_previous(_zone_list->iter);
+
+ if (!node) {
+ RC_LOG_INFO("no prev zone");
+ return -1;
+ }
+
+ _zone_list->iter = node;
+ *zone = (rc_zone_h) node->data;
+
+ return 0;
+}
+
+int _rc_get_zone_id(rc_zone_h zone, int* zone_id)
+{
+ *zone_id = zone->id;
+ return 0;
+}
+
+int _rc_free_zone_list(rc_zone_list_h zone_list)
+{
+ rc_zone_list_t* _zone_list = (rc_zone_list_t*)zone_list;
+
+ g_list_free_full(_zone_list->list, _rc_zone_free);
+ g_free(_zone_list);
+
+ return 0;
+}
+
+int _rc_set_app_zone_info(const char* app_id, int zone_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_SET_APP_ZONE_INFO,
+ g_variant_new("(isu)", command_id, app_id, zone_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08lX] __dbus_method_call() for SET_APP_ZONE_INFO is failed", (unsigned long int) command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08lX] __dbus_method_call() success, method return value is (%i)", (unsigned long int) command_id, dbus_ret);
+ if (dbus_ret)
+ ret = -1;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_set_pre_assigned_app_zone_info(const char* app_id, int zone_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_SET_PRE_ASSIGNED_APP_ZONE_INFO,
+ g_variant_new("(isi)", command_id, app_id, zone_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08lX] __dbus_method_call() for SET_PRE_ASSIGNED_APP_ZONE_INFO is failed", (unsigned long int) command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08lX] __dbus_method_call() success, method return value is (%i)", (unsigned long int) command_id, dbus_ret);
+ if (dbus_ret)
+ ret = -1;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_player_audio_start_done(int player_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_START_DONE,
+ g_variant_new("(ii)", command_id, player_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08lX] (%s) failed", (unsigned long int) command_id, RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_START_DONE);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_START_DONE, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_player_audio_stop_done(int player_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_STOP_DONE,
+ g_variant_new("(ii)", command_id, player_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_STOP_DONE);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_AUDIO_STOP_DONE, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_switch_best_quality_zone_info(int cur_zone_id, int next_zone_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_SWITCH_BEST_QUALITY_ZONE,
+ g_variant_new("(iii)", command_id, cur_zone_id, next_zone_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for BEST QUALITY ZONE INFO is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+
+ ret = dbus_ret;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+static unsigned int switched_signal_id = 0;
+static std::list<rc_best_quality_switched_callback_t*> switched_cb_list;
+
+static void onBestQualityZoneSwitched(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *object,
+ const gchar *interface,
+ const gchar *signal,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ int prev_zone_id;
+ int cur_zone_id;
+ int result;
+
+ g_variant_get(parameters, "(iii)", &prev_zone_id, &cur_zone_id, &result);
+ RC_LOG_INFO("signal (%s) received - (%d:%d:%d)", signal, prev_zone_id, cur_zone_id, result);
+
+ std::list<rc_best_quality_switched_callback_t*> copied_cb_list;
+ copied_cb_list.assign(switched_cb_list.begin(), switched_cb_list.end());
+
+ for (auto it = copied_cb_list.begin(); it != copied_cb_list.end(); ++it) {
+ rc_best_quality_switched_callback_t *cb = *it;
+ RC_LOG_INFO("call cb(0x%08lX) - (%d:%d:%d)", (unsigned long int) cb->user_cb, prev_zone_id, cur_zone_id, result);
+ cb->user_cb(prev_zone_id, cur_zone_id, result, cb->user_data);
+ }
+}
+
+static int _rc_add_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb, void *data)
+{
+ for (auto &it : switched_cb_list) {
+ if (it->user_cb == cb) {
+ RC_LOG_ERR("already registered callback (0x%08lX)", (unsigned long int) cb);
+ return -1;
+ }
+ }
+ rc_best_quality_switched_callback_t *cb_item = (rc_best_quality_switched_callback_t*) calloc(1, sizeof(rc_best_quality_switched_callback_t));
+
+ assert(cb_item);
+
+ cb_item->user_cb = cb;
+ cb_item->user_data = data;
+
+ switched_cb_list.push_back(cb_item);
+ RC_LOG_INFO("cb added (0x%08lX)", (unsigned long int) cb);
+ return 0;
+}
+
+static int _rc_remove_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb)
+{
+ for (auto it = switched_cb_list.begin(); it != switched_cb_list.end(); ++it) {
+ rc_best_quality_switched_callback_t *cb_item = *it;
+ if (cb_item->user_cb == cb) {
+ it = switched_cb_list.erase(it);
+ free(cb_item);
+ RC_LOG_INFO("cb removed (0x%08lX)", (unsigned long int) cb);
+ return switched_cb_list.size();
+ }
+ }
+
+ RC_LOG_ERR("not registered cb (0x%08lX)", (unsigned long int) cb);
+ return -1;
+}
+
+int _rc_register_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb, void *data)
+{
+ if (_rc_add_best_quality_zone_switched_callback(cb, data) < 0)
+ return -1;
+
+ if (switched_signal_id)
+ return 0;
+
+ GError *error = NULL;
+ GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!conn) {
+ RC_LOG_ERR("failed to get connection (%s)", (error)? error->message:"unknown");
+ _rc_remove_best_quality_zone_switched_callback(cb);
+ return -1;
+ }
+
+ switched_signal_id = g_dbus_connection_signal_subscribe(conn,
+ NULL,
+ RC_DBUS_INTERFACE_NAME,
+ "BestQualitZoneSwitched",
+ RC_DBUS_OBJ_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ onBestQualityZoneSwitched,
+ NULL,
+ NULL);
+
+ if (switched_signal_id == 0) {
+ if (error) {
+ RC_LOG_ERR("dbus connection close error: %s", error->message);
+ g_clear_error(&error);
+ }
+ _rc_remove_best_quality_zone_switched_callback(cb);
+ return -1;
+ }
+
+ RC_LOG_INFO("subscribe best quality zone switched (%d)", switched_signal_id);
+
+ return 0;
+}
+
+int _rc_unregister_best_quality_zone_switched_callback(rc_best_quality_zone_switched_cb cb)
+{
+ int remain = _rc_remove_best_quality_zone_switched_callback(cb);
+
+ if (remain != 0)
+ return (remain < 0)? -1 : 0;
+
+ GError *error = NULL;
+ GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!conn) {
+ RC_LOG_ERR("failed to get connection (%s)", (error)? error->message:"unknown");
+ return -1;
+ }
+
+ RC_LOG_INFO("unsubscribe best quality zone switched (%d)", switched_signal_id);
+ g_dbus_connection_signal_unsubscribe(conn, switched_signal_id);
+ switched_signal_id = 0;
+
+ return 0;
+}
+
+int _rc_is_audio_focused(const char* app_id)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_IS_AUDIO_FOCUSED,
+ g_variant_new("(is)", command_id, app_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for IS_AUDIO_FOCUSED is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+
+ g_variant_unref(result);
+ return dbus_ret;
+}
+
+int _rc_restore_best_quality_zone(void)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_RESTORE_BEST_QUALITY_ZONE,
+ g_variant_new("(i)", command_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for RESTORE BEST QUALITY ZONE INFO is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+
+ ret = dbus_ret;
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_get_focused_zone(rc_zone_h *zone)
+{
+ int ret = 0;
+ int zone_id = 0;
+ int scaler_id = -1;
+ char* app_id;
+ int command_id = __get_command_id();
+
+ GVariant *result = NULL;
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_FOCUSED_ZONE,
+ g_variant_new("(i)", command_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for GET_FOCUSED_ZONE is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(ii&s)", &zone_id, &scaler_id, &app_id);
+ RC_LOG_INFO("[%08X] focused zone (%d:%d:%s)", command_id, zone_id, scaler_id, (app_id)? app_id:"null");
+
+ rc_zone* z = (rc_zone*) calloc(1, sizeof(rc_zone));
+ assert(z);
+
+ z->id = zone_id;
+ z->scaler_id = scaler_id;
+ if (app_id)
+ z->app_id = strdup(app_id);
+
+ *zone = z;
+ g_variant_unref(result);
+ return ret;
+}
+
+static unsigned int rsc_change_signal_id = 0;
+std::map<std::string, rsc_change_cb*> rsc_change_cbs;
+
+static int _rc_add_resource_change_cb(const char* app_id, rc_resource_change_cb cb, void * data)
+{
+ std::string appid(app_id);
+
+ auto it = rsc_change_cbs.find(appid);
+ if (it != rsc_change_cbs.end()) {
+ RC_LOG_ERR("already registered (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+ return -1;
+ }
+
+ rsc_change_cb *cb_item = (rsc_change_cb*) calloc(1, sizeof(rsc_change_cb));
+ assert(cb_item);
+ cb_item->cb = cb;
+ cb_item->data = data;
+
+ rsc_change_cbs.insert(std::pair<std::string, rsc_change_cb*>(appid, cb_item));
+
+ RC_LOG_INFO("cb added (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+ return 0;
+}
+
+static int _rc_remove_resource_change_cb(const char* app_id, rc_resource_change_cb cb)
+{
+ std::string appid(app_id);
+
+ auto it = rsc_change_cbs.find(appid);
+ if (it == rsc_change_cbs.end()) {
+ RC_LOG_ERR("not registered (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+ return -1;
+ }
+
+ rsc_change_cb* cb_item = it->second;
+ rsc_change_cbs.erase(it);
+
+ if (cb_item) {
+ free(cb_item);
+ cb_item = NULL;
+ }
+
+ RC_LOG_INFO("cb removed (%s:0x%08lX)", appid.c_str(), (unsigned long int) cb);
+
+ return rsc_change_cbs.size();
+}
+
+int _rc_register_resource_change_callback_app_id(const char* app_id, void *func)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_RSC_CHANGE_REG_APP_ID,
+ g_variant_new("(iislu)", command_id, getpid(), app_id, (unsigned long int) func),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_RSC_CHANGE_REG_APP_ID);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_RSC_CHANGE_REG_APP_ID, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_unregister_resource_change_callback_app_id(const char* app_id, void *func)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_RSC_CHANGE_UNREG_APP_ID,
+ g_variant_new("(iislu)", command_id, getpid(), app_id, (unsigned long int) func),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_RSC_CHANGE_UNREG_APP_ID);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_RSC_CHANGE_UNREG_APP_ID, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+static void onRezChanged(GDBusConnection *conn,
+ const gchar *sender,
+ const gchar *object,
+ const gchar *interface,
+ const gchar *signal, GVariant *parameters, gpointer user_data)
+{
+ char* app_id; int max_rsz_changed = 0;
+ int audio_out_changed = 0;
+ int width = 0;
+ int height = 0;
+ int framerate = 0;
+
+ g_variant_get(parameters, "(&siiiii)", &app_id, &max_rsz_changed, &audio_out_changed, &width, &height, &framerate);
+ RC_LOG_INFO("signal (%s) received - (%s:%d:%d:%d:%d:%d)", signal, app_id, max_rsz_changed, audio_out_changed, width, height, framerate);
+
+ if (rsc_change_cbs.size() == 0) {
+ RC_LOG_ERR("empty list");
+ return;
+ }
+
+ std::map<std::string, rsc_change_cb*> cb_list;
+ std::copy(rsc_change_cbs.begin(), rsc_change_cbs.end(), std::inserter(cb_list, cb_list.begin()));
+
+ auto it = cb_list.find(std::string(app_id));
+ if (it == cb_list.end())
+ return;
+
+ rsc_change_cb *change_cb = (rsc_change_cb *) it->second;
+
+ rc_resource rsc;
+ rsc.max_rsz_changed = max_rsz_changed;
+ rsc.audio_out_changed = audio_out_changed;
+ rsc.width = width;
+ rsc.height = height;
+ rsc.framerate = framerate;
+
+ RC_LOG_INFO("call cb(0x%08lX)", (unsigned long int) change_cb->cb);
+ change_cb->cb(app_id, &rsc, change_cb->data);
+}
+
+int _rc_register_resource_change_callback(const char* app_id, rc_resource_change_cb cb, void *data)
+{
+ if (_rc_add_resource_change_cb(app_id, cb, data) < 0)
+ return -1;
+
+ if (_rc_register_resource_change_callback_app_id(app_id, (void*) cb) < 0) {
+ RC_LOG_ERR("failed to register app id(%s:%lu)", app_id, (unsigned long int) cb);
+ _rc_remove_resource_change_cb(app_id, cb);
+ return -1;
+ }
+
+ if (rsc_change_signal_id)
+ return 0;
+
+ GError *error = NULL;
+ GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!conn) {
+ RC_LOG_ERR("failed to get connection (%s)", (error)? error->message:"unknown");
+ _rc_remove_resource_change_cb(app_id, cb);
+ return -1;
+ }
+
+ rsc_change_signal_id = g_dbus_connection_signal_subscribe(conn,
+ NULL,
+ RC_DBUS_INTERFACE_NAME,
+ "AppRscChanged",
+ RC_DBUS_OBJ_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ onRezChanged,
+ NULL,
+ NULL);
+
+ if (rsc_change_signal_id == 0) {
+ if (error) {
+ RC_LOG_ERR("dbus connection close error: %s", error->message);
+ g_clear_error(&error);
+ }
+ _rc_remove_resource_change_cb(app_id, cb);
+ return -1;
+ }
+
+ RC_LOG_INFO("subscribe resource change (%d)", rsc_change_signal_id);
+ return 0;
+}
+
+int _rc_unregister_resource_change_callback(const char* app_id, rc_resource_change_cb cb)
+{
+ int remain = _rc_remove_resource_change_cb(app_id, cb);
+
+ if (remain < 0)
+ return -1;
+
+ if (_rc_unregister_resource_change_callback_app_id(app_id, (void*) cb) < 0)
+ RC_LOG_ERR("failed to unregister app id(%s:%lx)", app_id, (unsigned long int) cb);
+
+ if (remain > 0)
+ return 0;
+
+ GError *error = NULL;
+ GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!conn) {
+ RC_LOG_ERR("failed to get connection (%s)", (error)? error->message:"unknown");
+ return -1;
+ }
+
+ RC_LOG_INFO("unsubscribe resource change(%d)", rsc_change_signal_id);
+ g_dbus_connection_signal_unsubscribe(conn, rsc_change_signal_id);
+ rsc_change_signal_id = 0;
+ return 0;
+}
+
+int _rc_get_player_audio_out(int player_id, rc_player_audio_out_e* audio_out)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+ int active_audio_out = 0;
+
+ if (_rc_is_normal_mode()) {
+ active_audio_out = rm_get_active_audio_out(player_id);
+ RC_LOG_INFO("player : %d, active audio out : %d", player_id, active_audio_out);
+
+ if (active_audio_out < 0)
+ return -1;
+
+ if (active_audio_out & RM_AUDIO_OUT_MAIN)
+ *audio_out = RC_PLAYER_AUDIO_OUT_MAIN;
+ else if (active_audio_out & RM_AUDIO_OUT_SUB)
+ *audio_out = RC_PLAYER_AUDIO_OUT_SUB;
+ else
+ *audio_out = RC_PLAYER_AUDIO_OUT_NONE;
+
+ return 0;
+ }
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_GET_PLAYER_AUDIO_OUT,
+ g_variant_new("(ii)", command_id, player_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_METHOD_NAME_GET_PLAYER_AUDIO_OUT);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ g_variant_unref(result);
+
+ if (ret < 0) {
+ RC_LOG_ERR("[%08X] (%s) failed %d", command_id, RC_DBUS_METHOD_NAME_GET_PLAYER_AUDIO_OUT, ret);
+ return -1;
+ }
+
+ *audio_out = (rc_player_audio_out_e)ret;
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_METHOD_NAME_GET_PLAYER_AUDIO_OUT, ret);
+
+ return 0;
+}
+
+static void _dbus_player_video_signal_callback(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path,
+ const gchar *interface_name, const gchar *signal_name, GVariant *params, gpointer userdata)
+{
+ int command_id;
+ int player_id;
+ rc_player_video_callback_t *cb_data = (rc_player_video_callback_t *)userdata;
+
+ g_variant_get(params, "(ii)", &command_id, &player_id);
+
+ RC_LOG_INFO("[%08X] Signal(%s.%s) Received(%d)", command_id, interface_name, signal_name, player_id);
+
+ (cb_data->user_cb)(player_id, cb_data->user_data);
+}
+
+static void player_video_cb_data_free_func(gpointer data)
+{
+ rc_player_video_callback_t *cb_data = (rc_player_video_callback_t *)data;
+
+ g_free(cb_data);
+}
+
+unsigned int _rc_register_player_video_stop_request_callback(rc_player_video_request_cb callback, void* data)
+{
+ int ret = 0;
+ guint id = 0;
+
+ rc_player_video_callback_t *cb_data = (rc_player_video_callback_t*)g_malloc0(sizeof(rc_player_video_callback_t));
+ assert(cb_data);
+ cb_data->user_cb = callback;
+ cb_data->user_data = data;
+
+ ret = _dbus_subscribe_signal(RC_DBUS_SIGNAL_NAME_PLAYER_STOP_VIDEO, _dbus_player_video_signal_callback, &id, cb_data, player_video_cb_data_free_func);
+
+ if (ret) {
+ RC_LOG_ERR("(%s) failed", RC_DBUS_SIGNAL_NAME_PLAYER_STOP_VIDEO);
+ return -1;
+ }
+
+ RC_LOG_INFO("(%s) success :: (%lu)", RC_DBUS_SIGNAL_NAME_PLAYER_STOP_VIDEO, (unsigned long int)id);
+
+ return (unsigned int)id;
+}
+
+unsigned int _rc_register_player_video_start_request_callback(rc_player_video_request_cb callback, void* data)
+{
+ int ret = 0;
+ guint id = 0;
+
+ rc_player_video_callback_t *cb_data = (rc_player_video_callback_t*)g_malloc0(sizeof(rc_player_video_callback_t));
+ assert(cb_data);
+ cb_data->user_cb = callback;
+ cb_data->user_data = data;
+
+ ret = _dbus_subscribe_signal(RC_DBUS_SIGNAL_NAME_PLAYER_START_VIDEO, _dbus_player_video_signal_callback, &id, cb_data, player_audio_cb_data_free_func);
+
+ if (ret) {
+ RC_LOG_ERR("(%s) failed", RC_DBUS_SIGNAL_NAME_PLAYER_START_VIDEO);
+ return -1;
+ }
+
+ RC_LOG_INFO("(%s) success :: (%lu)", RC_DBUS_SIGNAL_NAME_PLAYER_START_VIDEO, (unsigned long int) id);
+
+ return (unsigned int)id;
+}
+
+int _rc_unregister_player_video_stop_request_callback(const unsigned int id)
+{
+ GDBusConnection *conn = NULL;
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ g_dbus_connection_signal_unsubscribe(conn, id);
+
+ return 0;
+}
+
+int _rc_unregister_player_video_start_request_callback(const unsigned int id)
+{
+ GDBusConnection *conn = NULL;
+
+ conn = __dbus_get_connection();
+
+ if (!conn)
+ return -1;
+
+ g_dbus_connection_signal_unsubscribe(conn, id);
+
+ return 0;
+}
+
+int _rc_player_video_start_done(int player_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_START_DONE,
+ g_variant_new("(ii)", command_id, player_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_START_DONE);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_START_DONE, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_player_video_stop_done(int player_id)
+{
+ int ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_STOP_DONE,
+ g_variant_new("(ii)", command_id, player_id),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] (%s) failed", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_STOP_DONE);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &ret);
+ RC_LOG_INFO("[%08X] (%s) success :: (%d)", command_id, RC_DBUS_SIGNAL_NAME_PLAYER_VIDEO_STOP_DONE, ret);
+
+ g_variant_unref(result);
+ return ret;
+}
+
+int _rc_notify_layout_state(rc_layout_state_e state)
+{
+ int ret = 0;
+ int dbus_ret = 0;
+ GVariant *result = NULL;
+ int command_id = __get_command_id();
+
+ ret = __dbus_method_call(RC_DBUS_METHOD_NAME_NOTIFY_LAYOUT_STATE,
+ g_variant_new("(ii)", command_id, (int)state),
+ &result);
+
+ if (ret) {
+ RC_LOG_ERR("[%08X] __dbus_method_call() for NOTIFY_LAYOUT_STATE is failed", command_id);
+ return -1;
+ }
+
+ g_variant_get(result, "(i)", &dbus_ret);
+ RC_LOG_INFO("[%08X] __dbus_method_call() success, method return value is (%i)", command_id, dbus_ret);
+ if (dbus_ret)
+ ret = -1;
+
+ g_variant_unref(result);
+ return ret;
+}
--- /dev/null
+SET(fw_test "${fw_name}-test")
+
+INCLUDE(FindPkgConfig)
+FOREACH(flag ${${fw_test}_CXXFLAGS})
+ SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}")
+ MESSAGE(${flag})
+ENDFOREACH()
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -Wall -pie")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+ GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+ MESSAGE("${src_name}")
+ ADD_EXECUTABLE(${src_name} ${src})
+ TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS})
+ENDFOREACH()
+
+INSTALL(TARGETS resource_center_test DESTINATION bin)
--- /dev/null
+/*
+ * Copyright (c) 2024 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 <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <glib.h>
+
+#include <resource_center.h>
+#include <resource_center_internal.h>
+
+#define MAX_STRING_LEN 256
+
+enum {
+ CURRENT_STATUS_MAINMENU,
+ CURRENT_STATUS_SET_RESOURCE_POLICY,
+ CURRENT_STATUS_SET_AUDIO_FOCUS,
+ CURRENT_STATUS_GET_AUDIO_FOCUS,
+ CURRENT_STATUS_PLAYER_UNREGISTER,
+ CURRENT_STATUS_REIGSTER_PLAYER_AUDIO_CALLBACK,
+ CURRENT_STATUS_UNREIGSTER_PLAYER_AUDIO_CALLBACK,
+ CURRENT_STATUS_GET_ZONE_LIST,
+ CURRENT_STATUS_FREE_ZONE_LIST,
+ CURRENT_STATUS_SET_APP_ZONE_INFO,
+ CURRENT_STATUS_GET_PLAYER_AUDIO_OUT,
+ CURRENT_STATUS_NOTIFY_LAYOUT_STATE,
+};
+
+static rc_zone_list_h zone_list;
+static int g_menu_state = CURRENT_STATUS_MAINMENU;
+
+GMainLoop* g_loop;
+
+void player_audio_stop_callback(int player_id, void* data)
+{
+ g_print("[%d] stop requested\n", player_id);
+}
+
+void player_audio_start_callback(int player_id, void* data)
+{
+ g_print("[%d] start requested\n", player_id);
+}
+
+void quit_program()
+{
+ g_main_loop_quit(g_loop);
+}
+
+void _interpret_main_menu(char *cmd)
+{
+ if (strncmp(cmd, "rpac", 4) == 0) {
+ g_menu_state = CURRENT_STATUS_REIGSTER_PLAYER_AUDIO_CALLBACK;
+ } else if (strncmp(cmd, "upac", 4) == 0) {
+ g_menu_state = CURRENT_STATUS_UNREIGSTER_PLAYER_AUDIO_CALLBACK;
+ } else if (strncmp(cmd, "srp", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_SET_RESOURCE_POLICY;
+ } else if (strncmp(cmd, "saf", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_SET_AUDIO_FOCUS;
+ } else if (strncmp(cmd, "gaf", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_GET_AUDIO_FOCUS;
+ } else if (strncmp(cmd, "gsl", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_GET_ZONE_LIST;
+ } else if (strncmp(cmd, "fsl", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_FREE_ZONE_LIST;
+ } else if (strncmp(cmd, "pur", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_PLAYER_UNREGISTER;
+ } else if (strncmp(cmd, "saz", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_SET_APP_ZONE_INFO;
+ } else if (strncmp(cmd, "gpa", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_GET_PLAYER_AUDIO_OUT;
+ } else if (strncmp(cmd, "nls", 3) == 0) {
+ g_menu_state = CURRENT_STATUS_NOTIFY_LAYOUT_STATE;
+ } else if (strncmp(cmd, "q", 1) == 0 ) {
+ g_print("closing the test suite\n");
+ quit_program();
+ } else {
+ g_print("unknown menu \n");
+ }
+
+}
+
+void display_sub_basic()
+{
+ g_print("\n");
+ g_print("=========================================================================================\n");
+ g_print(" Resource Center API Test (press q to quit) \n");
+ g_print("-----------------------------------------------------------------------------------------\n");
+ g_print("srp. Set Resource Policy \n");
+ g_print("saf. Set Audio Focus \t\t\t");
+ g_print("gaf. Get Audio Focus \n");
+ g_print("pur. Unregister Player \n");
+ g_print("rpac. Register Player Audio Start/Stop callbacks \n");
+ g_print("upac. Unregister Player Audio Start/Stop callback \n");
+ g_print("gsl. Get Zone List \t\t\t");
+ g_print("fsl. Free Zone List \n");
+ g_print("saz. Set Application Zone Info \n");
+ g_print("gpa. Get Player AudioOut \n");
+ g_print("nls. Notify Layout State \n");
+ g_print("=========================================================================================\n");
+}
+
+static void displaymenu()
+{
+ if (g_menu_state == CURRENT_STATUS_MAINMENU) {
+ display_sub_basic();
+ } else if (g_menu_state == CURRENT_STATUS_SET_RESOURCE_POLICY) {
+ g_print("*** input the resource policy\n");
+ } else if (g_menu_state == CURRENT_STATUS_SET_AUDIO_FOCUS) {
+ g_print("*** input the focused zone\n");
+ } else if (g_menu_state == CURRENT_STATUS_GET_AUDIO_FOCUS) {
+ g_print("*** Press enter to get audio focus\n");
+ } else if (g_menu_state == CURRENT_STATUS_PLAYER_UNREGISTER) {
+ g_print("*** input the player id\n");
+ } else if (g_menu_state == CURRENT_STATUS_REIGSTER_PLAYER_AUDIO_CALLBACK) {
+ g_print("*** Press enter to register callbacks\n");
+ } else if (g_menu_state == CURRENT_STATUS_UNREIGSTER_PLAYER_AUDIO_CALLBACK) {
+ g_print("*** input the callback id\n");
+ } else if (g_menu_state == CURRENT_STATUS_GET_ZONE_LIST) {
+ g_print("*** Press enter to get zone list\n");
+ } else if (g_menu_state == CURRENT_STATUS_FREE_ZONE_LIST) {
+ g_print("*** Press enter to free zone list\n");
+ } else if (g_menu_state == CURRENT_STATUS_SET_APP_ZONE_INFO) {
+ g_print("*** input tha app id and zone id\n");
+ } else if (g_menu_state == CURRENT_STATUS_GET_PLAYER_AUDIO_OUT) {
+ g_print("*** input the player id\n");
+ } else if (g_menu_state == CURRENT_STATUS_NOTIFY_LAYOUT_STATE) {
+ g_print("*** input the state\n");
+ } else {
+ g_print("*** unknown status\n");
+ quit_program();
+ }
+ g_print(" >>> ");
+}
+
+gboolean timeout_menu_display(void* data)
+{
+ displaymenu();
+ return FALSE;
+}
+
+gboolean timeout_quit_program(void* data)
+{
+ quit_program();
+ return FALSE;
+}
+
+void reset_menu_state(void)
+{
+ g_menu_state = CURRENT_STATUS_MAINMENU;
+}
+
+static void interpret (char *cmd)
+{
+ switch (g_menu_state) {
+ case CURRENT_STATUS_MAINMENU: {
+ _interpret_main_menu(cmd);
+ break;
+ }
+ case CURRENT_STATUS_SET_RESOURCE_POLICY: {
+ int policy = atoi(cmd);
+
+ if (rc_set_resource_policy((rc_rsc_policy_e) policy) != 0)
+ g_print("fail to set resource policy\n");
+ else
+ g_print("set resource policy success : %d\n", policy);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_SET_AUDIO_FOCUS: {
+ int zone_id = atoi(cmd);
+
+ if (rc_set_audio_focus(zone_id) != 0)
+ g_print("fail to set audio focus\n");
+ else
+ g_print("set audio focus success : %d\n", zone_id);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_GET_AUDIO_FOCUS: {
+ int zone_id = 0;
+
+ if (rc_get_audio_focus(&zone_id) != 0)
+ g_print("fail to get audio focus\n");
+ else
+ g_print("get audio focus success : %d\n", zone_id);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_PLAYER_UNREGISTER: {
+ int player_id = atoi(cmd);
+
+ if (rc_player_unregister(player_id) != 0)
+ g_print("fail to unregister player\n");
+ else
+ g_print("unregister player success : %d\n", player_id);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_REIGSTER_PLAYER_AUDIO_CALLBACK: {
+ unsigned int ret = rc_register_player_audio_stop_request_callback(player_audio_stop_callback, NULL);
+
+ if (ret == 0)
+ g_print("fail to register stop callback\n");
+ else
+ g_print("register stop callback success : %u\n", ret);
+
+ ret = rc_register_player_audio_start_request_callback(player_audio_start_callback, NULL);
+
+ if (ret == 0)
+ g_print("fail to register start callback\n");
+ else
+ g_print("register start callback success : %u\n", ret);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_UNREIGSTER_PLAYER_AUDIO_CALLBACK: {
+ unsigned int id = atoi(cmd);
+
+ if (rc_unregister_player_audio_stop_request_callback(id) != 0)
+ g_print("fail to unregister callback\n");
+ else
+ g_print("unregister callback success : %u\n", id);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_GET_ZONE_LIST: {
+ int id;
+ rc_zone_h zone;
+
+ if (rc_get_zone_list(&zone_list) != 0) {
+ g_print("fail to get zone list\n");
+ reset_menu_state();
+ break;
+ }
+
+ g_print("get zone list success : %p\n", zone_list);
+
+ while (!rc_get_next_zone(zone_list, &zone)) {
+ rc_get_zone_id(zone, &id);
+ g_print("Zone(%p) id : %d\n", zone, id);
+ }
+
+ g_print("tail of zone list\n");
+
+ while (!rc_get_prev_zone(zone_list, &zone)) {
+ rc_get_zone_id(zone, &id);
+ g_print("Zone(%p) id : %d\n", zone, id);
+ }
+
+ g_print("head of zone list\n");
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_FREE_ZONE_LIST: {
+ if (rc_free_zone_list(zone_list) != 0)
+ g_print("fail to free zone list\n");
+ else
+ g_print("free zone list success\n");
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_SET_APP_ZONE_INFO: {
+ static int saz_state = 0;
+ static char app_id[256];
+ static int zone_id;
+
+ if (!saz_state) {
+ strncpy(app_id, cmd, 255);
+ app_id[255] = 0;
+ saz_state++;
+ break;
+ }
+
+ zone_id = atoi(cmd);
+
+ if (rc_set_app_zone_info(app_id, zone_id) != 0)
+ g_print("fail to set app zone info\n");
+ else
+ g_print("set app zone info success : %s(%d)\n", app_id, zone_id);
+
+ saz_state = 0;
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_GET_PLAYER_AUDIO_OUT: {
+ int player_id = atoi(cmd);
+ rc_player_audio_out_e audio_out = RC_PLAYER_AUDIO_OUT_NONE;
+
+ if (rc_get_player_audio_out(player_id, &audio_out) != 0)
+ g_print("fail to get player audio out\n");
+ else
+ g_print("get player audio out success : %d(%d)\n", (int)audio_out, player_id);
+
+ reset_menu_state();
+ break;
+ }
+ case CURRENT_STATUS_NOTIFY_LAYOUT_STATE: {
+ int state = atoi(cmd);
+
+ if (rc_notify_layout_state((rc_layout_state_e)state) != 0)
+ g_print("fail to notify layout state\n");
+ else
+ g_print("notify layout state(%d) success\n", state);
+
+ reset_menu_state();
+ break;
+ }
+ }
+ g_timeout_add(100, timeout_menu_display, 0);
+}
+
+gboolean input(GIOChannel *channel, GIOCondition condition, gpointer data)
+{
+ 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(buf);
+
+ return TRUE;
+}
+
+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_loop = g_main_loop_new(NULL, 1);
+
+ displaymenu();
+ g_main_loop_run(g_loop);
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(${TEST_PKG_NAME} C CXX)
+INCLUDE(FindPkgConfig)
+pkg_check_modules(TOMATO_PKG REQUIRED
+ dlog
+ gio-2.0
+ gtest_gmock
+ resource-manager
+ resource-information
+)
+
+ADD_DEFINITIONS(-DTOMATO)
+
+FOREACH(flag ${TOMATO_PKG_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ SET(EXTRA_CXXFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${EXTRA_CFLAGS} -fPIC")
+SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib")
+
+SET(INCLUDE_DIR_TO_TEST
+ ${CMAKE_CURRENT_SOURCE_DIR}/inc
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include_internal
+)
+
+SET(SRC_TO_TEST
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/resource_center_private.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/resource_center.cpp
+)
+
+SET(SRC_TESTCASE
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/testcase/ut_main.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/testcase/ut_api.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/testcase/ut_util.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/testcase/TCPlayer.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/testcase/TCResource.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/testcase/TCApp.cpp
+)
+
+#FILE(GLOB SRC_TOMATOUTIL "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
+
+SET(TOMATO_TEST ${TEST_PKG_NAME})
+
+INCLUDE_DIRECTORIES(
+ ${INCLUDE_DIR_TO_TEST}
+)
+
+ADD_EXECUTABLE(${TEST_PKG_NAME} ${SRC_TESTCASE} ${SRC_TO_TEST})
+
+FIND_PACKAGE (Threads REQUIRED)
+MESSAGE("TEST_PKG_NAME : " ${TEST_PKG_NAME})
+MESSAGE("CMAKE_THREAD_LIBS_INIT : " ${CMAKE_THREAD_LIBS_INIT})
+MESSAGE("TEST_PKG_NAME : " ${TEST_PKG_NAME} )
+MESSAGE("TOMATO_PKG_LDFLAGS : " ${TOMATO_PKG_LDFLAGS} )
+MESSAGE("glib_pkg_LDFLAGS : " ${glib_pkg_LDFLAGS} )
+MESSAGE("CMAKE_EXE_LINKER_FLAGS : " ${CMAKE_EXE_LINKER_FLAGS} )
+
+TARGET_LINK_LIBRARIES(${TEST_PKG_NAME} ${CMAKE_THREAD_LIBS_INIT} ${TOMATO_PKG_LDFLAGS} ${glib_pkg_LDFLAGS} ${CMAKE_EXE_LINKER_FLAGS} )
+
+INSTALL(TARGETS ${TEST_PKG_NAME} DESTINATION ${TOMATO_BIN})
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __TC_APP_H__\r
+#define __TC_APP_H__\r
+#include <string>\r
+\r
+class TCApp\r
+{\r
+public:\r
+ TCApp(const char* app_id);\r
+ ~TCApp();\r
+\r
+ static void ResourceChangedCb(const char* app_id, rc_resource_h rsc, void *data);\r
+ int RegisterResourceChangeCb(void);\r
+ int UnregisterResourceChangeCb(void);\r
+\r
+ std::string GetAppId(void) { return m_app_id; }\r
+\r
+ void IncreaseCbCount(void) { m_cb_count++; }\r
+ void ResetCbCount(void) { m_cb_count = 0; }\r
+ int GetCbCount(void) { return m_cb_count;}\r
+\r
+ bool IsMaxRszChanged(void) { return m_max_rsz_changed; }\r
+ bool IsAudioRscChanged(void) { return m_audio_rsc_changed; }\r
+\r
+ void SetMaxRszChanged(bool changed) { m_max_rsz_changed = changed; }\r
+ void SetAudioRscChanged(bool changed) { m_audio_rsc_changed = changed; }\r
+ void SetMaxResolution(int w, int h, int f) { m_max_width = w; m_max_height = h; m_max_framerate = f; }\r
+ void GetMaxResolution(int *w, int *h, int *f) { *w = m_max_width, *h = m_max_height, *f = m_max_framerate; }\r
+ void ResetCbData(void) { m_max_width = 0; m_max_height = 0; m_max_framerate = 0; m_max_rsz_changed = false; m_audio_rsc_changed = false; }\r
+\r
+private:\r
+ std::string m_app_id;\r
+ int m_cb_count;\r
+\r
+ int m_max_width = 0;\r
+ int m_max_height = 0;\r
+ int m_max_framerate = 0;\r
+ bool m_max_rsz_changed = false;\r
+ bool m_audio_rsc_changed = false;\r
+};\r
+\r
+#endif //__TC_APP_H__
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __TC_PLAYER_H__\r
+#define __TC_PLAYER_H__\r
+\r
+#include <string>\r
+#include <map>\r
+#include <rm_api.h>\r
+\r
+class TCResource;\r
+class TCPlayer\r
+{\r
+public:\r
+ TCPlayer();\r
+ TCPlayer(std::string app_id) { m_app_id = app_id; }\r
+ ~TCPlayer();\r
+\r
+ static rm_cb_result ConflictCb(int handle, rm_callback_type event, rm_device_request_s *info, void* data);\r
+ int Register(void);\r
+ int Unregister(void);\r
+\r
+ int SetPriority(int priority);\r
+ int SetAppId(std::string app_id);\r
+ void SetCustomHandle(int handle) { m_handle = handle;}\r
+\r
+ int GetHandle(void) { return m_handle; }\r
+ std::string GetAppId(void) { return m_app_id; }\r
+ int AddResource(int category_id, int state);\r
+ int AddResource(int category_id, int category_option, int state);\r
+ void RemoveResources(void);\r
+ int GetAudioCategory(std::string codec_name, int mixing_mode);\r
+ int GetCapableVideoCategory(std::string codec_name, int h_size, int v_size, int color_depth, int sampling_format, int framerate);\r
+ int GetCapableCategoryIdFromRC(int category_id);\r
+\r
+ int AddQuery(int category_id, int category_option, int state);\r
+ void RemoveQueries(void);\r
+ int Query(int query_type, int *ans);\r
+\r
+ void AddAllocatedResource(int device_id);\r
+ int AllocateResources(void);\r
+ int ReleaseResources(void);\r
+ int ReleaseResource(int index);\r
+ int GetAllocatedResourceId(int index);\r
+ int GetAllocatedResourcesNum(void) { return m_allocated_resources.size(); }\r
+\r
+ void IncreaseConflictNum(void) { m_n_conflict++; }\r
+ int GetConflictNum(void) { return m_n_conflict; }\r
+ void SetConflictedResourcesNum(int n) { m_n_conflicted_rsc = n; }\r
+ int GetConflictedResourcesNum(void) { return m_n_conflicted_rsc; }\r
+\r
+ int GetActiveAudioOut(void);\r
+\r
+private:\r
+ std::map<int, int> m_allocated_resources;\r
+ std::map<int, TCResource*> m_requested_resources;\r
+ std::map<int, TCResource*> m_queries;\r
+\r
+ std::string m_app_id;\r
+ int m_handle;\r
+ int m_rsc_index;\r
+ int m_query_index;\r
+ int m_allocated_rsc_index;\r
+ int m_n_conflict;\r
+ int m_n_conflicted_rsc;\r
+};\r
+\r
+#endif //__TC_PLAYER_H__
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __TC_RESOURCE_H__\r
+#define __TC_RESOURCE_H__\r
+\r
+class TCResource\r
+{\r
+public:\r
+ TCResource(int category_id, int category_option, int state);\r
+ ~TCResource();\r
+\r
+ int GetCategoryId(void) {return m_category_id;}\r
+ int GetCategoryOption(void) {return m_category_option;}\r
+ int GetState(void) {return m_state;}\r
+\r
+private:\r
+ int m_category_id;\r
+ int m_category_option;\r
+ int m_state;\r
+};\r
+\r
+#endif //__TC_RESOURCE_H__
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+//invoke Tomato LIB\r
+#ifndef __TOMATO_GTEST_H__\r
+#define __TOMATO_GTEST_H__\r
+\r
+#include "TomatoAPI.h"\r
+\r
+//Set TC-config to tomato via Gtest macro\r
+#undef GTEST_TEST_\r
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\\r
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\\r
+ public:\\r
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\\r
+ private:\\r
+ virtual void TestBody();\\r
+ virtual void TestBody_();\\r
+ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\\r
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(\\r
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\\r
+};\\r
+\\r
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\\r
+ ::test_info_ =\\r
+ ::testing::internal::MakeAndRegisterTestInfo(\\r
+ #test_case_name, #test_name, NULL, NULL, \\r
+ (parent_id), \\r
+ parent_class::SetUpTestCase, \\r
+ parent_class::TearDownTestCase, \\r
+ new ::testing::internal::TestFactoryImpl<\\r
+ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\\r
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()\\r
+{\\r
+ CTomatoAPI::BeginTestCase(#test_name);\\r
+ this->TestBody_();\\r
+ CTomatoAPI::EndTestCase();\\r
+}\\r
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody_()\r
+\r
+// Re-define Gtest macro for redirecting gtest-report to tomato\r
+/*\r
+ EXPECT_EQ\r
+ ASSERT_EQ\r
+\r
+ @ refer to "gtest_pred_impl.h"\r
+*/\r
+// parvin.kumar\r
+\r
+#undef GTEST_PRED_FORMAT2_\r
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\\r
+ GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), v2, on_failure) \\r
+\r
+#undef GTEST_ASSERT_\r
+#define GTEST_ASSERT_(expression, v2, on_failure) \\r
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \\r
+ if (const ::testing::AssertionResult gtest_ar = (expression)) {\\r
+ CTomatoAPI::WriteTestResult( #v2, true , "success"); { \\r
+ else \\r
+ { on_failure(gtest_ar.failure_message()); \\r
+ CTomatoAPI::WriteTestResult( #v2, false , gtest_ar.failure_message()); {\r
+\r
+\r
+/*\r
+ EXPECT_TRUE : return TRUE -> PASS\r
+ EXPECT_FALSE : return FALSE -> PASS\r
+ ASSERT_TRUE\r
+ ASSERT_FALSE\r
+*/\r
+\r
+\r
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be\r
+// either a boolean expression or an AssertionResult. text is a textual\r
+// representation of expression as it was passed into the EXPECT_TRUE.\r
+#undef GTEST_TEST_BOOLEAN_\r
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \\r
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \\r
+ if (const ::testing::AssertionResult gtest_ar_ = \\r
+ ::testing::AssertionResult(expression)) {\\r
+ CTomatoAPI::WriteTestResult( text, true , "success"); { \\r
+ else {\\r
+ fail(::testing::internal::GetBoolAssertionFailureMessage(gtest_ar_, text, #actual, #expected).c_str());\\r
+ CTomatoAPI::WriteTestResult( test, false , ::testing::internal::GetBoolAssertionFailureMessage(gtest_ar_, text, #actual, #expected).c_str()); {\r
+\r
+\r
+#endif //__TOMATO_GTEST_H__\r
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __UT_LOG_H__\r
+#define __UT_LOG_H__\r
+\r
+#include <dlog.h>\r
+\r
+#ifdef LOG_TAG\r
+#undef LOG_TAG\r
+#endif//LOG_TAG\r
+\r
+#define LOG_TAG "RSC_CENTER_TC"\r
+#define RC_TEST_ERR(fmt, ...) LOGE(fmt, ##__VA_ARGS__)\r
+#define RC_TEST_INFO(fmt, ...) LOGI(fmt, ##__VA_ARGS__)\r
+#define RC_TEST_DBG(fmt, ...) LOGD(fmt, ##__VA_ARGS__)\r
+\r
+#endif //__UT_LOG_H__
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#ifndef __UT_UTIL_H__\r
+#define __UT_UTIL_H__\r
+#include <glib.h>\r
+#include <rm_api.h>\r
+#include <ri-api.h>\r
+\r
+int AddZoneInfo(int category_id, int zone_id);\r
+\r
+class CResourceManagerAPI\r
+{\r
+public:\r
+\r
+ typedef enum {\r
+ CB_NORMAL = 0,\r
+ CB_COUNT\r
+ } cb_option;\r
+\r
+ static CResourceManagerAPI* GetInstance();\r
+ static gboolean SetAppZoneIdAsync(gpointer data);\r
+ static gboolean SetAudioFocusAsync(gpointer data);\r
+\r
+ void Reset(void);\r
+ int RegisterPlayer(int cb_option, int expected);\r
+ int RegisterPlayer(std::string app_id, int cb_option, int expected);\r
+ int SetAppZoneIdAsync(std::string app_id, int zone_id, int sleep_sec);\r
+ int SetAudioFocusAsync(int zone_id, int sleep_sec);\r
+\r
+private:\r
+ CResourceManagerAPI() = default;\r
+ ~CResourceManagerAPI() = default;\r
+\r
+ rm_resource_cb GetConflictCB(int option);\r
+ static rm_cb_result ConflictCB(int handle, rm_callback_type event, rm_device_request_s *info, void* data);\r
+ static rm_cb_result ConflictCBCount(int handle, rm_callback_type event, rm_device_request_s *info, void* data);\r
+\r
+ static CResourceManagerAPI* m_instance;\r
+ int m_conflict_count;\r
+};\r
+\r
+\r
+class CVideoCategory\r
+{\r
+public:\r
+ CVideoCategory();\r
+ ~CVideoCategory() = default;\r
+\r
+ void SetProperties(std::string name, int width, int height, int framerate, int color_depth, int sampling);\r
+ ri_video_category_option_request_s* Build(void);\r
+ int GetCapableCategoryId(void);\r
+\r
+private:\r
+ void ResetProperties(void);\r
+ ri_video_category_option_request_s m_option;\r
+};\r
+\r
+class CAppInfo{\r
+public:\r
+ CAppInfo() = default;\r
+ ~CAppInfo() = default;\r
+\r
+ void SetAppId(std::string app_id) {m_app_id = app_id;}\r
+ std::string GetAppId(void) {return m_app_id;}\r
+ void SetZoneId(int id) {m_zone_id = id;}\r
+ int GetZoneId(void) {return m_zone_id;}\r
+ void SetSleep(int sec) {m_sleep = sec;}\r
+ int GetSleep(void) {return m_sleep;}\r
+\r
+private:\r
+ std::string m_app_id;\r
+ int m_zone_id;\r
+ int m_sleep;\r
+};\r
+\r
+class CFocusInfo{\r
+public:\r
+ CFocusInfo() = default;\r
+ ~CFocusInfo() = default;\r
+\r
+ void SetZoneId(int id) {m_zone_id = id;}\r
+ int GetZoneId(void) {return m_zone_id;}\r
+ void SetSleep(int sec) {m_sleep = sec;}\r
+ int GetSleep(void) {return m_sleep;}\r
+private:\r
+ int m_sleep;\r
+ int m_zone_id;\r
+};\r
+#endif //__UT_UTIL_H__
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "gtest/gtest.h"\r
+#include <resource_center.h>\r
+#include "TCApp.h"\r
+\r
+TCApp::TCApp(const char* app_id)\r
+{\r
+ if (app_id)\r
+ m_app_id.assign(app_id);\r
+ else\r
+ m_app_id.assign("");\r
+\r
+ m_cb_count = 0;\r
+\r
+ m_max_width = 0;\r
+ m_max_height = 0;\r
+ m_max_framerate = 0;\r
+}\r
+\r
+TCApp::~TCApp()\r
+{\r
+}\r
+\r
+void TCApp::ResourceChangedCb(const char* app_id, rc_resource_h rsc, void *data)\r
+{\r
+ int w;\r
+ int h;\r
+ int f;\r
+\r
+ if (!data)\r
+ return;\r
+\r
+ TCApp* app = (TCApp*) data;\r
+ app->IncreaseCbCount();\r
+\r
+ EXPECT_STREQ(app->GetAppId().c_str(), app_id);\r
+\r
+ if (rc_rsc_max_resolution_changed(rsc))\r
+ {\r
+ EXPECT_EQ(0, rc_rsc_get_video_max_resolution(rsc, &w, &h, &f));\r
+ app->SetMaxResolution(w, h, f);\r
+ app->SetMaxRszChanged(true);\r
+ }\r
+\r
+ if (rc_rsc_audio_out_changed(rsc))\r
+ {\r
+ app->SetAudioRscChanged(true);\r
+ }\r
+}\r
+\r
+int TCApp::RegisterResourceChangeCb(void)\r
+{\r
+ return rc_register_resource_change_callback(m_app_id.c_str(), TCApp::ResourceChangedCb, this);\r
+}\r
+\r
+int TCApp::UnregisterResourceChangeCb(void)\r
+{\r
+ return rc_unregister_resource_change_callback(m_app_id.c_str(), TCApp::ResourceChangedCb);\r
+}
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "gtest/gtest.h"\r
+#include <rm_api.h>\r
+#include <rm_module_api.h>\r
+#include <ut_log.h>\r
+#include <ri-api.h>\r
+#include <ri-module-api.h>\r
+#include <resource_center.h>\r
+#include "TCResource.h"\r
+#include "TCPlayer.h"\r
+\r
+TCPlayer::TCPlayer()\r
+{\r
+ m_handle = 0;\r
+ m_allocated_rsc_index = 0;\r
+ m_rsc_index = 0;\r
+ m_query_index = 0;\r
+ m_n_conflict = 0;\r
+ m_n_conflicted_rsc = 0;\r
+}\r
+\r
+TCPlayer::~TCPlayer()\r
+{\r
+ Unregister();\r
+}\r
+\r
+rm_cb_result TCPlayer::ConflictCb(int handle, rm_callback_type event, rm_device_request_s *info, void* data)\r
+{\r
+ if (!data)\r
+ return RM_CB_RESULT_ERROR;\r
+\r
+ TCPlayer *player = (TCPlayer*) data;\r
+ player->IncreaseConflictNum();\r
+ player->SetConflictedResourcesNum(info->request_num);\r
+\r
+ rm_deallocate_resources(handle, info);\r
+\r
+ return RM_CB_RESULT_OK;\r
+}\r
+\r
+int TCPlayer::Register(void)\r
+{\r
+ if (m_handle != 0)\r
+ return RM_ERROR;\r
+\r
+ return rm_register(TCPlayer::ConflictCb, this, &m_handle, NULL);\r
+}\r
+\r
+int TCPlayer::Unregister(void)\r
+{\r
+ int result = RM_ERROR;;\r
+\r
+ RemoveResources();\r
+ RemoveQueries();\r
+ m_allocated_resources.clear();\r
+\r
+ result = rm_unregister(m_handle);\r
+ m_handle = 0;\r
+\r
+ return result;\r
+}\r
+\r
+int TCPlayer::SetPriority(int priority)\r
+{\r
+ return rm_set_priority(m_handle, priority);\r
+}\r
+\r
+int TCPlayer::SetAppId(std::string app_id)\r
+{\r
+ m_app_id = app_id;\r
+ return rm_set_app_id(m_handle, (char*) app_id.c_str());\r
+}\r
+\r
+int TCPlayer::AddResource(int category_id, int state)\r
+{\r
+ TCResource* rsc = new TCResource(category_id, 0, state);\r
+ m_rsc_index++;\r
+ m_requested_resources.insert(std::pair<int, TCResource*>(m_rsc_index, rsc));\r
+ return 0;\r
+}\r
+\r
+int TCPlayer::AddResource(int category_id, int category_option, int state)\r
+{\r
+ TCResource* rsc = new TCResource(category_id, category_option, state);\r
+ m_rsc_index++;\r
+ m_requested_resources.insert(std::pair<int, TCResource*>(m_rsc_index, rsc));\r
+ return 0;\r
+}\r
+\r
+int TCPlayer::AddQuery(int category_id, int category_option, int state)\r
+{\r
+ TCResource* rsc = new TCResource(category_id, category_option, state);\r
+ m_query_index++;\r
+ m_queries.insert(std::pair<int, TCResource*>(m_query_index, rsc));\r
+ return 0;\r
+}\r
+\r
+void TCPlayer::RemoveResources(void)\r
+{\r
+ TCResource *rsc = nullptr;\r
+\r
+ for (auto &it : m_requested_resources) {\r
+ rsc = it.second;\r
+ if (rsc)\r
+ delete rsc;\r
+ }\r
+ m_requested_resources.clear();\r
+ m_rsc_index = 0;\r
+}\r
+\r
+int TCPlayer::GetAudioCategory(std::string codec_name, int mixing_mode)\r
+{\r
+ ri_audio_category_option_request_s audio_option;\r
+ memset(&audio_option, 0, sizeof(ri_audio_category_option_request_s));\r
+\r
+ audio_option.codec_name = codec_name.c_str();\r
+ audio_option.mixing_mode = (ri_audio_mixing_mode) mixing_mode;\r
+\r
+ return ri_get_capable_audio_category_id(&audio_option);\r
+}\r
+\r
+int TCPlayer::GetCapableVideoCategory(std::string codec_name, int h_size, int v_size, int color_depth, int sampling_format, int framerate)\r
+{\r
+ ri_video_category_option_request_s opt;\r
+ memset(&opt, 0, sizeof(ri_video_category_option_request_s));\r
+\r
+ opt.codec_name = strndup(codec_name.c_str(), codec_name.length());\r
+ opt.color_depth = color_depth;\r
+ opt.framerate = framerate;\r
+ opt.h_size = h_size;\r
+ opt.v_size = v_size;\r
+ opt.sampling_format = sampling_format;\r
+\r
+ return ri_get_capable_video_category_id(&opt);\r
+}\r
+\r
+int TCPlayer::GetCapableCategoryIdFromRC(int category_id)\r
+{\r
+ return rc_get_capable_category_id(m_handle, m_app_id.c_str(), category_id);\r
+}\r
+\r
+int TCPlayer::Query(int query_type, int *ans)\r
+{\r
+ rm_category_request_s req;\r
+ memset(&req, 0, sizeof(rm_category_request_s));\r
+\r
+ int i = 0;\r
+ int result = RM_ERROR;\r
+ int answer;\r
+\r
+ req.request_num = m_queries.size();\r
+\r
+ for (auto &it : m_queries) {\r
+ TCResource *rsc = it.second;\r
+ req.category_id[i] = (rm_rsc_category_e) rsc->GetCategoryId();\r
+ req.category_option[i] = rsc->GetCategoryOption();\r
+ req.state[i] = (rm_requests_resource_state_e) rsc->GetState();\r
+ i++;\r
+ }\r
+\r
+ result = rm_query(m_handle, (rm_query_type_e) query_type, &req, &answer);\r
+ *ans = answer;\r
+\r
+ return result;\r
+}\r
+\r
+void TCPlayer::RemoveQueries(void)\r
+{\r
+ TCResource *rsc = nullptr;\r
+\r
+ for (auto &it : m_queries) {\r
+ rsc = it.second;\r
+ if (rsc)\r
+ delete rsc;\r
+ }\r
+ m_queries.clear();\r
+}\r
+\r
+void TCPlayer::AddAllocatedResource(int device_id)\r
+{\r
+ m_allocated_resources.insert(std::pair<int, int>(++m_allocated_rsc_index, device_id));\r
+}\r
+\r
+int TCPlayer::GetAllocatedResourceId(int index)\r
+{\r
+ auto it = m_allocated_resources.find(index);\r
+\r
+ return (it == m_allocated_resources.end()) ? -1 : it->second;\r
+}\r
+\r
+int TCPlayer::AllocateResources(void)\r
+{\r
+ if (m_requested_resources.size() == 0)\r
+ return RM_ERROR;\r
+\r
+ int i = 0;\r
+ int result = RM_ERROR;\r
+\r
+ rm_category_request_s req;\r
+ memset(&req, 0, sizeof(rm_category_request_s));\r
+\r
+ req.request_num = m_requested_resources.size();\r
+\r
+ for (auto &it : m_requested_resources) {\r
+ TCResource *rsc = it.second;\r
+ req.category_id[i] = (rm_rsc_category_e) rsc->GetCategoryId();\r
+ req.category_option[i] = rsc->GetCategoryOption();\r
+ req.state[i] = (rm_requests_resource_state_e) rsc->GetState();\r
+ i++;\r
+ }\r
+\r
+ rm_device_return_s allocated;\r
+ memset(&allocated, 0, sizeof(allocated));\r
+\r
+ result = rm_allocate_resources(m_handle, &req, &allocated);\r
+\r
+ if (result == RM_OK) {\r
+ for (int j = 0; j < allocated.allocated_num; j++)\r
+ AddAllocatedResource(allocated.device_id[j]);\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+int TCPlayer::ReleaseResources(void)\r
+{\r
+ if (m_allocated_resources.size() <= 0)\r
+ return RM_ERROR;\r
+\r
+ int i = 0;\r
+ rm_device_request_s req;\r
+ memset(&req, 0, sizeof(req));\r
+\r
+ req.request_num = m_allocated_resources.size();\r
+\r
+ for (auto &it : m_allocated_resources) {\r
+ req.device_id[i] = it.second;\r
+ i++;\r
+ }\r
+\r
+ m_allocated_resources.clear();\r
+ m_allocated_rsc_index = 0;\r
+\r
+ return rm_deallocate_resources(m_handle, &req);\r
+}\r
+\r
+int TCPlayer::ReleaseResource(int index)\r
+{\r
+ if (m_allocated_resources.size() <= 0)\r
+ return RM_ERROR;\r
+\r
+ auto it = m_allocated_resources.find(index);\r
+ int device_id = (it == m_allocated_resources.end()) ? -1 : it->second;\r
+\r
+ rm_device_request_s req;\r
+ memset(&req, 0, sizeof(req));\r
+\r
+ req.request_num = 1;\r
+ req.device_id[0] = device_id;\r
+\r
+ m_allocated_resources.erase(index);\r
+\r
+ return rm_deallocate_resources(m_handle, &req);\r
+}\r
+\r
+int TCPlayer::GetActiveAudioOut(void)\r
+{\r
+ return rm_get_active_audio_out(m_handle);\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "TCResource.h"\r
+\r
+TCResource::TCResource(int category_id, int category_option, int state)\r
+{\r
+ m_category_id = category_id;\r
+ m_category_option = category_option;\r
+ m_state = state;\r
+}\r
+\r
+TCResource::~TCResource()\r
+{\r
+}\r
--- /dev/null
+/*
+ * Copyright (c) 2024 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 "gtest/gtest.h"
+#include <rm_api.h>
+#include <rm_module_api.h>
+#include <ri-api.h>
+#include <ri-module-api.h>
+#include <resource_center.h>
+
+#include <ut_log.h>
+
+#ifdef TOMATO
+#include "tomatoGtest.h"
+#endif//TOMATO
+
+static void _delay(int sec)
+{
+ sleep(sec);
+}
+
+TEST(UT_RSC, rc_set_resource_policy_p1)
+{
+ RC_TEST_INFO("rc_set_resource_policy_p1 start...");
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_N_DECODING_MV));
+ RC_TEST_INFO("rc_set_resource_policy_p1 end...");
+ _delay(1);
+}
+
+TEST(UT_RSC, rc_set_resource_policy_n1)
+{
+
+ RC_TEST_INFO("rc_set_resource_policy_n1 start...");
+ rc_rsc_policy_e val = (rc_rsc_policy_e) -1;
+ EXPECT_NE(0, rc_set_resource_policy(val));
+
+ val = (rc_rsc_policy_e) 100;
+ EXPECT_NE(0, rc_set_resource_policy(val));
+ RC_TEST_INFO("rc_set_resource_policy_n1 end...");
+ _delay(1);
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p1)
+{
+ /*
+ * Test scenario
+ * App - 3rd party app
+ * Resource policy - Normal
+ * > 1. Set resource policy to Normal
+ * > 2. Get category id of video scaler
+ * > Expected Result
+ * - The passed value shall be returned
+ */
+ RC_TEST_INFO("rc_get_capable_category_id_p1 start...");
+
+ int category = RM_CATEGORY_SCALER;
+ const char* app_id = "org.tizen.test";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+ EXPECT_EQ(category, rc_get_capable_category_id(100, app_id, category));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p1 end...");
+ _delay(1);
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p2)
+{
+ // Check return values for the categories not interested in
+ RC_TEST_INFO("rc_get_capable_category_id_p2 start...");
+
+ int category = RM_CATEGORY_TUNER;
+ const char* app_id = "org.tizen.test";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_N_DECODING_MV));
+
+ EXPECT_EQ(category, rc_get_capable_category_id(100, app_id, category));
+
+ category = RM_CATEGORY_EXT_AUDIO_SRC_HDMI;
+ EXPECT_EQ(category, rc_get_capable_category_id(100, app_id, category));
+
+ category = RM_CATEGORY_VIDEO_ENCODER;
+ EXPECT_EQ(category, rc_get_capable_category_id(100, app_id, category));
+
+ category = RM_CATEGORY_EXT_HDMI_SRC;
+ EXPECT_EQ(category, rc_get_capable_category_id(100, app_id, category));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p2 end...");
+ _delay(1);
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p3)
+{
+ RC_TEST_INFO("rc_get_capable_category_id_p3 start...");
+
+ const char* app_id = "org.tizen.tv-viewer";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+
+ ri_category_option_request_s req;
+ memset(&req, 0, sizeof(ri_category_option_request_s));
+
+ req.codec_name = RI_CODEC_NAME_HEVC;
+ req.preferred_mode = RI_TVP_VDEC_MODE_SPECIFIC;
+
+ ri_category_option_return_s result;
+ memset(&result, 0, sizeof(ri_category_option_return_s));
+
+ EXPECT_EQ(0, ri_get_video_category_id_by_codec(&req, &result));
+ EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_30P, result.category_option);
+ EXPECT_EQ(result.category_option, rc_get_capable_category_id(100, app_id, result.category_option));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p3 end...");
+ _delay(1);
+}
+
+static void max_rez_change_cb(const char* app_id, int width, int height, int framerate, void* data)
+{
+
+}
+
+TEST(UT_RSC, rc_register_max_video_resolution_changed_callback_p1)
+{
+ RC_TEST_INFO("rc_register_max_video_resolution_changed_callback_p1 start...");
+
+ const char* app_id = "com.samsung.tv.cobalt";
+
+ EXPECT_EQ(0, rc_register_max_video_resolution_changed_callback(app_id, max_rez_change_cb, NULL));
+ EXPECT_EQ(0, rc_unregister_max_video_resolution_changed_callback(app_id, max_rez_change_cb));
+
+ RC_TEST_INFO("rc_register_max_video_resolution_changed_callback_p1 end...");
+}
+
+TEST(UT_RSC, rc_register_max_video_resolution_changed_callback_n1)
+{
+ RC_TEST_INFO("rc_register_max_video_resolution_changed_callback_n1 start...");
+
+ const char* app_id = "com.samsung.tv.cobalt";
+
+ EXPECT_NE(0, rc_unregister_max_video_resolution_changed_callback(app_id, max_rez_change_cb));
+ EXPECT_EQ(0, rc_register_max_video_resolution_changed_callback(app_id, max_rez_change_cb, NULL));
+ EXPECT_EQ(0, rc_unregister_max_video_resolution_changed_callback(app_id, max_rez_change_cb));
+ EXPECT_NE(0, rc_unregister_max_video_resolution_changed_callback(app_id, max_rez_change_cb));
+
+ RC_TEST_INFO("rc_register_max_video_resolution_changed_callback_n1 end...");
+}
+
+TEST(UT_RSC, rc_register_max_video_resolution_changed_callback_n2)
+{
+ RC_TEST_INFO("rc_register_max_video_resolution_changed_callback_n2 start...");
+
+ const char* app_id = "com.samsung.tv.cobalt";
+
+ EXPECT_NE(0, rc_register_max_video_resolution_changed_callback(NULL, max_rez_change_cb, NULL));
+ EXPECT_NE(0, rc_register_max_video_resolution_changed_callback(app_id, NULL, NULL));
+
+ EXPECT_NE(0, rc_unregister_max_video_resolution_changed_callback(NULL, max_rez_change_cb));
+ EXPECT_NE(0, rc_unregister_max_video_resolution_changed_callback(app_id, NULL));
+
+ RC_TEST_INFO("rc_register_max_video_resolution_changed_callback_n2 end...");
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p4)
+{
+ RC_TEST_INFO("rc_get_capable_category_id_p4 start...");
+
+ const char* app_id = "";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_N_DECODING_MV));
+
+ // app id shall be a valid application id in N Decoding MV
+ EXPECT_EQ(RI_CATEGORY_NOT_PERMITTED, rc_get_capable_category_id(100, app_id, RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P));
+ EXPECT_EQ(RI_CATEGORY_NOT_PERMITTED, rc_get_capable_category_id(100, app_id, RI_CATEGORY_AUDIO_MAIN_OUT));
+ EXPECT_EQ(RI_CATEGORY_NOT_PERMITTED, rc_get_capable_category_id(100, app_id, RI_CATEGORY_AUDIO_DECODER_AC4));
+ EXPECT_EQ(RI_CATEGORY_NOT_PERMITTED, rc_get_capable_category_id(100, app_id, RI_CATEGORY_SCALER));
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p4 end...");
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p5)
+{
+ RC_TEST_INFO("rc_get_capable_category_id_p5 start...");
+
+ const char* app_id = "";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+
+ // In case app id is invalid, return the passed value as it is
+ EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P, rc_get_capable_category_id(100, app_id, RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P));
+ EXPECT_EQ(RI_CATEGORY_AUDIO_MAIN_OUT, rc_get_capable_category_id(100, app_id, RI_CATEGORY_AUDIO_MAIN_OUT));
+ EXPECT_EQ(RI_CATEGORY_AUDIO_DECODER_AC4, rc_get_capable_category_id(100, app_id, RI_CATEGORY_AUDIO_DECODER_AC4));
+ EXPECT_EQ(RI_CATEGORY_SCALER, rc_get_capable_category_id(100, app_id, RI_CATEGORY_SCALER));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p5 end...");
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p6)
+{
+ RC_TEST_INFO("rc_get_capable_category_id_p6 start...");
+
+ const char* app_id = "org.tizen.tv-viewer";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+
+ // In case resource policy is normal, return the passed value as it is
+ EXPECT_EQ(RI_CATEGORY_NONE, rc_get_capable_category_id(100, app_id, RI_CATEGORY_NONE));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p6 end...");
+}
+
+TEST(UT_RSC, rc_get_capable_category_id_p7)
+{
+ RC_TEST_INFO("rc_get_capable_category_id_p7 start...");
+
+ const char* app_id = "org.tizen.tv-viewer";
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_N_DECODING_MV));
+
+ // In case resource policy is n-decoding, return Not permitted value shall be returned
+ EXPECT_EQ(RI_CATEGORY_NOT_PERMITTED, rc_get_capable_category_id(100, app_id, RI_CATEGORY_NONE));
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+
+ RC_TEST_INFO("rc_get_capable_category_id_p7 end...");
+}
+
+TEST(UT_RSC, rc_get_focused_zone_info_p1)
+{
+ RC_TEST_INFO("rc_get_focused_zone_info_p1 start...");
+
+ const char* app_id = "org.tizen.rc_test";
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_N_DECODING_MV));
+ EXPECT_EQ(0, rc_set_app_zone_info(app_id, 1));
+ EXPECT_EQ(0, rc_set_audio_focus(1));
+
+ rc_zone_h zone_info;
+ EXPECT_EQ(0, rc_get_focused_zone(&zone_info));
+
+ EXPECT_EQ(1, rc_zone_get_id(zone_info));
+ EXPECT_EQ(-1, rc_zone_get_scaler_id(zone_info));
+ EXPECT_STREQ(app_id, rc_zone_get_app_id(zone_info));
+
+ rc_zone_free(zone_info);
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+
+ RC_TEST_INFO("rc_get_focused_zone_info_p1 end...");
+}
+
+TEST(UT_RSC, rc_get_focused_zone_info_n1)
+{
+ RC_TEST_INFO("rc_get_focused_zone_info_n1 start...");
+
+ rc_zone_h zone_info;
+ EXPECT_EQ(0, rc_get_focused_zone(&zone_info));
+
+ EXPECT_EQ(0, rc_zone_get_id(zone_info));
+ EXPECT_EQ(-1, rc_zone_get_scaler_id(zone_info));
+ EXPECT_STREQ("", rc_zone_get_app_id(zone_info));
+
+ rc_zone_free(zone_info);
+
+ EXPECT_EQ(0, rc_set_resource_policy(RC_RSC_POLICY_NORMAL));
+ RC_TEST_INFO("rc_get_focused_zone_info_n1 end...");
+}
+
+static void rsc_change_cb(const char* app_id, rc_resource_h rsc, void* data)
+{
+
+}
+
+TEST(UT_RSC, rc_register_resource_change_callback_p1)
+{
+ RC_TEST_INFO("rc_register_resource_change_callback_p1 start...");
+ const char* app_id = "org.tizen.rc_test";
+ EXPECT_EQ(0, rc_register_resource_change_callback(app_id, rsc_change_cb, NULL));
+ EXPECT_EQ(0, rc_unregister_resource_change_callback(app_id, rsc_change_cb));
+ RC_TEST_INFO("rc_register_resource_change_callback_p1 end...");
+}
--- /dev/null
+/*
+ * Copyright (c) 2024 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 "gtest/gtest.h"
+
+#include <ut_log.h>
+
+#ifdef TOMATO
+#include "tomatoGtest.h"
+#endif//TOMATO
+
+
+static gpointer tc_run_loop(gpointer data)
+{
+ RC_TEST_INFO("Run callback thread");
+ GMainLoop *main_loop = (GMainLoop*) data;
+
+ if (main_loop != NULL) {
+ g_main_loop_run(main_loop);
+ }
+
+ RC_TEST_INFO("callback thread terminated");
+ return NULL;
+}
+
+GTEST_API_ int main(int argc, char **argv)
+{
+ printf("Running main() from ut_main.cpp\n");
+
+ int ret;
+
+ GMainContext *context = g_main_context_new();
+ GMainLoop *main_loop = g_main_loop_new(context, FALSE);
+ GThread *cb_thread = g_thread_new("rc_cb_thread", tc_run_loop, main_loop);
+
+ if (cb_thread == NULL) {
+ g_main_loop_unref(main_loop);
+ RC_TEST_ERR("failed to create the callback thread");
+ }
+
+ testing::InitGoogleTest(&argc, argv);
+
+ ret = RUN_ALL_TESTS();
+
+ return ret;
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "gtest/gtest.h"\r
+#include <rm_api.h>\r
+#include <resource_center.h>\r
+#include <ut_util.h>\r
+\r
+CResourceManagerAPI* CResourceManagerAPI::m_instance = NULL;\r
+\r
+CResourceManagerAPI* CResourceManagerAPI::GetInstance()\r
+{\r
+ if (!m_instance)\r
+ m_instance = new CResourceManagerAPI();\r
+\r
+ return m_instance;\r
+}\r
+\r
+void CResourceManagerAPI::Reset(void)\r
+{\r
+ m_conflict_count = 0;\r
+}\r
+\r
+rm_resource_cb CResourceManagerAPI::GetConflictCB(int option)\r
+{\r
+ if (option == CB_NORMAL)\r
+ return &CResourceManagerAPI::ConflictCB;\r
+\r
+ if (option == CB_COUNT)\r
+ return &CResourceManagerAPI::ConflictCBCount;\r
+\r
+ return &CResourceManagerAPI::ConflictCB;\r
+}\r
+\r
+\r
+rm_cb_result CResourceManagerAPI::ConflictCB(int handle, rm_callback_type event, rm_device_request_s *info, void* data)\r
+{\r
+ rm_unregister(handle);\r
+ return RM_CB_RESULT_OK;\r
+}\r
+\r
+rm_cb_result CResourceManagerAPI::ConflictCBCount(int handle, rm_callback_type event, rm_device_request_s *info, void* data)\r
+{\r
+ CResourceManagerAPI* api = (CResourceManagerAPI*) data;\r
+ api->m_conflict_count++;\r
+ rm_unregister(handle);\r
+ return RM_CB_RESULT_OK;\r
+}\r
+\r
+int CResourceManagerAPI::RegisterPlayer(int option, int expected)\r
+{\r
+ int handle = 0;\r
+\r
+ EXPECT_EQ(expected, rm_register(GetConflictCB(option), this, &handle, NULL));\r
+\r
+ return handle;\r
+}\r
+\r
+int CResourceManagerAPI::RegisterPlayer(std::string app_id, int option, int expected)\r
+{\r
+ return 0;\r
+}\r
+\r
+gboolean CResourceManagerAPI::SetAppZoneIdAsync(gpointer data)\r
+{\r
+ CAppInfo *app_info = (CAppInfo*) data;\r
+ sleep(app_info->GetSleep());\r
+ EXPECT_EQ(0, rc_set_app_zone_info(app_info->GetAppId().c_str(), app_info->GetZoneId()));\r
+ delete app_info;\r
+ return G_SOURCE_REMOVE;\r
+}\r
+\r
+int CResourceManagerAPI::SetAppZoneIdAsync(std::string app_id, int zone_id, int sleep_sec)\r
+{\r
+ CAppInfo *app_info = new CAppInfo();\r
+ app_info->SetAppId(app_id);\r
+ app_info->SetZoneId(zone_id);\r
+ app_info->SetSleep(sleep_sec);\r
+\r
+ g_idle_add(&CResourceManagerAPI::SetAppZoneIdAsync, app_info);\r
+ return 0;\r
+}\r
+\r
+gboolean CResourceManagerAPI::SetAudioFocusAsync(gpointer data)\r
+{\r
+ CFocusInfo *focus_info = (CFocusInfo*) data;\r
+ sleep(focus_info->GetSleep());\r
+ EXPECT_EQ(0, rc_set_audio_focus(focus_info->GetZoneId()));\r
+ delete focus_info;\r
+ return G_SOURCE_REMOVE;\r
+}\r
+\r
+int CResourceManagerAPI::SetAudioFocusAsync(int zone_id, int sleep_sec)\r
+{\r
+ CFocusInfo *focus_info = new CFocusInfo();\r
+ focus_info->SetZoneId(zone_id);\r
+ focus_info->SetSleep(sleep_sec);\r
+\r
+ g_idle_add(&CResourceManagerAPI::SetAudioFocusAsync, focus_info);\r
+ return 0;\r
+}\r
+\r
+CVideoCategory::CVideoCategory()\r
+{\r
+ m_option.codec_name = NULL;\r
+ m_option.h_size = 0;\r
+ m_option.v_size = 0;\r
+ m_option.framerate = 0;\r
+ m_option.color_depth = 0;\r
+ m_option.sampling_format = 0;\r
+}\r
+\r
+void CVideoCategory::SetProperties(std::string codec, int width, int height, int framerate, int color_depth, int sampling)\r
+{\r
+ ResetProperties();\r
+\r
+ m_option.codec_name = strndup(codec.c_str(), codec.length());\r
+ m_option.h_size = width;\r
+ m_option.v_size = height;\r
+ m_option.framerate = framerate;\r
+ m_option.color_depth = color_depth;\r
+ m_option.sampling_format = sampling;\r
+}\r
+\r
+void CVideoCategory::ResetProperties(void)\r
+{\r
+ if (m_option.codec_name) {\r
+ free((void*) m_option.codec_name);\r
+ m_option.codec_name = NULL;\r
+ }\r
+\r
+ m_option.h_size = 0;\r
+ m_option.v_size = 0;\r
+ m_option.framerate = 0;\r
+ m_option.color_depth = 0;\r
+ m_option.sampling_format = 0;\r
+}\r
+\r
+ri_video_category_option_request_s* CVideoCategory::Build(void)\r
+{\r
+ return &m_option;\r
+}\r
+\r
+int CVideoCategory::GetCapableCategoryId(void)\r
+{\r
+ return ri_get_capable_video_category_id(&m_option);\r
+}\r
+\r
+int AddZoneInfo(int category_id, int zone_id)\r
+{\r
+ const int PM_ZONE_ID_OFFSET = 21;\r
+ int zone_info = (zone_id << PM_ZONE_ID_OFFSET);\r
+\r
+ return (category_id | zone_info);\r
+}\r
+\r
--- /dev/null
+resource-center.xml
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<TestCase Name="RESOURCE_CENTER_TEST" Description="RESOURCE_CENTER test" LogFilter="RSC_CENTER:* RSC_CENTER_API:* TOMATOCLIENT:*">
+ <Procedure Number="1" Description="resource center test">
+ <Step Name="start resource center package" Type="EXT_TEST_PACKAGE" Dbus="resource_center_tomato_test_pkg" Permission="ROOT" Command="export COVFILE=/opt/data/vdut/resource_center_ut.cov; /opt/usr/apps/tomato/testcase/resource_center_ut/bin/resource_center_ut --gtest_output=xml:/opt/data/vdut/resource_center_ut.xml">
+ <Input Expirytime="2400" />
+ <Output Type="DetectFile" FilePath="/opt/data/vdut/resource_center_ut.xml" />
+ </Step>
+ </Procedure>
+</TestCase>