#include <audio_hal_interface.h>
#include <system_info.h>
+#include "parser.hh"
+
using namespace std;
#define USE_IFSTREAM
// Todo : following value may vary depends on targets
const int default_frames = 6400;
const int default_periods = 5;
-
- // ToDo : following should be changed in runtime
- const string default_card = "sprdphone";
- const string default_device = "0";
+ const int default_rate = 44100;
+ const int default_channels = 2;
// ToDo : following types may need to be fixed.
const array<string, 8> vol_types = { "system", "notification", "alarm", "ringtone",
{
m_h = nullptr;
- m_spec.format = AUDIO_SAMPLE_S16LE;
- m_spec.rate = 44100;
- m_spec.channels = 2;
-
int32_t ret = audio_hal_interface_init(&m_h);
if (ret != AUDIO_HAL_SUCCESS)
cout << "audio hal init failed : " << ret << endl;
{
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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ int32_t ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
// 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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ int32_t ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ int32_t ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_IN, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ int32_t ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ int32_t ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
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 = audio_hal_interface_pcm_open(m_h, default_card.c_str(), default_device.c_str(),
+ int32_t ret = audio_hal_interface_pcm_open(m_h, card.c_str(), dev.c_str(),
DIRECTION_OUT, &m_spec, GetDefaultFrames(), default_periods, &pcm_h);
ASSERT_EQ(ret, AUDIO_HAL_SUCCESS);
--- /dev/null
+#include <iostream>
+#include <json.h>
+#include <assert.h>
+#include <string.h>
+#include <string>
+
+#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;
+
+class CDeviceMapParser
+{
+public:
+ CDeviceMapParser();
+ 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<string, string>& device);
+ void parse_device_file_array_object(json_object *device_file_array_o, pair<string, string>& 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 doens't define what is paired clearly....
+ pair<string, string> m_playback; // device_string, device_params
+ pair<string, string> m_capture; // device_string, device_params
+
+ json_object *m_json_obj;
+ json_object *m_json_device_files_obj;
+};
+
+CDeviceMapParser::CDeviceMapParser()
+{
+ open_json("/etc/pulse/device-map.json");
+}
+
+CDeviceMapParser::CDeviceMapParser(const char* map_file)
+{
+ 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 = NULL;
+ 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 = NULL;
+
+ 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 = NULL;
+
+ 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));
+
+ // <object example>
+ // 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<string, string>& device)
+{
+ json_object *device_file_prop_o = NULL;
+ string device_string, device_param;
+
+ assert(device_file_o);
+ assert(json_object_is_type(device_file_o, json_type_object));
+
+ // <object example>
+ // 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<string, string>& device)
+{
+ int num, idx;
+ json_object *device_file_o = NULL;
+
+ assert(device_file_array_o);
+ assert(json_object_is_type(device_file_array_o, json_type_array));
+
+ // <object example>
+ // {
+ // 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;
+ }
+}