[Sound] Added implementation for tizen 2.4
authorTomasz Marciniak <t.marciniak@samsung.com>
Tue, 3 Mar 2015 06:40:12 +0000 (07:40 +0100)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Tue, 10 Mar 2015 08:23:23 +0000 (09:23 +0100)
[Verification] Code compiles without errors.
Functions successfully tested.

Change-Id: Ie1b4442cdaac4f039d21e792f48638ee117cf106
Signed-off-by: Tomasz Marciniak <t.marciniak@samsung.com>
src/sound/sound_api.js
src/sound/sound_instance.cc
src/sound/sound_instance.h
src/sound/sound_manager.cc
src/sound/sound_manager.h

index b9301cdf5f0622de809747333d3eec9e40128f63..cbf94c8ac86288728e53841a08f42c7527ea4021 100644 (file)
@@ -26,6 +26,61 @@ var SoundModeType = {
   MUTE: 'MUTE'
 };
 
+function _createSoundDeviceInfoArray(e) {
+  var devices_array = [];
+
+  e.forEach(function (data) {
+    devices_array.push(new SoundDeviceInfo(data));
+  });
+
+  return devices_array;
+};
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+};
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  var obj = new SoundDeviceInfo(msg);
+  for (var watchId in this.listeners) {
+    if (this.listeners.hasOwnProperty(watchId)) {
+      this.listeners[watchId](obj);
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  var id = this.nextId;
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+    this.native.callSync('SoundManager_addDeviceStateChangeListener');
+    this.nativeSet = true;
+  }
+
+  this.listeners[id] = callback;
+  ++this.nextId;
+
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  }
+
+  if (this.nativeSet && type_.isEmptyObject(this.listeners)) {
+      this.native.callSync('SoundManager_removeDeviceStateChangeListener');
+      this.native.removeListener(this.listenerName);
+      this.nativeSet = false;
+  }
+};
+
+var DEVICE_STATE_CHANGE_LISTENER = 'SoundDeviceStateChangeCallback';
+var soundDeviceStateChangeListener = new ListenerManager(native_, DEVICE_STATE_CHANGE_LISTENER);
 
 function SoundManager() {}
 
@@ -132,5 +187,57 @@ SoundManager.prototype.unsetVolumeChangeListener = function() {
   }
 };
 
+SoundManager.prototype.getConnectedDeviceList = function() {
+  var result = native_.callSync('SoundManager_getConnectedDeviceList', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var devices = _createSoundDeviceInfoArray(native_.getResultObject(result));
+  return devices;
+};
+
+SoundManager.prototype.getActivatedDeviceList = function() {
+  var result = native_.callSync('SoundManager_getActivatedDeviceList', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var devices = _createSoundDeviceInfoArray(native_.getResultObject(result));
+  return devices;
+};
+
+SoundManager.prototype.addDeviceStateChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+       name : 'eventCallback',
+       type : types_.FUNCTION
+     }
+  ]);
+
+  return soundDeviceStateChangeListener.addListener(args.eventCallback);
+};
+
+SoundManager.prototype.removeDeviceStateChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+       name : 'watchId',
+       type : types_.LONG
+    }
+  ]);
+
+  soundDeviceStateChangeListener.removeListener(args.watchId);
+};
+
+function SoundDeviceInfo(data) {
+  Object.defineProperties(this, {
+    id: {value: data.id, writable: false, enumerable: true},
+    name: {value: data.name, writable: false, enumerable: true},
+    device : {value: data.device, writable: false, enumerable: true},
+    direction : {value: data.direction, writable: false, enumerable: true},
+    isConnected: {value: data.isConnected, writable: false, enumerable: true},
+    isActivated: {value: data.isActivated, writable: false, enumerable: true},
+  });
+};
 
 exports = new SoundManager();
index 7363a40a0b0a50c0f0a88c839995679b9f613893..5a6e78ec38b6678c9e41f6a0bcd57b91500d3d48 100644 (file)
@@ -34,6 +34,12 @@ SoundInstance::SoundInstance() {
   REGISTER_SYNC("SoundManager_setSoundModeChangeListener", SoundManagerSetSoundModeChangeListener);
   REGISTER_SYNC("SoundManager_setVolumeChangeListener", SoundManagerSetVolumeChangeListener);
   REGISTER_SYNC("SoundManager_getSoundMode", SoundManagerGetSoundMode);
+  REGISTER_SYNC("SoundManager_getConnectedDeviceList", SoundManagerGetConnectedDeviceList);
+  REGISTER_SYNC("SoundManager_getActivatedDeviceList", SoundManagerGetActivatedDeviceList);
+  REGISTER_SYNC("SoundManager_addDeviceStateChangeListener",
+                SoundManagerAddDeviceStateChangeListener);
+  REGISTER_SYNC("SoundManager_removeDeviceStateChangeListener",
+                SoundManagerRemoveDeviceStateChangeListener);
   #undef REGISTER_SYNC
 
   manager_ = SoundManager::GetInstance();
@@ -139,6 +145,46 @@ void SoundInstance::SoundManagerUnsetVolumeChangeListener(
     ReportError(status, &out);
 }
 
+void SoundInstance::SoundManagerGetConnectedDeviceList(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  manager_->GetDeviceList(SOUND_DEVICE_ALL_MASK, out);
+}
+
+void SoundInstance::SoundManagerGetActivatedDeviceList(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  manager_->GetDeviceList(SOUND_DEVICE_STATE_ACTIVATED_MASK, out);
+}
+
+void SoundInstance::SoundManagerAddDeviceStateChangeListener(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  PlatformResult result = manager_->AddDeviceStateChangeListener();
+
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void SoundInstance::SoundManagerRemoveDeviceStateChangeListener(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  PlatformResult result = manager_->RemoveDeviceStateChangeListener();
+
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
 #undef CHECK_EXIST
 
 } // namespace sound
index f3c762efd0b4cf2c0a6f6044eeda28195a0ce4d3..48a001addb1348fcf0777d6583e667923eca84e1 100644 (file)
@@ -27,6 +27,11 @@ class SoundInstance : public common::ParsedInstance, public SoundManagerSoundMod
   void SoundManagerSetSoundModeChangeListener(const picojson::value& args, picojson::object& out);
   void SoundManagerSetVolumeChangeListener(const picojson::value& args, picojson::object& out);
   void SoundManagerGetSoundMode(const picojson::value& args, picojson::object& out);
+  void SoundManagerGetConnectedDeviceList(const picojson::value& args, picojson::object& out);
+  void SoundManagerGetActivatedDeviceList(const picojson::value& args, picojson::object& out);
+  void SoundManagerAddDeviceStateChangeListener(const picojson::value& args, picojson::object& out);
+  void SoundManagerRemoveDeviceStateChangeListener(
+      const picojson::value& args, picojson::object& out);
 
   void OnSoundModeChange(const std::string& newmode);
 };
index 21968215e1a964a6cade2794577364f5bd55f3cf..89c16632b41bc6cec7ffacb3087ecf8577500abe 100644 (file)
@@ -8,6 +8,7 @@
 #include <vconf.h>
 #include <vconf-keys.h>
 
+#include "common/task-queue.h"
 
 //This constant was originally defined in vconf.h. However, in tizen 3, it
 //appears, it is removed (or defined only in vconf-internals.h)
@@ -24,6 +25,7 @@ namespace extension {
 namespace sound {
 
 using namespace common;
+using namespace common::tools;
 
 const std::map<std::string, sound_type_e> SoundManager::platform_enum_map_ = {
     {"SYSTEM", SOUND_TYPE_SYSTEM},
@@ -61,8 +63,48 @@ PlatformResult SoundManager::PlatformEnumToStr(const sound_type_e value,
   return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
 }
 
+std::string SoundManager::SoundDeviceTypeToString(sound_device_type_e type) {
+  switch (type) {
+    case SOUND_DEVICE_BUILTIN_SPEAKER:
+      return "SPEAKER";
+    case SOUND_DEVICE_BUILTIN_RECEIVER:
+      return "RECEIVER";
+    case SOUND_DEVICE_BUILTIN_MIC:
+      return "MIC";
+    case SOUND_DEVICE_AUDIO_JACK:
+      return "AUDIO_JACK";
+    case SOUND_DEVICE_BLUETOOTH:
+      return "BLUETOOTH";
+    case SOUND_DEVICE_HDMI:
+      return "HDMI";
+    case SOUND_DEVICE_MIRRORING:
+      return "MIRRORING";
+    case SOUND_DEVICE_USB_AUDIO:
+      return "USB_AUDIO";
+    default:
+      LoggerE("Invalid sound_device_type_e: %d", type);
+      return "";
+  }
+}
+
+std::string SoundManager::SoundIOTypeToString(sound_device_io_direction_e type) {
+  switch (type) {
+    case SOUND_DEVICE_IO_DIRECTION_IN:
+      return "IN";
+    case SOUND_DEVICE_IO_DIRECTION_OUT:
+      return "OUT";
+    case SOUND_DEVICE_IO_DIRECTION_BOTH:
+      return "BOTH";
+    default:
+      LoggerE("Invalid sound_device_io_direction_e: %d", type);
+      return "";
+  }
+}
+
 SoundManager::SoundManager()
-    : soundModeChangeListening(false), soundModeListener(nullptr) {
+    : soundModeChangeListening(false),
+      sound_device_change_listener_(false),
+      soundModeListener(nullptr) {
   FillMaxVolumeMap();
 }
 
@@ -73,6 +115,16 @@ SoundManager::~SoundManager() {
       LoggerE("Cannot disable listener!");
     }
   }
+
+  if (sound_device_change_listener_) {
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_connected_cb()) {
+      LoggerE("Cannot unregister connection listener!");
+    }
+
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_information_changed_cb()) {
+      LoggerE("Cannot unregister information listener!");
+    }
+  }
 }
 
 SoundManager* SoundManager::GetInstance() {
@@ -335,5 +387,216 @@ PlatformResult SoundManager::UnsetVolumeChangeListener() {
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+void SoundManager::GetDeviceList(sound_device_mask_e mask, picojson::object& out) {
+  LoggerD("Entered");
+
+  int ret = SOUND_MANAGER_ERROR_NONE;
+  sound_device_list_h device_list = nullptr;
+  sound_device_h device = nullptr;
+
+  picojson::value response = picojson::value(picojson::array());
+  picojson::array& response_array = response.get<picojson::array>();
+
+  ret = sound_manager_get_current_device_list(mask, &device_list);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device list failed"), &out);
+    return;
+  }
+
+  while (!(ret = sound_manager_get_next_device(device_list, &device))) {
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    PlatformResult result = GetDeviceInfo(device, true, false, &obj);
+
+    if (result.IsError()) {
+      ReportError(result, &out);
+      return;
+    }
+    response_array.push_back(val);
+  }
+
+  ReportSuccess(response, out);
+}
+
+PlatformResult SoundManager::GetDeviceInfo(sound_device_h device,
+                                           bool is_connected,
+                                           bool check_connection,
+                                           picojson::object* obj) {
+  LoggerD("Entered");
+
+  int ret = SOUND_MANAGER_ERROR_NONE;
+
+  //get id
+  int id = 0;
+  ret = sound_manager_get_device_id(device, &id);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device id failed");
+  }
+  obj->insert(std::make_pair("id", picojson::value(static_cast<double>(id))));
+
+  //get name
+  char *name = nullptr;
+  ret = sound_manager_get_device_name(device, &name);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device name failed");
+  }
+  obj->insert(std::make_pair("name", picojson::value(name)));
+
+  //get type
+  sound_device_type_e type = SOUND_DEVICE_BUILTIN_SPEAKER;
+  ret = sound_manager_get_device_type(device, &type);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device type failed");
+  }
+  obj->insert(std::make_pair("device", picojson::value(SoundDeviceTypeToString(type))));
+
+  //get direction
+  sound_device_io_direction_e direction = SOUND_DEVICE_IO_DIRECTION_IN;
+  ret = sound_manager_get_device_io_direction (device, &direction);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device direction failed");
+  }
+  obj->insert(std::make_pair("direction", picojson::value(SoundIOTypeToString(direction))));
+
+  //get state
+  sound_device_state_e state = SOUND_DEVICE_STATE_DEACTIVATED;
+  ret = sound_manager_get_device_state(device, &state);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device state failed");
+  }
+  obj->insert(std::make_pair("isActivated", picojson::value(static_cast<bool>(state))));
+
+  //get connection
+  if (check_connection) {
+    return IsDeviceConnected(type, direction, obj);
+  }
+
+  obj->insert(std::make_pair("isConnected", picojson::value(is_connected)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::IsDeviceConnected(sound_device_type_e type,
+                                               sound_device_io_direction_e direction,
+                                               picojson::object* obj) {
+  LoggerD("Entered");
+
+  sound_device_mask_e mask = SOUND_DEVICE_ALL_MASK;
+  switch (direction) {
+    case SOUND_DEVICE_IO_DIRECTION_IN:
+      mask = SOUND_DEVICE_IO_DIRECTION_IN_MASK;
+      break;
+    case SOUND_DEVICE_IO_DIRECTION_OUT:
+      mask = SOUND_DEVICE_IO_DIRECTION_OUT_MASK;
+      break;
+    case SOUND_DEVICE_IO_DIRECTION_BOTH:
+      mask = SOUND_DEVICE_IO_DIRECTION_BOTH_MASK;
+      break;
+    default:
+      LoggerD("Invalid IOType (%d)", direction);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid IO type");
+  }
+
+  int ret = SOUND_MANAGER_ERROR_NONE;
+  sound_device_list_h device_list = nullptr;
+  sound_device_h device = nullptr;
+  sound_device_type_e device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
+
+  ret = sound_manager_get_current_device_list(mask, &device_list);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device list failed");
+  }
+
+  while (!(ret = sound_manager_get_next_device(device_list, &device))) {
+    ret = sound_manager_get_device_type(device, &device_type);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device type failed");
+    }
+
+    if (type == device_type) {
+      obj->insert(std::make_pair("isConnected", picojson::value(true)));
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+
+  obj->insert(std::make_pair("isConnected", picojson::value(false)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SoundManager::DeviceChangeCB(sound_device_h device, bool is_connected, bool check_connection) {
+  LoggerD("Entered");
+
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+
+  PlatformResult result = GetDeviceInfo(device, is_connected, check_connection, &response_obj);
+
+  if (result.IsSuccess()) {
+    response_obj.insert(std::make_pair(
+        "listenerId", picojson::value("SoundDeviceStateChangeCallback")));
+
+    auto call_response = [response]()->void {
+      SoundInstance::GetInstance().PostMessage(response.serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Async(call_response);
+  }
+}
+
+void DeviceConnectionChangeCB(sound_device_h device, bool is_connected, void *user_data) {
+  LoggerD("Entered");
+
+  SoundManager::GetInstance()->DeviceChangeCB(device, is_connected, false);
+}
+
+void DeviceActivationChangeCB(sound_device_h device, sound_device_changed_info_e changed_info,
+                              void *user_data) {
+  LoggerD("Entered");
+
+  if (SOUND_DEVICE_CAHNGED_INFO_STATE == changed_info) {
+    SoundManager::GetInstance()->DeviceChangeCB(device, false, true);
+  }
+}
+
+PlatformResult SoundManager::AddDeviceStateChangeListener() {
+  LoggerD("Entered");
+
+  int ret = SOUND_MANAGER_ERROR_NONE;
+  sound_device_mask_e mask = SOUND_DEVICE_ALL_MASK;
+
+  if (!sound_device_change_listener_) {
+    ret = sound_manager_set_device_connected_cb(mask, DeviceConnectionChangeCB, nullptr);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Setting connection listener failed");
+    }
+
+    ret = sound_manager_set_device_information_changed_cb(mask, DeviceActivationChangeCB, nullptr);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Setting information listener failed");
+    }
+
+    sound_device_change_listener_ = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::RemoveDeviceStateChangeListener() {
+  LoggerD("Entered");
+
+  if (sound_device_change_listener_) {
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_connected_cb()) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsetting information listener failed");
+    }
+
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_information_changed_cb()) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsetting information listener failed");
+    }
+
+    sound_device_change_listener_ = false;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace sound
 }  // namespace extension
index 4c0781de92bb6d8005c10579102889b24b5ace4a..ecda42a475080aba4ca1dcdad8d15b6dd4e62ddf 100644 (file)
@@ -32,6 +32,10 @@ class SoundManager {
   common::PlatformResult UnsetSoundModeChangeListener();
   common::PlatformResult SetVolumeChangeListener();
   common::PlatformResult UnsetVolumeChangeListener();
+  void GetDeviceList(sound_device_mask_e mask, picojson::object& out);
+  void DeviceChangeCB(sound_device_h device, bool is_connected, bool check_connection);
+  common::PlatformResult AddDeviceStateChangeListener();
+  common::PlatformResult RemoveDeviceStateChangeListener();
 
  private:
   SoundManager();
@@ -50,9 +54,20 @@ class SoundManager {
                                                   sound_type_e* sound_type);
   static common::PlatformResult PlatformEnumToStr(const sound_type_e value,
                                                   std::string* sound_type);
+                                                  
+  common::PlatformResult GetDeviceInfo(sound_device_h device,
+                                       bool is_connected,
+                                       bool check_connection,
+                                       picojson::object* obj);
+  common::PlatformResult IsDeviceConnected(sound_device_type_e type,
+                                           sound_device_io_direction_e direction,
+                                           picojson::object* obj);
+  static std::string SoundDeviceTypeToString(sound_device_type_e type);
+  static std::string SoundIOTypeToString(sound_device_io_direction_e type);
   static double ConvertToSystemVolume(int max_volume, int volume);
   static void soundModeChangedCb(keynode_t* node, void* user_data);
   bool soundModeChangeListening;
+  bool sound_device_change_listener_;
   SoundManagerSoundModeChangedListener* soundModeListener;
 };