apply new version of audio-io for tizen 3.0 36/43036/7
authorKimJeongYeon <jeongyeon.kim@samsung.com>
Tue, 7 Jul 2015 07:46:14 +0000 (16:46 +0900)
committerKimJeongYeon <jeongyeon.kim@samsung.com>
Tue, 14 Jul 2015 01:35:58 +0000 (10:35 +0900)
[Version] 0.3.5
[Profile] Common
[Issue Type] Add features
[Dependency module] libmm-sound
[Dependency commit] NA
[Comment]
1. Completely re-written with C++.
2. Remove dependancy of sound server.
3. Support audio focus feature for backward compatibility.
4. merged from tizen_2.4_experimental branch(SPIN).

Signed-off-by: KimJeongYeon <jeongyeon.kim@samsung.com>
Change-Id: Id915e895463de3f1e320559c9d17b59a5b66243f

39 files changed:
.gitignore [new file with mode: 0644]
AUTHORS
CMakeLists.txt [changed mode: 0755->0644]
LICENSE [new file with mode: 0644]
LICENSE.APLv2 [deleted file]
doc/audio_io_doc.h [changed mode: 0755->0644]
include/CAudioError.h [new file with mode: 0644]
include/CAudioIO.h [new file with mode: 0644]
include/CAudioIODef.h [new file with mode: 0644]
include/CAudioInfo.h [new file with mode: 0644]
include/CAudioInput.h [new file with mode: 0644]
include/CAudioOutput.h [new file with mode: 0644]
include/CAudioSessionHandler.h [new file with mode: 0644]
include/CPulseAudioClient.h [new file with mode: 0644]
include/CPulseAudioPolicy.h [new file with mode: 0644]
include/CPulseAudioVolume.h [new file with mode: 0644]
include/CPulseStreamSpec.h [new file with mode: 0644]
include/IAudioSessionEventListener.h [new file with mode: 0644]
include/IPulseStreamListener.h [new file with mode: 0644]
include/audio_io.h
include/audio_io_private.h [deleted file]
include/cpp_audio_io.h [new file with mode: 0644]
packaging/capi-media-audio-io.manifest
packaging/capi-media-audio-io.spec
src/audio_io.c
src/audio_io_private.c [deleted file]
src/cpp/CAudioError.cpp [new file with mode: 0644]
src/cpp/CAudioIO.cpp [new file with mode: 0644]
src/cpp/CAudioInfo.cpp [new file with mode: 0644]
src/cpp/CAudioInput.cpp [new file with mode: 0644]
src/cpp/CAudioOutput.cpp [new file with mode: 0644]
src/cpp/CAudioSessionHandler.cpp [new file with mode: 0644]
src/cpp/CPulseAudioClient.cpp [new file with mode: 0644]
src/cpp/CPulseAudioPolicy.cpp [new file with mode: 0644]
src/cpp/CPulseAudioVolume.cpp [new file with mode: 0644]
src/cpp/CPulseStreamSpec.cpp [new file with mode: 0644]
src/cpp/cpp_audio_io.cpp [new file with mode: 0644]
test/CMakeLists.txt
test/audio_io_test.c [changed mode: 0755->0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..03736b5
--- /dev/null
@@ -0,0 +1,27 @@
+CMakeCache.txt
+*/CMakeFiles/*
+*.cmake
+CMakeFiles*
+*.a
+*.so
+Testing
+cmake.depends
+cmake.check_depends
+cmake.check_cache
+core
+core.*
+gmon.out
+install_manifest.txt
+*~
+.kdev_include_paths
+src.kdev4
+.cproject
+.project
+tet_captured
+tet_lock
+*.pc
+Makefile
+*-test
+*-test_*
+*tester.c
+.gitattributes
diff --git a/AUTHORS b/AUTHORS
index 56edb13317b3826900de85fe8a31ccf86a1794ba..c41c6664c89c22477f563b2d800a91380f0301f5 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,5 @@
 Kangho Hur <kanho.hur@samsung.com>
 Seungkeun Lee <sngn.lee@samsung.com>
 Seungbae Shin <seungbae.shin at samsung.com>
+SeonYoung Jeong <sy7787.jeong@samsung.com>
+JeongYeon Kim <jeongyeon.kim@samsung.com>
old mode 100755 (executable)
new mode 100644 (file)
index f2a7e53..af36fad
@@ -1,4 +1,3 @@
-
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 SET(fw_name "capi-media-audio-io")
 
@@ -10,18 +9,22 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(INC_DIR include)
 INCLUDE_DIRECTORIES(${INC_DIR})
 
-SET(dependents "dlog mm-sound capi-base-common capi-media-sound-manager")
+SET(dependents "dlog mm-sound capi-base-common capi-media-sound-manager mm-common mm-session libpulse vconf")
 SET(pc_dependents "capi-base-common capi-media-sound-manager")
 
 INCLUDE(FindPkgConfig)
 pkg_check_modules(${fw_name} REQUIRED ${dependents})
 FOREACH(flag ${${fw_name}_CFLAGS})
     SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+    SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}")
 ENDFOREACH(flag)
 
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror")
 SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
 
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -fPIC -Wall -Werror -std=c++0x")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+
 IF("${ARCH}" STREQUAL "arm")
     ADD_DEFINITIONS("-DTARGET")
 ENDIF("${ARCH}" STREQUAL "arm")
@@ -31,8 +34,12 @@ ADD_DEFINITIONS("-DTIZEN_DEBUG")
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}")
 
+aux_source_directory(src/cpp CPPSOURCES)
 aux_source_directory(src SOURCES)
-ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+
+SET(ALL_SRC ${SOURCES} ${CPPSOURCES})
+
+ADD_LIBRARY(${fw_name} SHARED ${ALL_SRC})
 
 SET_TARGET_PROPERTIES(${fw_name}
      PROPERTIES
@@ -55,6 +62,9 @@ INSTALL(
         DIRECTORY ${INC_DIR}/ DESTINATION include/media
         FILES_MATCHING
         PATTERN "*_private.h" EXCLUDE
+        PATTERN "*cpp*.h" EXCLUDE
+        PATTERN "C*.h" EXCLUDE
+        PATTERN "I*.h" EXCLUDE
         PATTERN "${INC_DIR}/*.h"
         )
 
@@ -70,16 +80,16 @@ CONFIGURE_FILE(
 )
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 
-ADD_SUBDIRECTORY(test)
+#ADD_SUBDIRECTORY(test)
 
 IF(UNIX)
 
 ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
 ADD_CUSTOM_COMMAND(
-        DEPENDS clean 
+        DEPENDS clean
         COMMENT "distribution clean"
         COMMAND find
-        ARGS    . 
+        ARGS    .
         -not -name config.cmake -and \(
         -name tester.c -or
         -name Testing -or
@@ -102,4 +112,3 @@ ADD_CUSTOM_COMMAND(
 )
 
 ENDIF(UNIX)
-
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..bbe9d02
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,206 @@
+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
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
deleted file mode 100644 (file)
index f94008a..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
-
-
old mode 100755 (executable)
new mode 100644 (file)
index 4ca1422..ee80e81
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 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.
diff --git a/include/CAudioError.h b/include/CAudioError.h
new file mode 100644 (file)
index 0000000..de1e1fb
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CAUDIOERROR_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CAUDIOERROR_H__
+
+
+#ifdef __cplusplus
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * Audio Error
+     */
+    class CAudioError {
+    public:
+        /* Constants Definition */
+        static const unsigned int MSG_LENGTH = 512;
+
+        enum EError {
+            ERROR_NONE,
+
+            ERROR_INVALID_ARGUMENT,
+            ERROR_INVALID_HANDLE,
+            ERROR_INVALID_SAMPLERATE,
+            ERROR_INVALID_CHANNEL,
+            ERROR_INVALID_FORMAT,
+            ERROR_INVALID_POINTER,
+            ERROR_INVALID_OPERATION,
+
+            ERROR_NOT_INITIALIZED,
+            ERROR_NOT_SUPPORTED,
+
+            ERROR_PERMISSION_DENIED,
+
+            ERROR_DEVICE_NOT_OPENED,
+            ERROR_DEVICE_NOT_CLOSED,
+
+            ERROR_OUT_OF_MEMORY,
+            ERROR_INTERNAL_OPERATION,
+            ERROR_FAILED_OPERATION,
+
+            ERROR_POLICY_BLOCKED,
+            ERROR_POLICY_INTERRUPTED,
+            ERROR_POLICY_DUPLICATED,
+
+            ERROR_MAX
+        };
+
+    private:
+        /* Members */
+        static EError mLastError;
+        static char   mLastErrorMsg[MSG_LENGTH];
+
+        EError        mError;
+        char          mErrorMsg[MSG_LENGTH];
+
+        const char* _convertErrorToString(EError err);
+
+    public:
+        /* Constructor & Destructor */
+        CAudioError(EError err);
+        CAudioError(EError err, const char* fileName, const char* parentFunc, int lineNum);
+        CAudioError(EError err, const char* msg, const char* fileName, const char* parentFunc, int lineNum);
+        //CAudioError(CAudioError& err);
+        ~CAudioError();
+
+        /* Static Methods */
+        static EError getLastError();
+        static const char* getLastErrorMsg();
+
+        /* Setter & Getter */
+        EError getError();
+        const char* getErrorMsg();
+
+        /* Overrided Operation */
+        CAudioError& operator =  (const EError err);
+        CAudioError& operator =  (const CAudioError& err);
+        bool         operator != (const EError err);
+        bool         operator == (const EError err);
+//        friend bool operator == (const CAudioError& src, const EError& err);
+    };
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_CPP_OBJECTS_IO_H__ */
diff --git a/include/CAudioIO.h b/include/CAudioIO.h
new file mode 100644 (file)
index 0000000..b920752
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CAUDIO_IO_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CAUDIO_IO_H__
+
+
+#ifdef __cplusplus
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     *  Abstract Class
+     *  You can't take this object directly.
+     */
+    class IPulseStreamListener;
+    class IAudioSessionEventListener;
+    class CAudioIO : public IPulseStreamListener, public IAudioSessionEventListener {
+    public:
+        struct SStreamCallback {
+            void* mUserData;
+            void (*onStream)(size_t nbytes, void* user_data);
+
+            SStreamCallback() : mUserData(NULL), onStream(NULL)
+            {/* Empty Body */}
+        };
+
+        struct SStateChangedCallback {
+            void* mUserData;
+            void (*onStateChanged)(CAudioInfo::EAudioIOState state, CAudioInfo::EAudioIOState statePrev, bool byPolicy, void* user_data);
+
+            SStateChangedCallback() : mUserData(NULL), onStateChanged(NULL)
+            {/* Empty Body */}
+        };
+
+        struct SInterruptCallback {
+            void* mUserData;
+            void (*onInterrupt)(IAudioSessionEventListener::EInterruptCode code, void* user_data);
+
+            SInterruptCallback() : mUserData(NULL), onInterrupt(NULL)
+            {/* Empty Body */}
+        };
+
+    private:
+        pthread_mutex_t       mMutex;
+        pthread_cond_t        mCond;
+        bool                  mIsInit;
+        bool                  mForceIgnore;
+
+    protected:
+        CAudioSessionHandler* mpAudioSessionHandler;
+        CPulseAudioClient*    mpPulseAudioClient;
+        CAudioInfo            mAudioInfo;
+
+        SStreamCallback       mStreamCallback;
+        SStateChangedCallback mStateChangedCallback;
+        SInterruptCallback    mInterruptCallback;
+
+        CAudioInfo::EAudioIOState mState;
+        CAudioInfo::EAudioIOState mStatePrev;
+        bool                  mByPolicy;
+
+        /* Protected Methods */
+        virtual void setInit(bool flag);
+        virtual bool isInit();
+        virtual bool IsReady();
+
+        void internalLock()   throw (CAudioError);
+        void internalUnlock() throw (CAudioError);
+        void internalWait()   throw (CAudioError);
+        void internalSignal() throw (CAudioError);
+
+        bool isForceIgnore();
+
+    public:
+        /* Constructor & Destructor */
+        CAudioIO();
+        CAudioIO(CAudioInfo& audioInfo);
+        virtual ~CAudioIO();
+
+        /* Pure Virtual Methods */
+        virtual void initialize() throw (CAudioError) = 0;
+        virtual void finalize() = 0;
+
+        virtual void prepare() throw (CAudioError)   = 0;
+        virtual void unprepare() throw (CAudioError) = 0;
+
+        virtual void pause() throw (CAudioError) = 0;
+        virtual void resume() throw (CAudioError) = 0;
+
+        virtual void drain() throw (CAudioError) = 0;
+        virtual void flush() throw (CAudioError) = 0;
+
+        virtual int  getBufferSize() throw (CAudioError) = 0;
+
+        /* Implemented Handlers */
+        virtual void onStream(CPulseAudioClient* pClient, size_t length);
+        virtual void onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy);
+        virtual void onStateChanged(CAudioInfo::EAudioIOState state);
+        virtual void onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info);
+        virtual void onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value);
+
+        /* Methods */
+        CAudioInfo getAudioInfo() throw (CAudioError);
+
+        virtual void setStreamCallback(SStreamCallback callback) throw (CAudioError);
+        SStreamCallback getStreamCallback() throw (CAudioError);
+
+        virtual void setStateChangedCallback(SStateChangedCallback callback) throw (CAudioError);
+        SStateChangedCallback getStateChangedCallback() throw (CAudioError);
+
+        void setInterruptCallback(SInterruptCallback callback) throw (CAudioError);
+        SInterruptCallback getInterruptCallback() throw (CAudioError);
+
+        void ignoreSession() throw (CAudioError);
+    };
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CAUDIO_IO_H__ */
diff --git a/include/CAudioIODef.h b/include/CAudioIODef.h
new file mode 100644 (file)
index 0000000..74bb000
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CAUDIO_DEF_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CAUDIO_DEF_H__
+
+
+#ifdef __cplusplus
+
+
+#include <stdio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "CAudioError.h"
+#include "CAudioInfo.h"
+#include "IAudioSessionEventListener.h"
+#include "CAudioSessionHandler.h"
+#include "IPulseStreamListener.h"
+#include "CPulseAudioVolume.h"
+#include "CPulseAudioPolicy.h"
+#include "CPulseStreamSpec.h"
+#include "CPulseAudioClient.h"
+#include "CAudioIO.h"
+#include "CAudioInput.h"
+#include "CAudioOutput.h"
+
+//#define _AUDIO_IO_DEBUG_TIMING_
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "TIZEN_N_AUDIO_IO"
+
+#define AUDIO_IO_LOGD(_fmt_, arg...) { \
+        LOGD(_fmt_, ##arg);      \
+}
+
+#define AUDIO_IO_LOGW(_fmt_, arg...) { \
+        LOGW(_fmt_, ##arg);      \
+}
+
+#define AUDIO_IO_LOGE(_fmt_, arg...) { \
+        LOGE(_fmt_, ##arg);      \
+}
+
+#define _AUDIO_IO_SHELL_COLOR_
+#ifdef _AUDIO_IO_SHELL_COLOR_
+#define COLOR_BLACK     "\033[0;30m"
+#define COLOR_RED       "\033[0;31m"
+#define COLOR_GREEN     "\033[0;32m"
+#define COLOR_YELLOW    "\033[0;33m"
+#define COLOR_BLUE      "\033[0;34m"
+#define COLOR_MAGENTA   "\033[0;35m"
+#define COLOR_CYAN      "\033[0;36m"
+#define COLOR_GRAY      "\033[0;37m"
+#define COLOR_WHITE     "\033[1;37m"
+#define COLOR_END       "\033[0m"
+#else
+#define COLOR_BLACK
+#define COLOR_RED
+#define COLOR_GREEN
+#define COLOR_BLUE
+#define COLOR_YELLOW
+#define COLOR_MAGENTA
+#define COLOR_CYAN
+#define COLOR_WHITE
+#define COLOR_END
+#endif
+
+
+#define RET_ERROR(_x_)              {return CAudioError((_x_), __FILE__, __func__, __LINE__);};
+#define RET_ERROR_MSG(_x_, _msg_)   {return CAudioError((_x_), (_msg_), __FILE__, __func__, __LINE__);};
+
+#define RET_ERROR_MSG_FORMAT(_x_, _format_, ...) {                     \
+    char _msg_[CAudioError::MSG_LENGTH] = {0, };                       \
+    snprintf(_msg_, CAudioError::MSG_LENGTH, _format_, ##__VA_ARGS__); \
+    return CAudioError((_x_), (_msg_), __FILE__, __func__, __LINE__);  \
+};
+
+
+#define THROW_ERROR(_x_)            {throw  CAudioError((_x_), __FILE__, __func__, __LINE__);};
+#define THROW_ERROR_MSG(_x_, _msg_) {throw  CAudioError((_x_), (_msg_), __FILE__, __func__, __LINE__);};
+
+#define THROW_ERROR_MSG_FORMAT(_x_, _format_, ...) {                   \
+    char _msg_[CAudioError::MSG_LENGTH] = {0, };                       \
+    snprintf(_msg_, CAudioError::MSG_LENGTH, _format_, ##__VA_ARGS__); \
+    throw CAudioError((_x_), (_msg_), __FILE__,  __func__, __LINE__);  \
+};
+
+#define VALID_POINTER_START(_x_) { \
+    if ((_x_) != NULL) {
+
+#define VALID_POINTER_END } \
+}
+
+#define SAFE_DELETE(_x_)   {if ((_x_)) {delete (_x_); (_x_) = NULL;}};
+#define SAFE_FINALIZE(_x_) {if ((_x_)) {(_x_)->finalize();}};
+#define SAFE_REMOVE(_x_)   {if ((_x_)) {(_x_)->finalize(); delete (_x_); (_x_) = NULL;}};
+
+
+#endif
+#endif /* __TIZEN_MEDIA_CPP_OBJECTS_IO_H__ */
diff --git a/include/CAudioInfo.h b/include/CAudioInfo.h
new file mode 100644 (file)
index 0000000..420042f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO__IO_CAUDIO_INFO_H__
+#define __TIZEN_MEDIA_AUDIO__IO_CAUDIO_INFO_H__
+
+
+#ifdef __cplusplus
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * Audio Information
+     */
+    class CAudioInfo {
+    public:
+        const static unsigned int MIN_SYSTEM_SAMPLERATE = 8000;
+        const static unsigned int MAX_SYSTEM_SAMPLERATE = 48000;
+
+        enum EChannel {
+            CHANNEL_MONO = 1,               /**< 1 channel, mono */
+            CHANNEL_STEREO,                 /**< 2 channel, stereo */
+            CHANNEL_MAX
+        };
+
+        enum ESampleType {
+            SAMPLE_TYPE_U8 = 1,             /**< Unsigned 8-bit audio samples */
+            SAMPLE_TYPE_S16_LE,             /**< Signed 16-bit audio samples */
+            SAMPLE_TYPE_MAX
+        };
+
+        enum EAudioType {
+            /* Only Input */
+            AUDIO_IN_TYPE_MEDIA = 0,
+            AUDIO_IN_TYPE_SYSTEM,
+            AUDIO_IN_TYPE_ALARM,
+            AUDIO_IN_TYPE_NOTIFICATION,
+            AUDIO_IN_TYPE_EMERGENCY,
+            AUDIO_IN_TYPE_VOICE_INFORMATION,
+            AUDIO_IN_TYPE_VOICE_RECOGNITION,
+            AUDIO_IN_TYPE_RINGTONE_VOIP,
+            AUDIO_IN_TYPE_VOIP,
+            AUDIO_IN_TYPE_LOOPBACK,   /**< only for loopback */
+
+            /* Only Output */
+            AUDIO_OUT_TYPE_MEDIA,
+            AUDIO_OUT_TYPE_SYSTEM,
+            AUDIO_OUT_TYPE_ALARM,
+            AUDIO_OUT_TYPE_NOTIFICATION,
+            AUDIO_OUT_TYPE_EMERGENCY,
+            AUDIO_OUT_TYPE_VOICE_INFORMATION,
+            AUDIO_OUT_TYPE_VOICE_RECOGNITION,
+            AUDIO_OUT_TYPE_RINGTONE_VOIP,
+            AUDIO_OUT_TYPE_VOIP,
+
+            AUDIO_TYPE_MAX
+        };
+
+        enum EAudioIOState {
+            AUDIO_IO_STATE_NONE,      /**< Audio-io handle is not created */
+            AUDIO_IO_STATE_IDLE,      /**< Audio-io handle is created, but not prepared */
+            AUDIO_IO_STATE_RUNNING,   /**< Audio-io handle is ready and the stream is running */
+            AUDIO_IO_STATE_PAUSED,    /**< Audio-io handle is ready and the stream is paused */
+        };
+
+    private:
+        unsigned int mSampleRate;
+        EChannel     mChannel;
+        ESampleType  mSampleType;
+        EAudioType   mAudioType;
+        int          mAudioIndex;
+
+        const char *StreamTypeTable[AUDIO_TYPE_MAX] = {
+            /* Only Input */
+            "media",                  /**< AUDIO_IN_TYPE_MEDIA */
+            "system",                 /**< AUDIO_IN_TYPE_SYSTEM */
+            "alarm",                  /**< AUDIO_IN_TYPE_ALARM */
+            "notification",           /**< AUDIO_IN_TYPE_NOTIFICATION */
+            "emergency",              /**< AUDIO_IN_TYPE_EMERGENCY */
+            "voice-information",      /**< AUDIO_IN_TYPE_VOICE_INFORMATION */
+            "voice-recognition",      /**< AUDIO_IN_TYPE_VOICE_RECOGNITION */
+            "ringtone-voip",          /**< AUDIO_IN_TYPE_RINGTONE_VOIP */
+            "voip",                   /**< AUDIO_IN_TYPE_VOIP */
+            "loopback",               /**< AUDIO_IN_TYPE_LOOPBACK */  /**< only for loopback */
+
+            /* Only Output */
+            "media",                  /**< AUDIO_OUT_TYPE_MEDIA */
+            "system",                 /**< AUDIO_OUT_TYPE_SYSTEM */
+            "alarm",                  /**< AUDIO_OUT_TYPE_ALARM */
+            "notification",           /**< AUDIO_OUT_TYPE_NOTIFICATION */
+            "emergency",              /**< AUDIO_OUT_TYPE_EMERGENCY */
+            "voice-information",      /**< AUDIO_OUT_TYPE_VOICE_INFORMATION */
+            "voice-recognition",      /**< AUDIO_OUT_TYPE_VOICE_RECOGNITION */
+            "ringtone-voip",          /**< AUDIO_OUT_TYPE_RINGTONE_VOIP */
+            "voip",                   /**< AUDIO_OUT_TYPE_VOIP */
+        };
+
+    public:
+        /* Constructors */
+        CAudioInfo();
+        CAudioInfo(unsigned int sampleRate, EChannel channel, ESampleType sampleType, EAudioType audioType, int audioIndex) throw (CAudioError);
+
+        /* Setter & Getter */
+        unsigned int getSampleRate();
+        EChannel getChannel();
+        ESampleType getSampleType();
+        EAudioType getAudioType();
+        void setAudioType(EAudioType AudioType);
+        int getAudioIndex();
+        void setAudioIndex(int AudioIndex);
+        void convertAudioType2StreamType (CAudioInfo::EAudioType audioType, char **streamType);
+        void convertStreamType2AudioType (char *streamType, CAudioInfo::EAudioType *audioType);
+    };
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO__IO_CAUDIO_INFO_H__ */
diff --git a/include/CAudioInput.h b/include/CAudioInput.h
new file mode 100644 (file)
index 0000000..3ecc898
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CAUDIO_INPUT_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CAUDIO_INPUT_H__
+
+
+#ifdef __cplusplus
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * A class CAudioInput that inherited from CAudioIO
+     */
+    class CAudioInput : public CAudioIO {
+    private:
+
+        const void* mpSyncReadDataPtr;
+        size_t      mSyncReadIndex;
+        size_t      mSyncReadLength;
+
+        bool mIsUsedSyncRead;
+        bool mIsInit;
+
+        /* Private Methods */
+        void setInit(bool flag);
+        bool IsInit();
+        bool IsReady();
+
+    public:
+        /* Constructor & Destructor */
+        CAudioInput(CAudioInfo& info);
+        CAudioInput(
+                    unsigned int            sampleRate,
+                    CAudioInfo::EChannel    channel,
+                    CAudioInfo::ESampleType sampleType,
+                    CAudioInfo::EAudioType  audioType);
+        ~CAudioInput();
+
+        /* Overridden Handler */
+        virtual void onStream(CPulseAudioClient* pClient, size_t length);
+        virtual void onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info);
+        virtual void onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value);
+
+        /* Implemented Methods */
+        virtual void initialize() throw (CAudioError);
+        virtual void finalize();
+
+        virtual void prepare() throw (CAudioError);
+        virtual void unprepare() throw (CAudioError);
+
+        virtual void pause() throw (CAudioError);
+        virtual void resume() throw (CAudioError);
+
+        virtual void drain() throw (CAudioError);
+        virtual void flush() throw (CAudioError);
+
+        virtual int  getBufferSize() throw (CAudioError);
+
+        /* Overridden Methods */
+        virtual void setStreamCallback(SStreamCallback callback) throw (CAudioError);
+
+        /* Methods */
+        int read(void* buffer, size_t length) throw (CAudioError);
+        int peek(const void** buffer, size_t* length) throw (CAudioError);
+        int drop() throw (CAudioError);
+    };
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CAUDIO_INPUT_H__ */
diff --git a/include/CAudioOutput.h b/include/CAudioOutput.h
new file mode 100644 (file)
index 0000000..59de7e3
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CAUDIO_OUTPUT_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CAUDIO_OUTPUT_H__
+
+
+#ifdef __cplusplus
+
+#include "CAudioIODef.h"
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * A class CAudioOutput that inherited from CAudioIO
+     */
+    class CAudioOutput : public CAudioIO {
+    private:
+        bool mIsUsedSyncWrite;
+        bool mIsInit;
+
+        /* Private Methods */
+        void setInit(bool flag);
+        bool IsInit();
+        bool IsReady();
+
+    public:
+        /* Constructor & Destructor */
+        CAudioOutput(CAudioInfo& info);
+        CAudioOutput(
+                    unsigned int            smapleRate,
+                    CAudioInfo::EChannel    channel,
+                    CAudioInfo::ESampleType sampleType,
+                    CAudioInfo::EAudioType  type);
+        ~CAudioOutput();
+
+        /* Overridden Handler */
+        virtual void onStream(CPulseAudioClient* pClient, size_t length);
+        virtual void onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info);
+        virtual void onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value);
+
+        /* Implemented Methods */
+        virtual void initialize() throw (CAudioError);
+        virtual void finalize();
+
+        virtual void prepare() throw (CAudioError);
+        virtual void unprepare() throw (CAudioError);
+
+        virtual void pause() throw (CAudioError);
+        virtual void resume() throw (CAudioError);
+
+        virtual void drain() throw (CAudioError);
+        virtual void flush() throw (CAudioError);
+
+        virtual int  getBufferSize() throw (CAudioError);
+
+        /* Methods */
+        int write(const void* buffer, unsigned int length) throw (CAudioError);
+    };
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CAUDIO_OUTPUT_H__ */
diff --git a/include/CAudioSessionHandler.h b/include/CAudioSessionHandler.h
new file mode 100644 (file)
index 0000000..7c4ab9a
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIOIO_IO_CAUDIO_SESSION_HANDLER_H__
+#define __TIZEN_MEDIA_AUDIOIO_IO_CAUDIO_SESSION_HANDLER_H__
+
+
+#ifdef __cplusplus
+
+
+#include <mm_session.h>
+#include <mm_session_private.h>
+#include <audio-session-manager.h>
+#include <mm_sound.h>
+#include <mm_sound_focus.h>
+
+namespace tizen_media_audio {
+
+
+    /**
+     * ASM Thread
+     */
+    class CAudioSessionHandler {
+    public:
+        enum EAudioSessionType {
+            AUDIO_SESSION_TYPE_CAPTURE,
+            AUDIO_SESSION_TYPE_PLAYBACK
+        };
+
+    private:
+        /* Static Member */
+        static int                  sCaptureRef;
+        static int                  sFocusRef;
+
+        /* Members */
+        int                         mId;
+        int                         mOptions;
+
+        EAudioSessionType           mAudioSession;
+        MMSessionType               mMultimediaSession;
+
+        mm_sound_focus_type_e       mFocusType;        /* For audio focus */
+        mm_sound_focus_state_e      mState;            /* For audio focus */
+        char*                       mReasonForChange;  /* For audio focus */
+        char*                       mAdditionalInfo;   /* For audio focus */
+
+        CAudioInfo                  mAudioInfo;        /* Referenced from CAudioIO */
+
+        IAudioSessionEventListener* mpEventListener;
+
+        bool                        mIsInit;
+
+        bool                        mUseFocus;
+        int                         mSubscribeId;
+
+        struct stream_type_table_s {
+            const char* name;
+            MMSessionType type;
+        };
+        const struct stream_type_table_s stream_type_table_in[MM_SESSION_TYPE_NUM] = {
+            {"media",        MM_SESSION_TYPE_MEDIA},
+            {"media",        MM_SESSION_TYPE_MEDIA_RECORD},
+            {"media",        MM_SESSION_TYPE_ALARM},
+            {"media",        MM_SESSION_TYPE_NOTIFY},
+            {"media",        MM_SESSION_TYPE_EMERGENCY},
+            {"media",        MM_SESSION_TYPE_CALL},
+            {"media",        MM_SESSION_TYPE_VIDEOCALL},
+            {"voip",         MM_SESSION_TYPE_VOIP},
+            {"media",        MM_SESSION_TYPE_VOICE_RECOGNITION},
+            {"media",        MM_SESSION_TYPE_RECORD_AUDIO},
+            {"media",        MM_SESSION_TYPE_RECORD_VIDEO}
+        };
+        const struct stream_type_table_s stream_type_table_out[MM_SESSION_TYPE_NUM] = {
+            {"media",        MM_SESSION_TYPE_MEDIA},
+            {"media",        MM_SESSION_TYPE_MEDIA_RECORD},
+            {"alarm",        MM_SESSION_TYPE_ALARM},
+            {"notification", MM_SESSION_TYPE_NOTIFY},
+            {"emergency",    MM_SESSION_TYPE_EMERGENCY},
+            {"media",        MM_SESSION_TYPE_CALL},
+            {"media",        MM_SESSION_TYPE_VIDEOCALL},
+            {"voip",         MM_SESSION_TYPE_VOIP},
+            {"media",        MM_SESSION_TYPE_VOICE_RECOGNITION},
+            {"media",        MM_SESSION_TYPE_RECORD_AUDIO},
+            {"media",        MM_SESSION_TYPE_RECORD_VIDEO}
+        };
+
+        /* Private Static Methods */
+        static int PCM_CAPTURE_COUNT_INC();
+        static int PCM_CAPTURE_COUNT_DEC();
+        static int PCM_CAPTURE_COUNT_GET();
+        static int FOCUS_ID_COUNT_INC();
+        static int FOCUS_ID_COUNT_DEC();
+        static int FOCUS_ID_COUNT_GET();
+
+        static void _sound_pcm_signal_cb(mm_sound_signal_name_t signal, int value, void *user_data);
+        static ASM_cb_result_t _sound_pcm_asm_cb(int handle, ASM_event_sources_t eventSrc, ASM_sound_commands_t command, unsigned int soundState, void *cbData);
+        static void _sound_pcm_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data);
+        static void _sound_pcm_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data);
+
+        /* Private Method */
+        CAudioError _convertStreamType(EAudioSessionType type1, MMSessionType type2, int *index);
+        CAudioError _getAsmInformation(MMSessionType *type, int *options);
+        bool _isFocusRequired(MMSessionType type, int options);
+
+    public:
+        /* Constructor & Destructor */
+        CAudioSessionHandler(EAudioSessionType sessionType, CAudioInfo& audioInfo, IAudioSessionEventListener* listener);
+        virtual ~CAudioSessionHandler();
+
+        /* Methods */
+        virtual void initialize() throw (CAudioError);
+        virtual void finalize();
+
+        bool isSkipSessionEvent() throw (CAudioError);
+
+        void registerSound() throw (CAudioError);
+        void unregisterSound() throw (CAudioError);
+
+        void updatePlaying() throw (CAudioError);
+        void updateStop() throw (CAudioError);
+        void disableSessionHandler() throw (CAudioError);
+
+        /* Setter & Getter */
+        int getId();
+        int getOptions();
+
+        EAudioSessionType    getAudioSession();
+        MMSessionType        getMultimediaSession();
+
+        int getSubscribeId();
+
+        CAudioInfo getAudioInfo();
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIOIO_IO_CAUDIO_SESSION_HANDLER_H__ */
diff --git a/include/CPulseAudioClient.h b/include/CPulseAudioClient.h
new file mode 100644 (file)
index 0000000..90a01fb
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_CLIENT_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_CLIENT_H__
+
+
+#ifdef __cplusplus
+
+
+#include <pulse/pulseaudio.h>
+#include <pulse/ext-policy.h>
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * PULSE Thread
+     */
+    class CPulseAudioVolume;
+    class CPulseAudioPolicy;
+    class CPulseStreamSpec;
+    class CPulseAudioClient {
+    public:
+        /* Constants */
+        static const char* CLIENT_NAME;
+
+        enum EStreamDirection {
+            STREAM_DIRECTION_RECORD,        /**< Record stream */
+            STREAM_DIRECTION_PLAYBACK       /**< Playback stream */
+        };
+
+    private:
+        /* Members */
+        EStreamDirection      mDirection;
+        CPulseStreamSpec      mSpec;
+        IPulseStreamListener* mpListener;
+
+        pa_threaded_mainloop* mpMainloop;
+        pa_context*           mpContext;
+        pa_stream*            mpStream;
+        pa_proplist*          mpPropList;
+
+        bool                  mIsInit;
+        bool                  mIsOperationSuccess;
+
+        /* Static Methods */
+
+        /* Private Method */
+
+        /* Private Calblack Method */
+        static void _contextStateChangeCb(pa_context* c, void* user_data);
+        static void _successContextCb(pa_context* c, int success, void* user_data);
+
+        static void _streamStateChangeCb(pa_stream* s, void* user_data);
+        static void _streamCaptureCb(pa_stream* s, size_t length, void* user_data);
+        static void _streamPlaybackCb(pa_stream* s, size_t length, void* user_data);
+        static void _streamLatencyUpdateCb(pa_stream* s, void* user_data);
+        static void _successStreamCb(pa_stream* s, int success, void* user_data);
+
+    public:
+        /* Constructor & Destructor */
+        CPulseAudioClient(EStreamDirection      direction,
+                          CPulseStreamSpec&     spec,
+                          IPulseStreamListener* listener);
+        ~CPulseAudioClient();
+
+        /* Implemented Methods */
+        void initialize() throw (CAudioError);
+        void finalize();
+
+        /* Methods */
+        int  peek(const void** data, size_t* length) throw (CAudioError);
+        int  drop() throw (CAudioError);
+        int  write(const void* data, size_t length) throw (CAudioError);
+
+        void cork(bool cork) throw (CAudioError);
+        bool isCorked() throw (CAudioError);
+
+        bool drain() throw (CAudioError);
+        bool flush() throw (CAudioError);
+
+        void checkRunningState() throw (CAudioError);
+        bool isInThread() throw (CAudioError);
+
+        size_t getWritableSize() throw (CAudioError);
+        size_t getReadableSize() throw (CAudioError);
+
+        size_t getBufferSize() throw (CAudioError);
+
+        pa_usec_t getLatency() throw (CAudioError);
+        pa_usec_t getFinalLatency() throw (CAudioError);
+
+        /* Setter & Getter */
+        EStreamDirection getStreamDirection();
+        CPulseStreamSpec getStreamSpec();
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_CLIENT_H__ */
diff --git a/include/CPulseAudioPolicy.h b/include/CPulseAudioPolicy.h
new file mode 100644 (file)
index 0000000..ce941bc
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+
+#if 0
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_POLICY_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_POLICY_H__
+
+
+#ifdef __cplusplus
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * class CPulseAudioPolicy
+     */
+    class CPulseAudioPolicy {
+    public:
+        /* Constants */
+        enum EPolicy {
+            POLICY_DEFAULT,
+            POLICY_OUT_AUTO,
+            POLICY_OUT_PHONE,
+            POLICY_OUT_VOIP,
+            POLICY_OUT_ALL,
+            POLICY_IN_VOIP,
+            POLICY_IN_LOOPBACK,
+            POLICY_IN_MIRRORING,
+            POLICY_HIGH_LATENCY,
+            POLICY_MAX
+        };
+
+    private:
+        /* Members */
+        EPolicy mPolicy;
+
+    public:
+        /* Constructors */
+        CPulseAudioPolicy();
+        CPulseAudioPolicy(EPolicy policy);
+        ~CPulseAudioPolicy();
+
+        /* getter & setter */
+        void setPolicy(EPolicy policy) throw (CAudioError);
+        EPolicy getPolicy();
+
+        /* Override */
+        bool operator != (const EPolicy policy);
+        bool operator == (const EPolicy policy);
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_POLICY_H__ */
+#endif
diff --git a/include/CPulseAudioVolume.h b/include/CPulseAudioVolume.h
new file mode 100644 (file)
index 0000000..f4cbbf5
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+
+#if 0
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_VOLUME_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_VOLUME_H__
+
+
+#ifdef __cplusplus
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * Audio Volume
+     */
+    class CPulseAudioVolume {
+    public:
+        /* Constants */
+        enum EVolume {
+            VOLUME_SYSTEM,                         /**< System volume type */
+            VOLUME_NOTIFICATION,                   /**< Notification volume type */
+            VOLUME_ALARM,                          /**< Alarm volume type */
+            VOLUME_RINGTONE,                       /**< Ringtone volume type */
+            VOLUME_MEDIA,                          /**< Media volume type */
+            VOLUME_CALL,                           /**< Call volume type */
+            VOLUME_VOIP,                           /**< VOIP volume type */
+            VOLUME_VOICE,                          /**< VOICE volume type */
+            VOLUME_FIXED,                          /**< Volume type for fixed acoustic level */
+            VOLUME_EXT_ANDROID = VOLUME_FIXED,     /**< External system volume for Android */
+            VOLUME_MAX                             /**< Volume type count */
+        };
+
+        enum EVolumeGain {
+            VOLUME_GAIN_DEFAULT,
+            VOLUME_GAIN_DIALER,
+            VOLUME_GAIN_TOUCH,
+            VOLUME_GAIN_AF,
+            VOLUME_GAIN_SHUTTER1,
+            VOLUME_GAIN_SHUTTER2,
+            VOLUME_GAIN_CAMCORDING,
+            VOLUME_GAIN_MIDI,
+            VOLUME_GAIN_BOOTING,
+            VOLUME_GAIN_VIDEO,
+            VOLUME_GAIN_TTS,
+            VOLUME_GAIN_MAX
+        };
+
+    private:
+        /* Members */
+        EVolume     mVolume;
+        EVolumeGain mVolumeGain;
+
+    public:
+        /* Constructor & Destructor */
+        CPulseAudioVolume();
+        CPulseAudioVolume(EVolume volume, EVolumeGain gain);
+        ~CPulseAudioVolume();
+
+        /* Methods */
+
+        /* Setter & Getter */
+        void setVolume(EVolume volume);
+        EVolume getVolume();
+
+        void setVolumeGain(EVolumeGain volumeGain);
+        EVolumeGain getVolumeGain();
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CPULSEAUDIO_VOLUME_H__ */
+#endif
diff --git a/include/CPulseStreamSpec.h b/include/CPulseStreamSpec.h
new file mode 100644 (file)
index 0000000..ca3bcec
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_CPULSESTREAM_SPEC_H__
+#define __TIZEN_MEDIA_AUDIO_IO_CPULSESTREAM_SPEC_H__
+
+
+#ifdef __cplusplus
+
+
+#include <pulse/pulseaudio.h>
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * class CPulseStreamSpec
+     */
+    class CPulseStreamSpec {
+    public:
+        /* Constants */
+        enum EStreamLatency {
+            STREAM_LATENCY_INPUT_LOW,
+            STREAM_LATENCY_INPUT_MID,
+            STREAM_LATENCY_INPUT_HIGH,
+            STREAM_LATENCY_INPUT_VOIP,
+            STREAM_LATENCY_OUTPUT_LOW,
+            STREAM_LATENCY_OUTPUT_MID,
+            STREAM_LATENCY_OUTPUT_HIGH,
+            STREAM_LATENCY_OUTPUT_VOIP,
+            STREAM_LATENCY_MAX
+        };
+
+    private:
+        /* Members */
+        EStreamLatency mLatency;
+        CAudioInfo     mAudioInfo;
+        pa_sample_spec mSampleSpec;
+        pa_channel_map mChannelMap;
+        const char*    mStreamName;
+
+        /* private meethod */
+        void _adjustSpec() throw (CAudioError);
+
+    public:
+        /* Constructor & Destructor */
+        CPulseStreamSpec() throw (CAudioError);
+        CPulseStreamSpec(EStreamLatency latency, CAudioInfo& audioInfo) throw (CAudioError);
+        CPulseStreamSpec(EStreamLatency latency, CAudioInfo& audioInfo, int customLatency) throw (CAudioError);
+        ~CPulseStreamSpec();
+
+        /* Setter & Getter */
+        EStreamLatency getStreamLatency();
+        CAudioInfo     getAudioInfo();
+        pa_sample_spec getSampleSpec();
+        pa_channel_map getChannelMap();
+        const char*    getStreamName();
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_CPULSESTREAM_SPEC_H__ */
diff --git a/include/IAudioSessionEventListener.h b/include/IAudioSessionEventListener.h
new file mode 100644 (file)
index 0000000..8c425a9
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_IAUDIO_SESSION_EVENT_LISTENER_H__
+#define __TIZEN_MEDIA_AUDIO_IO_IAUDIO_SESSION_EVENT_LISTENER_H__
+
+
+#ifdef __cplusplus
+
+
+#include <mm_sound.h>
+#include <mm_sound_focus.h>
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * Called by ASM Thread
+     */
+    class CAudioSessionHandler;
+    class IAudioSessionEventListener {
+    public:
+        enum EInterruptCode {
+            INTERRUPT_COMPLETED = 0,         /**< Interrupt completed */
+            INTERRUPT_BY_MEDIA,              /**< Interrupted by a media application */
+            INTERRUPT_BY_CALL,               /**< Interrupted by an incoming call */
+            INTERRUPT_BY_EARJACK_UNPLUG,     /**< Interrupted by unplugging headphones */
+            INTERRUPT_BY_RESOURCE_CONFLICT,  /**< Interrupted by a resource conflict */
+            INTERRUPT_BY_ALARM,              /**< Interrupted by an alarm */
+            INTERRUPT_BY_EMERGENCY,          /**< Interrupted by an emergency */
+            INTERRUPT_BY_NOTIFICATION,       /**< Interrupted by a notification */
+            INTERRUPT_MAX
+        };
+
+        static EInterruptCode convertInterruptedCode(int code, const char *reason_for_change);
+        virtual void onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) = 0;
+        virtual void onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) = 0;
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_IAUDIO_SESSION_EVENT_LISTENER_H__ */
diff --git a/include/IPulseStreamListener.h b/include/IPulseStreamListener.h
new file mode 100644 (file)
index 0000000..3a2e75d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_AUDIO_IO_IPULSESTREAM_LISTENER_H__
+#define __TIZEN_MEDIA_AUDIO_IO_IPULSESTREAM_LISTENER_H__
+
+
+#ifdef __cplusplus
+
+
+#include <stddef.h>
+
+
+namespace tizen_media_audio {
+
+
+    /**
+     * Called by PulseAudio Thread
+     */
+    class CPulseAudioClient;
+    class IPulseStreamListener {
+    public:
+        virtual void onStream(CPulseAudioClient* pClient, size_t length) = 0;
+        virtual void onStateChanged(CAudioInfo::EAudioIOState state) = 0;
+    };
+
+
+} /* namespace tizen_media_audio */
+
+#endif
+#endif /* __TIZEN_MEDIA_AUDIO_IO_IPULSESTREAM_LISTENER_H__ */
index 067cddc5a0caec03fa89aa5f357c52b20205e7ad..767011a6e61e7eca403fff73b8c62f375a0bc99a 100644 (file)
@@ -1,18 +1,18 @@
 /*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #ifndef __TIZEN_MEDIA_AUDIO_IO_H__
 #define __TIZEN_MEDIA_AUDIO_IO_H__
@@ -34,17 +34,17 @@ extern "C"
 /**
  * @addtogroup CAPI_MEDIA_AUDIO_IN_MODULE
  * @{
-*/
+ */
 
 /**
  * @brief The audio input handle.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  */
-typedef struct audio_in_s *audio_in_h;
+typedef struct audio_io_s *audio_in_h;
 
 /**
  * @}
-*/
+ */
 
 /**
  * @addtogroup CAPI_MEDIA_AUDIO_OUT_MODULE
@@ -55,7 +55,7 @@ typedef struct audio_in_s *audio_in_h;
  * @brief The audio output handle.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  */
-typedef struct audio_out_s *audio_out_h;
+typedef struct audio_io_s *audio_out_h;
 
  /**
  * @}
@@ -85,6 +85,17 @@ typedef enum {
     AUDIO_CHANNEL_STEREO,                       /**< 2 channel, stereo */
 } audio_channel_e;
 
+/**
+ * @brief Enumeration for audio input and output state.
+ * @since_tizen 3.0
+ */
+typedef enum
+{
+    AUDIO_IO_STATE_IDLE,      /**< Audio-io handle is created, but not prepared */
+    AUDIO_IO_STATE_RUNNING,   /**< Audio-io handle is ready and the stream is running */
+    AUDIO_IO_STATE_PAUSED,    /**< Audio-io handle is ready and the stream is paused */
+} audio_io_state_e;
+
 /**
  * @brief Enumeration for audio input and output error.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -100,9 +111,11 @@ typedef enum{
     AUDIO_IO_ERROR_DEVICE_NOT_CLOSED   = TIZEN_ERROR_AUDIO_IO | 0x02,   /**< Device close error */
     AUDIO_IO_ERROR_INVALID_BUFFER      = TIZEN_ERROR_AUDIO_IO | 0x03,   /**< Invalid buffer pointer */
     AUDIO_IO_ERROR_SOUND_POLICY        = TIZEN_ERROR_AUDIO_IO | 0x04,   /**< Sound policy error */
+    AUDIO_IO_ERROR_INVALID_STATE       = TIZEN_ERROR_AUDIO_IO | 0x05,   /**< Invalid state (Since 3.0) */
 } audio_io_error_e;
 
 /**
+ * @deprecated Deprecated since 3.0
  * @brief Enumeration for audio IO interrupted messages.
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  */
@@ -119,6 +132,7 @@ typedef enum
 } audio_io_interrupted_code_e;
 
 /**
+ * @deprecated Deprecated since 3.0. Use sound_stream_focus_state_changed_cb instead.
  * @brief Called when audio input or output is interrupted.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -134,12 +148,12 @@ typedef void (*audio_io_interrupted_cb)(audio_io_interrupted_code_e code, void *
 
 /**
  * @}
-*/
+ */
 
 /**
  * @addtogroup CAPI_MEDIA_AUDIO_IN_MODULE
  * @{
-*/
+ */
 
 //
 //AUDIO INPUT
@@ -154,21 +168,37 @@ typedef void (*audio_io_interrupted_cb)(audio_io_interrupted_code_e code, void *
  *
  * @param[in] handle The handle to the audio input
  * @param[in] nbytes The amount of available audio in data which can be peeked.
- * @param[in] userdata The user data passed from the callback registration function
+ * @param[in] user_data The user data passed from the callback registration function
  *
  * @see audio_in_set_stream_cb()
  */
-typedef void (*audio_in_stream_cb)(audio_in_h handle, size_t nbytes, void *userdata);
+typedef void (*audio_in_stream_cb)(audio_in_h handle, size_t nbytes, void *user_data);
+
+/**
+ * @brief Called when the state of audio input is changed.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] handle The handle of the audio input
+ * @param[in] previous The previous state of the audio input
+ * @param[in] current The current state of the audio input
+ * @param[in] by_policy @c true if the state is changed by policy, otherwise @c false if the state is not changed by policy
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see audio_in_set_state_changed_cb()
+ * @see audio_in_unset_state_changed_cb()
+ */
+typedef void (*audio_in_state_changed_cb)(audio_in_h handle, audio_io_state_e previous, audio_io_state_e current, bool by_policy, void *user_data);
 
 /**
  * @brief Creates an audio device instance and returns an input handle to record PCM (pulse-code modulation) data.
  *
+ * @details This function is used for audio input initialization.
+ *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @privlevel public
  * @privilege %http://tizen.org/privilege/recorder
  *
- * @details This function is used for audio input initialization.
- *
  * @remarks @a input must be released using audio_in_destroy().
  *
  * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz]
@@ -184,19 +214,23 @@ typedef void (*audio_in_stream_cb)(audio_in_h handle, size_t nbytes, void *userd
  * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened
  * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @post The state will be #AUDIO_IO_STATE_IDLE.\n
+ *       audio_in_set_stream_info() is recommended to be called after this API.
  * @see audio_in_destroy()
  */
 int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input);
 
 /**
+ * @deprecated Deprecated since 3.0. Use sound_manager_create_stream_information() instead.
  * @brief Creates an audio loopback device instance and returns an input handle to record PCM (pulse-code modulation) data.
  *
+ * @details This function is used for audio loopback input initialization.
+ *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  * @privlevel public
  * @privilege %http://tizen.org/privilege/recorder
  *
- * @details This function is used for audio loopback input initialization.
- *
  * @remarks @a input must be released using audio_in_destroy().
  *
  * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz]
@@ -212,6 +246,7 @@ int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_
  * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened
  * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ *
  * @see audio_in_destroy()
  */
 int audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input);
@@ -228,12 +263,38 @@ int audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sam
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_DEVICE_NOT_CLOSED Device not closed
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ *
  * @see audio_in_create()
  */
 int audio_in_destroy(audio_in_h input);
 
 /**
- * @brief Prepares reading audio input by starting buffering of audio data from the device.
+ * @brief Sets the sound stream information to the audio input.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks @a the sound stream information includes audio routing and volume type.
+ *          For more details, you can refer to @ref CAPI_MEDIA_SOUND_MANAGER_MODULE
+ *
+ * @param[in] input The handle to the audio input
+ * @param[in] stream_info The handle of stream information
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_IDLE.\n
+ *      Call audio_in_create() before calling this function.
+ * @post Call audio_in_prepare() after calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ */
+int audio_in_set_stream_info(audio_in_h input, sound_stream_info_h stream_info);
+
+/**
+ * @brief Prepares the audio input for reading audio data by starting buffering of audio data from the device.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  *
@@ -243,13 +304,15 @@ int audio_in_destroy(audio_in_h input);
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @post The state will be #AUDIO_IO_STATE_RUNNING.
  * @see audio_in_unprepare()
  */
 int audio_in_prepare(audio_in_h input);
 
 /**
- * @brief Unprepares reading audio input by stopping buffering the audio data from the device.
+ * @brief Unprepares the audio input.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  *
@@ -259,10 +322,51 @@ int audio_in_prepare(audio_in_h input);
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @post The state will be #AUDIO_IO_STATE_IDLE.
  * @see audio_in_prepare()
  */
 int audio_in_unprepare(audio_in_h input);
 
+/**
+ * @brief Pauses buffering of audio data from the device.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] input The handle to the audio input
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING.
+ * @post The state will be #AUDIO_IO_STATE_PAUSED.
+ * @see audio_in_resume()
+ */
+int audio_in_pause(audio_in_h input);
+
+/**
+ * @brief Resumes buffering audio data from the device.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] input The handle to the audio input
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_PAUSED.
+ * @post The state will be #AUDIO_IO_STATE_RUNNING.
+ * @see audio_in_pause()
+ */
+int audio_in_resume(audio_in_h input);
+
 /**
  * @brief Flushes and discards buffered audio data from the input stream.
  *
@@ -274,6 +378,9 @@ int audio_in_unprepare(audio_in_h input);
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING or #AUDIO_IO_STATE_PAUSED.
  */
 int audio_in_flush(audio_in_h input);
 
@@ -292,8 +399,9 @@ int audio_in_flush(audio_in_h input);
  * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error
  * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
- * @pre audio_in_start_recording().
-*/
+ *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING.
+ */
 int audio_in_read(audio_in_h input, void *buffer, unsigned int length);
 
 /**
@@ -309,7 +417,7 @@ int audio_in_read(audio_in_h input, void *buffer, unsigned int length);
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
  * @see audio_in_read()
-*/
+ */
 int audio_in_get_buffer_size(audio_in_h input, int *size);
 
 /**
@@ -324,16 +432,16 @@ int audio_in_get_buffer_size(audio_in_h input, int *size);
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
-*/
+ */
 int audio_in_get_sample_rate(audio_in_h input, int *sample_rate);
 
 /**
  * @brief Gets the channel type of the audio input data stream.
  *
- * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
- *
  * @details The audio channel type defines whether the audio is mono or stereo.
  *
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ *
  * @param[in] input The handle to the audio input
  * @param[out] channel The audio channel type
  * @return @c 0 on success,
@@ -341,7 +449,7 @@ int audio_in_get_sample_rate(audio_in_h input, int *sample_rate);
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
-*/
+ */
 int audio_in_get_channel(audio_in_h input, audio_channel_e *channel);
 
 /**
@@ -356,10 +464,11 @@ int audio_in_get_channel(audio_in_h input, audio_channel_e *channel);
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
-*/
+ */
 int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type);
 
 /**
+ * @deprecated Deprecated since 3.0. Use sound_manager_create_stream_information() instead.
  * @brief Registers a callback function to be invoked when the audio input handle is interrupted or the interrupt is completed.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -381,6 +490,7 @@ int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type);
 int audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data);
 
 /**
+ * @deprecated Deprecated since 3.0
  * @brief Unregisters the callback function.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -398,6 +508,7 @@ int audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callba
 int audio_in_unset_interrupted_cb(audio_in_h input);
 
 /**
+ * @deprecated Deprecated since 3.0
  * @brief Ignores session for input.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -415,19 +526,19 @@ int audio_in_ignore_session(audio_in_h input);
 /**
  * @brief Sets an asynchronous(event) callback function to handle recording PCM (pulse-code modulation) data.
  *
- * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
- *
  * @details @a callback will be called when you can read a PCM data.
  * It might cause dead lock if change the state of audio handle in callback.
  * (ex: audio_in_destroy, audio_in_prepare, audio_in_unprepare)
  * Recommend to use as a VOIP only.
  * Recommend not to hold callback too long.(it affects latency)
  *
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ *
  * @remarks @a input must be created using audio_in_create().
  *
  * @param[in] input    An audio input handle
  * @param[in] callback notify stream callback when user can read data (#audio_in_stream_cb)
- * @param[in] userdata user data to be retrieved when callback is called
+ * @param[in] user_data user data to be retrieved when callback is called
  * @return @c 0 on success,
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
@@ -439,7 +550,7 @@ int audio_in_ignore_session(audio_in_h input);
  *
  * @see audio_out_set_stream_cb()
  */
-int audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* userdata);
+int audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data);
 
 /**
  * @brief Unregisters the callback function.
@@ -461,10 +572,10 @@ int audio_in_unset_stream_cb(audio_in_h input);
 /**
  * @brief peek from audio in buffer
  *
- * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
- *
  * @details This function works correctly only with read, write callback. Otherwise it won't operate as intended.
  *
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ *
  * @remarks @a Works only in asynchronous(event) mode. This will just retrieve buffer pointer from audio in buffer. Drop after use.
  *
  * @param[in] input The handle to the audio input
@@ -476,7 +587,9 @@ int audio_in_unset_stream_cb(audio_in_h input);
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING.
  * @see audio_in_drop()
  */
 int audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length);
@@ -496,21 +609,57 @@ int audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length);
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_INVALID_OPERATION Invalid operation
  * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING.
  * @see audio_in_peek()
  */
 int audio_in_drop(audio_in_h input);
 
+/**
+ * @brief Sets the state changed callback function to the audio input handle.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks @a input must be created using audio_in_create().
+ *
+ * @param[in] input    The audio input handle
+ * @param[in] callback the state changed callback called when the state of the handle is changed (#audio_in_state_changed_cb)
+ * @param[in] user_data user data to be retrieved when callback is called
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see audio_in_unset_state_changed_cb()
+ */
+int audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data);
+
+/**
+ * @brief Unregisters the state changed callback function of the audio input handle.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] input The handle to the audio input
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see audio_in_set_state_changed_cb()
+ */
+int audio_in_unset_state_changed_cb(audio_in_h input);
 
+/**
+ * @}
+ */
 
 //
 // AUDIO OUTPUT
 //
 
-/**
- * @}
-*/
-
 /**
  * @addtogroup CAPI_MEDIA_AUDIO_OUT_MODULE
  * @{
@@ -524,24 +673,41 @@ int audio_in_drop(audio_in_h input);
  * @remarks @a use audio_out_write() to write pcm data inside this callback.
  * @param[in] handle The handle to the audio output
  * @param[in] nbytes The amount of audio in data which can be written.
- * @param[in] userdata The user data passed from the callback registration function
+ * @param[in] user_data The user data passed from the callback registration function
  *
  * @see audio_out_set_stream_cb()
  */
-typedef void (*audio_out_stream_cb)(audio_out_h handle, size_t nbytes, void *userdata);
+typedef void (*audio_out_stream_cb)(audio_out_h handle, size_t nbytes, void *user_data);
 
 /**
- * @brief Creates an audio device instance and returns an output handle to play PCM (pulse-code modulation) data.
+ * @brief Called when the state of audio output is changed.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] handle The handle of the audio output
+ * @param[in] previous The previous state of the audio output
+ * @param[in] current The current state of the audio output
+ * @param[in] by_policy @c true if the state is changed by policy, otherwise @c false if the state is not changed by policy
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see audio_out_set_state_changed_cb()
+ * @see audio_out_unset_state_changed_cb()
+ */
+typedef void (*audio_out_state_changed_cb)(audio_out_h handle, audio_io_state_e previous, audio_io_state_e current, bool by_policy, void *user_data);
 
- * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+/**
+ * @deprecated Deprecated since 3.0. Use audio_out_create_new() instead.
+ * @brief Creates an audio device instance and returns an output handle to play PCM (pulse-code modulation) data.
  *
  * @details This function is used for audio output initialization.
  *
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ *
  * @remarks @a output must be released by audio_out_destroy().
  *
  * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz]
  * @param[in] channel The audio channel type (mono or stereo)
- * @param[in] type The type of audio sample (8- or 16-bit)
+ * @param[in] type The type of audio sample (8-bit or 16-bit)
  * @param[in] sound_type The type of sound (#sound_type_e)
  * @param[out] output An audio output handle is created on success
  * @return @c 0 on success,
@@ -553,9 +719,37 @@ typedef void (*audio_out_stream_cb)(audio_out_h handle, size_t nbytes, void *use
  * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error
  *
  * @see audio_out_destroy()
-*/
+ */
 int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h *output);
 
+/**
+ * @brief Creates an audio device instance and returns an output handle to play PCM (pulse-code modulation) data.
+ *
+ * @details This function is used for audio output initialization.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks @a output must be released by audio_out_destroy().
+ *          It is recommended to call audio_out_set_stream_info() after this API.
+ *
+ * @param[in] sample_rate The audio sample rate in 8000[Hz] ~ 48000[Hz]
+ * @param[in] channel The audio channel type (mono or stereo)
+ * @param[in] type The type of audio sample (8-bit or 16-bit)
+ * @param[out] output An audio output handle is created on success
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #AUDIO_IO_ERROR_DEVICE_NOT_OPENED Device not opened
+ * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error
+ *
+ * @post The state will be #AUDIO_IO_STATE_IDLE.\n
+ *       audio_out_set_stream_info() is recommended to be called after this API.
+ * @see audio_out_destroy()
+ */
+int audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output);
+
 /**
  * @brief Releases the audio output handle, along with all its resources.
  *
@@ -570,11 +764,36 @@ int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type
  * @retval #AUDIO_IO_ERROR_DEVICE_NOT_CLOSED Device not closed
  *
  * @see audio_out_create()
-*/
+ */
 int audio_out_destroy(audio_out_h output);
 
 /**
- * @brief Prepares playing audio output, this must be called before audio_out_write().
+ * @brief Sets the sound stream information to the audio output.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks @a the sound stream information includes audio routing and volume type.
+ *          For more details, you can refer to sound_manager.h
+ *
+ * @param[in] output The handle to the audio output
+ * @param[in] stream_info The handle of stream information
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_NOT_SUPPORTED Not supported
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_IDLE.\n
+ *      Call audio_out_create_new() before calling this function.
+ * @post Call audio_out_prepare() after calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ */
+int audio_out_set_stream_info(audio_out_h output, sound_stream_info_h stream_info);
+
+/**
+ * @brief Prepares the audio output for playback, this must be called before audio_out_write().
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  *
@@ -583,13 +802,15 @@ int audio_out_destroy(audio_out_h output);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @post The state will be #AUDIO_IO_STATE_RUNNING.
  * @see audio_out_unprepare()
  */
 int audio_out_prepare(audio_out_h output);
 
 /**
- * @brief Unprepares playing audio output.
+ * @brief Unprepares the audio output.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
  *
@@ -598,11 +819,49 @@ int audio_out_prepare(audio_out_h output);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @post The state will be #AUDIO_IO_STATE_IDLE.
  * @see audio_out_prepare()
  */
 int audio_out_unprepare(audio_out_h output);
 
+/**
+ * @brief Pauses feeding of audio data to the device.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] output The handle to the audio output
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING.
+ * @post The state will be #AUDIO_IO_STATE_PAUSED.
+ * @see audio_out_resume()
+ */
+int audio_out_pause(audio_out_h output);
+
+/**
+ * @brief Resumes feeding of audio data to the device.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] output The handle to the audio output
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_PAUSED.
+ * @post The state will be #AUDIO_IO_STATE_RUNNING.
+ * @see audio_out_pause()
+ */
+int audio_out_resume(audio_out_h output);
+
 /**
  * @brief Drains buffered audio data from the output stream.
  *
@@ -615,7 +874,9 @@ int audio_out_unprepare(audio_out_h output);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING or #AUDIO_IO_STATE_PAUSED.
  * @see audio_out_flush()
  */
 int audio_out_drain(audio_out_h output);
@@ -630,7 +891,9 @@ int audio_out_drain(audio_out_h output);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
  *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING or #AUDIO_IO_STATE_PAUSED.
  * @see audio_out_drain()
  */
 int audio_out_flush(audio_out_h output);
@@ -648,7 +911,10 @@ int audio_out_flush(audio_out_h output);
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #AUDIO_IO_ERROR_INVALID_BUFFER Invalid buffer pointer
  * @retval #AUDIO_IO_ERROR_SOUND_POLICY Sound policy error
-*/
+ * @retval #AUDIO_IO_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #AUDIO_IO_STATE_RUNNING.
+ */
 int audio_out_write(audio_out_h output, void *buffer, unsigned int length);
 
 /**
@@ -664,7 +930,7 @@ int audio_out_write(audio_out_h output, void *buffer, unsigned int length);
  * @retval  #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
  *
  * @see audio_out_write()
-*/
+ */
 int audio_out_get_buffer_size(audio_out_h output, int *size);
 
 /**
@@ -678,11 +944,12 @@ int audio_out_get_buffer_size(audio_out_h output, int *size);
  *          otherwise a negative error value
  * @retval  #AUDIO_IO_ERROR_NONE Successful
  * @retval  #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
-*/
+ */
 int audio_out_get_sample_rate(audio_out_h output, int *sample_rate);
 
 /**
  * @brief Gets the channel type of the audio output data stream.
+ *
  * @details The audio channel type defines whether the audio is mono or stereo.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -693,7 +960,7 @@ int audio_out_get_sample_rate(audio_out_h output, int *sample_rate);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
-*/
+ */
 int audio_out_get_channel(audio_out_h output, audio_channel_e *channel);
 
 /**
@@ -707,10 +974,9 @@ int audio_out_get_channel(audio_out_h output, audio_channel_e *channel);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
-*/
+ */
 int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type);
 
-
 /**
  * @brief Gets the sound type supported by the audio output device.
  *
@@ -722,10 +988,11 @@ int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type);
  *         otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
-*/
+ */
 int audio_out_get_sound_type(audio_out_h output, sound_type_e *type);
 
 /**
+ * @deprecated Deprecated since 3.0. Use sound_manager_create_stream_information() instead.
  * @brief Registers a callback function to be invoked when the audio output handle is interrupted or the interrupt is completed.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -746,6 +1013,7 @@ int audio_out_get_sound_type(audio_out_h output, sound_type_e *type);
 int audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data);
 
 /**
+ * @deprecated Deprecated since 3.0
  * @brief Unregisters the callback function.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -762,6 +1030,7 @@ int audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb cal
 int audio_out_unset_interrupted_cb(audio_out_h output);
 
 /**
+ * @deprecated Deprecated since 3.0
  * @brief Ignores session for output.
  *
  * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
@@ -778,19 +1047,19 @@ int audio_out_ignore_session(audio_out_h output);
 /**
  * @brief Sets an asynchronous(event) callback function to handle playing PCM (pulse-code modulation) data.
  *
- * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
- *
  * @details @a callback will be called when you can write a PCM data.
  * It might cause dead lock if change the state of audio handle in callback.
  * (ex: audio_in_destroy, audio_in_prepare, audio_in_unprepare)
  * Recommend to use as a VOIP only.
  * Recommend not to hold callback too long.(it affects latency)
  *
+ * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
+ *
  * @remarks @a output must be created using audio_out_create().
  *
  * @param[in] output   An audio output handle
  * @param[in] callback notify stream callback when user can write data (#audio_out_stream_cb)
- * @param[in] userdata user data to be retrieved when callback is called
+ * @param[in] user_data user data to be retrieved when callback is called
  * @return 0 on success, otherwise a negative error value
  * @retval #AUDIO_IO_ERROR_NONE Successful
  * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
@@ -800,7 +1069,7 @@ int audio_out_ignore_session(audio_out_h output);
  *
  * @see audio_in_set_stream_cb()
  */
-int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* userdata);
+int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data);
 
 /**
  * @brief Unregisters the callback function.
@@ -816,9 +1085,44 @@ int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, vo
  * @see audio_out_set_stream_cb()
  */
 int audio_out_unset_stream_cb(audio_out_h output);
+
+/**
+ * @brief Sets the state changed callback function to the audio output handle.
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks @a input must be created using audio_out_create_new().
+ *
+ * @param[in] output    The audio output handle
+ * @param[in] callback the state changed callback called when the state of the handle is changed (#audio_out_state_changed_cb)
+ * @param[in] user_data user data to be retrieved when callback is called
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see audio_out_unset_state_changed_cb()
+ */
+int audio_out_set_state_changed_cb(audio_out_h output, audio_out_state_changed_cb callback, void* user_data);
+
+/**
+ * @brief Unregisters the state changed callback function of the audio output handle.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] output The handle to the audio output
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #AUDIO_IO_ERROR_NONE Successful
+ * @retval #AUDIO_IO_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see audio_out_set_state_changed_cb()
+ */
+int audio_out_unset_state_changed_cb(audio_out_h output);
+
 /**
  * @}
-*/
+ */
 
 #ifdef __cplusplus
 }
diff --git a/include/audio_io_private.h b/include/audio_io_private.h
deleted file mode 100644 (file)
index 8ce9181..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#ifndef __TIZEN_MEDIA_AUDIO_IO_PRIVATE_H__
-#define __TIZEN_MEDIA_AUDIO_IO_PRIVATE_H__
-#include <sound_manager.h>
-#include <mm_sound.h>
-#include "audio_io.h"
-
-/*
-* Internal Macros
-*/
-
-#define AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA       (AUDIO_IO_INTERRUPTED_BY_NOTIFICATION + 1)
-#define AUDIO_IO_INTERRUPTED_BY_RESUMABLE_CANCELED    (AUDIO_IO_INTERRUPTED_BY_NOTIFICATION + 2)
-
-#define AUDIO_IO_CHECK_CONDITION(condition,error,msg)   \
-                if(condition) {} else \
-                { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
-
-#define AUDIO_IO_NULL_ARG_CHECK(arg)   \
-       AUDIO_IO_CHECK_CONDITION(arg != NULL, AUDIO_IO_ERROR_INVALID_PARAMETER, "AUDIO_IO_ERROR_INVALID_PARAMETER" )
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct _audio_in_s{
-       MMSoundPcmHandle_t mm_handle;
-       int is_async;
-       int is_loopback;
-       int _buffer_size;
-       int _sample_rate;
-       audio_channel_e _channel;
-       audio_sample_type_e _type;
-       audio_io_interrupted_cb user_cb;
-       void* user_data;
-       audio_in_stream_cb stream_cb;
-       void* stream_userdata;
-} audio_in_s;
-
-typedef struct _audio_out_s{
-       MMSoundPcmHandle_t mm_handle;
-       int is_async;
-       int is_loopback;
-       int _buffer_size;
-       int _sample_rate;
-       audio_channel_e _channel;
-       audio_sample_type_e _type;
-       sound_type_e    _sound_type;
-       audio_io_interrupted_cb user_cb;
-       void* user_data;
-       audio_out_stream_cb stream_cb;
-       void* stream_userdata;
-} audio_out_s;
-
-int __convert_audio_io_error_code(int code, char *func_name);
-int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type);
-int __mm_sound_pcm_capture_msg_cb (int message, void *param, void *user_param);
-audio_io_interrupted_code_e __translate_interrupted_code (int code);
-
-int audio_in_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type , int source_type, audio_in_h* input);
-
-int audio_in_set_callback_private(audio_in_h input, audio_in_stream_cb callback, void* userdata);
-
-int audio_out_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output);
-
-int audio_out_set_callback_private(audio_out_h output, audio_out_stream_cb callback, void* userdata);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif //__TIZEN_MEDIA_AUDIO_IO_PRIVATE_H__
diff --git a/include/cpp_audio_io.h b/include/cpp_audio_io.h
new file mode 100644 (file)
index 0000000..fdaa8e7
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_MEDIA_CPP_AUDIO_IO_H__
+#define __TIZEN_MEDIA_CPP_AUDIO_IO_H__
+
+#include "audio_io.h"
+
+
+#ifdef __cplusplus
+
+
+extern "C"
+{
+#endif
+
+int cpp_audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input);
+int cpp_audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input);
+int cpp_audio_in_destroy(audio_in_h input);
+int cpp_audio_in_set_stream_info(audio_in_h input, sound_stream_info_h stream_info);
+int cpp_audio_in_prepare(audio_in_h input);
+int cpp_audio_in_unprepare(audio_in_h input);
+int cpp_audio_in_pause(audio_in_h input);
+int cpp_audio_in_resume(audio_in_h input);
+int cpp_audio_in_drain(audio_in_h input);
+int cpp_audio_in_flush(audio_in_h input);
+int cpp_audio_in_read(audio_in_h input, void *buffer, unsigned int length);
+int cpp_audio_in_get_buffer_size(audio_in_h input, int *size);
+int cpp_audio_in_get_sample_rate(audio_in_h input, int *sample_rate);
+int cpp_audio_in_get_channel(audio_in_h input, audio_channel_e *channel);
+int cpp_audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type);
+int cpp_audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data);
+int cpp_audio_in_unset_interrupted_cb(audio_in_h input);
+int cpp_audio_in_ignore_session(audio_in_h input);
+int cpp_audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data);
+int cpp_audio_in_unset_stream_cb(audio_in_h input);
+int cpp_audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length);
+int cpp_audio_in_drop(audio_in_h input);
+int cpp_audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data);
+int cpp_audio_in_unset_state_changed_cb(audio_in_h input);
+
+
+int cpp_audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h *output);
+int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output);
+int cpp_audio_out_destroy(audio_out_h output);
+int cpp_audio_out_set_stream_info(audio_out_h output, sound_stream_info_h stream_info);
+int cpp_audio_out_prepare(audio_out_h output);
+int cpp_audio_out_unprepare(audio_out_h output);
+int cpp_audio_out_pause(audio_out_h output);
+int cpp_audio_out_resume(audio_out_h output);
+int cpp_audio_out_drain(audio_out_h output);
+int cpp_audio_out_flush(audio_out_h output);
+int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length);
+int cpp_audio_out_get_buffer_size(audio_out_h output, int *size);
+int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate);
+int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel);
+int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type);
+int cpp_audio_out_get_sound_type(audio_out_h output, sound_type_e *type);
+int cpp_audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data);
+int cpp_audio_out_unset_interrupted_cb(audio_out_h output);
+int cpp_audio_out_ignore_session(audio_out_h output);
+int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data);
+int cpp_audio_out_unset_stream_cb(audio_out_h output);
+int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_changed_cb callback, void* user_data);
+int cpp_audio_out_unset_state_changed_cb(audio_out_h output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_MEDIA_CPP_AUDIO_IO_H__ */
index 017d22d3aff3db1cd32736351140c2fed580d1c0..a76fdbae7d915118498d7699ad37ccc98f8884f1 100644 (file)
@@ -1,5 +1,5 @@
 <manifest>
- <request>
-    <domain name="_"/>
- </request>
      <request>
+               <domain name="_" />
      </request>
 </manifest>
index f873d97499c7d507a64f42a4aaca4a0208399a6e..28a24545b5862e121bf713f35ebb50a39bed4478 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-audio-io
 Summary:    An Audio Input & Audio Output library in Tizen Native API
-Version: 0.2.3
+Version:    0.3.5
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -8,9 +8,14 @@ Source0:    %{name}-%{version}.tar.gz
 Source1001:    capi-media-audio-io.manifest
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(mm-common)
+BuildRequires:  pkgconfig(mm-session)
 BuildRequires:  pkgconfig(mm-sound)
+BuildRequires:  pkgconfig(vconf)
 BuildRequires:  pkgconfig(capi-media-sound-manager)
 BuildRequires:  pkgconfig(capi-base-common)
+BuildRequires:  pkgconfig(libpulse)
+Requires(post): libprivilege-control
 
 %description
 An Audio Input & Audio Output library in Tizen Native API
@@ -27,7 +32,6 @@ An Audio Input & Audio Output library in Tizen Native API (DEV)
 %setup -q
 cp %{SOURCE1001} .
 
-
 %build
 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 %cmake . -DFULLVER=%{version} -DMAJORVER=${MAJORVER}
@@ -36,15 +40,17 @@ make %{?jobs:-j%jobs}
 
 %install
 %make_install
+mkdir -p %{buildroot}/usr/share/privilege-control
 
-%post -p /sbin/ldconfig
+%post
+/sbin/ldconfig
+/usr/bin/api_feature_loader --verbose --dir=/usr/share/privilege-control
 
 %postun -p /sbin/ldconfig
 
-
 %files
 %manifest %{name}.manifest
-%license LICENSE.APLv2
+%license LICENSE
 %{_libdir}/libcapi-media-audio-io.so.*
 %manifest capi-media-audio-io.manifest
 
@@ -53,5 +59,5 @@ make %{?jobs:-j%jobs}
 %{_includedir}/media/audio_io.h
 %{_libdir}/pkgconfig/*.pc
 %{_libdir}/libcapi-media-audio-io.so
-
+#%{_prefix}/bin/audio_io_test
 
index 54a7f1e2dc6a980d2bb86ab59565e9f6a1e5f24b..57eea3f7d5360790966194cc9d7dfbad6e0c6ad7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 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.
 * limitations under the License.
 */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <mm.h>
-#include "audio_io_private.h"
-#include <dlog.h>
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "TIZEN_N_AUDIO_IO"
 
-#include <mm_sound_pcm_async.h>
-/*
-* Internal Implementation
-*/
+#include <mm.h>
+#include <cpp_audio_io.h>
 
 
-/*
-* Public Implementation
-*/
-
-/* Audio In */
 int audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input)
 {
-       return audio_in_create_private (sample_rate, channel, type, SUPPORT_SOURCE_TYPE_DEFAULT, input);
+    return cpp_audio_in_create(sample_rate, channel, type, input);
 }
 
 int audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h* input)
 {
-       return audio_in_create_private (sample_rate, channel, type, SUPPORT_SOURCE_TYPE_LOOPBACK, input);
+    return cpp_audio_in_create_loopback(sample_rate, channel, type, input);
 }
 
 int audio_in_destroy(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_capture_close_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_capture_close(handle->mm_handle);
-       }
-       if (ret != MM_ERROR_NONE) {
-               free(handle);
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-       free(handle);
+    return cpp_audio_in_destroy(input);
+}
 
-       LOGI("[%s] mm_sound_pcm_capture_close() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+int audio_in_set_stream_info(audio_in_h input, sound_stream_info_h stream_info)
+{
+    return cpp_audio_in_set_stream_info(input, stream_info);
 }
 
 int audio_in_prepare(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_capture_start_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_capture_start(handle->mm_handle);
-       }
-
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       LOGI("[%s] mm_sound_pcm_capture_start() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_prepare(input);
 }
 
 int audio_in_unprepare(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = MM_ERROR_NONE;
+    return cpp_audio_in_unprepare(input);
+}
 
-       if (handle->is_async) {
-               ret = mm_sound_pcm_capture_stop_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_capture_stop(handle->mm_handle);
-       }
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
+int audio_in_pause(audio_in_h input)
+{
+    return cpp_audio_in_pause(input);
+}
 
-       LOGI("[%s] mm_sound_pcm_capture_stop() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+int audio_in_resume(audio_in_h input)
+{
+    return cpp_audio_in_resume(input);
 }
 
 int audio_in_flush(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_capture_flush_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_capture_flush(handle->mm_handle);
-       }
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       LOGI("[%s] mm_sound_pcm_capture_flush() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_flush(input);
 }
 
 int audio_in_read(audio_in_h input, void *buffer, unsigned int length )
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(buffer);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = 0;
-       int result = 0;
-
-       if (handle->is_async) {
-               LOGE ("audio_in_read doesn't operate in async mode!!!, use audio_in_peek/audio_in_drop instead");
-               return AUDIO_IO_ERROR_INVALID_OPERATION;
-       }
-
-       ret = mm_sound_pcm_capture_read(handle->mm_handle, (void*) buffer, length);
-       if (ret > 0)
-               return ret;
-
-       switch(ret)
-       {
-               case MM_ERROR_SOUND_INVALID_STATE:
-                       result = AUDIO_IO_ERROR_INVALID_OPERATION;
-                       LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION);
-                       break;
-               default:
-                       result = __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-                       break;
-       }
-       return result;
+    return cpp_audio_in_read(input, buffer, length);
 }
 
 int audio_in_get_buffer_size(audio_in_h input, int *size)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(size);
-       audio_in_s *handle = (audio_in_s *) input;
-
-       *size = handle->_buffer_size;
-
-       LOGI("[%s] buffer size = %d",__FUNCTION__, *size);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_get_buffer_size(input, size);
 }
 
 int audio_in_get_sample_rate(audio_in_h input, int *sample_rate)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(sample_rate);
-       audio_in_s *handle = (audio_in_s *) input;
-
-       *sample_rate = handle->_sample_rate;
-
-       LOGI("[%s] sample rate = %d",__FUNCTION__, *sample_rate);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_get_sample_rate(input, sample_rate);
 }
 
-
 int audio_in_get_channel(audio_in_h input, audio_channel_e *channel)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(channel);
-       audio_in_s *handle = (audio_in_s *) input;
-
-       *channel = handle->_channel;
-
-       LOGI("[%s] channel = %d",__FUNCTION__, *channel);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_get_channel(input, channel);
 }
 
 int audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(type);
-       audio_in_s *handle = (audio_in_s *) input;
-
-       *type = handle->_type;
-
-       LOGI("[%s] sample type = %d",__FUNCTION__, *type);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_get_sample_type(input, type);
 }
 
 int audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(callback);
-       audio_in_s *handle = (audio_in_s *) input;
-
-       handle->user_cb = callback;
-       handle->user_data = user_data;
-
-       LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_set_interrupted_cb(input, callback, user_data);
 }
 
 int audio_in_unset_interrupted_cb(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s  * handle = (audio_in_s  *) input;
-
-       handle->user_cb = NULL;
-       handle->user_data = NULL;
-
-       LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_unset_interrupted_cb(input);
 }
 
 int audio_in_ignore_session(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s  * handle = (audio_in_s  *) input;
-       int ret = 0;
-
-       if (handle->is_async) {
-               LOGE ("Not supported in async mode");
-               return AUDIO_IO_ERROR_INVALID_OPERATION;
-       }
-
-       ret = mm_sound_pcm_capture_ignore_session(handle->mm_handle);
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       LOGI("[%s] mm_sound_pcm_capture_ignore_session() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_in_ignore_session(input);
 }
 
-int audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* userdata)
+int audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(callback);
-       return audio_in_set_callback_private(input, callback, userdata);
+    return cpp_audio_in_set_stream_cb(input, callback, user_data);
 }
 
 int audio_in_unset_stream_cb(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       return audio_in_set_callback_private(input, NULL, NULL);
+    return cpp_audio_in_unset_stream_cb(input);
 }
 
 int audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       AUDIO_IO_NULL_ARG_CHECK(buffer);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = 0;
-       int result = 0;
-       LOGE("handle->is_async : %d", handle->is_async);
-       if (!handle->is_async) {
-               LOGE ("audio_in_peek doesn't operate in poll mode!!!, use audio_in_read instead");
-               return AUDIO_IO_ERROR_INVALID_OPERATION;
-       }
-
-       LOGE("before mm_sound_pcm_capture_peek(handle[%p], buffer[%p], length[%d])", handle->mm_handle, buffer, length);
-       ret = mm_sound_pcm_capture_peek(handle->mm_handle, buffer, length);
-       LOGE("after mm_sound_pcm_capture_peek() ret[%d]", ret);
-       switch(ret)
-       {
-       case MM_ERROR_SOUND_INVALID_STATE:
-               result = AUDIO_IO_ERROR_INVALID_OPERATION;
-               LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION);
-               break;
-       default:
-               result = __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-               break;
-       }
-       return result;
+    return cpp_audio_in_peek(input, buffer, length);
 }
 
 int audio_in_drop(audio_in_h input)
 {
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       audio_in_s *handle = (audio_in_s *) input;
-       int ret = 0;
-       int result = 0;
-
-       if (!handle->is_async) {
-               LOGE ("audio_in_drop doesn't operate in poll mode!!!, use audio_in_read instead");
-               return AUDIO_IO_ERROR_INVALID_OPERATION;
-       }
+    return cpp_audio_in_drop(input);
+}
 
-       ret = mm_sound_pcm_capture_drop(handle->mm_handle);
-       if (ret == MM_ERROR_NONE) {
-               return ret;
-       }
+int audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data)
+{
+    return cpp_audio_in_set_state_changed_cb(input, callback, user_data);
+}
 
-       switch(ret)
-       {
-       case MM_ERROR_SOUND_INVALID_STATE:
-               result = AUDIO_IO_ERROR_INVALID_OPERATION;
-               LOGE("[%s] (0x%08x) : Not recording started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION);
-               break;
-       default:
-               result = __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-               break;
-       }
-       return result;
+int audio_in_unset_state_changed_cb(audio_in_h input)
+{
+    return cpp_audio_in_unset_state_changed_cb(input);
 }
 
 
 /* Audio Out */
 int audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type,  audio_out_h* output)
 {
-       return audio_out_create_private(sample_rate, channel, type, sound_type, output);
+    return cpp_audio_out_create(sample_rate, channel, type, sound_type, output);
 }
 
-int audio_out_destroy(audio_out_h output)
+int audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = MM_ERROR_NONE;
+    return cpp_audio_out_create_new(sample_rate, channel, type, output);
+}
 
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_close_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_play_close(handle->mm_handle);
-       }
-       if (ret != MM_ERROR_NONE) {
-               free(handle);
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-       free(handle);
+int audio_out_destroy(audio_out_h output)
+{
+    return cpp_audio_out_destroy(output);
+}
 
-       LOGI("[%s] mm_sound_pcm_play_close() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+int audio_out_set_stream_info(audio_out_h output, sound_stream_info_h stream_info)
+{
+    return cpp_audio_out_set_stream_info(output, stream_info);
 }
 
 int audio_out_prepare(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_start_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_play_start(handle->mm_handle);
-       }
-
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       LOGI("[%s] mm_sound_pcm_play_start() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_prepare(output);
 }
 
 int audio_out_unprepare(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_stop_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_play_stop(handle->mm_handle);
-       }
+    return cpp_audio_out_unprepare(output);
+}
 
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
+int audio_out_pause(audio_out_h output)
+{
+    return cpp_audio_out_pause(output);
+}
 
-       LOGI("[%s] mm_sound_pcm_play_stop() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+int audio_out_resume(audio_out_h output)
+{
+    return cpp_audio_out_resume(output);
 }
 
 int audio_out_drain(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_drain_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_play_drain(handle->mm_handle);
-       }
-
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       LOGI("[%s] mm_sound_pcm_play_drain() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_drain(output);
 }
 
 int audio_out_flush(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_flush_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_play_flush(handle->mm_handle);
-       }
-
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       LOGI("[%s] mm_sound_pcm_play_flush() success",__FUNCTION__);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_flush(output);
 }
 
 int audio_out_write(audio_out_h output, void* buffer, unsigned int length)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(buffer);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = MM_ERROR_NONE;
-
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_write_async(handle->mm_handle, (void*) buffer, length);
-       } else {
-               ret = mm_sound_pcm_play_write(handle->mm_handle, (void*) buffer, length);
-       }
-
-       if (ret > 0)
-               return ret;
-
-       switch(ret)
-       {
-               case MM_ERROR_SOUND_INVALID_STATE:
-                       ret = AUDIO_IO_ERROR_INVALID_OPERATION;
-                       LOGE("[%s] (0x%08x) : Not playing started yet.",(char*)__FUNCTION__, AUDIO_IO_ERROR_INVALID_OPERATION);
-                       break;
-               default:
-                       ret = __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-                       break;
-       }
-       return ret;
+    return cpp_audio_out_write(output, buffer, length);
 }
 
 int audio_out_get_buffer_size(audio_out_h output, int *size)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(size);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       *size = handle->_buffer_size;
-
-       LOGI("[%s] buffer size = %d",__FUNCTION__, *size);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_get_buffer_size(output, size);
 }
 
 int audio_out_get_sample_rate(audio_out_h output, int *sample_rate)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(sample_rate);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       *sample_rate = handle->_sample_rate;
-
-       LOGI("[%s] sample rate = %d",__FUNCTION__, *sample_rate);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_get_sample_rate(output, sample_rate);
 }
 
 int audio_out_get_channel(audio_out_h output, audio_channel_e *channel)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(channel);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       *channel = handle->_channel;
-
-       LOGI("[%s] channel = %d",__FUNCTION__, *channel);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_get_channel(output, channel);
 }
 
 int audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(type);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       *type = handle->_type;
-
-       LOGI("[%s] sample type = %d",__FUNCTION__, *type);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_get_sample_type(output, type);
 }
 
 int audio_out_get_sound_type(audio_out_h output, sound_type_e *type)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(type);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       *type = handle->_sound_type;
-
-       LOGI("[%s] sound type = %d",__FUNCTION__, *type);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_get_sound_type(output, type);
 }
 
 int audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(callback);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       handle->user_cb = callback;
-       handle->user_data = user_data;
-
-       LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_set_interrupted_cb(output, callback, user_data);
 }
 
 int audio_out_unset_interrupted_cb(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-
-       handle->user_cb = NULL;
-       handle->user_data = NULL;
-
-       LOGI("[%s] current interrupted cb (%p) / data (%p)",__FUNCTION__, handle->user_cb, handle->user_data);
-       return AUDIO_IO_ERROR_NONE;
+    return cpp_audio_out_unset_interrupted_cb(output);
 }
 
 int audio_out_ignore_session(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       audio_out_s *handle = (audio_out_s *) output;
-       int ret = 0;
-
-       if (handle->is_async) {
-               LOGE ("Not supported in async mode");
-               return AUDIO_IO_ERROR_INVALID_OPERATION;
-       }
+    return cpp_audio_out_ignore_session(output);
+}
 
-       ret = mm_sound_pcm_play_ignore_session(handle->mm_handle);
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-       LOGI("[%s] mm_sound_pcm_play_ignore_session() success",__FUNCTION__);
+int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data)
+{
+    return cpp_audio_out_set_stream_cb(output, callback, user_data);
+}
 
-       return AUDIO_IO_ERROR_NONE;
+int audio_out_unset_stream_cb(audio_out_h output)
+{
+    return cpp_audio_out_unset_stream_cb(output);
 }
 
-int audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* userdata)
+int audio_out_set_state_changed_cb(audio_out_h output, audio_out_state_changed_cb callback, void* user_data)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       AUDIO_IO_NULL_ARG_CHECK(callback);
-       return audio_out_set_callback_private(output, callback, userdata);
+    return cpp_audio_out_set_state_changed_cb(output, callback, user_data);
 }
 
-int audio_out_unset_stream_cb(audio_out_h output)
+int audio_out_unset_state_changed_cb(audio_out_h output)
 {
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       return audio_out_set_callback_private(output, NULL, NULL);
+    return cpp_audio_out_unset_state_changed_cb(output);
 }
diff --git a/src/audio_io_private.c b/src/audio_io_private.c
deleted file mode 100644 (file)
index b56a6de..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <mm.h>
-#include "audio_io_private.h"
-#include <dlog.h>
-
-#include <mm_sound_pcm_async.h>
-
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "TIZEN_N_AUDIO_IO"
-/*
-* Internal Implementation
-*/
-int __convert_audio_io_error_code(int code, char *func_name)
-{
-       int ret = AUDIO_IO_ERROR_INVALID_OPERATION;
-       char* msg = "AUDIO_IO_ERROR_INVALID_OPERATION";
-
-       switch(code)
-       {
-               case MM_ERROR_NONE:
-                       ret = AUDIO_IO_ERROR_NONE;
-                       msg = "AUDIO_IO_ERROR_NONE";
-                       break;
-               case MM_ERROR_INVALID_ARGUMENT:
-               case MM_ERROR_SOUND_DEVICE_INVALID_SAMPLERATE:
-               case MM_ERROR_SOUND_DEVICE_INVALID_CHANNEL:
-               case MM_ERROR_SOUND_DEVICE_INVALID_FORMAT:
-                       ret = AUDIO_IO_ERROR_INVALID_PARAMETER;
-                       msg = "AUDIO_IO_ERROR_INVALID_PARAMETER";
-                       break;
-               case MM_ERROR_SOUND_DEVICE_NOT_OPENED:
-                       ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED;
-                       msg = "AUDIO_IO_ERROR_DEVICE_NOT_OPENED";
-                       break;
-               case MM_ERROR_SOUND_PERMISSION_DENIED:
-                       ret = AUDIO_IO_ERROR_PERMISSION_DENIED;
-                       msg = "AUDIO_IO_ERROR_PERMISSION_DENIED";
-                       break;
-               case MM_ERROR_SOUND_INTERNAL:
-                       ret = AUDIO_IO_ERROR_INVALID_OPERATION;
-                       msg = "AUDIO_IO_ERROR_INVALID_OPERATION";
-                       break;
-               case MM_ERROR_SOUND_INVALID_POINTER:
-                       ret = AUDIO_IO_ERROR_INVALID_BUFFER;
-                       msg = "AUDIO_IO_ERROR_INVALID_BUFFER";
-                       break;
-               case MM_ERROR_POLICY_BLOCKED:
-               case MM_ERROR_POLICY_INTERRUPTED:
-               case MM_ERROR_POLICY_INTERNAL:
-               case MM_ERROR_POLICY_DUPLICATED:
-                       ret = AUDIO_IO_ERROR_SOUND_POLICY;
-                       msg = "AUDIO_IO_ERROR_SOUND_POLICY";
-                       break;
-       } 
-       LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
-       return ret;
-}
-
-int __check_parameter(int sample_rate, audio_channel_e channel, audio_sample_type_e type)
-{
-       if(sample_rate<8000 || sample_rate > 48000)     {
-               LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) :  Invalid sample rate (8000~48000Hz) : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,sample_rate);
-               return AUDIO_IO_ERROR_INVALID_PARAMETER;
-       }
-       if (channel < AUDIO_CHANNEL_MONO || channel > AUDIO_CHANNEL_STEREO) {
-               LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) :  Invalid audio channel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,channel);
-               return AUDIO_IO_ERROR_INVALID_PARAMETER;
-       }
-       if (type < AUDIO_SAMPLE_TYPE_U8 || type > AUDIO_SAMPLE_TYPE_S16_LE) {
-               LOGE("[%s] AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) :  Invalid sample typel : %d",__FUNCTION__, AUDIO_IO_ERROR_INVALID_PARAMETER,type);
-               return AUDIO_IO_ERROR_INVALID_PARAMETER;
-       }
-       return AUDIO_IO_ERROR_NONE;
-}
-
-//LCOV_EXCL_START
-audio_io_interrupted_code_e __translate_interrupted_code (int code)
-{
-       audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
-
-       switch(code)
-       {
-       case MM_MSG_CODE_INTERRUPTED_BY_CALL_END:
-       case MM_MSG_CODE_INTERRUPTED_BY_ALARM_END:
-       case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END:
-       case MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END:
-               e = AUDIO_IO_INTERRUPTED_COMPLETED;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_MEDIA:
-       case MM_MSG_CODE_INTERRUPTED_BY_OTHER_PLAYER_APP:
-               e = AUDIO_IO_INTERRUPTED_BY_MEDIA;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_CALL_START:
-               e = AUDIO_IO_INTERRUPTED_BY_CALL;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG:
-               e = AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_RESOURCE_CONFLICT:
-               e = AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_ALARM_START:
-               e = AUDIO_IO_INTERRUPTED_BY_ALARM;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START:
-               e = AUDIO_IO_INTERRUPTED_BY_NOTIFICATION;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START:
-               e = AUDIO_IO_INTERRUPTED_BY_EMERGENCY;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_MEDIA:
-               e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA;
-               break;
-
-       case MM_MSG_CODE_INTERRUPTED_BY_RESUMABLE_CANCELED:
-               e = AUDIO_IO_INTERRUPTED_BY_RESUMABLE_CANCELED;
-               break;
-       }
-
-       return e;
-}
-
-int __mm_sound_pcm_capture_msg_cb (int message, void *param, void *user_param)
-{
-       audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
-       audio_in_s *handle = (audio_in_s *) user_param;
-       MMMessageParamType *msg = (MMMessageParamType*)param;
-
-       LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code);
-
-       if (handle->user_cb == NULL) {
-               LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__);
-               return 0;
-       }
-
-       if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) {
-               e = __translate_interrupted_code (msg->code);
-       } else if (message == MM_MESSAGE_SOUND_PCM_CAPTURE_RESTRICTED) {
-               /* TODO : handling restricted code is needed */
-               /* e = _translate_restricted_code (msg->code); */
-       }
-
-       handle->user_cb (e, handle->user_data);
-
-       return 0;
-}
-
-static int __mm_sound_pcm_playback_msg_cb (int message, void *param, void *user_param)
-{
-       audio_io_interrupted_code_e e = AUDIO_IO_INTERRUPTED_COMPLETED;
-       audio_out_s *handle = (audio_out_s *) user_param;
-       MMMessageParamType *msg = (MMMessageParamType*)param;
-
-       LOGI("[%s] Got message type : 0x%x with code : %d" ,__FUNCTION__, message, msg->code);
-
-       if (handle->user_cb == NULL) {
-               LOGI("[%s] No interrupt callback is set. Skip this" ,__FUNCTION__);
-               return 0;
-       }
-
-       if (message == MM_MESSAGE_SOUND_PCM_INTERRUPTED) {
-               e = __translate_interrupted_code (msg->code);
-       }
-
-       handle->user_cb (e, handle->user_data);
-
-       return 0;
-}
-//LCOV_EXCL_STOP
-
-static int __audio_in_stream_cb (void* p, int nbytes, void* userdata)
-{
-       audio_in_s *handle = (audio_in_s *) userdata;
-
-       LOGI("<< p=%p, nbytes=%d, userdata=%p", p, nbytes, userdata);
-
-       if (handle && handle->stream_cb) {
-               handle->stream_cb ((audio_in_h)handle, nbytes, handle->stream_userdata);
-               LOGI("<< handle->stream_cb(handle:%p, nbytes:%d, handle->stream_userdata:%p)", p, nbytes, userdata);
-       } else {
-               LOGI("No stream callback is set. Skip this");
-       }
-       return 0;
-}
-
-static int __audio_out_stream_cb (void* p, int nbytes, void* userdata)
-{
-       audio_out_s *handle = (audio_out_s *) userdata;
-       bool is_started = false;
-       char * dummy = NULL;
-
-       LOGI(">> p=%p, nbytes=%d, userdata=%p", p, nbytes, userdata);
-
-       if (handle) {
-               mm_sound_pcm_is_started_async(handle->mm_handle, &is_started);
-               if (is_started) {
-                       if (handle->stream_cb) {
-                               handle->stream_cb ((audio_out_h)handle, nbytes, handle->stream_userdata);
-                       } else {
-                               LOGI("Started state but No stream callback is set. Skip this");
-                       }
-               } else {
-                       LOGI("Not started....write dummy data");
-                       if ((dummy = (char*)malloc(nbytes)) != NULL) {
-                               memset (dummy, 0, nbytes);
-                               mm_sound_pcm_play_write_async(handle->mm_handle, (void*) dummy, nbytes);
-                               free (dummy);
-                               LOGI("write done!!!");
-                       } else {
-                               LOGE("ERROR :  AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY);
-                       }
-               }
-       } else {
-               LOGE("Handle is invalid...");
-       }
-
-       return 0;
-}
-
-int audio_in_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type , int source_type, audio_in_h* input)
-{
-       int ret = 0;
-       audio_in_s *handle = NULL;
-
-       /* input condition check */
-       AUDIO_IO_NULL_ARG_CHECK(input);
-       if(__check_parameter(sample_rate, channel, type) != AUDIO_IO_ERROR_NONE)
-               return AUDIO_IO_ERROR_INVALID_PARAMETER;
-
-       /* Create Handle & Fill information */
-       if ((handle = (audio_in_s*)malloc( sizeof(audio_in_s))) == NULL) {
-               LOGE("ERROR :  AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY);
-               return AUDIO_IO_ERROR_OUT_OF_MEMORY;
-       }
-       memset(handle, 0, sizeof(audio_in_s));
-
-
-       /* Capture open */
-       if ((ret = mm_sound_pcm_capture_open_ex(&handle->mm_handle, sample_rate, channel, type, source_type)) < 0) {
-               LOGE("mm_sound_pcm_capture_open_ex() failed [0x%x]", ret);
-               goto ERROR;
-       }
-       LOGI("mm_sound_pcm_capture_open_ex() success");
-
-
-       if (source_type == SUPPORT_SOURCE_TYPE_LOOPBACK)
-       {
-           handle->is_loopback = 1;
-       }
-
-       handle->_buffer_size = ret; /* return by pcm_open */
-       handle->_sample_rate = sample_rate;
-       handle->_channel     = channel;
-       handle->_type        = type;
-
-       /* Set message interrupt callback */
-       if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_capture_msg_cb, handle)) < 0) {
-               LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret);
-               goto ERROR;
-       }
-       LOGI("mm_sound_pcm_set_message_callback() success");
-
-       /* Handle assign */
-       *input = (audio_in_h)handle;
-
-       return AUDIO_IO_ERROR_NONE;
-
-ERROR:
-       if (handle)
-               free (handle);
-       return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-}
-
-int audio_in_set_callback_private(audio_in_h input, audio_in_stream_cb callback, void* userdata)
-{
-       AUDIO_IO_NULL_ARG_CHECK(input);
-
-       int         ret         = AUDIO_IO_ERROR_NONE;
-       int         source_type = SUPPORT_SOURCE_TYPE_DEFAULT;
-       audio_in_s* handle      = (audio_in_s*)input;
-
-       // at first, release existing audio handle
-       if (handle->is_async) {
-               ret = mm_sound_pcm_capture_close_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_capture_close(handle->mm_handle);
-       }
-
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       // Initialize flags
-       handle->stream_cb       = NULL;
-       handle->stream_userdata = NULL;
-       handle->is_async        = 0;
-
-       // Checks loopback type
-       if (handle->is_loopback == 1) {
-               source_type = SUPPORT_SOURCE_TYPE_LOOPBACK;
-       }
-
-       /* Async (callback exists) or Sync (otherwise) */
-       if (callback != NULL) {
-               handle->stream_cb       = callback;
-               handle->stream_userdata = userdata;
-               handle->is_async        = 1;
-
-               /* Capture open */
-               if ((ret = mm_sound_pcm_capture_open_async(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, source_type,
-                               (mm_sound_pcm_stream_cb_t)__audio_in_stream_cb, handle)) < 0) {
-                       LOGE("mm_sound_pcm_capture_open_async() failed [0x%x]", ret);
-                       return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-               }
-               LOGI("mm_sound_pcm_capture_open_async() success");
-       } else {
-               /* Capture open */
-               if ((ret = mm_sound_pcm_capture_open_ex(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, source_type)) < 0) {
-                       LOGE("mm_sound_pcm_capture_open_ex() failed [0x%x]", ret);
-                       return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-               }
-               LOGI("mm_sound_pcm_capture_open_ex() success");
-       }
-
-       handle->_buffer_size = ret; /* return by pcm_open */
-
-       return AUDIO_IO_ERROR_NONE;
-}
-
-int audio_out_create_private(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h* output)
-{
-       audio_out_s *handle = NULL;
-       int ret = 0;
-
-       /* input condition check */
-       AUDIO_IO_NULL_ARG_CHECK(output);
-       if(__check_parameter(sample_rate, channel, type)!=AUDIO_IO_ERROR_NONE)
-               return AUDIO_IO_ERROR_INVALID_PARAMETER;
-       if(sound_type < SOUND_TYPE_SYSTEM || sound_type > SOUND_TYPE_VOICE) {
-               LOGE("ERROR :  AUDIO_IO_ERROR_INVALID_PARAMETER(0x%08x) : Invalid sample sound type : %d",
-                               AUDIO_IO_ERROR_INVALID_PARAMETER,sound_type );
-               return AUDIO_IO_ERROR_INVALID_PARAMETER;
-       }
-
-       /* Create Handle & Fill information */
-       if ((handle = (audio_out_s*)malloc( sizeof(audio_out_s))) == NULL) {
-               LOGE("ERROR :  AUDIO_IO_ERROR_OUT_OF_MEMORY(0x%08x)", AUDIO_IO_ERROR_OUT_OF_MEMORY);
-               return AUDIO_IO_ERROR_OUT_OF_MEMORY;
-       }
-       memset(handle, 0 , sizeof(audio_out_s));
-
-
-       if ((ret = mm_sound_pcm_play_open(&handle->mm_handle,sample_rate, channel, type, sound_type)) < 0) {
-               LOGE("mm_sound_pcm_play_open() failed [0x%x]", ret);
-               goto ERROR;
-       }
-       LOGI("mm_sound_pcm_play_open() success");
-
-
-       handle->_buffer_size = ret; /* return by pcm_open */
-       handle->_sample_rate = sample_rate;
-       handle->_channel     = channel;
-       handle->_type        = type;
-       handle->_sound_type  = sound_type;
-
-       /* Set message interrupt callback */
-       if ((ret = mm_sound_pcm_set_message_callback(handle->mm_handle, __mm_sound_pcm_playback_msg_cb, handle)) < 0) {
-               LOGE("mm_sound_pcm_set_message_callback() failed [0x%x]", ret);
-               goto ERROR;
-       }
-       LOGI("mm_sound_pcm_set_message_callback() success");
-
-       /* Handle assign */
-       *output = (audio_out_h)handle;
-
-       return AUDIO_IO_ERROR_NONE;
-
-ERROR:
-       if (handle)
-               free (handle);
-       return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-}
-
-int audio_out_set_callback_private(audio_out_h output, audio_out_stream_cb callback, void* userdata)
-{
-       AUDIO_IO_NULL_ARG_CHECK(output);
-
-       int          ret    = AUDIO_IO_ERROR_NONE;
-       audio_out_s* handle = (audio_out_s*)output;
-
-       // at first, release existing mm handle
-       if (handle->is_async) {
-               ret = mm_sound_pcm_play_close_async(handle->mm_handle);
-       } else {
-               ret = mm_sound_pcm_play_close(handle->mm_handle);
-       }
-
-       if (ret != MM_ERROR_NONE) {
-               return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-       }
-
-       // Initialize flags
-       handle->stream_cb       = NULL;
-       handle->stream_userdata = NULL;
-       handle->is_async        = 0;
-
-       /* Async (callback exists) or Sync (otherwise) */
-       if (callback != NULL) {
-               handle->stream_cb       = callback;
-               handle->stream_userdata = userdata;
-               handle->is_async        = 1;
-
-               /* Playback open */
-               if ((ret = mm_sound_pcm_play_open_async(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, handle->_sound_type,
-                               (mm_sound_pcm_stream_cb_t)__audio_out_stream_cb, handle)) < 0) {
-                       LOGE("mm_sound_pcm_play_open_async() failed [0x%x]", ret);
-                       return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-               }
-               LOGI("mm_sound_pcm_play_open_async() success");
-       } else {
-               if ((ret = mm_sound_pcm_play_open(&handle->mm_handle, handle->_sample_rate, handle->_channel, handle->_type, handle->_sound_type)) < 0) {
-                       LOGE("mm_sound_pcm_play_open() failed [0x%x]", ret);
-                       return __convert_audio_io_error_code(ret, (char*)__FUNCTION__);
-               }
-               LOGI("mm_sound_pcm_play_open() success");
-       }
-       handle->_buffer_size = ret; /* return by pcm_open */
-
-       return AUDIO_IO_ERROR_NONE;
-}
diff --git a/src/cpp/CAudioError.cpp b/src/cpp/CAudioError.cpp
new file mode 100644 (file)
index 0000000..b0bbfdb
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015 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 <dlog.h>
+#include "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CAudioError
+ */
+CAudioError::EError CAudioError::mLastError = CAudioError::ERROR_NONE;
+char CAudioError::mLastErrorMsg[CAudioError::MSG_LENGTH];
+
+CAudioError::CAudioError(EError err) : mError(err) {
+    mLastError = mError;
+}
+
+CAudioError::CAudioError(EError err, const char* fileName, const char* parentFunc, int lineNum) : mError(err) {
+    mLastError = mError;
+
+    const char* findFileName = strrchr(fileName, '/');
+    findFileName++;
+    const char* errStr = _convertErrorToString(mError);
+
+    snprintf(mErrorMsg, CAudioError::MSG_LENGTH, "["
+            COLOR_RED    "THROW" COLOR_END ":%s|"
+            COLOR_YELLOW "ERR"    COLOR_END ":%s|"
+            COLOR_YELLOW "FUNC"   COLOR_END ":%s(%d)]", findFileName, errStr, parentFunc, lineNum);
+
+    snprintf(mLastErrorMsg, CAudioError::MSG_LENGTH, "LastError:%s", mErrorMsg);
+}
+
+CAudioError::CAudioError(EError err, const char* msg, const char* fileName, const char* parentFunc, int lineNum) : mError(err) {
+    mLastError = mError;
+
+    const char* findFileName = strrchr(fileName, '/');
+    findFileName++;
+    const char* errStr = _convertErrorToString(mError);
+
+    snprintf(mErrorMsg, CAudioError::MSG_LENGTH, "["
+            COLOR_RED    "THROW" COLOR_END ":%s|"
+            COLOR_YELLOW "ERR"    COLOR_END ":%s|"
+            COLOR_YELLOW "FUNC"   COLOR_END ":%s(%d)]"
+            COLOR_YELLOW "MSG"    COLOR_END ":"
+            COLOR_CYAN   "%s"     COLOR_END, findFileName, errStr, parentFunc, lineNum, msg);
+
+    snprintf(mLastErrorMsg, CAudioError::MSG_LENGTH, "LastError:%s", mErrorMsg);
+}
+
+//CAudioError::CAudioError(CAudioError& err) {
+//    mError = err.mError;
+//    strncpy(mErrorMsg, err.mErrorMsg, MSG_LENGTH);
+//}
+
+CAudioError::~CAudioError() {
+}
+
+const char* CAudioError::_convertErrorToString(EError err) {
+    switch (err) {
+
+    default:
+    case ERROR_NONE:                return COLOR_GREEN "ERROR_NONE"               COLOR_END;
+    case ERROR_INVALID_ARGUMENT:    return COLOR_RED   "ERROR_INVALID_ARGUMENT"   COLOR_END;
+    case ERROR_INVALID_HANDLE:      return COLOR_RED   "ERROR_INVALID_HANDLE"     COLOR_END;
+    case ERROR_INVALID_SAMPLERATE:  return COLOR_RED   "ERROR_INVALID_SAMPLERATE" COLOR_END;
+    case ERROR_INVALID_CHANNEL:     return COLOR_RED   "ERROR_INVALID_CHANNEL"    COLOR_END;
+    case ERROR_INVALID_FORMAT:      return COLOR_RED   "ERROR_INVALID_FORMAT"     COLOR_END;
+    case ERROR_INVALID_POINTER:     return COLOR_RED   "ERROR_INVALID_POINTER"    COLOR_END;
+    case ERROR_INVALID_OPERATION:   return COLOR_RED   "ERROR_INVALID_OPERATION"  COLOR_END;
+    case ERROR_NOT_INITIALIZED:     return COLOR_RED   "ERROR_NOT_INITIALIZED"    COLOR_END;
+    case ERROR_NOT_SUPPORTED:       return COLOR_RED   "ERROR_NOT_SUPPORTED"      COLOR_END;
+    case ERROR_PERMISSION_DENIED:   return COLOR_RED   "ERROR_PERMISSION_DENIED"  COLOR_END;
+    case ERROR_DEVICE_NOT_OPENED:   return COLOR_RED   "ERROR_DEVICE_NOT_OPENED"  COLOR_END;
+    case ERROR_DEVICE_NOT_CLOSED:   return COLOR_RED   "ERROR_DEVICE_NOT_CLOSED"  COLOR_END;
+    case ERROR_OUT_OF_MEMORY:       return COLOR_RED   "ERROR_OUT_OF_MEMORY"      COLOR_END;
+    case ERROR_INTERNAL_OPERATION:  return COLOR_RED   "ERROR_INTERNAL_OPERATION" COLOR_END;
+    case ERROR_FAILED_OPERATION:    return COLOR_RED   "ERROR_FAILED_OPERATION"   COLOR_END;
+    case ERROR_POLICY_BLOCKED:      return COLOR_RED   "ERROR_POLICY_BLOCKED"     COLOR_END;
+    case ERROR_POLICY_INTERRUPTED:  return COLOR_RED   "ERROR_POLICY_INTERRUPTED" COLOR_END;
+    case ERROR_POLICY_DUPLICATED:   return COLOR_RED   "ERROR_POLICY_DUPLICATED"  COLOR_END;
+    }
+}
+
+CAudioError::EError CAudioError::getLastError() {
+    return mLastError;
+}
+
+const char* CAudioError::getLastErrorMsg() {
+    return mLastErrorMsg;
+}
+
+CAudioError::EError CAudioError::getError() {
+    return mError;
+}
+
+const char* CAudioError::getErrorMsg() {
+    return mErrorMsg;
+}
+
+CAudioError& CAudioError::operator = (const EError err) {
+    mError = err;
+    mLastError = mError;
+    return *this;
+}
+
+CAudioError& CAudioError::operator = (const CAudioError& err) {
+    mError = err.mError;
+    mLastError = mError;
+    memcpy(mErrorMsg, err.mErrorMsg, MSG_LENGTH);
+    memcpy(mLastErrorMsg, mErrorMsg, MSG_LENGTH);
+    return *this;
+}
+
+bool CAudioError::operator != (const EError err) {
+    return (mError != err);
+}
+
+bool CAudioError::operator == (const EError err) {
+    return (mError == err);
+}
+
+//bool operator == (const CAudioError& src, const CAudioError::EError& err) {
+//    //return (src.mLastError == err);
+//    return true;
+//}
diff --git a/src/cpp/CAudioIO.cpp b/src/cpp/CAudioIO.cpp
new file mode 100644 (file)
index 0000000..94bed76
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2015 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 <mm.h>
+#include <pthread.h>
+#include <assert.h>
+#include <audio-session-manager.h>
+#include "CAudioIODef.h"
+
+#define AUDIO_IO_DEBUG
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CAudioIO
+ */
+CAudioIO::CAudioIO() : mIsInit(false), mForceIgnore(false), mpAudioSessionHandler(NULL), mpPulseAudioClient(NULL) {
+    mState = CAudioInfo::AUDIO_IO_STATE_NONE;
+    mStatePrev = CAudioInfo::AUDIO_IO_STATE_NONE;
+    mByPolicy = false;
+}
+
+CAudioIO::CAudioIO(CAudioInfo& audioInfo) : mIsInit(false), mForceIgnore(false), mpAudioSessionHandler(NULL), mpPulseAudioClient(NULL) {
+    mAudioInfo = audioInfo;
+    mState = CAudioInfo::AUDIO_IO_STATE_NONE;
+    mStatePrev = CAudioInfo::AUDIO_IO_STATE_NONE;
+    mByPolicy = false;
+}
+
+CAudioIO::~CAudioIO() {
+}
+
+void CAudioIO::setInit(bool flag) {
+    mIsInit = flag;
+}
+
+bool CAudioIO::isInit() {
+    return mIsInit;
+}
+
+bool CAudioIO::IsReady() {
+    return ((mState == CAudioInfo::AUDIO_IO_STATE_RUNNING || mState == CAudioInfo::AUDIO_IO_STATE_PAUSED)? true : false);
+}
+
+void CAudioIO::internalLock() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    if (pthread_mutex_lock(&mMutex) != 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
+    }
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD(COLOR_RED"LOCK"COLOR_END);
+#endif
+}
+
+void CAudioIO::internalUnlock() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    if (pthread_mutex_unlock(&mMutex) != 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_INTERNAL_OPERATION, "Failed pthread_mutex_lock()");
+    }
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD(COLOR_GREEN"UNLOCK"COLOR_END);
+#endif
+}
+
+void CAudioIO::internalWait() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD(COLOR_RED"WAIT"COLOR_END);
+#endif
+
+    pthread_cond_wait(&mCond, &mMutex);
+}
+
+void CAudioIO::internalSignal() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD(COLOR_GREEN"SIGNAL"COLOR_END);
+#endif
+
+    pthread_cond_signal(&mCond);
+}
+
+bool CAudioIO::isForceIgnore() {
+    return mForceIgnore;
+}
+
+void CAudioIO::initialize() throw (CAudioError) {
+    if (mIsInit == true) {
+        return;
+    }
+
+    AUDIO_IO_LOGD("initialize");
+
+    int ret = pthread_mutex_init(&mMutex, NULL);
+    if (ret != 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_init()");
+    }
+
+    ret = pthread_cond_init(&mCond, NULL);
+    if (ret != 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_init()");
+    }
+
+    mIsInit = true;
+}
+
+void CAudioIO::finalize() {
+    if (mIsInit == false) {
+        return;
+    }
+
+    AUDIO_IO_LOGD("finalize");
+
+    int ret = pthread_mutex_destroy(&mMutex);
+    if (ret != 0) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pthread_mutex_destroy() ret:%d", ret);
+    }
+
+    ret = pthread_cond_destroy(&mCond);
+    if (ret != 0) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pthread_cond_destroy() ret:%d", ret);
+    }
+
+    mIsInit = false;
+}
+
+void CAudioIO::onStream(CPulseAudioClient* pClient, size_t length) {
+    assert(mIsInit == true);
+    assert(pClient != NULL);
+    assert(length > 0);
+
+    if (mStreamCallback.onStream != NULL) {
+        mStreamCallback.onStream(length, mStreamCallback.mUserData);
+    }
+}
+
+void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state, bool byPolicy) {
+    assert(mIsInit == true);
+    assert(state > 0);
+
+    mStatePrev = mState;
+    mState     = state;
+    mByPolicy  = byPolicy;
+
+    AUDIO_IO_LOGD("current(%d), previous(%d), by_policy(%d)", mState, mStatePrev, mByPolicy);
+
+    if (mStateChangedCallback.onStateChanged != NULL) {
+        mStateChangedCallback.onStateChanged(mState, mStatePrev, mByPolicy, mStateChangedCallback.mUserData);
+    }
+}
+
+void CAudioIO::onStateChanged(CAudioInfo::EAudioIOState state) {
+    onStateChanged(state, false);
+}
+
+void CAudioIO::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
+    assert(pHandler);
+
+    int session_option = pHandler->getOptions();
+
+    if (id == -1) {
+        ///////////////////////////////////////
+        // Triggered by 'focus watch callback'
+        ///////////////////////////////////////
+
+        if (session_option & (ASM_SESSION_OPTION_PAUSE_OTHERS | ASM_SESSION_OPTION_UNINTERRUPTIBLE)) {
+            AUDIO_IO_LOGD("Session option is pausing others or uninterruptible, skip...");
+            return;
+        }
+
+        if (state == FOCUS_IS_RELEASED) {
+            // Focus handle(id) of the other application was released, do resume if possible
+            internalLock();
+
+            mpPulseAudioClient->cork(false);
+            onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING);
+
+            internalUnlock();
+
+            // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
+            state = FOCUS_IS_ACQUIRED;
+        } else if (state == FOCUS_IS_ACQUIRED) {
+            // Focus handle(id) of the other application was acquired, do pause if possible
+            internalLock();
+            if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::STREAM_DIRECTION_PLAYBACK) {
+                if (mpPulseAudioClient->drain() == false) {
+                    AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
+                }
+            }
+
+            mpPulseAudioClient->cork(true);
+            onStateChanged(CAudioInfo::AUDIO_IO_STATE_PAUSED);
+
+            internalUnlock();
+
+            // Focus watch callback doesn't have focus handle, but it need to convert & report to application for convenience
+            state = FOCUS_IS_RELEASED;
+        }
+    } else {
+        ///////////////////////////////////////
+        // Triggered by 'focus callback'
+        ///////////////////////////////////////
+
+        if (pHandler->getId() != id) {
+            AUDIO_IO_LOGW("Id is different, why? [mId : %d]", pHandler->getId());
+        }
+
+        if (session_option & ASM_SESSION_OPTION_UNINTERRUPTIBLE) {
+            AUDIO_IO_LOGD("Session option is uninterruptible, skip...");
+            return;
+        }
+
+        if (state == FOCUS_IS_RELEASED) {
+            // Focus handle(id) was released, do pause here
+            internalLock();
+            if (mpPulseAudioClient->getStreamDirection() == CPulseAudioClient::STREAM_DIRECTION_PLAYBACK) {
+                if (mpPulseAudioClient->drain() == false) {
+                    AUDIO_IO_LOGE("Failed CPulseAudioClient::drain()");
+                }
+            }
+
+            mpPulseAudioClient->cork(true);
+            onStateChanged(CAudioInfo::AUDIO_IO_STATE_PAUSED);
+
+            internalUnlock();
+        } else if (state == FOCUS_IS_ACQUIRED) {
+            // Focus handle(id) was acquired again,
+            // check reason_for_change ("call-voice","call-video","voip","alarm","notification", ...)
+            // do resume here and call interrupt completed callback to application.
+            internalLock();
+
+            mpPulseAudioClient->cork(false);
+            onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING);
+
+            internalUnlock();
+        }
+    }
+
+    if (mInterruptCallback.onInterrupt != NULL) {
+        IAudioSessionEventListener::EInterruptCode e = IAudioSessionEventListener::INTERRUPT_COMPLETED;
+        e = IAudioSessionEventListener::convertInterruptedCode(state, reason_for_change);
+        mInterruptCallback.onInterrupt(e, mInterruptCallback.mUserData);
+    }
+}
+
+void CAudioIO::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) {
+    assert(pHandler);
+
+    if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
+        if (value == 1 && pHandler->getSubscribeId() >= 0) {
+            // Unregister focus watch callback & disable session handler
+            pHandler->disableSessionHandler();
+            AUDIO_IO_LOGD("Session handler disabled by signal");
+        } else if (value == 0) {
+            // Currently do nothing...
+        }
+    }
+}
+
+void CAudioIO::prepare() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    try {
+        internalLock();
+        AUDIO_IO_LOGD("prepare");
+        /* Do nothing */
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioIO::unprepare() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    try {
+        internalLock();
+        AUDIO_IO_LOGD("unprepare");
+        /* Do nothing */
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioIO::pause() throw (CAudioError) {
+    if (mIsInit == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
+    }
+
+    try {
+        internalLock();
+        AUDIO_IO_LOGD("pause");
+        mpPulseAudioClient->cork(true);
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioIO::resume() throw (CAudioError) {
+    if (mIsInit == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
+    }
+
+    try {
+        internalLock();
+        AUDIO_IO_LOGD("resume");
+        mpPulseAudioClient->cork(false);
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioIO::drain() throw (CAudioError) {
+    if (mIsInit == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
+    }
+
+    try {
+        internalLock();
+        AUDIO_IO_LOGD("drain");
+        mpPulseAudioClient->drain();
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioIO::flush() throw (CAudioError) {
+    if (mIsInit == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioIO");
+    }
+
+    try {
+        internalLock();
+        AUDIO_IO_LOGD("flush");
+        mpPulseAudioClient->flush();
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+CAudioInfo CAudioIO::getAudioInfo() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    return mAudioInfo;
+}
+
+void CAudioIO::setStreamCallback(SStreamCallback callback) throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    internalLock();
+    mStreamCallback = callback;
+    internalUnlock();
+}
+
+CAudioIO::SStreamCallback CAudioIO::getStreamCallback() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    return mStreamCallback;
+}
+
+void CAudioIO::setStateChangedCallback(SStateChangedCallback callback) throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    internalLock();
+    mStateChangedCallback = callback;
+    internalUnlock();
+}
+
+CAudioIO::SStateChangedCallback CAudioIO::getStateChangedCallback() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    return mStateChangedCallback;
+}
+
+void CAudioIO::setInterruptCallback(SInterruptCallback callback) throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    mInterruptCallback = callback;
+}
+
+CAudioIO::SInterruptCallback CAudioIO::getInterruptCallback() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    return mInterruptCallback;
+}
+
+
+void CAudioIO::ignoreSession() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioIO");
+    }
+
+    internalLock();
+
+    try {
+        if (mpPulseAudioClient != NULL && mpPulseAudioClient->isCorked() == false) {
+            THROW_ERROR_MSG(CAudioError::ERROR_INVALID_OPERATION, "An Operation is not permitted while started");
+        }
+
+        bool isSkip = mpAudioSessionHandler->isSkipSessionEvent();
+        if (isSkip == false && mpAudioSessionHandler->getId() >= 0) {
+            mpAudioSessionHandler->unregisterSound();
+            mForceIgnore = true;
+        }
+    } catch (CAudioError e) {
+        internalUnlock();
+
+        throw e;
+    }
+
+    internalUnlock();
+}
diff --git a/src/cpp/CAudioInfo.cpp b/src/cpp/CAudioInfo.cpp
new file mode 100644 (file)
index 0000000..0c18bf4
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015 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 "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CAudioInfo
+ */
+CAudioInfo::CAudioInfo()
+    :  mSampleRate(MAX_SYSTEM_SAMPLERATE), mChannel(CHANNEL_MONO),
+       mSampleType(SAMPLE_TYPE_U8), mAudioType(AUDIO_IN_TYPE_MEDIA),
+       mAudioIndex(-1) {
+}
+
+CAudioInfo::CAudioInfo(unsigned int sampleRate, EChannel channel, ESampleType sampleType, EAudioType audioType, int audioIndex) throw (CAudioError)
+    :  mSampleRate(sampleRate), mChannel(channel), mSampleType(sampleType), mAudioType(audioType), mAudioIndex(audioIndex) {
+    // Check to invalid AudioInfo
+    if (sampleRate < CAudioInfo::MIN_SYSTEM_SAMPLERATE || sampleRate > CAudioInfo::MAX_SYSTEM_SAMPLERATE) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The sampleRate is invalid [sampleRate:%d]", sampleRate);
+    }
+
+    if (channel < CAudioInfo::CHANNEL_MONO || channel >= CAudioInfo::CHANNEL_MAX) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The channel is invalid [channel:%d]", channel);
+    }
+
+    if (sampleType < CAudioInfo::SAMPLE_TYPE_U8 || sampleType >= CAudioInfo::SAMPLE_TYPE_MAX) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The sampleType is invalid [sampleType:%d]", sampleType);
+    }
+
+    if (audioType < CAudioInfo::AUDIO_IN_TYPE_MEDIA || audioType >= CAudioInfo::AUDIO_TYPE_MAX) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [audioType:%d]", audioType);
+    }
+}
+
+unsigned int CAudioInfo::getSampleRate() {
+    return mSampleRate;
+}
+
+CAudioInfo::EChannel CAudioInfo::getChannel() {
+    return mChannel;
+}
+
+CAudioInfo::ESampleType CAudioInfo::getSampleType() {
+    return mSampleType;
+}
+
+CAudioInfo::EAudioType CAudioInfo::getAudioType() {
+    return mAudioType;
+}
+
+void CAudioInfo::setAudioType(CAudioInfo::EAudioType AudioType) {
+    mAudioType = AudioType;
+    return;
+}
+
+int CAudioInfo::getAudioIndex() {
+    return mAudioIndex;
+}
+
+void CAudioInfo::setAudioIndex(int AudioIndex) {
+    mAudioIndex = AudioIndex;
+    return;
+}
+
+void CAudioInfo::convertAudioType2StreamType (CAudioInfo::EAudioType audioType, char **streamType)
+{
+    if (audioType < CAudioInfo::AUDIO_IN_TYPE_MEDIA || audioType >= CAudioInfo::AUDIO_TYPE_MAX) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [audioType:%d]", audioType);
+    }
+    *streamType = (char *)StreamTypeTable[audioType];
+    return;
+}
+
+void CAudioInfo::convertStreamType2AudioType (char *streamType, CAudioInfo::EAudioType *audioType)
+{
+    unsigned int i;
+    for (i = 0 ; i < CAudioInfo::AUDIO_TYPE_MAX ; i++) {
+        if (!strcmp((char *)StreamTypeTable[i], streamType)) {
+            break;
+        }
+    }
+    if (i < CAudioInfo::AUDIO_IN_TYPE_MEDIA || i >= CAudioInfo::AUDIO_TYPE_MAX) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The streamType is invalid [streamType:%s]", streamType);
+    }
+    *audioType = (CAudioInfo::EAudioType)i;
+    return;
+}
+
diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp
new file mode 100644 (file)
index 0000000..9440bc2
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2015 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 "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CAudioInput inherited by CAudioIO
+ */
+CAudioInput::CAudioInput(CAudioInfo& info)
+    : CAudioIO(info),
+      mpSyncReadDataPtr(NULL),
+      mSyncReadIndex(0),
+      mSyncReadLength(0),
+      mIsUsedSyncRead(true) {
+}
+
+CAudioInput::CAudioInput(
+        unsigned int            sampleRate,
+        CAudioInfo::EChannel    channel,
+        CAudioInfo::ESampleType type,
+        CAudioInfo::EAudioType  audioType)
+      : mpSyncReadDataPtr(NULL),
+        mSyncReadIndex(0),
+        mSyncReadLength(0),
+        mIsUsedSyncRead(true) {
+    mAudioInfo = CAudioInfo(sampleRate, channel, type, audioType, -1);
+}
+
+CAudioInput::~CAudioInput() {
+}
+
+void CAudioInput::onStream(CPulseAudioClient* pClient, size_t length) {
+    assert(pClient);
+
+    /*
+     * Does not call CAudioIO::onStream() for synchronization
+     * if a user is using read()
+     */
+    if (mIsUsedSyncRead == true) {
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+        AUDIO_IO_LOGD("Sync Read Mode! - signal! - pClient:[%p], length:[%d]", pClient, length);
+#endif
+        internalSignal();
+        return;
+    }
+
+    /*
+     * Accrues callback function
+     */
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("pClient:[%p], length:[%d]", pClient, length);
+#endif
+    CAudioIO::onStream(pClient, length);
+}
+
+void CAudioInput::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
+    assert(pHandler);
+    AUDIO_IO_LOGD("[pHandler:0x%x], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s]", pHandler, focus_type, state, reason_for_change, additional_info);
+    CAudioIO::onInterrupt(pHandler, id, focus_type, state, reason_for_change, additional_info);
+}
+
+void CAudioInput::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) {
+    assert(pHandler);
+    AUDIO_IO_LOGD("[pHandler:0x%x], [signal:%d], [value:%d]", pHandler, signal, value);
+    CAudioIO::onSignal(pHandler, signal, value);
+}
+
+void CAudioInput::setInit(bool flag) {
+    mIsInit = flag;
+}
+
+bool CAudioInput::IsInit() {
+    return (CAudioIO::isInit() == true && mIsInit == true);
+}
+
+bool CAudioInput::IsReady() {
+    return CAudioIO::IsReady();
+}
+
+void CAudioInput::initialize() throw (CAudioError) {
+    if (IsInit() == true) {
+        return;
+    }
+
+    try {
+        CAudioIO::initialize();
+
+        // Create ASM Handler
+        mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this);
+        if (mpAudioSessionHandler == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object");
+        }
+
+        // Initialize ASM Handler
+        mpAudioSessionHandler->initialize();
+
+        setInit(true);
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_IDLE);
+    } catch (CAudioError err) {
+        finalize();
+        throw err;
+    }
+}
+
+void CAudioInput::finalize() {
+    if (IsInit() == false) {
+        AUDIO_IO_LOGD("Did not initialize");
+        return;
+    }
+
+    SAFE_FINALIZE(mpAudioSessionHandler);
+    SAFE_DELETE(mpAudioSessionHandler);
+
+    CAudioIO::finalize();
+
+    setInit(false);
+}
+
+void CAudioInput::prepare() throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput");
+    }
+
+    if (IsReady() == true) {
+        AUDIO_IO_LOGD("Already prepared CAudioInput");
+        return;
+    }
+
+    try {
+        internalLock();
+
+        // Check to invalid AudioType
+        CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType();
+        if (audioType < CAudioInfo::AUDIO_IN_TYPE_MEDIA || audioType > CAudioInfo::AUDIO_IN_TYPE_LOOPBACK) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [type:%d]", static_cast<int>(audioType));
+        }
+
+        if (mpAudioSessionHandler->getId() < 0) {  //Did not registerSound()
+            // Check session to skip registration
+            if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+                // Register ASM Listener
+                AUDIO_IO_LOGD("Register ASM Listener");
+                mpAudioSessionHandler->registerSound();
+            }
+        }
+
+        // Init StreamSpec
+        AUDIO_IO_LOGD("Set Strem Spec : CPulseStreamSpec::STREAM_LATENCY_INPUT_MID");
+        CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::STREAM_LATENCY_INPUT_MID;
+        CPulseStreamSpec spec(streamSpec, mAudioInfo);
+
+        // Create PulseAudio Handler
+        mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::STREAM_DIRECTION_RECORD, spec, this);
+        if (mpPulseAudioClient == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to allocate CPulseAudioClient object");
+        }
+
+        // Initialize PulseAudio Handler
+        mpPulseAudioClient->initialize();
+
+        if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+            /* Updates ASM to PLAYING */
+            mpAudioSessionHandler->updatePlaying();
+        }
+
+        internalUnlock();
+
+        // Do Prepare
+        CAudioIO::prepare();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioInput::unprepare() throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput");
+    }
+
+    if (IsReady() == false) {
+        AUDIO_IO_LOGD("Already unprepared");
+        return;
+    }
+
+    try{
+        // Do unprepare
+        CAudioIO::unprepare();
+
+        internalLock();
+
+        SAFE_FINALIZE(mpPulseAudioClient);
+        SAFE_DELETE(mpPulseAudioClient);
+
+        if (mpAudioSessionHandler->getId() >= 0) {
+            /* Updates ASM to STOP */
+            if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+                mpAudioSessionHandler->updateStop();
+            }
+
+            bool isSkip = mpAudioSessionHandler->isSkipSessionEvent();
+            if (isSkip == false) {
+                mpAudioSessionHandler->unregisterSound();
+            }
+        }
+
+        internalUnlock();
+
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_IDLE);
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioInput::pause() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    try{
+        CAudioIO::pause();
+
+        internalLock();
+
+        /* Updates ASM to STOP */
+        if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+            mpAudioSessionHandler->updateStop();
+        }
+
+        internalUnlock();
+
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_PAUSED);
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioInput::resume() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    try {
+        internalLock();
+
+        if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+
+            /* Updates ASM to PLAYING */
+            mpAudioSessionHandler->updatePlaying();
+        }
+
+        internalUnlock();
+
+        CAudioIO::resume();
+
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING);
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioInput::drain() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    try{
+        CAudioIO::drain();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioInput::flush() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    try {
+        CAudioIO::flush();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+int CAudioInput::getBufferSize() throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput");
+    }
+
+    if (IsReady() == false) {
+        AUDIO_IO_LOGD("Warning: Did not prepare CAudioInput, then return zero");
+        return 0;
+    }
+
+    int size = 0;
+
+    try {
+        internalLock();
+        size = mpPulseAudioClient->getBufferSize();
+        internalUnlock();
+    } catch (CAudioError err) {
+        internalUnlock();
+        throw err;
+    }
+
+    return size;
+}
+
+void CAudioInput::setStreamCallback(SStreamCallback callback) throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioInput");
+    }
+
+    internalLock();
+    if (callback.onStream == NULL) {
+        AUDIO_IO_LOGD("mIsUsedSyncRead = true");
+        mIsUsedSyncRead = true;
+    } else {
+        AUDIO_IO_LOGD("mIsUsedSyncRead = false");
+        mIsUsedSyncRead = false;
+    }
+    internalUnlock();
+
+    CAudioIO::setStreamCallback(callback);
+}
+
+int CAudioInput::read(void* buffer, unsigned int length) throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    if (buffer == NULL) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are invalid - buffer:%p, length:%d", buffer, length);
+    }
+
+    /* Checks synchronous flag */
+    if (mIsUsedSyncRead == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "Does not support read() if receive stream callback");
+    }
+
+    internalLock();
+
+    unsigned int lengthIter = length;
+    int ret = 0;
+
+    try {
+        while (lengthIter > 0) {
+            size_t l;
+
+            while (mpSyncReadDataPtr == NULL) {
+                ret = mpPulseAudioClient->peek(&mpSyncReadDataPtr, &mSyncReadLength);
+                if (ret != 0) {
+                    THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed CPulseAudioClient::peek() ret:[%d]", ret);
+                }
+
+                if (mSyncReadLength <= 0) {
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+                    AUDIO_IO_LOGD("readLength(%d byte) is not valid.. wait..", mSyncReadLength);
+#endif
+                    internalWait();
+                } else if (mpSyncReadDataPtr == NULL) {
+                    /* There's a hole in the stream, skip it. We could generate
+                     * silence, but that wouldn't work for compressed streams.
+                     */
+                    ret = mpPulseAudioClient->drop();
+                    if (ret != 0) {
+                        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed CPulseAudioClient::drop() ret:[%d]", ret);
+                    }
+                } else {
+                    mSyncReadIndex = 0;
+                }
+            }//end of while (pReadData == NULL)
+
+            if (mSyncReadLength < lengthIter) {
+                l = mSyncReadLength;
+            } else {
+                l = lengthIter;
+            }
+
+            // Copy partial pcm data on out parameter
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+            AUDIO_IO_LOGD("memcpy() that a peeked buffer(%p), index(%d), length(%d), on out buffer", (const uint8_t*)(mpSyncReadDataPtr) + mSyncReadIndex, mSyncReadIndex, l);
+#endif
+            memcpy(buffer, (const uint8_t*)mpSyncReadDataPtr + mSyncReadIndex, l);
+
+            // Move next position
+            buffer = (uint8_t*)buffer + l;
+            lengthIter -= l;
+
+            // Adjusts the rest length
+            mSyncReadIndex  += l;
+            mSyncReadLength -= l;
+
+            if (mSyncReadLength == 0) {
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+                AUDIO_IO_LOGD("mSyncReadLength is zero - Do drop()");
+#endif
+                ret = mpPulseAudioClient->drop();
+                if (ret != 0) {
+                    THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed CPulseAudioClient::drop() ret:[%d]", ret);
+                }
+
+                // Reset the internal pointer
+                mpSyncReadDataPtr = NULL;
+                mSyncReadLength   = 0;
+                mSyncReadIndex    = 0;
+            }
+        }//end of while (length > 0)
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+
+    internalUnlock();
+
+    return length;
+}
+
+int CAudioInput::peek(const void** buffer, unsigned int* length) throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    if (buffer == NULL || length == NULL) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL buffer:%p, length:%p", buffer, length);
+    }
+
+    /* Checks synchronous flag */
+    internalLock();
+    if (mIsUsedSyncRead == true) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "Does not support peek() if does not receive a stream callback");
+    }
+    internalUnlock();
+
+    int ret = 0;
+
+    try {
+        internalLock();
+        ret = mpPulseAudioClient->peek(buffer, length);
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+
+    return ret;
+}
+
+int CAudioInput::drop() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioInput");
+    }
+
+    /* Checks synchronous flag */
+    internalLock();
+    if (mIsUsedSyncRead == true) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "Does not support drop() if does not receive a stream callback");
+    }
+    internalUnlock();
+
+    int ret = 0;
+
+    try {
+        internalLock();
+        ret = mpPulseAudioClient->drop();
+        internalUnlock();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+
+    return ret;
+}
diff --git a/src/cpp/CAudioOutput.cpp b/src/cpp/CAudioOutput.cpp
new file mode 100644 (file)
index 0000000..f050401
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2015 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 <vconf.h>
+#include "CAudioIODef.h"
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CAudioOutput
+ */
+CAudioOutput::CAudioOutput(CAudioInfo& info) : CAudioIO(info), mIsUsedSyncWrite(false) {
+}
+
+CAudioOutput::CAudioOutput(
+        unsigned int            sampleRate,
+        CAudioInfo::EChannel    channel,
+        CAudioInfo::ESampleType sampleType,
+        CAudioInfo::EAudioType  audioType) : mIsUsedSyncWrite(false) {
+    mAudioInfo = CAudioInfo(sampleRate, channel, sampleType, audioType, -1);
+}
+
+CAudioOutput::~CAudioOutput() {
+
+}
+
+void CAudioOutput::onStream(CPulseAudioClient* pClient, size_t length) {
+    assert(pClient);
+
+    /*
+     * Does not call CAudioIO::onStream() for synchronization
+     * if a user is using write()
+     */
+    if (mIsUsedSyncWrite == true) {
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+        AUDIO_IO_LOGD("Sync Write Mode! - signal! - pClient:[%p], length:[%d]", pClient, length);
+#endif
+        internalSignal();
+        return;
+    }
+
+    /*
+     * Accrues callback function
+     */
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("pClient:[%p], length:[%d]", pClient, length);
+#endif
+    CAudioIO::onStream(pClient, length);
+}
+
+void CAudioOutput::onInterrupt(CAudioSessionHandler* pHandler, int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info) {
+    assert(pHandler);
+    AUDIO_IO_LOGD("[pHandler:0x%x], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s]", pHandler, focus_type, state, reason_for_change, additional_info);
+    CAudioIO::onInterrupt(pHandler, id, focus_type, state, reason_for_change, additional_info);
+}
+
+void CAudioOutput::onSignal(CAudioSessionHandler* pHandler, mm_sound_signal_name_t signal, int value) {
+    assert(pHandler);
+    AUDIO_IO_LOGD("[pHandler:0x%x], [signal:%d], [value:%d]", pHandler, signal, value);
+    CAudioIO::onSignal(pHandler, signal, value);
+}
+
+void CAudioOutput::setInit(bool flag) {
+    mIsInit = flag;
+}
+
+bool CAudioOutput::IsInit() {
+    return (CAudioIO::isInit() == true && mIsInit == true);
+}
+
+bool CAudioOutput::IsReady() {
+    return CAudioIO::IsReady();
+}
+
+void CAudioOutput::initialize() throw (CAudioError) {
+    if (IsInit() == true) {
+        return;
+    }
+
+    try {
+        CAudioIO::initialize();
+
+        // Create ASM Handler
+        mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::AUDIO_SESSION_TYPE_PLAYBACK, mAudioInfo, this);
+        if (mpAudioSessionHandler == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to allocate CAudioSessionHandler object");
+        }
+
+        // Initialize ASM Handler
+        mpAudioSessionHandler->initialize();
+
+        setInit(true);
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_IDLE);
+    } catch (CAudioError err) {
+        finalize();
+        throw err;
+    }
+}
+
+void CAudioOutput::finalize() {
+    if (IsInit() == false) {
+        AUDIO_IO_LOGD("Did not initialize");
+        return;
+    }
+
+    SAFE_FINALIZE(mpAudioSessionHandler);
+    SAFE_DELETE(mpAudioSessionHandler);
+
+    CAudioIO::finalize();
+
+    setInit(false);
+}
+
+void CAudioOutput::prepare() throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioOutput");
+    }
+
+    if (IsReady() == true) {
+        AUDIO_IO_LOGD("Already prepared CAudioOutput");
+        return;
+    }
+
+    try {
+        internalLock();
+
+        // Check to invalid AudioType
+        CAudioInfo::EAudioType audioType = mAudioInfo.getAudioType();
+        if (audioType < CAudioInfo::AUDIO_OUT_TYPE_MEDIA || audioType >= CAudioInfo::AUDIO_TYPE_MAX) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [type:%d]", static_cast<int>(audioType));
+        }
+
+        if (mpAudioSessionHandler->getId() < 0) {  //Did not registerSound()
+            if (isForceIgnore() == false) {
+                // Register ASM Listener
+                AUDIO_IO_LOGD("Register ASM Listener");
+                mpAudioSessionHandler->registerSound();
+            }
+        }
+
+        // Init StreamSpec
+        AUDIO_IO_LOGD("Set Stream Spec : CPulseStreamSpec::STREAM_LATENCY_OUTPUT_MID");
+        CPulseStreamSpec::EStreamLatency streamSpec = CPulseStreamSpec::STREAM_LATENCY_OUTPUT_MID;
+        CPulseStreamSpec spec(streamSpec, mAudioInfo);
+
+        // Create PulseAudio Handler
+        mpPulseAudioClient = new CPulseAudioClient(CPulseAudioClient::STREAM_DIRECTION_PLAYBACK, spec, this);
+        if (mpPulseAudioClient == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to allocate CPulseAudioClient object");
+        }
+
+        // Initialize PulseAudio Handler
+        mpPulseAudioClient->initialize();
+
+        if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+            /* Updates ASM to PLAYING */
+            mpAudioSessionHandler->updatePlaying();
+        }
+
+        internalUnlock();
+
+        CAudioIO::prepare();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioOutput::unprepare() throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioOutput");
+    }
+
+    if (IsReady() == false) {
+        AUDIO_IO_LOGD("Already unprepared");
+        return;
+    }
+
+    try {
+        CAudioIO::unprepare();
+
+        internalLock();
+
+        SAFE_FINALIZE(mpPulseAudioClient);
+        SAFE_DELETE(mpPulseAudioClient);
+
+        if (mpAudioSessionHandler->getId() >= 0) {
+            /* Updates ASM to STOP */
+            if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+                mpAudioSessionHandler->updateStop();
+            }
+
+            bool isSkip = mpAudioSessionHandler->isSkipSessionEvent();
+            if (isSkip == false) {
+                mpAudioSessionHandler->unregisterSound();
+            }
+        }
+
+        internalUnlock();
+
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_IDLE);
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioOutput::pause() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput");
+    }
+
+    try {
+        CAudioIO::pause();
+
+        internalLock();
+
+        /* Updates ASM to STOP */
+        if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+            mpAudioSessionHandler->updateStop();
+        }
+
+        internalUnlock();
+
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_PAUSED);
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioOutput::resume() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput");
+    }
+
+    try {
+        internalLock();
+
+        if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) {
+
+            /* Updates ASM to PLAYING */
+            mpAudioSessionHandler->updatePlaying();
+        }
+
+        internalUnlock();
+
+        CAudioIO::resume();
+        CAudioIO::onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING);
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioOutput::drain() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput");
+    }
+
+    try {
+        CAudioIO::drain();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+void CAudioOutput::flush() throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput");
+    }
+
+    try {
+        CAudioIO::flush();
+    } catch (CAudioError e) {
+        internalUnlock();
+        throw e;
+    }
+}
+
+int CAudioOutput::getBufferSize() throw (CAudioError) {
+    if (IsInit() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CAudioOutput");
+    }
+
+    if (IsReady() == false) {
+        AUDIO_IO_LOGD("Warning: Did not prepare CAudioOutput, then return zero");
+        return 0;
+    }
+
+    int size = 0;
+
+    try {
+        internalLock();
+        size = mpPulseAudioClient->getBufferSize();
+        internalUnlock();
+    } catch (CAudioError err) {
+        internalUnlock();
+        throw err;
+    }
+
+    return size;
+}
+
+int CAudioOutput::write(const void* buffer, unsigned int length) throw (CAudioError) {
+    if (IsInit() == false || IsReady() == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize or prepare CAudioOutput");
+    }
+
+    if (buffer == NULL) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are invalid - buffer:%p, length:%d", buffer, length);
+    }
+
+    /*
+     * Check skip condition.
+     * If accessibility screen reader (VOICE type with NoSession), no need to check, always do write.
+     */
+    if (mpAudioSessionHandler->isSkipSessionEvent() == false) {
+        /* Check whether voicerecorder is running */
+        int vrState = 0;
+
+        vconf_get_int(VCONFKEY_RECORDER_STATE, &vrState);
+        if (vrState == VCONFKEY_RECORDER_STATE_RECORDING) {
+            THROW_ERROR_MSG(CAudioError::ERROR_POLICY_BLOCKED, "During Voicerecording --> MUTE");
+        }
+    }
+
+    /* When write() is called in PulseAudio callback, bypass a pcm data to PulseAudioClient (For  Asynchronous) */
+    if (mpPulseAudioClient->isInThread() == true) {
+        int ret = mpPulseAudioClient->write(buffer, length);
+        if (ret == 0) {
+            return length;
+        }
+    }
+
+    /* For synchronization */
+    internalLock();
+
+    // Sets synchronous flag
+    mIsUsedSyncWrite = true;
+
+    unsigned int lengthIter = length;
+    try {
+        while (lengthIter > 0) {
+            int l, r;
+
+            while ((l = mpPulseAudioClient->getWritableSize()) == 0) {
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+                AUDIO_IO_LOGD("writableSize is [%d].. wait", l);
+#endif
+                internalWait();
+            }
+
+            if (l == -1) {
+                THROW_ERROR_MSG(CAudioError::ERROR_INTERNAL_OPERATION, "The Writable size is invalid");
+            }
+
+            if (static_cast<unsigned int>(l) > lengthIter) {
+                l = lengthIter;
+            }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+            AUDIO_IO_LOGD("PulseAudioClient->write(buffer:%p, length:%d)", buffer, l);
+#endif
+
+            r = mpPulseAudioClient->write(buffer, l);
+            if (r < 0) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "The written result is invalid ret:%d", r);
+            }
+
+            buffer = static_cast<const uint8_t*>(buffer) + l;
+            lengthIter -= l;
+        }//end of while (length > 0)
+    } catch (CAudioError e) {
+        // Unsets synchronous flag
+        mIsUsedSyncWrite = false;
+        internalUnlock();
+        throw e;
+    }
+
+    // Unsets synchronous flag
+    mIsUsedSyncWrite = false;
+    internalUnlock();
+
+    return length;
+}
diff --git a/src/cpp/CAudioSessionHandler.cpp b/src/cpp/CAudioSessionHandler.cpp
new file mode 100644 (file)
index 0000000..f6a37b1
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2015 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 <mm_error.h>
+#include "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CAudioSessionHandler
+ */
+int CAudioSessionHandler::sCaptureRef = 0;
+
+int CAudioSessionHandler::PCM_CAPTURE_COUNT_INC() {
+    int actual;
+    do {
+        actual = sCaptureRef;
+    } while (!__sync_bool_compare_and_swap(&sCaptureRef, actual, actual + 1));
+    AUDIO_IO_LOGD("CaptureRefCount+1 > [%d]", sCaptureRef);
+    return sCaptureRef;
+}
+
+int CAudioSessionHandler::PCM_CAPTURE_COUNT_DEC() {
+    int actual;
+    do {
+        actual = sCaptureRef;
+    } while (!__sync_bool_compare_and_swap(&sCaptureRef, actual, actual - 1));
+    AUDIO_IO_LOGD("CaptureRefCount-1 > [%d]", sCaptureRef);
+    if (sCaptureRef < 0) {
+        AUDIO_IO_LOGE("A CaptureRef[%d] is not valid! Something is wrong!", sCaptureRef);
+        sCaptureRef = 0;
+    }
+    return sCaptureRef;
+}
+
+int CAudioSessionHandler::PCM_CAPTURE_COUNT_GET() {
+    AUDIO_IO_LOGD("CaptureRefCount > [%d]", sCaptureRef);
+    return sCaptureRef;
+}
+
+int CAudioSessionHandler::sFocusRef = 0;
+
+int CAudioSessionHandler::FOCUS_ID_COUNT_INC() {
+    int actual;
+    do {
+        actual = sFocusRef;
+    } while (!__sync_bool_compare_and_swap(&sFocusRef, actual, actual + 1));
+    AUDIO_IO_LOGD("FocusRefCount+1 > [%d]", sFocusRef);
+    return sFocusRef;
+}
+
+int CAudioSessionHandler::FOCUS_ID_COUNT_DEC() {
+    int actual;
+    do {
+        actual = sFocusRef;
+    } while (!__sync_bool_compare_and_swap(&sFocusRef, actual, actual - 1));
+    AUDIO_IO_LOGD("FocusRefCount-1 > [%d]", sFocusRef);
+    return sFocusRef;
+}
+
+int CAudioSessionHandler::FOCUS_ID_COUNT_GET() {
+    /* AUDIO_IO_LOGD("FocusRefCount > [%d]", sFocusRef); */
+    return sFocusRef;
+}
+
+CAudioSessionHandler::CAudioSessionHandler(EAudioSessionType sessionType, CAudioInfo& audioInfo, IAudioSessionEventListener* listener)
+: mId(-1),
+  mOptions(0),
+  mAudioSession(sessionType),
+  mMultimediaSession(MM_SESSION_TYPE_MEDIA),
+  mpEventListener(listener),
+  mIsInit(false),
+  mUseFocus(false),
+  mSubscribeId(-1) {
+    mAudioInfo = audioInfo;
+}
+
+CAudioSessionHandler::~CAudioSessionHandler() {
+}
+
+CAudioError CAudioSessionHandler::_convertStreamType(EAudioSessionType type1, MMSessionType type2, int *index) {
+    unsigned int i;
+    int idx = -1;
+
+    assert(index != NULL);
+
+    if (type1 == AUDIO_SESSION_TYPE_CAPTURE) {
+        for (i = 0 ; i < sizeof(stream_type_table_in) / sizeof(stream_type_table_in[0]) ; i++) {
+            if (stream_type_table_in[i].type == type2) {
+                idx = i;
+                break;
+            }
+        }
+    } else {
+        for (i = 0 ; i < sizeof(stream_type_table_out) / sizeof(stream_type_table_out[0]) ; i++) {
+            if (stream_type_table_out[i].type == type2) {
+                idx = i;
+                break;
+            }
+        }
+    }
+
+    if (idx < 0) {
+        RET_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "Does not support session type.");
+    }
+    *index = idx;
+    RET_ERROR(CAudioError::ERROR_NONE);
+}
+
+CAudioError CAudioSessionHandler::_getAsmInformation(MMSessionType *type, int *options) {
+    assert(type != NULL);
+    assert(options != NULL);
+
+    MMSessionType currentSession = MM_SESSION_TYPE_MEDIA;
+    int           sessionOptions = 0;
+
+    /* Read session information */
+    int ret = 0;
+    if ((ret = _mm_session_util_read_information(-1, (int*)&currentSession, &sessionOptions)) < 0) {
+        if(ret == (int) MM_ERROR_INVALID_HANDLE) {
+            RET_ERROR_MSG(CAudioError::ERROR_INVALID_HANDLE, "Failed _mm_session_util_read_information(). Invalid handle");
+        } else {
+            RET_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed _mm_session_util_read_information(). Not exist");
+        }
+    }
+
+    *type    = currentSession;
+    *options = sessionOptions;
+
+    RET_ERROR(CAudioError::ERROR_NONE);
+}
+
+bool CAudioSessionHandler::_isFocusRequired(MMSessionType type, int options) {
+    if((options & ASM_SESSION_OPTION_PAUSE_OTHERS)
+        || ((type != MM_SESSION_TYPE_MEDIA) && (type != MM_SESSION_TYPE_MEDIA_RECORD)))
+        return true;
+    else
+        return false;
+}
+
+int CAudioSessionHandler::getId() {
+    return mId;
+}
+
+int CAudioSessionHandler::getOptions() {
+    return mOptions;
+}
+
+CAudioSessionHandler::EAudioSessionType CAudioSessionHandler::getAudioSession() {
+    return mAudioSession;
+}
+
+MMSessionType CAudioSessionHandler::getMultimediaSession() {
+    return mMultimediaSession;
+}
+
+int CAudioSessionHandler::getSubscribeId() {
+    return mSubscribeId;
+}
+
+CAudioInfo CAudioSessionHandler::getAudioInfo() {
+    return mAudioInfo;
+}
+
+void CAudioSessionHandler::_sound_pcm_signal_cb(mm_sound_signal_name_t signal, int value, void *user_data) {
+    assert(user_data);
+
+    AUDIO_IO_LOGD("[signal:%d], [value:%d], [user_data:0x%x]", signal, value, user_data);
+
+    CAudioSessionHandler* pHandler = static_cast<CAudioSessionHandler*>(user_data);
+    if (pHandler->mpEventListener != NULL) {
+        pHandler->mpEventListener->onSignal(pHandler, signal, value);
+    }
+}
+
+void CAudioSessionHandler::initialize() throw (CAudioError) {
+    AUDIO_IO_LOGD("");
+    if (mIsInit == true) {
+        return;
+    }
+
+    MMSessionType currentSession = MM_SESSION_TYPE_MEDIA;
+    int           sessionOptions = 0;  // Mix with others by default
+
+    CAudioError err = _getAsmInformation(&currentSession, &sessionOptions);
+    if (err == CAudioError::ERROR_NONE) {
+        // Session was configured before, use focus callback
+        mUseFocus = true;
+        AUDIO_IO_LOGD("Use audio focus concept internally!");
+    } else {
+        if (err == CAudioError::ERROR_INVALID_HANDLE) {
+            int value = 0;
+            unsigned int subscribe_id;
+
+            int errorCode = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &value);
+            if (errorCode != MM_ERROR_NONE) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_get_signal_value() err:0x%x", errorCode);
+            }
+
+            if (value == 1) {
+                // stream_info was created or focus watch callback was configured before
+                mUseFocus = false;
+                AUDIO_IO_LOGD("Skip audio focus concept!");
+            } else if (value == 0) {
+                // No session, No stream_info, No focus watch callback before
+                // Use focus watch callback with signal subscribe
+                errorCode = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &subscribe_id, _sound_pcm_signal_cb, static_cast<void*>(this));
+                if (errorCode != MM_ERROR_NONE) {
+                    THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_get_signal_value() err:0x%x", errorCode);
+                }
+
+                mSubscribeId = (int)subscribe_id;
+                AUDIO_IO_LOGD("Subscribed mm_sound signal");
+
+                sessionOptions = 0;  // Mix with others by default
+                mUseFocus = true;
+                AUDIO_IO_LOGD("Use audio focus(watch) concept internally!");
+            }
+        } else {
+            mUseFocus = false;
+            AUDIO_IO_LOGD("Skip audio focus concept!");
+        }
+
+        if (mAudioSession == AUDIO_SESSION_TYPE_CAPTURE) {
+            AUDIO_IO_LOGD("Set default \"Media_Record\" type");
+            currentSession = MM_SESSION_TYPE_MEDIA_RECORD;
+        } else {
+            AUDIO_IO_LOGD("Set default \"Media\" type");
+            currentSession = MM_SESSION_TYPE_MEDIA;
+        }
+    }
+
+    // Updates session information
+    mMultimediaSession = currentSession;
+    mOptions           = sessionOptions;
+
+    if (this->mAudioSession == AUDIO_SESSION_TYPE_CAPTURE) {
+        PCM_CAPTURE_COUNT_INC();
+    }
+
+    mIsInit = true;
+}
+
+void CAudioSessionHandler::finalize() {
+    AUDIO_IO_LOGD("");
+    if (mIsInit == false) {
+        return;
+    }
+
+    if (mAudioSession == AUDIO_SESSION_TYPE_CAPTURE) {
+        PCM_CAPTURE_COUNT_DEC();
+    }
+
+    if (mSubscribeId >= 0) {
+        mm_sound_unsubscribe_signal(mSubscribeId);
+    }
+
+    mIsInit = false;
+}
+
+bool CAudioSessionHandler::isSkipSessionEvent() throw (CAudioError) {
+    bool ret = false;
+
+    // To be regarded...
+#if 0
+    /* Only Support below Event */
+    if (mEvent != ASM_EVENT_CALL              && mEvent != ASM_EVENT_VOIP              &&
+        mEvent != ASM_EVENT_VIDEOCALL         && mEvent != ASM_EVENT_VOICE_RECOGNITION &&
+        mEvent != ASM_EVENT_MMCAMCORDER_AUDIO && mEvent != ASM_EVENT_MMCAMCORDER_VIDEO) {
+
+        // Check AudioType
+        switch (mAudioInfo.getAudioType()) {
+        case CAudioInfo::AUDIO_IN_TYPE_MEDIA:
+        case CAudioInfo::AUDIO_IN_TYPE_VOICECONTROL:
+            ret = false;
+            break;
+
+        case CAudioInfo::AUDIO_IN_TYPE_MIRRORING:
+        case CAudioInfo::AUDIO_IN_TYPE_LOOPBACK:
+            ret = true;
+            break;
+
+        default:
+            return false;
+        }
+
+        if (ret == true) {
+            int captureCount = CAudioSessionHandler::PCM_CAPTURE_COUNT_GET();
+            if (captureCount == 1) {/* If this is last one */
+                /* Recover session information to MEDIA */
+                int sessionResult = _mm_session_util_write_information(-1, MM_SESSION_TYPE_MEDIA, mOptions);
+                if (sessionResult != 0) {
+                    THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "Failed _mm_session_util_write_information() ret:%d", sessionResult);
+                }
+            }
+        }
+    }
+#endif
+
+    return ret;
+}
+
+void CAudioSessionHandler::_sound_pcm_focus_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data) {
+    assert(user_data);
+
+    AUDIO_IO_LOGD("[id:%d], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s], [user_data:0x%x]", id, focus_type, state, reason_for_change, additional_info, user_data);
+
+    CAudioSessionHandler* pHandler = static_cast<CAudioSessionHandler*>(user_data);
+    pHandler->mFocusType       = focus_type;
+    pHandler->mState           = state;
+    pHandler->mReasonForChange = (char *)reason_for_change;
+    pHandler->mAdditionalInfo  = (char *)additional_info;
+
+    if (pHandler->mpEventListener != NULL) {
+        pHandler->mpEventListener->onInterrupt(pHandler, id, focus_type, state, reason_for_change, additional_info);
+    }
+
+    return;
+}
+
+void CAudioSessionHandler::_sound_pcm_focus_watch_cb(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data) {
+    AUDIO_IO_LOGD("[id:%d], [focus_type:%d], [state:%d], [reason_for_change:%s], [additional_info:%s], [user_data:0x%x]", id, focus_type, state, reason_for_change, additional_info, user_data);
+
+    CAudioSessionHandler::_sound_pcm_focus_cb(-1, focus_type, state, reason_for_change, additional_info, user_data);
+
+    return;
+}
+
+void CAudioSessionHandler::registerSound() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
+    }
+
+    if (mUseFocus == true) {
+        if (mId >= 0) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Already registered [id:%d]", mId);
+        }
+
+        int errorCode = 0;
+
+        if (_isFocusRequired(mMultimediaSession, mOptions)) {
+            int index = 0;
+            CAudioError err = _convertStreamType(mAudioSession, mMultimediaSession, &index);
+            if (err != CAudioError::ERROR_NONE) {
+                throw err;
+            }
+
+            errorCode = mm_sound_focus_get_id(&mId);
+            if (errorCode != MM_ERROR_NONE) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_focus_get_id() err:0x%x", errorCode);
+            }
+
+            // Register focus callback
+            errorCode = mm_sound_register_focus(mId,
+                                                mAudioSession == AUDIO_SESSION_TYPE_CAPTURE ? stream_type_table_in[index].name : stream_type_table_out[index].name,
+                                                _sound_pcm_focus_cb,
+                                                static_cast<void*>(this));
+            if (errorCode != MM_ERROR_NONE) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_register_focus() err:0x%x", errorCode);
+            }
+
+            FOCUS_ID_COUNT_INC();
+
+            AUDIO_IO_LOGD("Focus callback registered successfully [id:%d]", mId);
+        } else if (!(mOptions & ASM_SESSION_OPTION_UNINTERRUPTIBLE)) {
+            // Register focus watch callback
+            errorCode = mm_sound_set_focus_watch_callback(FOCUS_FOR_BOTH, _sound_pcm_focus_watch_cb, static_cast<void*>(this), &mId);
+            if (errorCode < 0) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_set_focus_watch_callback() err:0x%x", errorCode);
+            }
+
+            FOCUS_ID_COUNT_INC();
+
+            AUDIO_IO_LOGD("Focus watch callback registered successfully [id:%d]", mId);
+        }
+    }
+}
+
+void CAudioSessionHandler::unregisterSound() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
+    }
+
+    if (mUseFocus == true) {
+        if (mId < 0) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Did not register [id:%d]", mId);
+        }
+
+        int errorCode = 0;
+
+        if (_isFocusRequired(mMultimediaSession, mOptions)) {
+            // Unregister focus callback
+            errorCode = mm_sound_unregister_focus(mId);
+            if (errorCode != MM_ERROR_NONE) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_unregister_focus() err:0x%x", errorCode);
+            }
+
+            FOCUS_ID_COUNT_DEC();
+
+            AUDIO_IO_LOGD("Focus callback unregistered successfully [id:%d]", mId);
+            mId = -1;
+        } else if (!(mOptions & ASM_SESSION_OPTION_UNINTERRUPTIBLE)) {
+            // Unregister focus watch callback.
+            errorCode = mm_sound_unset_focus_watch_callback(mId);
+            if (errorCode < 0) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_unset_focus_watch_callback() err:0x%x", errorCode);
+            }
+
+            FOCUS_ID_COUNT_DEC();
+
+            AUDIO_IO_LOGD("Focus watch callback unregistered successfully [id:%d]", mId);
+            mId = -1;
+        }
+    }
+}
+
+void CAudioSessionHandler::updatePlaying() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
+    }
+
+    if (mUseFocus && _isFocusRequired(mMultimediaSession, mOptions)) {
+        if (mId >= 0) {
+            int ret = mm_sound_acquire_focus(mId, FOCUS_FOR_BOTH, "audio-io acquire focus");
+            if (ret != MM_ERROR_NONE) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_acquire_focus() err:0x%x", ret);
+            }
+            AUDIO_IO_LOGD("Focus acquired successfully [id:%d]", mId);
+        }
+    }
+}
+
+void CAudioSessionHandler::updateStop() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Doesn't initialize CAudioSessionHandler");
+    }
+
+    if (mUseFocus && _isFocusRequired(mMultimediaSession, mOptions)) {
+        if (mId >= 0) {
+            int ret = mm_sound_release_focus(mId, FOCUS_FOR_BOTH, "audio-io release focus");
+            if (ret != MM_ERROR_NONE) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_POLICY_BLOCKED, "Failed mm_sound_release_focus() err:0x%x", ret);
+            }
+            AUDIO_IO_LOGD("Focus released successfully [id:%d]", mId);
+        }
+    }
+}
+
+void CAudioSessionHandler::disableSessionHandler() throw (CAudioError) {
+    CAudioSessionHandler::updateStop();
+    CAudioSessionHandler::unregisterSound();
+
+    CAudioSessionHandler::mUseFocus = false;
+}
+
+/**
+ * class IAudioSessionEventListener
+ */
+IAudioSessionEventListener::EInterruptCode IAudioSessionEventListener::convertInterruptedCode(int code, const char *reason_for_change) {
+    EInterruptCode e = INTERRUPT_COMPLETED;
+
+    switch (code)
+    {
+    case FOCUS_IS_ACQUIRED:
+        e = INTERRUPT_COMPLETED;
+        break;
+
+    case FOCUS_IS_RELEASED:
+        if (!strcmp(reason_for_change, "media"))              e = INTERRUPT_BY_MEDIA;
+        if (!strcmp(reason_for_change, "radio"))              e = INTERRUPT_BY_MEDIA;
+        if (!strcmp(reason_for_change, "loopback"))           e = INTERRUPT_BY_MEDIA;
+        if (!strcmp(reason_for_change, "system"))             e = INTERRUPT_BY_MEDIA;
+        if (!strcmp(reason_for_change, "alarm"))              e = INTERRUPT_BY_ALARM;
+        if (!strcmp(reason_for_change, "notification"))       e = INTERRUPT_BY_NOTIFICATION;
+        if (!strcmp(reason_for_change, "emergency"))          e = INTERRUPT_BY_EMERGENCY;
+        if (!strcmp(reason_for_change, "voice-information"))  e = INTERRUPT_BY_MEDIA;  //for what?
+        if (!strcmp(reason_for_change, "voice-recognition"))  e = INTERRUPT_BY_MEDIA;  //for what?
+        if (!strcmp(reason_for_change, "ringtone-voip"))      e = INTERRUPT_BY_MEDIA;  //for what?
+        if (!strcmp(reason_for_change, "ringtone-call"))      e = INTERRUPT_BY_MEDIA;  //for what?
+        if (!strcmp(reason_for_change, "voip"))               e = INTERRUPT_BY_MEDIA;  //for what?
+        if (!strcmp(reason_for_change, "call-voice"))         e = INTERRUPT_BY_MEDIA;  //for what?
+        if (!strcmp(reason_for_change, "call-video"))         e = INTERRUPT_BY_MEDIA;  //for what?
+        break;
+    }
+
+    return e;
+}
diff --git a/src/cpp/CPulseAudioClient.cpp b/src/cpp/CPulseAudioClient.cpp
new file mode 100644 (file)
index 0000000..55d2f39
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+ * Copyright (c) 2015 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 <mm.h>
+#include "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CPulseAudioClient
+ */
+const char* CPulseAudioClient::CLIENT_NAME = "AUDIO_IO_PA_CLIENT";
+
+CPulseAudioClient::CPulseAudioClient(EStreamDirection      direction,
+                                     CPulseStreamSpec&     spec,
+                                     IPulseStreamListener* listener)
+    : mDirection(direction), mSpec(spec),     mpListener(listener),
+      mpMainloop(NULL),      mpContext(NULL), mpStream(NULL),
+      mpPropList(NULL),      mIsInit(false),  mIsOperationSuccess(false) {
+}
+
+CPulseAudioClient::~CPulseAudioClient() {
+    finalize();
+}
+
+void CPulseAudioClient::_contextStateChangeCb(pa_context* c, void* user_data) {
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+    assert(pClient);
+    assert(c);
+
+    switch (pa_context_get_state(c)) {
+    case PA_CONTEXT_READY:
+        AUDIO_IO_LOGD("The context is ready!");
+    case PA_CONTEXT_FAILED:
+    case PA_CONTEXT_TERMINATED:
+        pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
+        break;
+
+    case PA_CONTEXT_UNCONNECTED:
+    case PA_CONTEXT_CONNECTING:
+    case PA_CONTEXT_AUTHORIZING:
+    case PA_CONTEXT_SETTING_NAME:
+        break;
+    }
+}
+
+void CPulseAudioClient::_successContextCb(pa_context* c, int success, void* user_data) {
+    AUDIO_IO_LOGD("pa_context[%p], success[%d], user_data[%p]", c, success, user_data);
+    assert(c);
+    assert(user_data);
+
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+    pClient->mIsOperationSuccess = static_cast<bool>(success);
+
+    pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
+}
+
+void CPulseAudioClient::_streamStateChangeCb(pa_stream* s, void* user_data) {
+    assert(s);
+    assert(user_data);
+
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+
+    switch (pa_stream_get_state(s)) {
+    case PA_STREAM_READY:
+        AUDIO_IO_LOGD("The stream is ready!");
+        pClient->mpListener->onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING);
+    case PA_STREAM_FAILED:
+    case PA_STREAM_TERMINATED:
+        pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
+        break;
+
+    case PA_STREAM_UNCONNECTED:
+        break;
+    case PA_STREAM_CREATING:
+        break;
+    }
+}
+
+void CPulseAudioClient::_streamCaptureCb(pa_stream* s, size_t length, void* user_data) {
+    assert(s);
+    assert(user_data);
+
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+    assert(pClient->mpListener);
+
+    pClient->mpListener->onStream(pClient, length);
+}
+
+void CPulseAudioClient::_streamPlaybackCb(pa_stream* s, size_t length, void* user_data) {
+    //AUDIO_IO_LOGD("_streamPlaybackCb()");
+    assert(s);
+    assert(user_data);
+
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+    assert(pClient->mpListener);
+
+    if (pClient->mIsInit == false) {
+        AUDIO_IO_LOGD("Occurred this listener when an out stream is on the way to create - Dummy write[length:%d]", length);
+
+        char* dummy = new char[length];
+        memset(dummy, 0, length);
+        pa_stream_write(s, dummy, length, NULL, 0LL, PA_SEEK_RELATIVE);
+        delete [] dummy;
+
+        return;
+    }
+
+    pClient->mpListener->onStream(pClient, length);
+}
+
+void CPulseAudioClient::_streamLatencyUpdateCb(pa_stream* s, void* user_data) {
+    assert(s);
+    assert(user_data);
+
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+
+    pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
+}
+
+void CPulseAudioClient::_successStreamCb(pa_stream* s, int success, void* user_data) {
+    AUDIO_IO_LOGD("pa_stream[%p], success[%d], user_data[%p]", s, success, user_data);
+    assert(s);
+    assert(user_data);
+
+    CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
+    pClient->mIsOperationSuccess = static_cast<bool>(success);
+
+    pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
+}
+
+void CPulseAudioClient::initialize() throw (CAudioError) {
+    AUDIO_IO_LOGD("");
+    if (mIsInit == true) {
+        return;
+    }
+
+    int ret = 0;
+    int err = 0;
+
+    try {
+        // Allocates PA proplist
+        mpPropList = pa_proplist_new();
+        if (mpPropList == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_proplist_new()");
+        }
+
+        // Adds values on proplist for delivery to PULSEAUDIO
+        char *streamType = NULL;
+        CAudioInfo::EAudioType audioType = mSpec.getAudioInfo().getAudioType();
+        mSpec.getAudioInfo().convertAudioType2StreamType(audioType, &streamType);
+        pa_proplist_sets(mpPropList, PA_PROP_MEDIA_ROLE, streamType);
+
+        int index = mSpec.getAudioInfo().getAudioIndex();
+        if (index >= 0) {
+            pa_proplist_setf(mpPropList, PA_PROP_MEDIA_PARENT_ID, "%u", (unsigned int) index);
+        }
+
+        // Adds latency on proplist for delivery to PULSEAUDIO
+        CPulseStreamSpec::EStreamLatency latency = mSpec.getStreamLatency();
+        AUDIO_IO_LOGD("LATENCY : %d", latency);
+
+        pa_proplist_setf(mpPropList, PA_PROP_MEDIA_TIZEN_AUDIO_LATENCY, "%d", latency);
+
+        // Allocates PA mainloop
+        mpMainloop = pa_threaded_mainloop_new();
+        if (mpMainloop == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_threaded_mainloop_new()");
+        }
+
+        // Allocates PA context
+        mpContext = pa_context_new(pa_threaded_mainloop_get_api(mpMainloop), CLIENT_NAME);
+        if (mpContext == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_context_new()");
+        }
+
+        // Sets context state changed callback
+        pa_context_set_state_callback(mpContext, _contextStateChangeCb, this);
+
+        // Connects this client with PA server
+        if (pa_context_connect(mpContext, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_context_connect()");
+        }
+
+        // LOCK for synchronous connection
+        pa_threaded_mainloop_lock(mpMainloop);
+
+        // Start mainloop
+        if (pa_threaded_mainloop_start(mpMainloop) < 0) {
+            pa_threaded_mainloop_unlock(mpMainloop);
+            THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_threaded_mainloop_start()");
+        }
+
+        // Connection process is asynchronously
+        // So, this function will be waited when occurred context state change event
+        // If I got a signal, do next processing
+        while (true) {
+            pa_context_state_t state;
+            state = pa_context_get_state(mpContext);
+
+            if (state == PA_CONTEXT_READY) {
+                break;
+            }
+
+            if (!PA_CONTEXT_IS_GOOD(state)) {
+                err = pa_context_errno(mpContext);
+                pa_threaded_mainloop_unlock(mpMainloop);
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "pa_context's state is not good err:[%d]", err);
+            }
+
+            /* Wait until the context is ready */
+            pa_threaded_mainloop_wait(mpMainloop);
+        }
+
+        // Allocates PA stream
+        pa_sample_spec ss   = mSpec.getSampleSpec();
+        pa_channel_map map  = mSpec.getChannelMap();
+
+        mpStream = pa_stream_new_with_proplist(mpContext, mSpec.getStreamName(), &ss, &map, mpPropList);
+        if (mpStream == NULL) {
+            pa_threaded_mainloop_unlock(mpMainloop);
+            THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_new_with_proplist()()");
+        }
+
+        // Sets stream callbacks
+        pa_stream_set_state_callback(mpStream, _streamStateChangeCb, this);
+        pa_stream_set_read_callback(mpStream, _streamCaptureCb, this);
+        pa_stream_set_write_callback(mpStream, _streamPlaybackCb, this);
+        pa_stream_set_latency_update_callback(mpStream, _streamLatencyUpdateCb, this);
+
+        // Connect stream with PA Server
+
+        if (mDirection == STREAM_DIRECTION_PLAYBACK) {
+            pa_stream_flags_t flags = static_cast<pa_stream_flags_t>(
+                    PA_STREAM_INTERPOLATE_TIMING |
+                    PA_STREAM_ADJUST_LATENCY     |
+                    PA_STREAM_AUTO_TIMING_UPDATE);
+
+            ret = pa_stream_connect_playback(mpStream, NULL, NULL, flags, NULL, NULL);
+        } else {
+            pa_stream_flags_t flags = static_cast<pa_stream_flags_t>(
+                    PA_STREAM_INTERPOLATE_TIMING |
+                    PA_STREAM_ADJUST_LATENCY     |
+                    PA_STREAM_AUTO_TIMING_UPDATE);
+
+            ret = pa_stream_connect_record(mpStream, NULL, NULL, flags);
+        }
+
+        if (ret != 0) {
+            err = pa_context_errno(mpContext);
+            pa_threaded_mainloop_unlock(mpMainloop);
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_connect() err:[%d]", err);
+        }
+
+        while (true) {
+            pa_stream_state_t state;
+            state = pa_stream_get_state(mpStream);
+
+            if (state == PA_STREAM_READY) {
+                AUDIO_IO_LOGD("STREAM READY");
+                break;
+            }
+
+            if (!PA_STREAM_IS_GOOD(state)) {
+                err = pa_context_errno(mpContext);
+                pa_threaded_mainloop_unlock(mpMainloop);
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "pa_stream's state is not good err:[%d]", err);
+            }
+
+            /* Wait until the stream is ready */
+            pa_threaded_mainloop_wait(mpMainloop);
+        }
+
+        // End of synchronous
+        pa_threaded_mainloop_unlock(mpMainloop);
+
+        mIsInit = true;
+    } catch (CAudioError e) {
+        finalize();
+        throw e;
+    }
+}
+
+void CPulseAudioClient::finalize() {
+    AUDIO_IO_LOGD("");
+    if (mIsInit == false) {
+        return;
+    }
+
+    if (mpMainloop != NULL) {
+        pa_threaded_mainloop_stop(mpMainloop);
+    }
+    if (mpStream != NULL) {
+        pa_stream_disconnect(mpStream);
+        mpStream = NULL;
+    }
+
+    if (mpContext != NULL) {
+        pa_context_disconnect(mpContext);
+        pa_context_unref(mpContext);
+        mpContext = NULL;
+    }
+
+    if (mpMainloop != NULL) {
+        pa_threaded_mainloop_free(mpMainloop);
+        mpMainloop = NULL;
+    }
+
+    if (mpPropList != NULL) {
+        pa_proplist_free(mpPropList);
+        mpPropList = NULL;
+    }
+
+    mIsInit = false;
+}
+
+int CPulseAudioClient::peek(const void** data, size_t* length) throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("data:[%p], length:[%p]", data, length);
+#endif
+
+    checkRunningState();
+
+    if (data == NULL || length == NULL) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The parameter is invalid - data:%p, length:%p", data, length);
+    }
+
+    if (mDirection == STREAM_DIRECTION_PLAYBACK) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "The Playback client couldn't use this function");
+    }
+
+    int ret = 0;
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        ret = pa_stream_peek(mpStream, data, length);
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        ret = pa_stream_peek(mpStream, data, length);
+    }
+
+    if (ret < 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_peek()");
+    }
+
+    return ret;
+}
+
+int CPulseAudioClient::drop() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("");
+#endif
+
+    checkRunningState();
+
+    if (mDirection == STREAM_DIRECTION_PLAYBACK) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "The Playback client couldn't use this function");
+    }
+
+    int ret = 0;
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        ret = pa_stream_drop(mpStream);
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        ret = pa_stream_drop(mpStream);
+    }
+
+    if (ret < 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_drop()");
+    }
+
+    return ret;
+}
+
+int CPulseAudioClient::write(const void* data, size_t length) throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("data[%p], length:[%d]", data, length);
+#endif
+
+    checkRunningState();
+
+    if (data == NULL || length < 0) {
+        THROW_ERROR_MSG(CAudioError::ERROR_INVALID_ARGUMENT, "The parameter is invalid");
+    }
+
+    if (mDirection == STREAM_DIRECTION_RECORD) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "The Playback client couldn't use this function");
+    }
+
+    int ret = 0;
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        ret = pa_stream_write(mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        ret = pa_stream_write(mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
+    }
+
+    if (ret < 0) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_write() err:%d", ret);
+    }
+
+    return ret;
+}
+
+void CPulseAudioClient::cork(bool cork) throw (CAudioError) {
+    AUDIO_IO_LOGD("bool cork:%d", cork);
+
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    if (isInThread() == true) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "This operation is not supported in callback");
+    }
+
+    checkRunningState();
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        pa_operation_unref(pa_stream_cork(mpStream, static_cast<int>(cork), _successStreamCb, this));
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        pa_operation_unref(pa_stream_cork(mpStream, static_cast<int>(cork), _successStreamCb, this));
+    }
+
+    return;
+}
+
+bool CPulseAudioClient::isCorked() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    int isCork = 0;
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        isCork = pa_stream_is_corked(mpStream);
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        isCork = pa_stream_is_corked(mpStream);
+    }
+
+    AUDIO_IO_LOGD("isCork:%d", isCork);
+    return static_cast<bool>(isCork);
+}
+
+bool CPulseAudioClient::drain() throw (CAudioError) {
+    AUDIO_IO_LOGD("drain");
+
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        pa_operation_unref(pa_stream_drain(mpStream, _successStreamCb, this));
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        pa_operation_unref(pa_stream_drain(mpStream, _successStreamCb, this));
+    }
+
+    return true;
+}
+
+bool CPulseAudioClient::flush() throw (CAudioError) {
+    AUDIO_IO_LOGD("flush");
+
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        pa_operation_unref(pa_stream_flush(mpStream, _successStreamCb, this));
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        pa_operation_unref(pa_stream_flush(mpStream, _successStreamCb, this));
+    }
+
+    return true;
+}
+
+size_t CPulseAudioClient::getWritableSize() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    if (mDirection != STREAM_DIRECTION_PLAYBACK) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "This client is used for Playback");
+    }
+
+    size_t ret = 0;
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        ret = pa_stream_writable_size(mpStream);
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        ret = pa_stream_writable_size(mpStream);
+    }
+
+    return ret;
+}
+
+void CPulseAudioClient::checkRunningState() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    if (mpContext == NULL || PA_CONTEXT_IS_GOOD(pa_context_get_state(mpContext)) == 0) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_INITIALIZED, "The context[%p] is not created or not good state", mpContext);
+    }
+    if (mpStream == NULL || PA_STREAM_IS_GOOD(pa_stream_get_state(mpStream)) == 0) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_INITIALIZED, "The stream[%p] is not created or not good state", mpStream);
+    }
+    if (pa_context_get_state(mpContext) != PA_CONTEXT_READY || pa_stream_get_state(mpStream)   != PA_STREAM_READY) {
+        THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_INITIALIZED, "The context[%p] or stream[%p] state is not ready", mpContext, mpStream);
+    }
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("This client is running");
+#endif
+}
+
+bool CPulseAudioClient::isInThread() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    int ret = pa_threaded_mainloop_in_thread(mpMainloop);
+
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+    AUDIO_IO_LOGD("isInThread : [%d][TRUE:1][FALSE:0]", ret);
+#endif
+    return static_cast<bool>(ret);
+}
+
+size_t CPulseAudioClient::getReadableSize() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    if (mDirection != STREAM_DIRECTION_RECORD) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "This client is used for Capture");
+    }
+
+    size_t ret = 0;
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_lock(mpMainloop);
+        ret = pa_stream_writable_size(mpStream);
+        pa_threaded_mainloop_unlock(mpMainloop);
+    } else {
+        ret = pa_stream_writable_size(mpStream);
+    }
+
+    return ret;
+}
+
+size_t CPulseAudioClient::getBufferSize() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    size_t ret = 0;
+
+    try {
+        if (isInThread() == false) {
+            pa_threaded_mainloop_lock(mpMainloop);
+        }
+
+        const pa_buffer_attr* attr = pa_stream_get_buffer_attr(mpStream);
+        if (attr == NULL) {
+            int _err = pa_context_errno(mpContext);
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_get_buffer_attr() err:%d", _err);
+        }
+
+        if (mDirection == STREAM_DIRECTION_PLAYBACK) {
+            ret = attr->tlength;
+            AUDIO_IO_LOGD("PLAYBACK buffer size : %d", ret);
+        } else {
+            ret = attr->fragsize;
+            AUDIO_IO_LOGD("RECORD buffer size : %d", ret);
+        }
+    } catch (CAudioError err) {
+        if (isInThread() == false) {
+            pa_threaded_mainloop_unlock(mpMainloop);
+        }
+        throw err;
+    }
+
+    if (isInThread() == false) {
+        pa_threaded_mainloop_unlock(mpMainloop);
+    }
+
+    return ret;
+}
+
+pa_usec_t CPulseAudioClient::getLatency() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    pa_usec_t ret = 0;
+    int negative  = 0;
+
+    if (isInThread() == false) {
+        if (pa_stream_get_latency(mpStream, &ret, &negative) < 0) {
+            int _err = pa_context_errno(mpContext);
+            if (_err != PA_ERR_NODATA) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_get_latency() err:%d", _err);
+            }
+        }
+        return negative ? 0 : ret;
+    }
+
+        pa_threaded_mainloop_lock(mpMainloop);
+
+    try {
+        while (true) {
+            if (pa_stream_get_latency(mpStream, &ret, &negative) >= 0) {
+                break;
+            }
+
+            int _err = pa_context_errno(mpContext);
+            if (_err != PA_ERR_NODATA) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_get_latency() err:%d", _err);
+            }
+
+            /* Wait until latency data is available again */
+            pa_threaded_mainloop_wait(mpMainloop);
+        }
+    } catch (CAudioError e) {
+        pa_threaded_mainloop_unlock(mpMainloop);
+        throw e;
+    }
+
+    pa_threaded_mainloop_unlock(mpMainloop);
+
+    return negative ? 0 : ret;
+}
+
+pa_usec_t CPulseAudioClient::getFinalLatency() throw (CAudioError) {
+    if (mIsInit == false) {
+        THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
+    }
+
+    checkRunningState();
+
+    pa_usec_t ret = 0;
+    uint32_t  ver = 0;
+
+    try {
+        if (isInThread() == false) {
+            pa_threaded_mainloop_lock(mpMainloop);
+        }
+
+        ver = pa_context_get_server_protocol_version(mpContext);
+        if (ver >= 13) {
+            const pa_buffer_attr* buffer_attr = pa_stream_get_buffer_attr(mpStream);
+            const pa_sample_spec* sample_spec = pa_stream_get_sample_spec(mpStream);
+            const pa_timing_info* timing_info = pa_stream_get_timing_info(mpStream);
+
+            if (buffer_attr == NULL || sample_spec == NULL || timing_info == NULL) {
+                THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to get buffer_attr[%p] or sample_spec[%p] or timing_info[%p] from a pa_stream",
+                        buffer_attr, sample_spec, timing_info);
+            }
+
+            if (mDirection == STREAM_DIRECTION_PLAYBACK) {
+                ret = (pa_bytes_to_usec(buffer_attr->tlength, sample_spec) + timing_info->configured_sink_usec);
+                AUDIO_IO_LOGD("FINAL PLAYBACK LATENCY : %d", ret);
+            } else {
+                ret = (pa_bytes_to_usec(buffer_attr->fragsize, sample_spec) + timing_info->configured_source_usec);
+                AUDIO_IO_LOGD("FINAL RECORD LATENCY : %d", ret);
+            }
+        } else {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_SUPPORTED, "This version(ver.%d) is not supported", ver);
+        }
+
+        if (isInThread() == false) {
+            pa_threaded_mainloop_unlock(mpMainloop);
+        }
+    } catch (CAudioError e) {
+        if (isInThread() == false) {
+            pa_threaded_mainloop_unlock(mpMainloop);
+        }
+        throw e;
+    }
+
+    return ret;
+}
+
+CPulseAudioClient::EStreamDirection CPulseAudioClient::getStreamDirection() {
+    return mDirection;
+}
+
+CPulseStreamSpec CPulseAudioClient::getStreamSpec() {
+    return mSpec;
+}
diff --git a/src/cpp/CPulseAudioPolicy.cpp b/src/cpp/CPulseAudioPolicy.cpp
new file mode 100644 (file)
index 0000000..0c96f84
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+
+#if 0
+#include "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CPulseAudioPolicy
+ */
+CPulseAudioPolicy::CPulseAudioPolicy() : mPolicy(POLICY_DEFAULT) {
+}
+
+CPulseAudioPolicy::CPulseAudioPolicy(EPolicy policy) : mPolicy(policy) {
+}
+
+CPulseAudioPolicy::~CPulseAudioPolicy() {
+}
+
+void CPulseAudioPolicy::setPolicy(EPolicy policy) throw (CAudioError) {
+    if (policy < POLICY_DEFAULT || policy >= POLICY_MAX) {
+        THROW_ERROR_MSG(CAudioError::ERROR_INVALID_ARGUMENT, "The argument is out of range");
+    }
+
+    mPolicy = policy;
+}
+
+CPulseAudioPolicy::EPolicy CPulseAudioPolicy::getPolicy() {
+    return mPolicy;
+}
+
+bool CPulseAudioPolicy::operator != (const EPolicy policy) {
+    return (mPolicy != policy);
+}
+
+bool CPulseAudioPolicy::operator == (const EPolicy policy) {
+    return (mPolicy == policy);
+}
+#endif
diff --git a/src/cpp/CPulseAudioVolume.cpp b/src/cpp/CPulseAudioVolume.cpp
new file mode 100644 (file)
index 0000000..12aaf05
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+
+#if 0
+#include "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * class CPulseAudioVolume
+ */
+CPulseAudioVolume::CPulseAudioVolume() : mVolume(VOLUME_MEDIA), mVolumeGain(VOLUME_GAIN_DEFAULT) {
+}
+
+CPulseAudioVolume::CPulseAudioVolume(EVolume volume, EVolumeGain gain) : mVolume(volume), mVolumeGain(gain) {
+}
+
+CPulseAudioVolume::~CPulseAudioVolume() {
+}
+
+void CPulseAudioVolume::setVolume(EVolume volume) {
+    mVolume = volume;
+}
+
+CPulseAudioVolume::EVolume CPulseAudioVolume::getVolume() {
+    return mVolume;
+}
+
+void CPulseAudioVolume::setVolumeGain(EVolumeGain volumeGain) {
+    mVolumeGain = volumeGain;
+}
+
+CPulseAudioVolume::EVolumeGain CPulseAudioVolume::getVolumeGain() {
+    return mVolumeGain;
+}
+#endif
diff --git a/src/cpp/CPulseStreamSpec.cpp b/src/cpp/CPulseStreamSpec.cpp
new file mode 100644 (file)
index 0000000..c564944
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 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 "CAudioIODef.h"
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+static const char* STREAM_NAME_INPUT               = "CAPTURE";
+static const char* STREAM_NAME_INPUT_LOW_LATENCY   = "LOW LATENCY CAPTURE";
+static const char* STREAM_NAME_INPUT_HIGH_LATENCY  = "HIGH LATENCY CAPTURE";
+static const char* STREAM_NAME_INPUT_VOIP          = "VOIP CAPTURE";
+
+static const char* STREAM_NAME_OUTPUT              = "PLAYBACK";
+static const char* STREAM_NAME_OUTPUT_LOW_LATENCY  = "LOW LATENCY PLAYBACK";
+static const char* STREAM_NAME_OUTPUT_HIGH_LATENCY = "HIGH LATENCY PLAYBACK";
+static const char* STREAM_NAME_OUTPUT_VOIP         = "VOIP PLAYBACK";
+
+
+CPulseStreamSpec::CPulseStreamSpec() throw (CAudioError)
+        : mLatency(STREAM_LATENCY_INPUT_MID), mStreamName(NULL) {
+    _adjustSpec();
+}
+
+CPulseStreamSpec::CPulseStreamSpec(EStreamLatency latency, CAudioInfo& audioInfo) throw (CAudioError)
+        : mLatency(latency), mAudioInfo(audioInfo), mStreamName(NULL) {
+    _adjustSpec();
+}
+
+CPulseStreamSpec::CPulseStreamSpec(EStreamLatency latency, CAudioInfo& audioInfo, int customLatency) throw (CAudioError)
+        : mLatency(latency), mAudioInfo(audioInfo), mStreamName(NULL) {
+    _adjustSpec();
+}
+
+CPulseStreamSpec::~CPulseStreamSpec() {
+}
+
+void CPulseStreamSpec::_adjustSpec() throw (CAudioError) {
+    // Sets a sampleRate
+    mSampleSpec.rate = mAudioInfo.getSampleRate();
+
+    // Convert channels for PA
+    switch (mAudioInfo.getChannel()) {
+    case CAudioInfo::CHANNEL_MONO:
+        mSampleSpec.channels = 1;
+        break;
+
+    case CAudioInfo::CHANNEL_STEREO:
+    default:
+        mSampleSpec.channels = 2;
+        break;
+    }
+
+    // Convert format for PA
+    switch (mAudioInfo.getSampleType()) {
+    case CAudioInfo::SAMPLE_TYPE_U8:
+        mSampleSpec.format = PA_SAMPLE_U8;
+        break;
+
+    case CAudioInfo::SAMPLE_TYPE_S16_LE:
+    default:
+        mSampleSpec.format = PA_SAMPLE_S16LE;
+        break;
+    }
+
+    // Sets channelmap
+    pa_channel_map_init_auto(&mChannelMap, mSampleSpec.channels, PA_CHANNEL_MAP_ALSA);
+
+    // Sets stream name
+    switch (mLatency) {
+    case STREAM_LATENCY_OUTPUT_MID:
+        mStreamName = STREAM_NAME_OUTPUT;
+        break;
+
+    case STREAM_LATENCY_OUTPUT_HIGH:
+        mStreamName = STREAM_NAME_OUTPUT_HIGH_LATENCY;
+        break;
+
+    case STREAM_LATENCY_OUTPUT_LOW:
+        mStreamName = STREAM_NAME_OUTPUT_LOW_LATENCY;
+        break;
+
+    case STREAM_LATENCY_OUTPUT_VOIP:
+         mStreamName = STREAM_NAME_OUTPUT_VOIP;
+         break;
+
+    case STREAM_LATENCY_INPUT_HIGH:
+        mStreamName = STREAM_NAME_INPUT_HIGH_LATENCY;
+        break;
+
+    case STREAM_LATENCY_INPUT_LOW:
+        mStreamName = STREAM_NAME_INPUT_LOW_LATENCY;
+        break;
+
+    case STREAM_LATENCY_INPUT_VOIP:
+        mStreamName = STREAM_NAME_INPUT_VOIP;
+        break;
+
+    case STREAM_LATENCY_INPUT_MID:
+    default:
+        mStreamName = STREAM_NAME_INPUT;
+        break;
+    }
+}
+
+CPulseStreamSpec::EStreamLatency CPulseStreamSpec::getStreamLatency() {
+    return mLatency;
+}
+
+CAudioInfo CPulseStreamSpec::getAudioInfo() {
+    return mAudioInfo;
+}
+
+pa_sample_spec CPulseStreamSpec::getSampleSpec() {
+    return mSampleSpec;
+}
+
+pa_channel_map CPulseStreamSpec::getChannelMap() {
+    return mChannelMap;
+}
+
+const char* CPulseStreamSpec::getStreamName() {
+    return mStreamName;
+}
diff --git a/src/cpp/cpp_audio_io.cpp b/src/cpp/cpp_audio_io.cpp
new file mode 100644 (file)
index 0000000..6f2f5fb
--- /dev/null
@@ -0,0 +1,1499 @@
+/*
+ * Copyright (c) 2015 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 "audio_io.h"
+#include "cpp_audio_io.h"
+#include "CAudioIODef.h"
+#include <sound_manager_internal.h>
+
+
+using namespace std;
+using namespace tizen_media_audio;
+
+
+/**
+ * Defines Structures
+ * type : struct
+ * Name : audio_io_interrupted_cb_s
+ * Declaration : Keeps user callback pointer and user data for delivering an interrupt event
+ */
+typedef struct audio_io_interrupted_cb_s {
+    void* user_data;
+    audio_io_interrupted_cb onInterrupt;
+
+    audio_io_interrupted_cb_s() : user_data(NULL), onInterrupt(NULL)
+    {/* Empty Body */}
+}   audio_io_interrupted_cb_s;
+
+/**
+ * Defines Structures
+ * type : struct
+ * Name : audio_io_stream_cb_s
+ * Declaration : Keeps user callback pointer and user data for delivering an stream event
+ */
+typedef struct audio_io_stream_cb_s {
+    void* user_data;
+    audio_in_stream_cb onStream;
+
+    audio_io_stream_cb_s() : user_data(NULL), onStream(NULL)
+    {/* Empty Body */}
+}   audio_io_stream_cb_s;
+
+/**
+ * Defines Structures
+ * type : struct
+ * Name : audio_io_state_changed_cb_s
+ * Declaration : Keeps user callback pointer and user data for delivering an state changed event
+ */
+typedef struct audio_io_state_changed_cb_s {
+    void* user_data;
+    audio_in_state_changed_cb onStateChanged;
+
+    audio_io_state_changed_cb_s() : user_data(NULL), onStateChanged(NULL)
+    {/* Empty Body */}
+}   audio_io_state_changed_cb_s;
+
+/**
+ * Defines Structures
+ * type : struct
+ * Name : audio_io_s
+ * Declaration : An handle of AudioIO
+ * The handle has two struct for user callback
+ * And the handle has a pointer of private audioIO object
+ * The CAudioIO is a abstract class object about Input and Output
+ */
+typedef struct audio_io_s {
+    CAudioIO*                    audioIoHandle;
+    audio_io_interrupted_cb_s    interrupt_callback;
+    audio_io_stream_cb_s         stream_callback;
+    audio_io_state_changed_cb_s  state_changed_callback;
+
+    audio_io_s() : audioIoHandle(NULL)
+    {/* Empty Body */}
+}   audio_io_s;
+
+
+/**
+ * Internal functions
+ */
+static audio_io_error_e _convert_CAudioError(CAudioError& error) {
+    audio_io_error_e    ret = AUDIO_IO_ERROR_NONE;
+    CAudioError::EError err = error.getError();
+
+    switch(err)
+    {
+    case CAudioError::ERROR_NONE:
+        ret = AUDIO_IO_ERROR_NONE;
+        break;
+
+    case CAudioError::ERROR_INVALID_ARGUMENT:
+    case CAudioError::ERROR_INVALID_HANDLE:
+    case CAudioError::ERROR_INVALID_SAMPLERATE:
+    case CAudioError::ERROR_INVALID_CHANNEL:
+    case CAudioError::ERROR_INVALID_FORMAT:
+        ret = AUDIO_IO_ERROR_INVALID_PARAMETER;
+        break;
+
+    case CAudioError::ERROR_DEVICE_NOT_OPENED:
+        ret = AUDIO_IO_ERROR_DEVICE_NOT_OPENED;
+        break;
+
+    case CAudioError::ERROR_DEVICE_NOT_CLOSED:
+        ret = AUDIO_IO_ERROR_DEVICE_NOT_CLOSED;
+        break;
+
+    case CAudioError::ERROR_PERMISSION_DENIED:
+        ret = AUDIO_IO_ERROR_PERMISSION_DENIED;
+        break;
+
+    case CAudioError::ERROR_NOT_SUPPORTED:
+        ret = AUDIO_IO_ERROR_NOT_SUPPORTED;
+        break;
+
+    case CAudioError::ERROR_MAX:
+    case CAudioError::ERROR_INTERNAL_OPERATION:
+    case CAudioError::ERROR_NOT_INITIALIZED:
+    case CAudioError::ERROR_FAILED_OPERATION:
+    case CAudioError::ERROR_INVALID_OPERATION:
+        ret = AUDIO_IO_ERROR_INVALID_OPERATION;
+        break;
+
+    case CAudioError::ERROR_OUT_OF_MEMORY:
+    case CAudioError::ERROR_INVALID_POINTER:
+        ret = AUDIO_IO_ERROR_INVALID_BUFFER;
+        break;
+
+    case CAudioError::ERROR_POLICY_BLOCKED:
+    case CAudioError::ERROR_POLICY_INTERRUPTED:
+    case CAudioError::ERROR_POLICY_DUPLICATED:
+        ret = AUDIO_IO_ERROR_SOUND_POLICY;
+        break;
+    }
+    return ret;
+
+}
+
+static void _convert_channel_2_audio_info_channel(const audio_channel_e& src_channel, CAudioInfo::EChannel& dst_channel) {
+    switch (src_channel) {
+    case AUDIO_CHANNEL_MONO:
+        dst_channel = CAudioInfo::CHANNEL_MONO;
+        break;
+    case AUDIO_CHANNEL_STEREO:
+        dst_channel = CAudioInfo::CHANNEL_STEREO;
+        break;
+    default:
+        dst_channel = CAudioInfo::CHANNEL_MONO;
+    }
+}
+
+static void _convert_audio_info_channel_2_channel(const CAudioInfo::EChannel& src_channel, audio_channel_e& dst_channel) {
+    switch (src_channel) {
+    case CAudioInfo::CHANNEL_MONO:
+        dst_channel = AUDIO_CHANNEL_MONO;
+        break;
+    case CAudioInfo::CHANNEL_STEREO:
+        dst_channel = AUDIO_CHANNEL_STEREO;
+        break;
+    default:
+        dst_channel = AUDIO_CHANNEL_MONO;
+    }
+}
+
+static void _convert_sample_type_2_audio_info_sample_type(const audio_sample_type_e& src_type, CAudioInfo::ESampleType& dst_type) {
+    switch (src_type) {
+    case AUDIO_SAMPLE_TYPE_U8:
+        dst_type = CAudioInfo::SAMPLE_TYPE_U8;
+        break;
+    case AUDIO_SAMPLE_TYPE_S16_LE:
+        dst_type = CAudioInfo::SAMPLE_TYPE_S16_LE;
+        break;
+    default:
+        dst_type = CAudioInfo::SAMPLE_TYPE_U8;
+    }
+}
+
+static void _convert_audio_info_sample_type_2_sample_type(const CAudioInfo::ESampleType& src_type, audio_sample_type_e& dst_type) {
+    switch (src_type) {
+    case CAudioInfo::SAMPLE_TYPE_U8:
+        dst_type = AUDIO_SAMPLE_TYPE_U8;
+        break;
+    case CAudioInfo::SAMPLE_TYPE_S16_LE:
+        dst_type = AUDIO_SAMPLE_TYPE_S16_LE;
+        break;
+    default:
+        dst_type = AUDIO_SAMPLE_TYPE_U8;
+    }
+}
+
+static void _convert_sound_type_2_audio_info_audio_type(const sound_type_e& src_type, CAudioInfo::EAudioType& dst_type) {
+    switch (src_type) {
+        case SOUND_TYPE_SYSTEM:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_SYSTEM;
+            break;
+        case SOUND_TYPE_NOTIFICATION:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_NOTIFICATION;
+            break;
+        case SOUND_TYPE_ALARM:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_ALARM;
+            break;
+        case SOUND_TYPE_RINGTONE:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_RINGTONE_VOIP;
+            break;
+        case SOUND_TYPE_MEDIA:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_MEDIA;
+            break;
+        case SOUND_TYPE_CALL:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_SYSTEM;
+            break;
+        case SOUND_TYPE_VOIP:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_VOIP;
+            break;
+        case SOUND_TYPE_VOICE:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_VOICE_INFORMATION;
+            break;
+        default:
+            dst_type = CAudioInfo::AUDIO_OUT_TYPE_MEDIA;
+            break;
+        }
+}
+
+static void _convert_audio_info_audio_type_2_sound_type(const CAudioInfo::EAudioType& src_type, sound_type_e& dst_type) {
+    switch (src_type) {
+        case CAudioInfo::AUDIO_OUT_TYPE_MEDIA:
+            dst_type = SOUND_TYPE_MEDIA;
+            break;
+        case CAudioInfo::AUDIO_OUT_TYPE_SYSTEM:
+            dst_type = SOUND_TYPE_SYSTEM;
+            break;
+        case CAudioInfo::AUDIO_OUT_TYPE_ALARM:
+            dst_type = SOUND_TYPE_ALARM;
+            break;
+        case CAudioInfo::AUDIO_OUT_TYPE_NOTIFICATION:
+        case CAudioInfo::AUDIO_OUT_TYPE_EMERGENCY:
+            dst_type = SOUND_TYPE_NOTIFICATION;
+            break;
+        case CAudioInfo::AUDIO_OUT_TYPE_VOICE_INFORMATION:
+        case CAudioInfo::AUDIO_OUT_TYPE_VOICE_RECOGNITION:
+            dst_type = SOUND_TYPE_VOICE;
+            break;
+        case CAudioInfo::AUDIO_OUT_TYPE_RINGTONE_VOIP:
+            dst_type = SOUND_TYPE_RINGTONE;
+            break;
+        case CAudioInfo::AUDIO_OUT_TYPE_VOIP:
+            dst_type = SOUND_TYPE_VOIP;
+            break;
+        default:
+            dst_type = SOUND_TYPE_MEDIA;
+            break;
+        }
+}
+
+static audio_io_state_e _convert_state_type(const CAudioInfo::EAudioIOState src_state) {
+    audio_io_state_e dst_state;
+    switch (src_state) {
+    case CAudioInfo::AUDIO_IO_STATE_NONE:
+        dst_state = AUDIO_IO_STATE_IDLE;
+        break;
+    case CAudioInfo::AUDIO_IO_STATE_IDLE:
+        dst_state = AUDIO_IO_STATE_IDLE;
+        break;
+    case CAudioInfo::AUDIO_IO_STATE_RUNNING:
+        dst_state = AUDIO_IO_STATE_RUNNING;
+        break;
+    case CAudioInfo::AUDIO_IO_STATE_PAUSED:
+        dst_state = AUDIO_IO_STATE_PAUSED;
+        break;
+    default:
+        dst_state = AUDIO_IO_STATE_IDLE;
+    }
+    return dst_state;
+}
+
+static CAudioInfo _generate_audio_input_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) throw (CAudioError) {
+    CAudioInfo::EChannel     dstChannel;
+    CAudioInfo::ESampleType dstSampleType;
+    CAudioInfo::EAudioType  dstAudioType = CAudioInfo::AUDIO_IN_TYPE_MEDIA;
+
+    _convert_channel_2_audio_info_channel(channel, dstChannel);
+    _convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
+
+    return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
+}
+
+static CAudioInfo _generate_audio_input_loopback_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type) throw (CAudioError) {
+    CAudioInfo::EChannel     dstChannel;
+    CAudioInfo::ESampleType dstSampleType;
+    CAudioInfo::EAudioType  dstAudioType = CAudioInfo::AUDIO_IN_TYPE_LOOPBACK;
+
+    _convert_channel_2_audio_info_channel(channel, dstChannel);
+    _convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
+
+    return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
+}
+
+static CAudioInfo _generate_audio_output_info(int sampleRate, audio_channel_e channel, audio_sample_type_e sample_type, sound_type_e sound_type) throw (CAudioError) {
+    CAudioInfo::EChannel     dstChannel;
+    CAudioInfo::ESampleType dstSampleType;
+    CAudioInfo::EAudioType  dstAudioType;
+
+    _convert_channel_2_audio_info_channel(channel, dstChannel);
+    _convert_sample_type_2_audio_info_sample_type(sample_type, dstSampleType);
+    _convert_sound_type_2_audio_info_audio_type(sound_type, dstAudioType);
+
+    return CAudioInfo(sampleRate, dstChannel, dstSampleType, dstAudioType, -1);
+}
+
+static audio_io_interrupted_code_e _convert_interrupted_code(IAudioSessionEventListener::EInterruptCode code) {
+    switch (code) {
+    case IAudioSessionEventListener::INTERRUPT_COMPLETED:
+        return AUDIO_IO_INTERRUPTED_COMPLETED;
+    case IAudioSessionEventListener::INTERRUPT_BY_CALL:
+        return AUDIO_IO_INTERRUPTED_BY_CALL;
+    case IAudioSessionEventListener::INTERRUPT_BY_EARJACK_UNPLUG:
+        return AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG;
+    case IAudioSessionEventListener::INTERRUPT_BY_RESOURCE_CONFLICT:
+        return AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT;
+    case IAudioSessionEventListener::INTERRUPT_BY_ALARM:
+        return AUDIO_IO_INTERRUPTED_BY_ALARM;
+    case IAudioSessionEventListener::INTERRUPT_BY_EMERGENCY:
+        return AUDIO_IO_INTERRUPTED_BY_EMERGENCY;
+    case IAudioSessionEventListener::INTERRUPT_BY_NOTIFICATION:
+        return AUDIO_IO_INTERRUPTED_BY_NOTIFICATION;
+    case IAudioSessionEventListener::INTERRUPT_BY_MEDIA:
+    case IAudioSessionEventListener::INTERRUPT_MAX:
+    default:
+        return AUDIO_IO_INTERRUPTED_BY_MEDIA;
+    }
+}
+
+/**
+ * Implements CAPI functions
+ */
+int cpp_audio_in_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_in_h *input) {
+    audio_io_s* handle = NULL;
+    try {
+        if (input == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        handle = new audio_io_s;
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
+        }
+
+        CAudioInfo audioInfo = _generate_audio_input_info(sample_rate, channel, type);
+
+        handle->audioIoHandle = new CAudioInput(audioInfo);
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
+        }
+
+        handle->audioIoHandle->initialize();
+
+        *input = handle;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+
+        VALID_POINTER_START(handle)
+            SAFE_FINALIZE(handle->audioIoHandle);
+            SAFE_DELETE(handle->audioIoHandle);
+            SAFE_DELETE(handle);
+        VALID_POINTER_END
+
+        VALID_POINTER_START(input)
+            *input = NULL;
+        VALID_POINTER_END
+
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+
+}
+
+int cpp_audio_in_create_loopback(int sample_rate, audio_channel_e channel, audio_sample_type_e type , audio_in_h* input) {
+    audio_io_s* handle = NULL;
+    try {
+        if (input == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        handle = new audio_io_s;
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
+        }
+
+        CAudioInfo audioInfo = _generate_audio_input_loopback_info(sample_rate, channel, type);
+
+        handle->audioIoHandle = new CAudioInput(audioInfo);
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
+        }
+
+        handle->audioIoHandle->initialize();
+
+        *input = handle;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+
+        VALID_POINTER_START(handle)
+            SAFE_FINALIZE(handle->audioIoHandle);
+            SAFE_DELETE(handle->audioIoHandle);
+            SAFE_DELETE(handle);
+        VALID_POINTER_END
+
+        VALID_POINTER_START(input)
+            *input = NULL;
+        VALID_POINTER_END
+
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_destroy(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        SAFE_FINALIZE(handle->audioIoHandle);
+        SAFE_DELETE(handle->audioIoHandle);
+        SAFE_DELETE(handle);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_set_stream_info(audio_in_h input, sound_stream_info_h stream_info) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || stream_info == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, stream_info:%p", input, stream_info);
+        }
+
+        assert(handle->audioIoHandle);
+
+        int errorCode = SOUND_MANAGER_ERROR_NONE;
+        CAudioInfo::EAudioType AudioType = CAudioInfo::AUDIO_IN_TYPE_MEDIA;
+        char *type = NULL;
+        int index = -1;
+
+        if ((errorCode = sound_manager_get_type_from_stream_information (stream_info, &type)) != SOUND_MANAGER_ERROR_NONE) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode);
+        }
+        handle->audioIoHandle->getAudioInfo().convertStreamType2AudioType(type, &AudioType);
+        handle->audioIoHandle->getAudioInfo().setAudioType(AudioType);
+
+        if ((errorCode = sound_manager_get_index_from_stream_information (stream_info, &index)) != SOUND_MANAGER_ERROR_NONE) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode);
+        }
+        handle->audioIoHandle->getAudioInfo().setAudioIndex(index);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_prepare(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->prepare();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_unprepare(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->unprepare();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_pause(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->pause();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_resume(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->resume();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_drain(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->drain();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_flush(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->flush();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_read(audio_in_h input, void *buffer, unsigned int length) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+    int ret = 0;
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        CAudioInput* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
+        ret = inputHandle->read(buffer, length);
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+        AUDIO_IO_LOGD("ret:%d", ret);
+#endif
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return ret;
+}
+
+int cpp_audio_in_get_buffer_size(audio_in_h input, int *size) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || size == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, size:%p", input, size);
+        }
+
+        assert(handle->audioIoHandle);
+
+        CAudioIO* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
+        *size = inputHandle->getBufferSize();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_get_sample_rate(audio_in_h input, int *sample_rate) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || sample_rate == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, sample_rate:%p", input, sample_rate);
+        }
+
+        assert(handle->audioIoHandle);
+        *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_get_channel(audio_in_h input, audio_channel_e *channel) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || channel == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, channel:%p", input, channel);
+        }
+
+        assert(handle->audioIoHandle);
+
+        const CAudioInfo::EChannel srcChannel = handle->audioIoHandle->getAudioInfo().getChannel();
+        audio_channel_e dstChannel = AUDIO_CHANNEL_MONO;
+        _convert_audio_info_channel_2_channel(srcChannel, dstChannel);
+
+        *channel = dstChannel;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_get_sample_type(audio_in_h input, audio_sample_type_e *type) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || type == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, type:%p", input, type);
+        }
+
+        assert(handle->audioIoHandle);
+
+        const CAudioInfo::ESampleType srcSampleType = handle->audioIoHandle->getAudioInfo().getSampleType();
+        audio_sample_type_e     dstSampleType = AUDIO_SAMPLE_TYPE_U8;
+        _convert_audio_info_sample_type_2_sample_type(srcSampleType, dstSampleType);
+
+        *type = dstSampleType;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+static void _interrupt_cb_internal(IAudioSessionEventListener::EInterruptCode _code, void* user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(user_data);
+    audio_io_interrupted_code_e code = _convert_interrupted_code(_code);
+
+    assert(handle);
+
+    if (handle->interrupt_callback.onInterrupt != NULL) {
+        handle->interrupt_callback.onInterrupt(code, handle->interrupt_callback.user_data);
+    }
+}
+
+int cpp_audio_in_set_interrupted_cb(audio_in_h input, audio_io_interrupted_cb callback, void *user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || callback == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, callback:%p", input, callback);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->interrupt_callback.onInterrupt = callback;
+        handle->interrupt_callback.user_data    = user_data;
+
+        CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
+        cb.mUserData   = static_cast<void*>(handle);
+        cb.onInterrupt = _interrupt_cb_internal;
+
+        handle->audioIoHandle->setInterruptCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_unset_interrupted_cb(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->interrupt_callback.onInterrupt = NULL;
+        handle->interrupt_callback.user_data    = NULL;
+
+        CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
+        cb.mUserData   = NULL;
+        cb.onInterrupt = NULL;
+
+        handle->audioIoHandle->setInterruptCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_ignore_session(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->ignoreSession();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+static void _stream_cb_internal(size_t nbytes, void *user_data) {
+    audio_io_s* audioIo = static_cast<audio_io_s*>(user_data);
+    assert(audioIo);
+
+    if (audioIo->stream_callback.onStream != NULL) {
+        audioIo->stream_callback.onStream(audioIo, nbytes, audioIo->stream_callback.user_data);
+    }
+}
+
+static void _state_changed_cb_internal(CAudioInfo::EAudioIOState state, CAudioInfo::EAudioIOState state_prev, bool by_policy, void *user_data) {
+    audio_io_s* audioIo = static_cast<audio_io_s*>(user_data);
+    assert(audioIo);
+
+    if (audioIo->state_changed_callback.onStateChanged != NULL) {
+        audioIo->state_changed_callback.onStateChanged(audioIo, _convert_state_type(state_prev), _convert_state_type(state), by_policy, audioIo->state_changed_callback.user_data);
+    }
+}
+
+int cpp_audio_in_set_stream_cb(audio_in_h input, audio_in_stream_cb callback, void* user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL || callback == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p, callback:%p", input, callback);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->stream_callback.onStream = callback;
+        handle->stream_callback.user_data = user_data;
+
+        CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
+        cb.mUserData = static_cast<void*>(handle);
+        cb.onStream  = _stream_cb_internal;
+
+        handle->audioIoHandle->setStreamCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_unset_stream_cb(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->stream_callback.onStream = NULL;
+        handle->stream_callback.user_data = NULL;
+
+        CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
+        cb.mUserData = NULL;
+        cb.onStream  = NULL;
+
+        handle->audioIoHandle->setStreamCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_peek(audio_in_h input, const void **buffer, unsigned int *length) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        CAudioInput* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
+        assert(inputHandle);
+
+        inputHandle->peek(buffer, length);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_drop(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL input:%p", input);
+        }
+
+        CAudioInput* inputHandle = dynamic_cast<CAudioInput*>(handle->audioIoHandle);
+        assert(inputHandle);
+
+        inputHandle->drop();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_set_state_changed_cb(audio_in_h input, audio_in_state_changed_cb callback, void* user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", input, callback);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->state_changed_callback.onStateChanged = callback;
+        handle->state_changed_callback.user_data = user_data;
+
+        CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
+        cb.mUserData = static_cast<void*>(handle);
+        cb.onStateChanged = _state_changed_cb_internal;
+
+        handle->audioIoHandle->setStateChangedCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_in_unset_state_changed_cb(audio_in_h input) {
+    audio_io_s* handle = static_cast<audio_io_s*>(input);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", input);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->state_changed_callback.onStateChanged = NULL;
+        handle->state_changed_callback.user_data = NULL;
+
+        CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
+        cb.mUserData = NULL;
+        cb.onStateChanged  = NULL;
+
+        handle->audioIoHandle->setStateChangedCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+
+/**
+ * Audio Out
+ */
+int cpp_audio_out_create(int sample_rate, audio_channel_e channel, audio_sample_type_e type, sound_type_e sound_type, audio_out_h *output) {
+    audio_io_s* handle = NULL;
+    try {
+        handle = new audio_io_s;
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
+        }
+
+        CAudioInfo audioInfo = _generate_audio_output_info(sample_rate, channel, type, sound_type);
+
+        handle->audioIoHandle = new CAudioOutput(audioInfo);
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
+        }
+
+        handle->audioIoHandle->initialize();
+
+        *output = handle;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+
+        VALID_POINTER_START(handle)
+            SAFE_FINALIZE(handle->audioIoHandle);
+            SAFE_DELETE(handle->audioIoHandle);
+            SAFE_DELETE(handle);
+        VALID_POINTER_END
+
+        VALID_POINTER_START(output)
+        *output = NULL;
+        VALID_POINTER_END
+
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_create_new(int sample_rate, audio_channel_e channel, audio_sample_type_e type, audio_out_h *output) {
+    audio_io_s* handle = NULL;
+    try {
+        handle = new audio_io_s;
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation handle");
+        }
+
+        CAudioInfo audioInfo = _generate_audio_output_info(sample_rate, channel, type, SOUND_TYPE_MEDIA /* default sound_tyoe */);
+
+        handle->audioIoHandle = new CAudioOutput(audioInfo);
+        if (handle == NULL) {
+            THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed allocation internal handle");
+        }
+
+        handle->audioIoHandle->initialize();
+
+        *output = handle;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+
+        VALID_POINTER_START(handle)
+            SAFE_FINALIZE(handle->audioIoHandle);
+            SAFE_DELETE(handle->audioIoHandle);
+            SAFE_DELETE(handle);
+        VALID_POINTER_END
+
+        VALID_POINTER_START(output)
+        *output = NULL;
+        VALID_POINTER_END
+
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_destroy(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        SAFE_FINALIZE(handle->audioIoHandle);
+        SAFE_DELETE(handle->audioIoHandle);
+        SAFE_DELETE(handle);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_set_stream_info(audio_out_h output, sound_stream_info_h stream_info) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || stream_info == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, stream_info:%p", output, stream_info);
+        }
+
+        assert(handle->audioIoHandle);
+
+        int errorCode = SOUND_MANAGER_ERROR_NONE;
+        CAudioInfo::EAudioType AudioType = CAudioInfo::AUDIO_OUT_TYPE_MEDIA;
+        char *type = NULL;
+        int index = -1;
+
+        if ((errorCode = sound_manager_get_type_from_stream_information (stream_info, &type)) != SOUND_MANAGER_ERROR_NONE) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->stream_type is invalid [ret:%d]", errorCode);
+        }
+        handle->audioIoHandle->getAudioInfo().convertStreamType2AudioType(type, &AudioType);
+        handle->audioIoHandle->getAudioInfo().setAudioType(AudioType);
+
+        if ((errorCode = sound_manager_get_index_from_stream_information (stream_info, &index)) != SOUND_MANAGER_ERROR_NONE) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter stream_info->index is invalid [ret:%d]", errorCode);
+        }
+        handle->audioIoHandle->getAudioInfo().setAudioIndex(index);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_prepare(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->prepare();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_unprepare(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->unprepare();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_pause(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->pause();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_resume(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->resume();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_drain(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->drain();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_flush(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->flush();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+    int ret = 0;
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameter is NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        CAudioOutput* outputHandle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
+        ret = outputHandle->write(buffer, length);
+#ifdef _AUDIO_IO_DEBUG_TIMING_
+        AUDIO_IO_LOGD("ret:%d", ret);
+#endif
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return ret;
+}
+
+int cpp_audio_out_get_buffer_size(audio_out_h output, int *size) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || size == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, size:%p", output, size);
+        }
+
+        assert(handle->audioIoHandle);
+
+        CAudioOutput* outputHandle = dynamic_cast<CAudioOutput*>(handle->audioIoHandle);
+        *size = outputHandle->getBufferSize();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_get_sample_rate(audio_out_h output, int *sample_rate) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || sample_rate == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, sample_rate:%p", output, sample_rate);
+        }
+
+        assert(handle->audioIoHandle);
+        *sample_rate = handle->audioIoHandle->getAudioInfo().getSampleRate();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_get_channel(audio_out_h output, audio_channel_e *channel) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || channel == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, channel:%p", output, channel);
+        }
+
+        assert(handle->audioIoHandle);
+
+        const CAudioInfo::EChannel srcChannel = handle->audioIoHandle->getAudioInfo().getChannel();
+        audio_channel_e dstChannel = AUDIO_CHANNEL_MONO;
+        _convert_audio_info_channel_2_channel(srcChannel, dstChannel);
+
+        *channel = dstChannel;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_get_sample_type(audio_out_h output, audio_sample_type_e *type) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || type == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, type:%p", output, type);
+        }
+
+        assert(handle->audioIoHandle);
+
+        const CAudioInfo::ESampleType srcSampleType = handle->audioIoHandle->getAudioInfo().getSampleType();
+        audio_sample_type_e     dstSampleType = AUDIO_SAMPLE_TYPE_U8;
+        _convert_audio_info_sample_type_2_sample_type(srcSampleType, dstSampleType);
+
+        *type = dstSampleType;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_get_sound_type(audio_out_h output, sound_type_e *type) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || type == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, type:%p", output, type);
+        }
+
+        assert(handle->audioIoHandle);
+
+        const CAudioInfo::EAudioType srcAudioType = handle->audioIoHandle->getAudioInfo().getAudioType();
+        sound_type_e                 dstSoundType = SOUND_TYPE_MEDIA;
+        _convert_audio_info_audio_type_2_sound_type(srcAudioType, dstSoundType);
+
+        *type = dstSoundType;
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_set_interrupted_cb(audio_out_h output, audio_io_interrupted_cb callback, void *user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL || callback == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", output, callback);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->interrupt_callback.onInterrupt = callback;
+        handle->interrupt_callback.user_data    = user_data;
+
+        CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
+        cb.mUserData   = static_cast<void*>(handle);
+        cb.onInterrupt = _interrupt_cb_internal;
+
+        handle->audioIoHandle->setInterruptCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_unset_interrupted_cb(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->interrupt_callback.onInterrupt = NULL;
+        handle->interrupt_callback.user_data    = NULL;
+
+        CAudioIO::SInterruptCallback cb = handle->audioIoHandle->getInterruptCallback();
+        cb.mUserData   = NULL;
+        cb.onInterrupt = NULL;
+
+        handle->audioIoHandle->setInterruptCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_ignore_session(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->audioIoHandle->ignoreSession();
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_set_stream_cb(audio_out_h output, audio_out_stream_cb callback, void* user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", output, callback);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->stream_callback.onStream = callback;
+        handle->stream_callback.user_data = user_data;
+
+        CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
+        cb.mUserData = static_cast<void*>(handle);
+        cb.onStream  = _stream_cb_internal;
+
+        handle->audioIoHandle->setStreamCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_unset_stream_cb(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->stream_callback.onStream = NULL;
+        handle->stream_callback.user_data = NULL;
+
+        CAudioIO::SStreamCallback cb = handle->audioIoHandle->getStreamCallback();
+        cb.mUserData = NULL;
+        cb.onStream  = NULL;
+
+        handle->audioIoHandle->setStreamCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_set_state_changed_cb(audio_out_h output, audio_in_state_changed_cb callback, void* user_data) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p, callback:%p", output, callback);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->state_changed_callback.onStateChanged = callback;
+        handle->state_changed_callback.user_data = user_data;
+
+        CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
+        cb.mUserData = static_cast<void*>(handle);
+        cb.onStateChanged = _state_changed_cb_internal;
+
+        handle->audioIoHandle->setStateChangedCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
+
+int cpp_audio_out_unset_state_changed_cb(audio_out_h output) {
+    audio_io_s* handle = static_cast<audio_io_s*>(output);
+
+    try {
+        if (handle == NULL) {
+            THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "Parameters are NULL output:%p", output);
+        }
+
+        assert(handle->audioIoHandle);
+
+        handle->state_changed_callback.onStateChanged = NULL;
+        handle->state_changed_callback.user_data = NULL;
+
+        CAudioIO::SStateChangedCallback cb = handle->audioIoHandle->getStateChangedCallback();
+        cb.mUserData = NULL;
+        cb.onStateChanged  = NULL;
+
+        handle->audioIoHandle->setStateChangedCallback(cb);
+    } catch (CAudioError e) {
+        AUDIO_IO_LOGE("%s", e.getErrorMsg());
+        return _convert_CAudioError(e);
+    }
+
+    return AUDIO_IO_ERROR_NONE;
+}
index 0d1116058221a130ecbeffc221f7a35562d6a957..67cedc2debeb51126d3ef3e5e876ddaac6634744 100644 (file)
@@ -1,4 +1,3 @@
-
 SET(fw_test "${fw_name}-test")
 
 INCLUDE(FindPkgConfig)
@@ -6,13 +5,15 @@ FOREACH(flag ${${fw_test}_CFLAGS})
     SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror -pie")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -fPIC -Wall -Werror -std=c++0x -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})
+    TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS} -lm)
 ENDFOREACH()
 
+INSTALL(TARGETS audio_io_test DESTINATION bin)
old mode 100755 (executable)
new mode 100644 (file)
index 9aba129..c96771b
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 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.
 * 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. 
+* limitations under the License.
 */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <audio_io.h>  
-
-int audio_io_test()
-{
-       int ret, size;
-       audio_in_h input;
-       if ((ret = audio_in_create(44100, AUDIO_CHANNEL_STEREO ,AUDIO_SAMPLE_TYPE_S16_LE, &input)) == AUDIO_IO_ERROR_NONE) {
-               ret = audio_in_ignore_session(input);
-               if (ret != 0) {
-                       printf ("ERROR, set session mix\n");
-                       audio_in_destroy(input);
-                       return 0;
-               }
-
-               audio_in_prepare(input);
-               if ((ret = audio_in_get_buffer_size(input, &size)) == AUDIO_IO_ERROR_NONE) {
-                       size = 500000;
-                       char *buffer = alloca(size);
-                       if ((ret = audio_in_read(input, (void*)buffer, size)) > AUDIO_IO_ERROR_NONE) {
-                               FILE* fp = fopen ("/root/test.raw", "wb+");
-                               fwrite (buffer, size, sizeof(char), fp);
-                               fclose (fp);
-                               printf ("PASS, size=%d, ret=%d\n", size, ret);
-                       }
-                       else {
-                               printf ("FAIL, size=%d, ret=%d\n", size, ret);
-                       }
-               }
-               audio_in_destroy(input);
-       }
-
-       return 1;
+#include <unistd.h>
+#include <math.h>
+#include <audio_io.h>
+#include <sound_manager.h>
+
+//#define _NEW_SOUND_MANAGER_API_
+#define _SESSION_SOUND_MANAGER_API_
+
+#ifndef M_PI
+#define M_PI  (3.14159265)
+#endif
+
+#define TABLE_SIZE   (200)
+typedef struct
+{
+    float sine[TABLE_SIZE];
+    int left_channel;
+    int right_channel;
+} test_wav_t;
+test_wav_t test_wav;
+
+static int ch_table[3] = { 0, AUDIO_CHANNEL_MONO, AUDIO_CHANNEL_STEREO };
+
+void play_file(char *file, int length, int ch)
+{
+    audio_out_h output;
+    FILE* fp = fopen (file, "r");
+    if (fp == NULL) {
+        printf ("fopen failed\n");
+        return;
+    }
+
+    char * buf = malloc (length);
+    if (buf == NULL) {
+        printf ("malloc failed\n");
+        fclose (fp);
+        return;
+    }
+
+    printf ("start to play [%s][%d][%d]\n", file, length, ch);
+    //audio_out_create(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output);
+    audio_out_create_new(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, &output);
+    if (fread (buf, 1, length, fp) != length) {
+        printf ("error!!!!\n");
+    }
+
+    audio_out_prepare(output);
+    audio_out_write(output, buf, length);
+    audio_out_unprepare(output);
+
+    audio_out_destroy (output);
+
+    fclose (fp);
+
+    printf ("play done\n");
+}
+
+#define DUMP_FILE "/root/test.raw"
+
+
+void play_file_sample(char *file, int frequency, int ch, int type)
+{
+    audio_out_h output;
+    int file_size = 0;
+    int read_bytes = 0;
+    int buffer_size = 0;
+    char * buf = NULL;
+
+    if(ch < 0 || ch > 2) {
+        ch = 0;
+    }
+
+    FILE* fp = fopen (file, "r");
+    if (fp == NULL) {
+        printf("open failed\n");
+        return;
+    }
+    /*Get the size*/
+    fseek(fp, 0, SEEK_END);
+    file_size = ftell(fp);
+    fseek(fp, 0, SEEK_SET);
+
+    printf ("start to play [%s] of size [%d] with [%d][%d][%d]\n", file, file_size, frequency, ch, type);
+    if (type) {
+        //audio_out_create(frequency, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output);
+        audio_out_create_new(frequency, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, &output);
+    } else {
+        //audio_out_create(frequency, ch_table[ch] ,AUDIO_SAMPLE_TYPE_U8, SOUND_TYPE_MEDIA, &output);
+        audio_out_create_new(frequency, ch_table[ch] ,AUDIO_SAMPLE_TYPE_U8, &output);
+    }
+    audio_out_prepare(output);
+    audio_out_get_buffer_size(output, &buffer_size);
+
+    buf = (char *) malloc(buffer_size);
+    if (buf == NULL) {
+        printf ("malloc failed\n");
+        audio_out_unprepare(output);
+        audio_out_destroy(output);
+        fclose (fp);
+        return;
+    }
+    //audio_out_prepare(output);
+
+    while (file_size > 0) {
+        read_bytes = fread (buf, 1, buffer_size, fp);
+        printf ("Read %d Requested - %d\n", read_bytes, buffer_size);
+        audio_out_write(output, buf, read_bytes);
+        file_size = file_size - read_bytes;
+    }
+
+    audio_out_unprepare(output);
+    audio_out_destroy (output);
+
+    free(buf);
+    fclose (fp);
+    printf ("play done\n");
+}
+
+int audio_io_test(int length, int num, int ch)
+{
+    int ret, size, i;
+    audio_in_h input;
+    if ((ret = audio_in_create(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, &input)) == AUDIO_IO_ERROR_NONE) {
+        ret = audio_in_ignore_session(input);
+        if (ret != 0) {
+            printf ("ERROR, set session mix\n");
+            audio_in_destroy(input);
+            return 0;
+        }
+
+        ret = audio_in_prepare(input);
+        if (ret != 0) {
+            printf ("ERROR, prepare\n");
+            audio_in_destroy(input);
+            return 0;
+        }
+
+        FILE* fp = fopen (DUMP_FILE, "wb+");
+
+        if (fp == NULL) {
+            printf ("ERROR, file open failed\n");
+            audio_in_destroy(input);
+            return 0;
+        }
+
+        if ((ret = audio_in_get_buffer_size(input, &size)) == AUDIO_IO_ERROR_NONE) {
+            size = length;
+            char *buffer = alloca(size);
+
+            for (i=0; i<num; i++) {
+                printf ("### loop = %d ============== \n", i);
+                if ((ret = audio_in_read(input, (void*)buffer, size)) > AUDIO_IO_ERROR_NONE) {
+                    fwrite (buffer, size, sizeof(char), fp);
+                    printf ("PASS, size=%d, ret=%d\n", size, ret);
+                } else {
+                    printf ("FAIL, size=%d, ret=%d\n", size, ret);
+                }
+            }
+        }
+
+        fclose (fp);
+
+        audio_in_destroy(input);
+    }
+
+    play_file (DUMP_FILE, length*num, ch);
+
+    return 1;
+}
+
+int audio_io_loopback_in_test()
+{
+    int ret, size;
+    audio_in_h input;
+    FILE* fp = fopen ("/tmp/dump_test.raw", "wb+");
+
+    if(fp == NULL) {
+        printf("open failed \n");
+        return 0;
+    }
+
+    if ((ret = audio_in_create(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, &input)) == AUDIO_IO_ERROR_NONE) {
+        ret = audio_in_ignore_session(input);
+        if (ret != 0) {
+            printf ("ERROR, set session mix\n");
+            goto exit;
+        }
+
+        ret = audio_in_prepare(input);
+        if (ret != 0) {
+            printf ("ERROR, prepare\n");
+            goto exit;
+        }
+
+        ret = audio_in_get_buffer_size(input, &size);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_in_get_buffer_size failed.\n");
+            goto exit;
+        }
+
+        while(1) {
+            char *buffer = alloca(size);
+            if ((ret = audio_in_read(input, (void*)buffer, size)) > AUDIO_IO_ERROR_NONE) {
+                fwrite (buffer, size, sizeof(char), fp);
+                printf ("PASS, size=%d, ret=%d\n", size, ret);
+            } else {
+                printf ("FAIL, size=%d, ret=%d\n", size, ret);
+            }
+        }
+    }
+
+exit:
+    audio_in_destroy(input);
+
+    fclose (fp);
+
+    return ret;
+
+}
+
+int audio_io_loopback_test()
+{
+    int ret, size;
+    audio_in_h input;
+    audio_out_h output;
+    char *buffer = NULL;
+
+    ret = audio_in_create(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, &input);
+    if(ret != AUDIO_IO_ERROR_NONE) {
+        printf ("audio_in_create_ex failed. \n");
+        return 0;
+    }
+
+    //ret = audio_out_create(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_CALL, &output);
+    ret = audio_out_create_new(16000, AUDIO_CHANNEL_MONO , AUDIO_SAMPLE_TYPE_S16_LE, &output);
+    if(ret != AUDIO_IO_ERROR_NONE) {
+        printf ("audio_out_create failed. \n");
+        return 0;
+    }
+
+    ret = audio_in_prepare(input);
+    if (ret != 0) {
+        printf ("audio_in_prepare failed.\n");
+        audio_in_destroy(input);
+        return 0;
+    } else {
+        ret = audio_in_get_buffer_size(input, &size);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_in_get_buffer_size failed.\n");
+            return 0;
+        } else {
+            printf("size(%d)\n", size);
+            buffer = alloca(size);
+        }
+    }
+
+    ret = audio_out_prepare(output);
+    if (ret != 0) {
+        printf ("audio_out_prepare failed.\n");
+        audio_out_destroy(output);
+        return 0;
+    }
+
+    if(buffer == NULL) {
+        printf("buffer is null\n");
+        return 0;
+    }
+
+    while(1) {
+        ret = audio_in_read(input, (void*)buffer, size);
+        if(ret > AUDIO_IO_ERROR_NONE) {
+            ret = audio_out_write(output, buffer, size);
+            if(ret > AUDIO_IO_ERROR_NONE) {
+                printf("audio read/write success. buffer(%p), size(%d)\n", buffer, size);
+            } else {
+                printf("audio read success, write failed. buffer(%p), size(%d)\n", buffer, size);
+            }
+        } else
+            printf("audio read/write failed. buffer(%p), size(%d)\n", buffer, size);
+    }
+
+}
+
+audio_in_h input;
+audio_out_h output;
+
+FILE* fp_w = NULL;
+
+#ifdef _NEW_SOUND_MANAGER_API_
+sound_stream_info_h g_stream_info_read_h = NULL;
+sound_stream_info_h g_stream_info_write_h = NULL;
+
+static void focus_callback_read (sound_stream_info_h stream_info, sound_stream_focus_change_reason_e reason_for_change, const char *additional_info, void *user_data) {
+    int ret = 0;
+    sound_stream_focus_state_e playback_focus_state;
+    sound_stream_focus_state_e recording_focus_state;
+    printf ("*** focus_callback_read is called, stream_info(%p) ***\n", stream_info);
+    printf (" - reason_for_change(%d), additional_info(%s), user_data(%p)\n", reason_for_change, additional_info, user_data);
+    ret = sound_manager_get_focus_state (stream_info, &playback_focus_state, &recording_focus_state);
+    if (!ret)
+        printf (" - focus_state(playback_focus:%d, recording_focus:%d)\n", playback_focus_state, recording_focus_state);
+    if (playback_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED) {
+        printf (" -- PLAYBACK_FOCUS acquired\n");
+    }
+    if (recording_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED) {
+        printf (" -- FOCUS_RECORDING acquired\n");
+    }
+    printf ("*** focus_callback_read is ended, stream_info(%p) ****\n", stream_info);
+    return;
+}
+
+static void focus_callback_write (sound_stream_info_h stream_info, sound_stream_focus_change_reason_e reason_for_change, const char *additional_info, void *user_data) {
+    int ret = 0;
+    sound_stream_focus_state_e playback_focus_state;
+    sound_stream_focus_state_e recording_focus_state;
+    printf ("*** focus_callback_write is called, stream_info(%p) ***\n", stream_info);
+    printf (" - reason_for_change(%d), additional_info(%s), user_data(%p)\n", reason_for_change, additional_info, user_data);
+    ret = sound_manager_get_focus_state (stream_info, &playback_focus_state, &recording_focus_state);
+    if (!ret)
+        printf (" - focus_state(playback_focus:%d, recording_focus:%d)\n", playback_focus_state, recording_focus_state);
+    if (playback_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED) {
+        printf (" -- PLAYBACK_FOCUS acquired\n");
+    }
+    if (recording_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED) {
+        printf (" -- FOCUS_RECORDING acquired\n");
+    }
+    printf ("*** focus_callback_write is ended, stream_info(%p) ****\n", stream_info);
+    return;
+}
+#endif
+
+static void interrupted_callback_read(audio_io_interrupted_code_e code, void *user_data) {
+    printf ("*** interrupted_callback_read is called, code(%d), user_data(%p) ***\n", code, user_data);
+}
+
+static void interrupted_callback_write(audio_io_interrupted_code_e code, void *user_data) {
+    printf ("*** interrupted_callback_write is called, code(%d), user_data(%p) ***\n", code, user_data);
+}
+
+static void _audio_io_stream_read_cb (audio_in_h handle, size_t nbytes, void *user_data)
+{
+    const void * buffer = NULL;
+
+//    printf("_audio_io_stream_read_cb : handle=%p, nbytes=%d, user_data=%p\n", handle, nbytes, user_data);
+
+    if (nbytes > 0) {
+        audio_in_peek (handle, &buffer, &nbytes);
+        if (fp_w) {
+            fwrite(buffer, sizeof(char), nbytes, fp_w);
+        }
+        audio_in_drop (handle);
+    }
+}
+
+static void _audio_io_stream_write_cb (audio_out_h handle, size_t nbytes, void *user_data)
+{
+    short* buffer = NULL;
+    int ret = 0;
+    int i = 0;
+
+//    printf("_audio_io_stream_write_cb : handle=%p, nbytes=%d, user_data=%p\n", handle, nbytes, user_data);
+
+    if (nbytes > 0) {
+        buffer = (short *) malloc(nbytes);
+        if (buffer == NULL) {
+            printf ("malloc failed\n");
+            return;
+        }
+        memset (buffer, 0, nbytes);
+
+        for(i=0; i<nbytes/2; i+=2)
+        {
+            buffer[i]   = (short) 32768 * test_wav.sine[test_wav.left_channel];   /* left */
+            buffer[i+1] = (short) 32768 * test_wav.sine[test_wav.right_channel];  /* right */
+            test_wav.left_channel += 1;
+            if( test_wav.left_channel >= TABLE_SIZE ) test_wav.left_channel -= TABLE_SIZE;
+            test_wav.right_channel += 3;
+            if( test_wav.right_channel >= TABLE_SIZE ) test_wav.right_channel -= TABLE_SIZE;
+        }
+
+        ret = audio_out_write(handle, buffer, nbytes);
+        if(ret > AUDIO_IO_ERROR_NONE) {
+//            printf("audio write success. buffer(%p), nbytes(%d)\n", buffer, nbytes);
+        }
+
+        free (buffer);
+    }
+}
+
+static void _audio_in_state_cb (audio_in_h handle, audio_io_state_e previous, audio_io_state_e current, bool by_policy, void *user_data)
+{
+    printf(">>> _audio_in_state_cb() : handle(%p), current(%d), previous(%d), by_policy(%d), user_data(%p)\n", handle, current, previous, by_policy, user_data);
+}
+
+static void _audio_out_state_cb (audio_in_h handle, audio_io_state_e previous, audio_io_state_e current, bool by_policy, void *user_data)
+{
+    printf(">>> _audio_out_state_cb() : handle(%p), current(%d), previous(%d), by_policy(%d), user_data(%p)\n", handle, current, previous, by_policy, user_data);
+}
+
+int _convert_cmd_and_run(char cmd, int mode) {
+    int ret = 0;
+    switch (cmd) {
+        case 'P':
+            if(mode & 0x01)  ret = audio_out_prepare(output);
+            if(mode & 0x02)  ret = audio_in_prepare(input);
+            break;
+        case 'u':
+            if(mode & 0x01)  ret = audio_out_unprepare(output);
+            if(mode & 0x02)  ret = audio_in_unprepare(input);
+            break;
+        case 'p':
+            if(mode & 0x01)  ret = audio_out_pause(output);
+            if(mode & 0x02)  ret = audio_in_pause(input);
+            break;
+        case 'r':
+            if(mode & 0x01)  ret = audio_out_resume(output);
+            if(mode & 0x02)  ret = audio_in_resume(input);
+            break;
+        case 'd':
+            if(mode & 0x01)  ret = audio_out_drain(output);
+            //if(mode & 0x02)  ret = audio_in_drain(input);
+            break;
+        case 'f':
+            if(mode & 0x01)  ret = audio_out_flush(output);
+            if(mode & 0x02)  ret = audio_in_flush(input);
+            break;
+        case 'i':
+#ifdef _NEW_SOUND_MANAGER_API_
+            ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, focus_callback_write, NULL, &g_stream_info_write_h);
+            if (ret) {
+                printf ("fail to sound_manager_create_stream_information(), ret(0x%x)\n", ret);
+            }
+#endif
+#ifdef _SESSION_SOUND_MANAGER_API_
+            ret = sound_manager_set_session_type(SOUND_SESSION_TYPE_MEDIA);
+            if (ret) {
+                printf ("fail to sound_manager_set_session_type(), ret(0x%x)\n", ret);
+            }
+            ret = sound_manager_set_media_session_option (SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START, SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY);
+            if (ret) {
+                printf ("fail to sound_manager_set_media_session_option(), ret(0x%x)\n", ret);
+            }
+#endif
+            break;
+        case 'q':  /* quit */
+            ret = 1;
+            break;
+        default:
+            ret = 1;
+            break;
+    }
+    return ret;
+}
+
+int audio_io_async_test(int mode)
+{
+    int ret, size;
+    char *buffer = NULL;
+    int i=0;
+
+    char cmd = 0;
+    int cmd_ret;
+
+    int write_mode = (mode & 0x01);
+    int read_mode = (mode & 0x02);
+
+    if((write_mode == 0) && (read_mode == 0)) {
+        printf ("not vaild mode.\n");
+        return 0;
+    }
+
+    if (read_mode) {
+
+#ifdef _SESSION_SOUND_MANAGER_API_
+        printf ("set session for capture.\n");
+
+        ret = sound_manager_set_session_type(SOUND_SESSION_TYPE_MEDIA);
+        if (ret) {
+            printf ("fail to sound_manager_set_session_type(), ret(0x%x)\n", ret);
+        }
+
+        ret = sound_manager_set_media_session_option (SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START, SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY);
+        if (ret) {
+            printf ("fail to sound_manager_set_media_session_option(), ret(0x%x)\n", ret);
+        }
+#endif
+
+        printf ("audio_in_create\n");
+        ret = audio_in_create(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, &input);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_in_create_ex failed. \n");
+            return 0;
+        }
+        printf ("audio_in_create success!!! [%p]\n", input);
+
+        ret = audio_in_set_stream_cb(input, _audio_io_stream_read_cb, NULL);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_in_set_stream_cb failed. \n");
+            return 0;
+        }
+        printf ("audio_in_set_stream_cb success!!! [%p]\n", input);
+
+        ret = audio_in_set_state_changed_cb(input, _audio_in_state_cb, NULL);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_out_set_state_changed_cb failed. \n");
+            return 0;
+        }
+        printf ("audio_out_set_state_changed_cb success!!! [%p]\n", input);
+
+        fp_w = fopen( "/tmp/pcm_w.raw", "w");
+
+#ifdef _NEW_SOUND_MANAGER_API_
+        //set stream type as SOUND_STREAM_TYPE_MEDIA
+        ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, focus_callback_read, NULL, &g_stream_info_read_h);
+        if (ret) {
+            printf ("fail to sound_manager_create_stream_information(), ret(0x%x)\n", ret);
+        }
+        ret = audio_in_set_stream_info(input, g_stream_info_read_h);
+#endif
+
+        ret = audio_in_set_interrupted_cb(input, interrupted_callback_read, NULL);
+    }
+
+    if (write_mode) {
+        printf ("before audio_out_create\n");
+        getchar();
+
+#ifdef _SESSION_SOUND_MANAGER_API_
+        printf ("set session for playback.\n");
+
+        ret = sound_manager_set_session_type(SOUND_SESSION_TYPE_MEDIA);
+        if (ret) {
+            printf ("fail to sound_manager_set_session_type(), ret(0x%x)\n", ret);
+        }
+
+        ret = sound_manager_set_media_session_option (SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START, SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY);
+        if (ret) {
+            printf ("fail to sound_manager_set_media_session_option(), ret(0x%x)\n", ret);
+        }
+#endif
+
+        printf ("audio_out_create\n");
+        //ret = audio_out_create(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output);
+        ret = audio_out_create_new(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, &output);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_out_create failed. \n");
+            return 0;
+        }
+        printf ("audio_out_create success!!! [%p]\n", output);
+
+        ret = audio_out_set_stream_cb(output, _audio_io_stream_write_cb, NULL);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_out_set_stream_cb failed. \n");
+            return 0;
+        }
+        printf ("audio_out_set_stream_cb success!!! [%p]\n", output);
+
+        ret = audio_out_set_state_changed_cb(output, _audio_out_state_cb, NULL);
+        if(ret != AUDIO_IO_ERROR_NONE) {
+            printf ("audio_out_set_state_changed_cb failed. \n");
+            return 0;
+        }
+        printf ("audio_out_set_state_changed_cb success!!! [%p]\n", output);
+
+#ifdef _NEW_SOUND_MANAGER_API_
+        //set stream type as SOUND_STREAM_TYPE_MEDIA
+        ret = sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, focus_callback_write, NULL, &g_stream_info_write_h);
+        if (ret) {
+            printf ("fail to sound_manager_create_stream_information(), ret(0x%x)\n", ret);
+        }
+        ret = audio_out_set_stream_info(output, g_stream_info_write_h);
+#endif
+
+        ret = audio_out_set_interrupted_cb(output, interrupted_callback_write, NULL);
+
+        //generate wave data
+        for(i=0; i<TABLE_SIZE; i++) {
+            test_wav.sine[i] = 0.9 * (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
+        }
+        test_wav.left_channel = test_wav.right_channel = 0;
+    }
+
+    if (read_mode) {
+        printf ("before audio_in_prepare\n");
+        getchar();
+        printf ("audio_in_prepare\n");
+        ret = audio_in_prepare(input);
+        if (ret != 0) {
+            printf ("audio_in_prepare failed.\n");
+            audio_in_destroy(input);
+            return 0;
+        } else {
+            ret = audio_in_get_buffer_size(input, &size);
+            if(ret != AUDIO_IO_ERROR_NONE) {
+                printf ("audio_in_get_buffer_size failed.\n");
+                return 0;
+            } else {
+                printf("size(%d)\n", size);
+                buffer = alloca(size);
+            }
+        }
+
+        if(buffer == NULL) {
+            printf("buffer is null\n");
+            return 0;
+        }
+    }
+
+    if (write_mode) {
+        printf ("before audio_out_prepare\n");
+        getchar();
+        printf ("audio_out_prepare\n");
+        ret = audio_out_prepare(output);
+        if (ret != 0) {
+            printf ("audio_out_prepare failed.\n");
+            audio_out_destroy(output);
+            return 0;
+        }
+    }
+
+    do {
+        printf ("command(q:quit) : ");
+        cmd = (char) getchar();
+        if(cmd != '\n')  getchar();
+        cmd_ret = _convert_cmd_and_run(cmd, mode);
+        printf ("  - result code : %d\n", cmd_ret);
+    } while (cmd != 'q');
+
+    //printf ("loop start\n");
+    //for (i=0; i<10; i++) {
+    //    printf ("-------- %d -------\n",i);
+    //    usleep (1000000);
+    //}
+
+    //getchar();
+
+    if (read_mode) {
+        printf ("audio_in_unprepare\n");
+        audio_in_unprepare(input);
+        printf ("audio_in_destroy\n");
+        audio_in_destroy(input);
+
+        fclose(fp_w);
+        fp_w = NULL;
+
+#ifdef _NEW_SOUND_MANAGER_API_
+        ret = sound_manager_destroy_stream_information(g_stream_info_read_h);
+        if (ret) {
+            printf ("fail to sound_manager_destroy_stream_information(), ret(0x%x)\n", ret);
+        } else {
+            g_stream_info_read_h = NULL;
+        }
+#endif
+    }
+
+    //getchar();
+
+    if (write_mode) {
+        printf ("audio_out_unprepare\n");
+        audio_out_unprepare(output);
+        printf ("audio_out_destroy\n");
+        audio_out_destroy(output);
+
+#ifdef _NEW_SOUND_MANAGER_API_
+        ret = sound_manager_destroy_stream_information(g_stream_info_write_h);
+        if (ret) {
+            printf ("fail to sound_manager_destroy_stream_information(), ret(0x%x)\n", ret);
+        } else {
+            g_stream_info_write_h = NULL;
+        }
+#endif
+    }
+
+    return 0;
 }
 
 int main(int argc, char ** argv)
 {
-       audio_io_test();
-       return 0;
+    if ( argc == 2 && !strcmp(argv[1],"call-forwarding-loop")) {
+        audio_io_loopback_test();
+    } else if ( argc == 2 && !strcmp(argv[1],"call-forwarding-in")) {
+        audio_io_loopback_in_test();
+    } else if ( argc == 3 && !strcmp(argv[1],"async")) {
+        audio_io_async_test(atoi(argv[2]));
+    } else if (argc == 4) {
+        printf ("run with [%s][%s][%s]\n", argv[1],argv[2],argv[3]);
+        audio_io_test(atoi (argv[1]), atoi (argv[2]), atoi(argv[3]));
+    } else if (argc == 6) {
+        play_file_sample(argv[2], atoi(argv[3]), atoi(argv[4]), atoi(argv[5]));
+    } else {
+        printf ("1. usage : audio_io_test call-forwarding-loop\n");
+        printf ("2. usage : audio_io_test call-forwarding-in\n");
+        printf ("3. usage : audio_io_test [length to read] [number of iteration] [channels]\n");
+        printf ("4. usage : audio_io_test async [write(1) | read(2)]\n");
+        printf ("5. Uasge : audio_io_test play [filename] [sample rate] [channels] [type(0:U8)]\n");
+    }
+    return 0;
 }