From: Jaechul Lee Date: Tue, 16 Mar 2021 04:24:47 +0000 (+0900) Subject: Add testcases for audio-hal-interfaces X-Git-Tag: submit/tizen/20210405.034048~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bc0cc0da924cced0d95f9d548b819a8decaa021a;p=platform%2Fhal%2Fapi%2Faudio.git Add testcases for audio-hal-interfaces [Version] 0.0.4 [Issue Type] Testcase Change-Id: Id79ce8ef4c96b32dd874fb92bb8b5eb4364667a5 Signed-off-by: Jaechul Lee --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ee91b0..678f955 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(hal-api-audio C) +PROJECT(hal-api-audio C CXX) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "${CMAKE_INSTALL_PREFIX}/bin") @@ -46,3 +46,4 @@ INSTALL(DIRECTORY include/ DESTINATION include/hal INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIBDIR}/pkgconfig) +ADD_SUBDIRECTORY(testcase) diff --git a/hal-api-audio-haltests.manifest b/hal-api-audio-haltests.manifest new file mode 100644 index 0000000..81ace0c --- /dev/null +++ b/hal-api-audio-haltests.manifest @@ -0,0 +1,6 @@ + + + + + + diff --git a/packaging/hal-api-audio.spec b/packaging/hal-api-audio.spec index b7e729a..632cf80 100644 --- a/packaging/hal-api-audio.spec +++ b/packaging/hal-api-audio.spec @@ -1,6 +1,6 @@ Name: hal-api-audio Summary: TIZEN Audio HAL -Version: 0.0.3 +Version: 0.0.4 Release: 0 Group: System/Libraries License: Apache-2.0 @@ -9,6 +9,10 @@ Source0: hal-api-audio-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(hal-api-common) BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(json-c) +BuildRequires: pkgconfig(gmock) %description TIZEN Audio HAL @@ -21,6 +25,14 @@ Requires: %{name} = %{version}-%{release} %description devel %{name} interface development package for product vendor developer +%package haltests +Summary: gtest for audio HAL APIs +Group: Development/Tools +Version: %{version} + +%description haltests +haltests for audio HAL APIs. + %prep %setup -q -n %{name}-%{version} %cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DCMAKE_LIBDIR_PREFIX=%{_libdir} @@ -33,6 +45,8 @@ export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" make %{?jobs:-j%jobs} %install +install -d -m 755 %{buildroot}%{_datadir}/testcase/res/audio/ +install -m 644 testcase/*.raw %{buildroot}%{_datadir}/testcase/res/audio/ %make_install @@ -53,3 +67,10 @@ make %{?jobs:-j%jobs} %defattr(-,root,root,-) %{_includedir}/hal/*.h %{_libdir}/pkgconfig/*.pc + +%files haltests +%defattr(-,root,root,-) +%manifest %{name}-haltests.manifest +%{_bindir}/hal/audio-haltests +%{_datadir}/testcase/res/audio/* + diff --git a/testcase/CMakeLists.txt b/testcase/CMakeLists.txt new file mode 100644 index 0000000..3de3682 --- /dev/null +++ b/testcase/CMakeLists.txt @@ -0,0 +1,16 @@ +SET(target "audio-haltests") + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(${target} REQUIRED dlog json-c capi-system-info gmock) +FOREACH(flag ${${target}_CFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH() + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -fPIC -Wall -Werror -std=c++0x -pie") + +AUX_SOURCE_DIRECTORY(. sources) +ADD_EXECUTABLE(${target} ${sources}) +TARGET_LINK_LIBRARIES(${target} ${${target}_LDFLAGS} ${PROJECT_NAME} -lpthread) + +INSTALL(TARGETS ${target} DESTINATION /usr/bin/hal) + diff --git a/testcase/audio_haltests.cpp b/testcase/audio_haltests.cpp new file mode 100644 index 0000000..7e6da81 --- /dev/null +++ b/testcase/audio_haltests.cpp @@ -0,0 +1,1218 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Seungbae Shin + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include "parser.hh" + +using namespace std; + +#define USE_IFSTREAM +#define DISABLE_DEBUG_LOG + +typedef void *pcm_handle; + +typedef enum audio_sample_format { + AUDIO_SAMPLE_U8, + AUDIO_SAMPLE_ALAW, + AUDIO_SAMPLE_ULAW, + AUDIO_SAMPLE_S16LE, + AUDIO_SAMPLE_S16BE, + AUDIO_SAMPLE_FLOAT32LE, + AUDIO_SAMPLE_FLOAT32BE, + AUDIO_SAMPLE_S32LE, + AUDIO_SAMPLE_S32BE, + AUDIO_SAMPLE_S24LE, + AUDIO_SAMPLE_S24BE, + AUDIO_SAMPLE_S24_32LE, + AUDIO_SAMPLE_S24_32BE, + AUDIO_SAMPLE_MAX, + AUDIO_SAMPLE_INVALID = -1 +} audio_sample_format_t; + +typedef struct { + audio_sample_format_t format; + uint32_t rate; + uint8_t channels; +} audio_pcm_sample_spec_t; + +/* + * TestSuite Class + */ +class AudioHalTest : public testing::Test +{ + public: + virtual void SetUp(); + virtual void TearDown(); + + protected: + void SetRouteToSpeaker(); + void SetRouteToMicrophone(); + int32_t WritePcmFromFile(pcm_handle pcm_h); + int32_t ReadPcmFromDevice(pcm_handle pcm_h); + uint32_t BytesToFrames(uint32_t bytes, audio_pcm_sample_spec_t *spec); + uint32_t BytesToFrames(uint32_t bytes); + uint32_t FramesToBytes(uint32_t frames, audio_pcm_sample_spec_t *spec); + uint32_t FramesToBytes(uint32_t frames); + uint32_t GetDefaultFrames(); + + static void HalMessageCallback(const char *name, int value, void *user_data); + + void *m_h; + audio_pcm_sample_spec_t m_spec; + + // Todo : following value may vary depends on targets + const int default_frames = 6400; + const int default_periods = 5; + const int default_rate = 44100; + const int default_channels = 2; + + // ToDo : following types may need to be fixed. + const array vol_types = { "system", "notification", "alarm", "ringtone", + "media", "call", "voip", "voice" }; + +}; + +void AudioHalTest::SetUp() +{ + m_h = nullptr; + + int32_t ret = hal_audio_init(&m_h); + if (ret != AUDIO_RET_OK) + cout << "audio hal init failed : " << ret << endl; +} + +void AudioHalTest::TearDown() +{ + if (m_h == nullptr) + return; + + int32_t ret = hal_audio_deinit(m_h); + if (ret != AUDIO_RET_OK) + cout << "audio hal deinit failed : " << ret << endl; + + m_h = nullptr; +} + +void AudioHalTest::SetRouteToSpeaker() +{ + audio_route_info info; + int32_t num_of_devices = 1; + + memset(&info, 0, sizeof(audio_route_info)); + + info.role = "media"; + info.device_infos = (device_info_s*)malloc(sizeof(device_info_s) * num_of_devices); + if (info.device_infos == nullptr) { + cout << "malloc error!!! : " << errno << endl; + return; + } + info.device_infos[0].direction = AUDIO_DIRECTION_OUT; + info.device_infos[0].type = "builtin-speaker"; + info.device_infos[0].id = 100; + info.num_of_devices = num_of_devices; + + int32_t ret = hal_audio_update_route(m_h, &info); + cout << "update route : " << ret << endl; + + free(info.device_infos); +} + +void AudioHalTest::SetRouteToMicrophone() +{ + audio_route_info info; + int32_t num_of_devices = 1; + + memset(&info, 0, sizeof(audio_route_info)); + + info.role = "media"; + info.device_infos = (device_info_s*)malloc(sizeof(device_info_s) * num_of_devices); + if (info.device_infos == nullptr) { + cout << "malloc error!!! : " << errno << endl; + return; + } + info.device_infos[0].direction = AUDIO_DIRECTION_IN; + info.device_infos[0].type = "builtin-mic"; + info.device_infos[0].id = 100; + info.num_of_devices = num_of_devices; + + int32_t ret = hal_audio_update_route(m_h, &info); + cout << "update route : " << ret << endl; + + free(info.device_infos); +} + +int32_t AudioHalTest::WritePcmFromFile(pcm_handle pcm_h) +{ + int32_t ret = AUDIO_RET_OK; + uint32_t avail_frames = 0; + int bytes_read; + char buffer[65536]; + + const char res_path[] = "/usr/share/testcase/res/audio/test_16le_44100_2ch.raw"; +#ifdef USE_IFSTREAM + ifstream fs; + fs.open(res_path, fstream::in | fstream::binary); + if (fs.fail()) { + cout << "Failed to open : " << res_path << endl; + return AUDIO_ERR_INTERNAL; + } +#else + int fd = open(res_path, O_RDONLY); + if (fd == -1) { + cout << "Failed to open : " << res_path << ", " << errno << endl; + return AUDIO_ERR_INTERNAL; + } +#endif + + cout << "start to play dtmf+noise sounds ( " << res_path << " ) for 5 sec. " << endl; + + while (1) { + ret = hal_audio_pcm_avail(m_h, pcm_h, &avail_frames); + if (ret == AUDIO_ERR_INTERNAL) + break; + + if (avail_frames == 0) { + usleep(20000); // 20ms + continue; + } + +#ifdef USE_IFSTREAM + fs.read(buffer, FramesToBytes(avail_frames)); + bytes_read = fs.gcount(); +#else + bytes_read = read(fd, buffer, FramesToBytes(avail_frames)); +#endif + + cout << "avail frames : " << avail_frames << ", read_n : " << bytes_read << endl; + + ret = hal_audio_pcm_write(m_h, pcm_h, buffer, BytesToFrames(bytes_read)); + if (ret == AUDIO_ERR_INTERNAL) + break; + +#ifdef USE_IFSTREAM + if (!fs.good()) { + if (fs.eof()) + cout << "EOS!!!" << endl; + else if (fs.fail() || fs.bad()) + cout << "Error..." << endl; + break; + } +#else + if (bytes_read < static_cast(FramesToBytes(avail_frames))) { + cout << "EOS!!!" << endl; + break; + } +#endif + } + +#ifdef USE_IFSTREAM + fs.close(); +#else + close(fd); +#endif + + cout << "Done!!!" << endl; + + return ret; +} + +int32_t AudioHalTest::ReadPcmFromDevice(pcm_handle pcm_h) +{ + int32_t ret = AUDIO_RET_OK; + uint32_t avail_frames = 0; + char buffer[65536]; + int iter_left = 100; + + cout << "start to record for few seconds..." << endl; + + do { + ret = hal_audio_pcm_avail(m_h, pcm_h, &avail_frames); + if (ret == AUDIO_ERR_INTERNAL) + break; + + if (avail_frames == 0) { + usleep(20000); // 20ms + continue; + } + + ret = hal_audio_pcm_read(m_h, pcm_h, buffer, avail_frames); + if (ret == AUDIO_ERR_INTERNAL) + break; + + cout << iter_left << ", read success, avail frames : " << avail_frames << endl; + } while (--iter_left); + + cout << "Done!!!" << endl; + + return ret; +} + +uint32_t AudioHalTest::BytesToFrames(uint32_t bytes, audio_pcm_sample_spec_t *spec) +{ + // ToDo : support various sample format + return (spec->format == AUDIO_SAMPLE_S16LE) ? bytes / spec->channels / 2 : 0; +} + +uint32_t AudioHalTest::BytesToFrames(uint32_t bytes) +{ + // ToDo : support various sample format + return (m_spec.format == AUDIO_SAMPLE_S16LE) ? bytes / m_spec.channels / 2 : 0; +} + +uint32_t AudioHalTest::FramesToBytes(uint32_t frames, audio_pcm_sample_spec_t *spec) +{ + // ToDo : support various sample format + return (spec->format == AUDIO_SAMPLE_S16LE) ? frames * spec->channels * 2 : 0; +} + +uint32_t AudioHalTest::FramesToBytes(uint32_t frames) +{ + // ToDo : support various sample format + return (m_spec.format == AUDIO_SAMPLE_S16LE) ? frames * m_spec.channels * 2 : 0; +} + +uint32_t AudioHalTest::GetDefaultFrames() +{ + return BytesToFrames(default_frames); +} + +void AudioHalTest::HalMessageCallback(const char *name, int value, void *user_data) +{ + cout << name << "," << value << "," << user_data << endl; +} + +/** + * @testcase InitP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Initialize audio HAL handle + * @apicovered audio_init, audio_deinit + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST(AudioHalPreTest, InitP) +{ + void *h = nullptr; + + int32_t ret = hal_audio_init(&h); + ASSERT_EQ(ret, AUDIO_RET_OK); + ASSERT_NE(h, nullptr); + + ret = hal_audio_deinit(h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase InitN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Initialize audio HAL handle + * @apicovered audio_init + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST(AudioHalPreTest, InitN) +{ + int32_t ret = hal_audio_init(nullptr); + ASSERT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase DeinitP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Deinitialize audio HAL handle + * @apicovered audio_init, audio_deinit + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST(AudioHalPreTest, DeinitP) +{ + void *h = nullptr; + + int32_t ret = hal_audio_init(&h); + ASSERT_EQ(ret, AUDIO_RET_OK); + ASSERT_NE(h, nullptr); + + ret = hal_audio_deinit(h); + ASSERT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase GetVolumeLevelMaxP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Get maximum volume level of each volume types + * @apicovered audio_get_volume_level_max + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeLevelMaxP) +{ + uint32_t level_max; + audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT }; + + for (const auto& i : vol_types) { + info.type = i.c_str(); + int32_t ret = hal_audio_get_volume_level_max(m_h, &info, &level_max); + cout << i << " : " << level_max << endl; + EXPECT_EQ(ret, AUDIO_RET_OK); + } +} + +/** + * @testcase GetVolumeLevelMaxN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Get maximum volume level of each volume types + * @apicovered audio_get_volume_level_max + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeLevelMaxN) +{ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_get_volume_level_max(m_h, &info, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase GetVolumeLevelP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Get volume level of each volume types + * @apicovered audio_get_volume_level + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeLevelP) +{ + uint32_t level; + int32_t ret; + audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT }; + + for (const auto& i : vol_types) { + info.type = i.c_str(); + ret = hal_audio_get_volume_level(m_h, &info, &level); + cout << i << " : " << level << endl; + EXPECT_EQ(ret, AUDIO_RET_OK); + } +} + +/** + * @testcase GetVolumeLevelN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Get volume level of each volume types + * @apicovered audio_get_volume_level + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeLevelN) +{ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_get_volume_level(m_h, &info, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase SetVolumeLevelP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Set volume level of each volume types + * @apicovered audio_set_volume_level + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, SetVolumeLevelP) +{ + /* FIXME : need to revise */ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_set_volume_level(m_h, &info, 15); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_set_volume_level(m_h, &info, 7); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + + +/** + * @testcase SetVolumeLevelN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Set volume level of each volume types + * @apicovered audio_set_volume_level + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, SetVolumeLevelN) +{ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_set_volume_level(m_h, &info, 10000); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + + +/** + * @testcase GetVolumeValueP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Get volume value of each volume types with given volume level + * @apicovered audio_get_volume_value + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeValueP) +{ + double value; + uint32_t level_max; + int32_t ret; + audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT }; + + for (const auto& i : vol_types) { + info.type = i.c_str(); + ret = hal_audio_get_volume_level_max(m_h, &info, &level_max); + EXPECT_EQ(ret, AUDIO_RET_OK); + + for (uint32_t l = 0; l < level_max ; l++) { + info.type = i.c_str(); + ret = hal_audio_get_volume_value(m_h, &info, l, &value); + EXPECT_EQ(ret, AUDIO_RET_OK); + cout << i << ", level " << l << ", value : " << value << endl; + } + } +} + +/** + * @testcase GetVolumeValueN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Get volume value of each volume types with given volume level + * @apicovered audio_get_volume_value + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeValueN) +{ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_get_volume_value(m_h, &info, 0, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase GetVolumeMuteP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Get volume mute of each volume types. + * @apicovered audio_get_volume_mute + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeMuteP) +{ + uint32_t mute = 0; + int32_t ret; + audio_volume_info_s info = { NULL, NULL, AUDIO_DIRECTION_OUT }; + + for (const auto& i : vol_types) { + info.type = i.c_str(); + ret = hal_audio_get_volume_mute(m_h, &info, &mute); + EXPECT_EQ(ret, AUDIO_RET_OK); + cout << i << " mute : " << mute << endl; + } +} + +/** + * @testcase GetVolumeMuteN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Get volume mute of each volume types. + * @apicovered audio_get_volume_mute + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, GetVolumeMuteN) +{ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_get_volume_mute(m_h, &info, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase SetVolumeMuteP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Set volume mute of each volume types. + * @apicovered audio_set_volume_mute + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, SetVolumeMuteP) +{ + audio_volume_info_s info = { "media", NULL, AUDIO_DIRECTION_OUT }; + int32_t ret = hal_audio_set_volume_mute(m_h, &info, 1); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_set_volume_mute(m_h, &info, 0); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +#if 0 // can't test because mute is not implemented yet... +TEST_F(AudioHalTest, SetVolumeMuteN) +{ + int32_t ret = hal_audio_set_volume_mute(m_h, "media", AUDIO_DIRECTION_OUT, 10000); + EXPECT_EQ(ret, AUDIO_ERR_INTERNAL); +} +#endif + +/** + * @testcase UpdateRouteP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Update route + * @apicovered audio_update_route + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, UpdateRouteP) +{ + audio_route_info info; + int32_t num_of_devices = 1; + + memset(&info, 0, sizeof(audio_route_info)); + + info.role = "media"; + info.device_infos = (device_info_s*)malloc(sizeof(device_info_s) * num_of_devices); + ASSERT_NE(info.device_infos, nullptr); + info.device_infos[0].direction = AUDIO_DIRECTION_OUT; + info.device_infos[0].type = "builtin-speaker"; + info.device_infos[0].id = 100; + info.num_of_devices = num_of_devices; + + int32_t ret = hal_audio_update_route(m_h, &info); + EXPECT_EQ(ret, AUDIO_RET_OK); + + free(info.device_infos); +} + + +/** + * @testcase UpdateRouteN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Update route + * @apicovered audio_update_route + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, UpdateRouteN) +{ + int32_t ret = hal_audio_update_route(m_h, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); + + audio_route_info info; + memset(&info, 0, sizeof(audio_route_info)); + info.role = nullptr; + ret = hal_audio_update_route(m_h, &info); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase UpdateRouteOptionP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Update route option + * @apicovered audio_update_route_option + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, UpdateRouteOptionP) +{ + audio_route_option_s option; + + int32_t ret = hal_audio_update_route_option(m_h, &option); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + + +/** + * @testcase UpdateRouteOptionN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Update route option + * @apicovered audio_update_route_option + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, UpdateRouteOptionN) +{ + int32_t ret = hal_audio_update_route_option(m_h, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase NotifyStreamConnectionChangedP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, Notify stream connection changed + * @apicovered audio_notify_stream_connection_changed + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, NotifyStreamConnectionChangedP) +{ + audio_stream_info_s info; + + memset(&info, 0, sizeof(audio_stream_info_s)); + info.role = "media"; + info.direction = AUDIO_DIRECTION_OUT; + info.idx = 100; + + int32_t ret = hal_audio_notify_stream_connection_changed(m_h, &info, 1); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase NotifyStreamConnectionChangedN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, Notify stream connection changed + * @apicovered audio_notify_stream_connection_changed + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, NotifyStreamConnectionChangedN) +{ + // check for nullptr ptr + int32_t ret = hal_audio_notify_stream_connection_changed(m_h, nullptr, 1); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); + + // check for invalid role + audio_stream_info_s info; + memset(&info, 0, sizeof(audio_stream_info_s)); + info.role = nullptr; + info.direction = AUDIO_DIRECTION_OUT; + info.idx = 100; + + ret = hal_audio_notify_stream_connection_changed(m_h, &info, 1); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase MessageCallbackP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, add/remove message callback + * @apicovered audio_add_message_cb, audio_remove_message_cb + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, MessageCallbackP) +{ + int32_t ret = hal_audio_add_message_cb(m_h, HalMessageCallback, nullptr); + ASSERT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_remove_message_cb(m_h, HalMessageCallback); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase MessageCallbackN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, add/remove message callback + * @apicovered audio_add_message_cb, audio_remove_message_cb + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, MessageCallbackN) +{ + int32_t ret = hal_audio_add_message_cb(m_h, nullptr, nullptr); + ASSERT_EQ(ret, AUDIO_ERR_PARAMETER); + + ret = hal_audio_remove_message_cb(m_h, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + + +/** + * @testcase PcmGetFdP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, get fd from the pcm handle + * @apicovered audio_pcm_get_fd, audio_pcm_open, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmGetFdP) +{ + pcm_handle pcm_h = nullptr; + + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_playback(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + SetRouteToSpeaker(); + + int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_OUT, &m_spec, + GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + int pcm_fd = -1; + ret = hal_audio_pcm_get_fd(m_h, pcm_h, &pcm_fd); + EXPECT_EQ(ret, AUDIO_RET_OK); + cout << "pcm fd : " << pcm_fd << endl; + + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmGetFdN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, get fd from the pcm handle + * @apicovered audio_pcm_get_fd, audio_pcm_open, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmGetFdN) +{ + // check for pcm handle + int pcm_fd = -1; + int32_t ret = hal_audio_pcm_get_fd(m_h, nullptr, &pcm_fd); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); + + // check for fd + pcm_handle pcm_h = nullptr; + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_playback(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + SetRouteToSpeaker(); + + ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_OUT, &m_spec, + GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_get_fd(m_h, pcm_h, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); + + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmOpenWriteCloseP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, open pcm handle, start pcm handle, write pcm buffers, stop pcm handle and close pcm_handle + * @apicovered audio_pcm_open, audio_pcm_start, audio_pcm_avail, audio_pcm_write, audio_pcm_stop, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmOpenWriteCloseP) +{ + pcm_handle pcm_h = nullptr; + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_playback(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + SetRouteToSpeaker(); + + int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_OUT, &m_spec, + GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_start(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = WritePcmFromFile(pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_stop(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmOpenReadCloseP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, open pcm handle, start pcm handle, read pcm buffers, stop pcm handle and close pcm_handle + * @apicovered audio_pcm_open, audio_pcm_start, audio_pcm_avail, audio_pcm_read, audio_pcm_stop, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmOpenReadCloseP) +{ + pcm_handle pcm_h = nullptr; + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_capture(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + SetRouteToMicrophone(); + + int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_IN, &m_spec, + GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_start(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = ReadPcmFromDevice(pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_stop(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmRecoverN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, pcm recovery + * @apicovered audio_pcm_recover + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmRecoverN) +{ + int32_t ret = hal_audio_pcm_recover(m_h, nullptr, 0); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +/** + * @testcase PcmSetParamP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, set audio parameters + * @apicovered audio_pcm_pcm_set_param, audio_pcm_open, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmSetParamP) +{ + pcm_handle pcm_h = nullptr; + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_playback(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + SetRouteToSpeaker(); + + int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_OUT, &m_spec, + GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_set_params(m_h, pcm_h, AUDIO_DIRECTION_OUT, &m_spec, + GetDefaultFrames(), default_periods); + EXPECT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmSetParamN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, set audio parameters + * @apicovered audio_pcm_pcm_set_param, audio_pcm_open, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmSetParamN) +{ + pcm_handle pcm_h = nullptr; + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_playback(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + SetRouteToSpeaker(); + + int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + ret = hal_audio_pcm_set_params(m_h, nullptr, AUDIO_DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); + + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmGetParamP + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Positive, get audio parameters + * @apicovered audio_pcm_pcm_get_param, audio_pcm_open, audio_pcm_close + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmGetParamP) +{ + pcm_handle pcm_h = nullptr; + string card, dev; + int rate = default_rate, channels = default_channels; + + CDeviceMapParser parser; + parser.get_playback(card, dev, rate, channels); + + m_spec.format = AUDIO_SAMPLE_S16LE; + m_spec.rate = rate; + m_spec.channels = channels; + + // Precondition + SetRouteToSpeaker(); + int32_t ret = hal_audio_pcm_open(m_h, card.c_str(), dev.c_str(), + AUDIO_DIRECTION_OUT, &m_spec, + GetDefaultFrames(), default_periods, &pcm_h); + ASSERT_EQ(ret, AUDIO_RET_OK); + + // Test Body + audio_pcm_sample_spec_t local_spec; + audio_pcm_sample_spec_t * p_spec = &local_spec; + uint32_t period_size = 0; + uint32_t periods = 0; + + memset(p_spec, 0, sizeof(audio_pcm_sample_spec_t)); + ret = hal_audio_pcm_get_params(m_h, pcm_h, AUDIO_DIRECTION_OUT, (void**)&p_spec, &period_size, &periods); + EXPECT_EQ(ret, AUDIO_RET_OK); + + cout << p_spec->format << "," << + p_spec->rate << "," << + static_cast(p_spec->channels) << "," << + period_size << "," << + periods << endl; + + // Cleanup + ret = hal_audio_pcm_close(m_h, pcm_h); + EXPECT_EQ(ret, AUDIO_RET_OK); +} + +/** + * @testcase PcmGetParamN + * @since_tizen 4.0 + * @author SR(seungbae.shin) + * @reviewer SR(sc11.lee) + * @type auto + * @description Negative, get audio parameters + * @apicovered audio_pcm_pcm_get_param + * @passcase XXX + * @failcase YYY + * @precondition None + * @postcondition None + */ +TEST_F(AudioHalTest, PcmGetParamN) +{ + int32_t ret = hal_audio_pcm_get_params(m_h, nullptr, AUDIO_DIRECTION_OUT, nullptr, nullptr, nullptr); + EXPECT_EQ(ret, AUDIO_ERR_PARAMETER); +} + +int main(int argc, char **argv) +{ +#ifdef DISABLE_DEBUG_LOG + cout.rdbuf(NULL); +#endif + + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/testcase/parser.cpp b/testcase/parser.cpp new file mode 100644 index 0000000..608ed3a --- /dev/null +++ b/testcase/parser.cpp @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include + +#include "parser.hh" + +#define DEVICE_FILE_OBJECT "device-files" +#define DEVICE_TYPE_PROP_PLAYBACK_DEVICES "playback-devices" +#define DEVICE_TYPE_PROP_CAPTURE_DEVICES "capture-devices" +#define DEVICE_TYPE_PROP_DEVICE_STRING "device-string" +#define DEVICE_TYPE_PROP_ROLE "role" + +/* device-files example + device-files : { + playback-devices : [ + { + device-string : alsa:sprdphone,0, + role : { normal : rate=44100 } + } + { + device-string : alsa:VIRTUALAUDIOW,0, + role : { call-voice : rate=16000 channels=1 tsched=0 alternate_rate=16000 } + } + ] + capture-devices : [ + { + device-string : alsa:sprdphone,0, + role : { normal : rate=44100 } + } + ] + } +*/ + +using namespace std; + +CDeviceMapParser::CDeviceMapParser() + : m_json_obj(nullptr), m_json_device_files_obj(nullptr) +{ + open_json("/etc/pulse/device-map.json"); +} + +CDeviceMapParser::CDeviceMapParser(const char* map_file) + : m_json_obj(nullptr), m_json_device_files_obj(nullptr) +{ + open_json(map_file); +} + +CDeviceMapParser::~CDeviceMapParser() +{ + close_json(); +} + +void CDeviceMapParser::open_json(const char* json_file) +{ + m_json_obj = json_object_from_file(json_file); + if (!m_json_obj) { + cout << "Read device-map " << json_file << " failed" << endl; + return; + } + + if (!json_object_object_get_ex(m_json_obj, DEVICE_FILE_OBJECT, &m_json_device_files_obj)) { + cout << "Get device files object failed" << endl; + return; + } + if (!json_object_is_type(m_json_device_files_obj, json_type_object)) { + cout << "json object type failed" << endl; + json_object_put(m_json_obj); + m_json_obj = nullptr; + return; + } + + cout << DEVICE_FILE_OBJECT << " : {" << endl; +} + +void CDeviceMapParser::close_json() +{ + if (!m_json_obj) + return; + + json_object_put(m_json_obj); + + cout << "}" << endl; +} + +void CDeviceMapParser::parse_playback() +{ + json_object *playback_devices_o = nullptr; + + if (!json_object_object_get_ex(m_json_device_files_obj, DEVICE_TYPE_PROP_PLAYBACK_DEVICES, &playback_devices_o)) { + cout << "failed to get playback" << endl; + return; + } + + cout << " " << DEVICE_TYPE_PROP_PLAYBACK_DEVICES << " : [" << endl; + parse_device_file_array_object(playback_devices_o, m_playback); + cout << " ]" << endl; +} + +void CDeviceMapParser::parse_capture() +{ + json_object *capture_devices_o = nullptr; + + if (!json_object_object_get_ex(m_json_device_files_obj, DEVICE_TYPE_PROP_CAPTURE_DEVICES, &capture_devices_o)) { + cout << "failed to get capture" << endl; + return; + } + + cout << " " << DEVICE_TYPE_PROP_CAPTURE_DEVICES << " : [" << endl; + parse_device_file_array_object(capture_devices_o, m_capture); + cout << " ]" << endl; +} + +void CDeviceMapParser::get_device(string& s, string& card, string& device_num) +{ + // eg. alsa:0,0 + string delimiter = ","; + string s1(s.substr(s.find_last_of(':') + 1)); + + // eg. 0,0 + size_t pos = s1.find(delimiter); + string token(s1.substr(0, pos)); + s1.erase(0, pos + delimiter.length()); + + card.assign(token); + device_num.assign(s1); +} + +void CDeviceMapParser::get_single_param(string& s, int& rate, int& channels) +{ + // eg. rate=44100 + string delimiter = "="; + size_t pos = s.find(delimiter); + string token = s.substr(0, pos); + s.erase(0, pos + delimiter.length()); + + if (token.compare("rate") == 0) + rate = stoi(s); + else if (token.compare("channels") == 0) + channels = stoi(s); +} + +void CDeviceMapParser::get_params(string& s, int& rate, int& channels) +{ + // eg. rate=44100 channels=1 + string delimiter = " "; + size_t pos = 0; + string token; + string s1(s); + + while ((pos = s1.find(delimiter)) != string::npos) { + token = s1.substr(0, pos); + get_single_param(token, rate, channels); + s1.erase(0, pos + delimiter.length()); + } + get_single_param(s1, rate, channels); +} + + +void CDeviceMapParser::dump_devices() +{ + string card, device_num; + int rate = -1, channels = -1; + + get_playback(card, device_num, rate, channels); + get_capture(card, device_num, rate, channels); +} + +void CDeviceMapParser::get_playback(string& card, string& device_num, int& rate, int& channels) +{ + parse_playback(); + + get_device(m_playback.first, card, device_num); + get_params(m_playback.second, rate, channels); + cout << " 1. PLAYBACK" << endl; + cout << " > card=" << card << ", device=" << device_num << endl; + cout << " > rate=" << rate << ", channels=" << channels << endl << endl; +} + +void CDeviceMapParser::get_capture(string& card, string& device_num, int& rate, int& channels) +{ + parse_capture(); + + get_device(m_capture.first, card, device_num); + get_params(m_capture.second, rate, channels); + cout << " 2. CAPTURE" << endl; + cout << " > card=" << card << ", device=" << device_num << endl; + cout << " > rate=" << rate << ", channels=" << channels << endl; +} + +void CDeviceMapParser::parse_device_string_object(json_object *device_string_o, string& device_string) +{ + assert(device_string_o); + assert(json_object_is_type(device_string_o, json_type_string)); + + // object example + // device-string : alsa:sprdphone,0, + + device_string.assign(json_object_get_string(device_string_o)); + + cout << " " << DEVICE_TYPE_PROP_DEVICE_STRING << " : " << device_string << "," << endl; +} + +void CDeviceMapParser::parse_device_role_object(json_object *device_role_o, string& device_params) +{ + struct json_object_iterator it, it_end; + + assert(device_role_o); + assert(json_object_is_type(device_role_o, json_type_object)); + + // + // role : { normal : rate=44100 } + + it = json_object_iter_begin(device_role_o); + it_end = json_object_iter_end(device_role_o); + + while (!json_object_iter_equal(&it, &it_end)) { + if (strcmp(json_object_iter_peek_name(&it), "normal") == 0) { + device_params.assign(json_object_get_string(json_object_iter_peek_value(&it))); + cout << " " << DEVICE_TYPE_PROP_ROLE << " : { normal : " << device_params << " }" << endl; + break; + } + + json_object_iter_next(&it); + } +} + +void CDeviceMapParser::parse_device_file_object(json_object *device_file_o, pair& device) +{ + json_object *device_file_prop_o = nullptr; + string device_string, device_param; + + assert(device_file_o); + assert(json_object_is_type(device_file_o, json_type_object)); + + // + // device-string : alsa:sprdphone,0, + // role : { normal : rate=44100 } + + // parse role + if (!json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_ROLE, &device_file_prop_o)) { + cout << "Get device role object failed" << endl; + return; + } + parse_device_role_object(device_file_prop_o, device_param); + + if (device_param.empty()) { + cout << " " << "[E] This is not a normal device..skip" << endl; + return; + } + + // parse device-string + if (!json_object_object_get_ex(device_file_o, DEVICE_TYPE_PROP_DEVICE_STRING, &device_file_prop_o)) { + cout << "Get device-string object failed" << endl; + return; + } + parse_device_string_object(device_file_prop_o, device_string); + + // store device information + device = make_pair(device_string, device_param); +} + +void CDeviceMapParser::parse_device_file_array_object(json_object *device_file_array_o, pair& device) +{ + int num, idx; + json_object *device_file_o = nullptr; + + assert(device_file_array_o); + assert(json_object_is_type(device_file_array_o, json_type_array)); + + // + // { + // device-string : alsa:sprdphone,0, + // role : { normal : rate=44100 } + // } + + // ToDo : this might be replaced with iterator such as foreach? + num = json_object_array_length(device_file_array_o); + for (idx = 0; idx < num; idx++) { + if (!(device_file_o = json_object_array_get_idx(device_file_array_o, idx))) { + cout << "Get device file object failed" << endl; + return; + } + + cout << " {" << endl; + parse_device_file_object(device_file_o, device); + cout << " }" << endl; + } +} diff --git a/testcase/parser.hh b/testcase/parser.hh new file mode 100644 index 0000000..34b7f14 --- /dev/null +++ b/testcase/parser.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Seungbae Shin + * + * 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 +#include +#include + +using namespace std; + +class CDeviceMapParser +{ +public: + CDeviceMapParser(); + explicit CDeviceMapParser(const char* map_file); + virtual ~CDeviceMapParser(); + + void dump_devices(); + + void get_playback(string& card, string& device_num, int& rate, int& channels); + void get_capture(string& card, string& device_num, int& rate, int& channels); + +private: + void open_json(const char* json_file); + void close_json(); + void parse_device_string_object(json_object *device_string_o, string& device_string); + void parse_device_role_object(json_object *device_role_o, string& device_params); + void parse_device_file_object(json_object *device_file_o, pair& device); + void parse_device_file_array_object(json_object *device_file_array_o, pair& device); + + void parse_playback(); + void parse_capture(); + void get_device(string& s, string& card, string& device_num); + void get_params(string& s, int& rate, int& channels); + void get_single_param(string& s, int& rate, int& channels); + + // FixMe, pair doesn't define what is paired clearly.... + pair m_playback; // device_string, device_params + pair m_capture; // device_string, device_params + + json_object *m_json_obj; + json_object *m_json_device_files_obj; +}; + + diff --git a/testcase/test_16le_44100_2ch.raw b/testcase/test_16le_44100_2ch.raw new file mode 100644 index 0000000..cbc25eb Binary files /dev/null and b/testcase/test_16le_44100_2ch.raw differ