[adsp] Add gui sound playback with selectable channel position on dsp addon callbacks
authorAlwinEsch <alwin.esch@web.de>
Sun, 12 Apr 2015 18:43:35 +0000 (20:43 +0200)
committerAchimTuran <wisler@kodi.tv>
Sun, 19 Jul 2015 16:54:27 +0000 (18:54 +0200)
Makefile.include.in
lib/addons/library.kodi.adsp/libKODI_adsp.cpp
xbmc/addons/AddonCallbacks.h
xbmc/addons/AddonCallbacksAudioDSP.cpp
xbmc/addons/AddonCallbacksAudioDSP.h
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.h
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.cpp
xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAESound.h
xbmc/cores/AudioEngine/Interfaces/AESound.h

index 54ec04d..e54672c 100644 (file)
@@ -39,6 +39,7 @@ LDFLAGS+=@LDFLAGS@
 LDFLAGS_FOR_BUILD+=@LDFLAGS_FOR_BUILD@
 INCLUDES+=-I@abs_top_srcdir@/lib
 INCLUDES+=-I@abs_top_srcdir@/xbmc
+INCLUDES+=-I@abs_top_srcdir@/xbmc/addons/include
 INCLUDES+=-I@abs_top_srcdir@/addons/library.kodi.guilib
 INCLUDES+=-I@abs_top_srcdir@/addons/library.xbmc.addon
 INCLUDES+=-I@abs_top_srcdir@/addons/library.kodi.adsp
index 5034a5e..a2d0716 100644 (file)
@@ -89,4 +89,86 @@ DLLEXPORT void ADSP_unregister_mode(void *hdl, void* cb, AE_DSP_MODES::AE_DSP_MO
   ((CB_ADSPLib*)cb)->UnregisterMode(((AddonCB*)hdl)->addonData, mode);
 }
 
+///-------------------------------------
+/// CAddonSoundPlay
+
+DLLEXPORT CAddonSoundPlay* ADSP_get_sound_play(void *hdl, void *cb, const char *filename)
+{
+  return new CAddonSoundPlay(hdl, cb, filename);
+}
+
+DLLEXPORT void ADSP_release_sound_play(CAddonSoundPlay* p)
+{
+  delete p;
+}
+
+CAddonSoundPlay::CAddonSoundPlay(void *hdl, void *cb, const char *filename)
+ : m_Filename(filename)
+{
+  m_PlayHandle = NULL;
+  if (!hdl || !cb)
+    fprintf(stderr, "libKODI_adsp-ERROR: ADSP_get_sound_play is called with NULL handle !!!\n");
+  else
+  {
+    m_Handle     = hdl;
+    m_cb         = cb;
+    m_PlayHandle = ((CB_ADSPLib*)m_cb)->SoundPlay_GetHandle(((AddonCB*)m_Handle)->addonData, m_Filename.c_str());
+    if (!m_PlayHandle)
+      fprintf(stderr, "libKODI_adsp-ERROR: ADSP_get_sound_play can't get callback table from KODI !!!\n");
+  }
+}
+
+CAddonSoundPlay::~CAddonSoundPlay()
+{
+  if (m_PlayHandle)
+    ((CB_ADSPLib*)m_cb)->SoundPlay_ReleaseHandle(((AddonCB*)m_Handle)->addonData, m_PlayHandle);
+}
+
+void CAddonSoundPlay::Play()
+{
+  if (m_PlayHandle)
+    ((CB_ADSPLib*)m_cb)->SoundPlay_Play(((AddonCB*)m_Handle)->addonData, m_PlayHandle);
+}
+
+void CAddonSoundPlay::Stop()
+{
+  if (m_PlayHandle)
+    ((CB_ADSPLib*)m_cb)->SoundPlay_Stop(((AddonCB*)m_Handle)->addonData, m_PlayHandle);
+}
+
+bool CAddonSoundPlay::IsPlaying()
+{
+  if (!m_PlayHandle)
+    return false;
+
+  return ((CB_ADSPLib*)m_cb)->SoundPlay_IsPlaying(((AddonCB*)m_Handle)->addonData, m_PlayHandle);
+}
+
+void CAddonSoundPlay::SetChannel(AE_DSP_CHANNEL channel)
+{
+  if (m_PlayHandle)
+    ((CB_ADSPLib*)m_cb)->SoundPlay_SetChannel(((AddonCB*)m_Handle)->addonData, m_PlayHandle, channel);
+}
+
+AE_DSP_CHANNEL CAddonSoundPlay::GetChannel()
+{
+  if (!m_PlayHandle)
+    return AE_DSP_CH_INVALID;
+  return ((CB_ADSPLib*)m_cb)->SoundPlay_GetChannel(((AddonCB*)m_Handle)->addonData, m_PlayHandle);
+}
+
+void CAddonSoundPlay::SetVolume(float volume)
+{
+  if (m_PlayHandle)
+    ((CB_ADSPLib*)m_cb)->SoundPlay_SetVolume(((AddonCB*)m_Handle)->addonData, m_PlayHandle, volume);
+}
+
+float CAddonSoundPlay::GetVolume()
+{
+  if (!m_PlayHandle)
+    return 0.0f;
+
+  return ((CB_ADSPLib*)m_cb)->SoundPlay_GetVolume(((AddonCB*)m_Handle)->addonData, m_PlayHandle);
+}
+
 };
index d91087f..7c659c6 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdint.h>
 
 #include "../../addons/library.kodi.guilib/libKODI_guilib.h"
+#include "../../addons/library.kodi.adsp/libKODI_adsp.h"
 #include "cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h"
 #include "addons/include/kodi_adsp_types.h"
 #include "addons/include/xbmc_pvr_types.h"
@@ -368,6 +369,16 @@ typedef void (*ADSPRemoveMenuHook)(void *addonData, AE_DSP_MENUHOOK *hook);
 typedef void (*ADSPRegisterMode)(void *addonData, AE_DSP_MODES::AE_DSP_MODE *mode);
 typedef void (*ADSPUnregisterMode)(void *addonData, AE_DSP_MODES::AE_DSP_MODE *mode);
 
+typedef ADSPHANDLE (*ADSPSoundPlay_GetHandle)(void *addonData, const char *filename);
+typedef void (*ADSPSoundPlay_ReleaseHandle)(void *addonData, ADSPHANDLE handle);
+typedef void (*ADSPSoundPlay_Play)(void *addonData, ADSPHANDLE handle);
+typedef void (*ADSPSoundPlay_Stop)(void *addonData, ADSPHANDLE handle);
+typedef bool (*ADSPSoundPlay_IsPlaying)(void *addonData, ADSPHANDLE handle);
+typedef void (*ADSPSoundPlay_SetChannel)(void *addonData, ADSPHANDLE handle, AE_DSP_CHANNEL channel);
+typedef AE_DSP_CHANNEL (*ADSPSoundPlay_GetChannel)(void *addonData, ADSPHANDLE handle);
+typedef void (*ADSPSoundPlay_SetVolume)(void *addonData, ADSPHANDLE handle, float volume);
+typedef float (*ADSPSoundPlay_GetVolume)(void *addonData, ADSPHANDLE handle);
+
 typedef struct CB_ADSPLib
 {
   ADSPAddMenuHook               AddMenuHook;
@@ -375,6 +386,15 @@ typedef struct CB_ADSPLib
   ADSPRegisterMode              RegisterMode;
   ADSPUnregisterMode            UnregisterMode;
 
+  ADSPSoundPlay_GetHandle       SoundPlay_GetHandle;
+  ADSPSoundPlay_ReleaseHandle   SoundPlay_ReleaseHandle;
+  ADSPSoundPlay_Play            SoundPlay_Play;
+  ADSPSoundPlay_Stop            SoundPlay_Stop;
+  ADSPSoundPlay_IsPlaying       SoundPlay_IsPlaying;
+  ADSPSoundPlay_SetChannel      SoundPlay_SetChannel;
+  ADSPSoundPlay_GetChannel      SoundPlay_GetChannel;
+  ADSPSoundPlay_SetVolume       SoundPlay_SetVolume;
+  ADSPSoundPlay_GetVolume       SoundPlay_GetVolume;
 } CB_ADSPLib;
 
 typedef void (*PVRTransferEpgEntry)(void *userData, const ADDON_HANDLE handle, const EPG_TAG *epgentry);
index abd2b38..2087f67 100644 (file)
@@ -43,6 +43,16 @@ CAddonCallbacksADSP::CAddonCallbacksADSP(CAddon* addon)
   m_callbacks->RemoveMenuHook             = ADSPRemoveMenuHook;
   m_callbacks->RegisterMode               = ADSPRegisterMode;
   m_callbacks->UnregisterMode             = ADSPUnregisterMode;
+
+  m_callbacks->SoundPlay_GetHandle        = ADSPSoundPlay_GetHandle;
+  m_callbacks->SoundPlay_ReleaseHandle    = ADSPSoundPlay_ReleaseHandle;
+  m_callbacks->SoundPlay_Play             = ADSPSoundPlay_Play;
+  m_callbacks->SoundPlay_Stop             = ADSPSoundPlay_Stop;
+  m_callbacks->SoundPlay_IsPlaying        = ADSPSoundPlay_IsPlaying;
+  m_callbacks->SoundPlay_SetChannel       = ADSPSoundPlay_SetChannel;
+  m_callbacks->SoundPlay_GetChannel       = ADSPSoundPlay_GetChannel;
+  m_callbacks->SoundPlay_SetVolume        = ADSPSoundPlay_SetVolume;
+  m_callbacks->SoundPlay_GetVolume        = ADSPSoundPlay_GetVolume;
 }
 
 CAddonCallbacksADSP::~CAddonCallbacksADSP()
@@ -147,4 +157,116 @@ void CAddonCallbacksADSP::ADSPUnregisterMode(void* addonData, AE_DSP_MODES::AE_D
   transferMode.Delete();
 }
 
+ADSPHANDLE CAddonCallbacksADSP::ADSPSoundPlay_GetHandle(void *addonData, const char *filename)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!filename || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return NULL;
+  }
+
+  IAESound *sound = CAEFactory::MakeSound(filename);
+  if (!sound)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - failed to make sound play data", __FUNCTION__);
+    return NULL;
+  }
+
+  return sound;
+}
+
+void CAddonCallbacksADSP::ADSPSoundPlay_ReleaseHandle(void *addonData, ADSPHANDLE handle)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return;
+  }
+
+  CAEFactory::FreeSound((IAESound*)handle);
+}
+
+void CAddonCallbacksADSP::ADSPSoundPlay_Play(void *addonData, ADSPHANDLE handle)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return;
+  }
+  ((IAESound*)handle)->Play();
+}
+
+void CAddonCallbacksADSP::ADSPSoundPlay_Stop(void *addonData, ADSPHANDLE handle)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return;
+  }
+  ((IAESound*)handle)->Stop();
+}
+
+bool CAddonCallbacksADSP::ADSPSoundPlay_IsPlaying(void *addonData, ADSPHANDLE handle)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return false;
+  }
+  return ((IAESound*)handle)->IsPlaying();
+}
+
+void CAddonCallbacksADSP::ADSPSoundPlay_SetChannel(void *addonData, ADSPHANDLE handle, AE_DSP_CHANNEL channel)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return;
+  }
+
+  ((IAESound*)handle)->SetChannel(CActiveAEDSP::GetKODIChannel(channel));
+}
+
+AE_DSP_CHANNEL CAddonCallbacksADSP::ADSPSoundPlay_GetChannel(void *addonData, ADSPHANDLE handle)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return AE_DSP_CH_INVALID;
+  }
+
+  return CActiveAEDSP::GetDSPChannel(((IAESound*)handle)->GetChannel());
+}
+
+void CAddonCallbacksADSP::ADSPSoundPlay_SetVolume(void *addonData, ADSPHANDLE handle, float volume)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return;
+  }
+
+  ((IAESound*)handle)->SetVolume(volume);
+}
+
+float CAddonCallbacksADSP::ADSPSoundPlay_GetVolume(void *addonData, ADSPHANDLE handle)
+{
+  CActiveAEDSPAddon *addon = GetAudioDSPAddon(addonData);
+  if (!handle || !addon)
+  {
+    CLog::Log(LOGERROR, "Audio DSP - %s - invalid sound play data", __FUNCTION__);
+    return 0.0f;
+  }
+
+  return ((IAESound*)handle)->GetVolume();
+}
+
 }; /* namespace ADDON */
index 7c95159..6a48f60 100644 (file)
@@ -73,6 +73,78 @@ public:
    */
   static void ADSPUnregisterMode(void* addonData, AE_DSP_MODES::AE_DSP_MODE* mode);
 
+  /*! @name KODI background sound play handling */
+  //@{
+  /*!
+   * @brief Get a handle to open a gui sound wave playback
+   * @param addonData A pointer to the add-on.
+   * @param filename the related wave file to open
+   * @return pointer to sound play handle
+   */
+  static ADSPHANDLE ADSPSoundPlay_GetHandle(void *addonData, const char *filename);
+
+  /*!
+   * @brief Release the selected handle on KODI
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   */
+  static void ADSPSoundPlay_ReleaseHandle(void *addonData, ADSPHANDLE handle);
+
+  /*!
+   * @brief Start the wave file playback
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   */
+  static void ADSPSoundPlay_Play(void *addonData, ADSPHANDLE handle);
+
+  /*!
+   * @brief Stop the wave file playback
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   */
+  static void ADSPSoundPlay_Stop(void *addonData, ADSPHANDLE handle);
+
+  /*!
+   * @brief Ask that the playback of wave is in progress
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   * @return true if playing
+   */
+  static bool ADSPSoundPlay_IsPlaying(void *addonData, ADSPHANDLE handle);
+
+  /*!
+   * @brief Set the optional playback channel position, if not used it is on all channels
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   * @param used channel pointer for the playback, AE_DSP_CH_INVALID for on all
+   */
+  static void ADSPSoundPlay_SetChannel(void *addonData, ADSPHANDLE handle, AE_DSP_CHANNEL channel);
+
+  /*!
+   * @brief Get the selected playback channel position
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   * @return the used channel pointer for the playback, AE_DSP_CH_INVALID for on all
+   */
+  static AE_DSP_CHANNEL ADSPSoundPlay_GetChannel(void *addonData, ADSPHANDLE handle);
+
+  /*!
+   * @brief Set the volume for the wave file playback
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   * @param volume for the file playback
+   */
+  static void ADSPSoundPlay_SetVolume(void *addonData, ADSPHANDLE handle, float volume);
+
+  /*!
+   * @brief Get the volume which is set for the playback
+   * @param addonData A pointer to the add-on.
+   * @param handle pointer to sound play handle
+   * @return current volume for the file playback
+   */
+  static float ADSPSoundPlay_GetVolume(void *addonData, ADSPHANDLE handle);
+  //@}
+
 private:
   static ActiveAE::CActiveAEDSPAddon* GetAudioDSPAddon(void* addonData);
 
index 4a02067..b5b6ed1 100644 (file)
@@ -177,6 +177,7 @@ CActiveAE::CActiveAE() :
   m_audioCallback = NULL;
   m_vizInitialized = false;
   m_sinkHasVolume = false;
+  m_aeGUISoundForce = false;
   m_stats.Reset(44100);
 }
 
@@ -548,11 +549,15 @@ void CActiveAE::StateMachine(int signal, Protocol *port, Message *msg)
         case CActiveAEDataProtocol::PLAYSOUND:
           CActiveAESound *sound;
           sound = *(CActiveAESound**)msg->data;
-          if (m_settings.guisoundmode == AE_SOUND_OFF ||
-             (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty()))
-            return;
           if (sound)
           {
+            m_aeGUISoundForce = m_settings.dspaddonsenabled && sound->GetChannel() != AE_CH_NULL;
+
+            if ((m_settings.guisoundmode == AE_SOUND_OFF ||
+                (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty())) &&
+                !m_aeGUISoundForce)
+              return;
+
             SoundState st = {sound, 0};
             m_sounds_playing.push_back(st);
             m_extTimeout = 0;
@@ -1200,7 +1205,8 @@ void CActiveAE::Configure(AEAudioFormat *desiredFmt)
   if (!CompareFormat(oldInternalFormat, m_internalFormat))
   {
     if (m_settings.guisoundmode == AE_SOUND_ALWAYS ||
-       (m_settings.guisoundmode == AE_SOUND_IDLE && m_streams.empty()))
+       (m_settings.guisoundmode == AE_SOUND_IDLE && m_streams.empty()) ||
+       m_aeGUISoundForce)
     {
       std::vector<CActiveAESound*>::iterator it;
       for (it = m_sounds.begin(); it != m_sounds.end(); ++it)
@@ -1365,6 +1371,8 @@ void CActiveAE::SStopSound(CActiveAESound *sound)
   {
     if (it->sound == sound)
     {
+      if (sound->GetChannel() != AE_CH_NULL)
+        m_aeGUISoundForce = false;
       m_sounds_playing.erase(it);
       return;
     }
@@ -1389,7 +1397,6 @@ void CActiveAE::DiscardSound(CActiveAESound *sound)
 
 void CActiveAE::ChangeResamplers()
 {
-  
   std::list<CActiveAEStream*>::iterator it;
   for(it=m_streams.begin(); it!=m_streams.end(); ++it)
   {
@@ -2692,8 +2699,9 @@ void CActiveAE::StopSound(CActiveAESound *sound)
  */
 void CActiveAE::ResampleSounds()
 {
-  if (m_settings.guisoundmode == AE_SOUND_OFF ||
-     (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty()))
+  if ((m_settings.guisoundmode == AE_SOUND_OFF ||
+      (m_settings.guisoundmode == AE_SOUND_IDLE && !m_streams.empty())) &&
+      !m_aeGUISoundForce)
     return;
 
   std::vector<CActiveAESound*>::iterator it;
@@ -2729,6 +2737,21 @@ bool CActiveAE::ResampleSound(CActiveAESound *sound)
   dst_config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_internalFormat.m_dataFormat);
   dst_config.dither_bits = CAEUtil::DataFormatToDitherBits(m_internalFormat.m_dataFormat);
 
+  AEChannel testChannel = sound->GetChannel();
+  CAEChannelInfo outChannels;
+  if (sound->GetSound(true)->config.channels == 1 && testChannel != AE_CH_NULL)
+  {
+    for (unsigned int out=0; out < m_internalFormat.m_channelLayout.Count(); out++)
+    {
+      if (m_internalFormat.m_channelLayout[out] == AE_CH_FC && testChannel != AE_CH_FC) /// To become center clear on position test ??????
+        outChannels += AE_CH_FL;
+      else if (m_internalFormat.m_channelLayout[out] == testChannel)
+        outChannels += AE_CH_FC;
+      else
+        outChannels += m_internalFormat.m_channelLayout[out];
+    }
+  }
+
   IAEResample *resampler = CAEResampleFactory::Create(AERESAMPLEFACTORY_QUICK_RESAMPLE);
   resampler->Init(dst_config.channel_layout,
                   dst_config.channels,
@@ -2744,7 +2767,7 @@ bool CActiveAE::ResampleSound(CActiveAESound *sound)
                   orig_config.dither_bits,
                   false,
                   true,
-                  NULL,
+                  outChannels.Count() > 0 ? &outChannels : NULL,
                   m_settings.resampleQuality,
                   false);
 
index 8b999cd..850ba2e 100644 (file)
@@ -361,5 +361,6 @@ protected:
   // polled via the interface
   float m_aeVolume;
   bool m_aeMuted;
+  bool m_aeGUISoundForce;
 };
 };
index 7ef03e3..50073e7 100644 (file)
@@ -38,7 +38,8 @@ using namespace XFILE;
 CActiveAESound::CActiveAESound(const std::string &filename) :
   IAESound         (filename),
   m_filename       (filename),
-  m_volume         (1.0f    )
+  m_volume         (1.0f    ),
+  m_channel        (AE_CH_NULL)
 {
   m_orig_sound = NULL;
   m_dst_sound = NULL;
index 5d6c72d..0022151 100644 (file)
@@ -37,6 +37,8 @@ public:
   virtual void Stop();
   virtual bool IsPlaying();
 
+  virtual void SetChannel(AEChannel channel) { m_channel = channel; }
+  virtual AEChannel GetChannel() { return m_channel; }
   virtual void SetVolume(float volume) { m_volume = std::max(0.0f, std::min(1.0f, volume)); }
   virtual float GetVolume() { return m_volume; }
 
@@ -62,6 +64,7 @@ protected:
   bool m_isSeekPossible;
   int m_fileSize;
   float m_volume;
+  AEChannel m_channel;
 
   CSoundPacket *m_orig_sound;
   CSoundPacket *m_dst_sound;
index e20b77d..01853e0 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <string>
+#include "cores/AudioEngine/Utils/AEAudioFormat.h"
 
 class IAESound
 {
@@ -38,6 +39,12 @@ public:
   /* return true if the sound is currently playing */
   virtual bool IsPlaying() = 0;
 
+  /* set the playback channel of this sound, AE_CH_NULL for all */
+  virtual void SetChannel(AEChannel channel) = 0;
+
+  /* get the current playback channel of this sound, AE_CH_NULL for all */
+  virtual AEChannel GetChannel() = 0;
+
   /* set the playback volume of this sound */
   virtual void SetVolume(float volume) = 0;