Skip to content
This repository
Browse code

Merge pull request #2098 from mcrosson/android-feature-auto-adjust-vo…

…lume

[droid] Native volume control
  • Loading branch information...
commit c45b7fe384494db51f300a3280b8b01de6f163a1 2 parents 16a5abd + 3967e18
jmarshallnz authored
12  xbmc/Application.cpp
@@ -335,6 +335,10 @@
335 335
 #include "input/SDLJoystick.h"
336 336
 #endif
337 337
 
  338
+#if defined(TARGET_ANDROID)
  339
+#include "android/activity/XBMCApp.h"
  340
+#endif
  341
+
338 342
 using namespace std;
339 343
 using namespace ADDON;
340 344
 using namespace XFILE;
@@ -2859,15 +2863,19 @@ bool CApplication::OnAction(const CAction &action)
2859 2863
       if (g_settings.m_bMute)
2860 2864
         UnMute();
2861 2865
       float volume = g_settings.m_fVolumeLevel;
  2866
+// Android has steps based on the max available volume level
  2867
+#if defined(TARGET_ANDROID)
  2868
+      float step = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / CXBMCApp::GetMaxSystemVolume();
  2869
+#else
2862 2870
       float step   = (VOLUME_MAXIMUM - VOLUME_MINIMUM) / VOLUME_CONTROL_STEPS;
  2871
+
2863 2872
       if (action.GetRepeat())
2864 2873
         step *= action.GetRepeat() * 50; // 50 fps
2865  
-
  2874
+#endif
2866 2875
       if (action.GetID() == ACTION_VOLUME_UP)
2867 2876
         volume += (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2868 2877
       else
2869 2878
         volume -= (float)fabs(action.GetAmount()) * action.GetAmount() * step;
2870  
-
2871 2879
       SetVolume(volume, false);
2872 2880
     }
2873 2881
     // show visual feedback of volume change...
69  xbmc/android/activity/XBMCApp.cpp
@@ -127,7 +127,6 @@ ActivityResult CXBMCApp::onActivate()
127 127
     default:
128 128
       break;
129 129
   }
130  
-  
131 130
   return ActivityOK;
132 131
 }
133 132
 
@@ -975,3 +974,71 @@ bool CXBMCApp::GetStorageUsage(const std::string &path, std::string &usage)
975 974
   usage = fmt.str();
976 975
   return true;
977 976
 }
  977
+
  978
+// Used in Application.cpp to figure out volume steps
  979
+int CXBMCApp::GetMaxSystemVolume()
  980
+{
  981
+  static int maxVolume = -1;
  982
+  if (maxVolume == -1)
  983
+  {
  984
+    JNIEnv *env = NULL;
  985
+    AttachCurrentThread(&env);
  986
+    maxVolume = GetMaxSystemVolume(env);
  987
+    DetachCurrentThread();
  988
+  }
  989
+  return maxVolume;
  990
+}
  991
+
  992
+int CXBMCApp::GetMaxSystemVolume(JNIEnv *env)
  993
+{
  994
+  jobject oActivity = m_activity->clazz;
  995
+  jclass cActivity = env->GetObjectClass(oActivity);
  996
+
  997
+  // Get Audio manager
  998
+  //  (AudioManager)getSystemService(Context.AUDIO_SERVICE)
  999
+  jmethodID mgetSystemService = env->GetMethodID(cActivity, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
  1000
+  jstring sAudioService = env->NewStringUTF("audio");
  1001
+  jobject oAudioManager = env->CallObjectMethod(oActivity, mgetSystemService, sAudioService);
  1002
+  env->DeleteLocalRef(sAudioService);
  1003
+  env->DeleteLocalRef(cActivity);
  1004
+
  1005
+  // Get max volume
  1006
+  //  int max_volume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
  1007
+  jclass cAudioManager = env->GetObjectClass(oAudioManager);
  1008
+  jmethodID mgetStreamMaxVolume = env->GetMethodID(cAudioManager, "getStreamMaxVolume", "(I)I");
  1009
+  jfieldID fstreamMusic = env->GetStaticFieldID(cAudioManager, "STREAM_MUSIC", "I");
  1010
+  jint stream_music = env->GetStaticIntField(cAudioManager, fstreamMusic);
  1011
+  int maxVolume = (int)env->CallObjectMethod(oAudioManager, mgetStreamMaxVolume, stream_music); // AudioManager.STREAM_MUSIC
  1012
+
  1013
+  env->DeleteLocalRef(oAudioManager);
  1014
+  env->DeleteLocalRef(cAudioManager);
  1015
+
  1016
+  return maxVolume;
  1017
+}
  1018
+
  1019
+void CXBMCApp::SetSystemVolume(JNIEnv *env, float percent)
  1020
+{
  1021
+  CLog::Log(LOGDEBUG, "CXBMCApp::SetSystemVolume: %f", percent);
  1022
+
  1023
+  jobject oActivity = m_activity->clazz;
  1024
+  jclass cActivity = env->GetObjectClass(oActivity);
  1025
+
  1026
+  // Get Audio manager
  1027
+  //  (AudioManager)getSystemService(Context.AUDIO_SERVICE)
  1028
+  jmethodID mgetSystemService = env->GetMethodID(cActivity, "getSystemService","(Ljava/lang/String;)Ljava/lang/Object;");
  1029
+  jstring sAudioService = env->NewStringUTF("audio");
  1030
+  jobject oAudioManager = env->CallObjectMethod(oActivity, mgetSystemService, sAudioService);
  1031
+  jclass cAudioManager = env->GetObjectClass(oAudioManager);
  1032
+  env->DeleteLocalRef(sAudioService);
  1033
+  env->DeleteLocalRef(cActivity);
  1034
+
  1035
+  // Set volume
  1036
+  //   mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, max_volume, 0);
  1037
+  jfieldID fstreamMusic = env->GetStaticFieldID(cAudioManager, "STREAM_MUSIC", "I");
  1038
+  jint stream_music = env->GetStaticIntField(cAudioManager, fstreamMusic);
  1039
+  jmethodID msetStreamVolume = env->GetMethodID(cAudioManager, "setStreamVolume", "(III)V");
  1040
+  env->CallObjectMethod(oAudioManager, msetStreamVolume, stream_music, int(GetMaxSystemVolume(env)*percent), 0);
  1041
+  env->DeleteLocalRef(oAudioManager);
  1042
+  env->DeleteLocalRef(cAudioManager);
  1043
+}
  1044
+
6  xbmc/android/activity/XBMCApp.h
@@ -87,6 +87,7 @@ class CXBMCApp : public IActivityHandler
87 87
   static bool ListApplications(std::vector <androidPackage> *applications);
88 88
   static bool GetIconSize(const std::string &packageName, int *width, int *height);
89 89
   static bool GetIcon(const std::string &packageName, void* buffer, unsigned int bufSize); 
  90
+
90 91
   /*!
91 92
    * \brief If external storage is available, it returns the path for the external storage (for the specified type)
92 93
    * \param path will contain the path of the external storage (for the specified type)
@@ -95,6 +96,7 @@ class CXBMCApp : public IActivityHandler
95 96
    */
96 97
   static bool GetExternalStorage(std::string &path, const std::string &type = "");
97 98
   static bool GetStorageUsage(const std::string &path, std::string &usage);
  99
+  static int GetMaxSystemVolume();
98 100
 
99 101
   static int GetDPI();
100 102
 protected:
@@ -106,6 +108,9 @@ class CXBMCApp : public IActivityHandler
106 108
   static int AttachCurrentThread(JNIEnv** p_env, void* thr_args = NULL);
107 109
   static int DetachCurrentThread();
108 110
 
  111
+  static int GetMaxSystemVolume(JNIEnv *env);
  112
+  static void SetSystemVolume(JNIEnv *env, float percent);
  113
+
109 114
 private:
110 115
   static bool HasLaunchIntent(const std::string &package);
111 116
   bool getWakeLock(JNIEnv *env);
@@ -116,7 +121,6 @@ class CXBMCApp : public IActivityHandler
116 121
 
117 122
   static ANativeActivity *m_activity;
118 123
   jobject m_wakeLock;
119  
-  
120 124
   typedef enum {
121 125
     // XBMC_Initialize hasn't been executed yet
122 126
     Uninitialized,
10  xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
@@ -228,9 +228,11 @@ bool CAESinkAUDIOTRACK::HasVolume()
228 228
   return true;
229 229
 }
230 230
 
231  
-void  CAESinkAUDIOTRACK::SetVolume(float volume)
  231
+void  CAESinkAUDIOTRACK::SetVolume(float scale)
232 232
 {
233  
-  m_volume = volume;
  233
+  // Android uses fixed steps, reverse scale back to percent
  234
+  float gain = CAEUtil::ScaleToGain(scale);
  235
+  m_volume = CAEUtil::GainToPercent(gain);
234 236
   m_volume_changed = true;
235 237
 }
236 238
 
@@ -273,7 +275,6 @@ void CAESinkAUDIOTRACK::Process()
273 275
   jmethodID jmRelease           = jenv->GetMethodID(jcAudioTrack, "release", "()V");
274 276
   jmethodID jmWrite             = jenv->GetMethodID(jcAudioTrack, "write", "([BII)I");
275 277
   jmethodID jmPlayState         = jenv->GetMethodID(jcAudioTrack, "getPlayState", "()I");
276  
-  jmethodID jmSetStereoVolume   = jenv->GetMethodID(jcAudioTrack, "setStereoVolume", "(FF)I");
277 278
   jmethodID jmPlayHeadPosition  = jenv->GetMethodID(jcAudioTrack, "getPlaybackHeadPosition", "()I");
278 279
   jmethodID jmGetMinBufferSize  = jenv->GetStaticMethodID(jcAudioTrack, "getMinBufferSize", "(III)I");
279 280
 
@@ -322,8 +323,7 @@ void CAESinkAUDIOTRACK::Process()
322 323
     {
323 324
       // check of volume changes and make them,
324 325
       // do it here to keep jni calls local to this thread.
325  
-      jfloat jvolume = m_volume;
326  
-      jenv->CallIntMethod(joAudioTrack, jmSetStereoVolume, jvolume, jvolume);
  326
+      CXBMCApp::SetSystemVolume(jenv, m_volume);
327 327
       m_volume_changed = false;
328 328
     }
329 329
     if (m_draining)
2  xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h
@@ -42,7 +42,7 @@ class CAESinkAUDIOTRACK : public CThread, public IAESink
42 42
   virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
43 43
   virtual void         Drain           ();
44 44
   virtual bool         HasVolume       ();
45  
-  virtual void         SetVolume       (float volume);
  45
+  virtual void         SetVolume       (float scale);
46 46
   static void          EnumerateDevicesEx(AEDeviceInfoList &list);
47 47
 
48 48
 private:
24  xbmc/cores/AudioEngine/Utils/AEUtil.h
@@ -71,6 +71,19 @@ class CAEUtil
71 71
     return (value - 1)*db_range;
72 72
   }
73 73
 
  74
+  /*! \brief convert a dB gain to volume percentage (as a proportion)
  75
+   We assume a dB range of 60dB, i.e. assume that 0% volume corresponds
  76
+   to a reduction of 60dB.
  77
+   \param the corresponding gain in dB from -60dB .. 0dB.
  78
+   \return value the volume from 0..1
  79
+   \sa ScaleToGain
  80
+   */
  81
+  static inline const float GainToPercent(const float gain)
  82
+  {
  83
+    static const float db_range = 60.0f;
  84
+    return 1+(gain/db_range);
  85
+  }
  86
+
74 87
   /*! \brief convert a dB gain to a scale factor for audio manipulation
75 88
    Inverts gain = 20 log_10(scale)
76 89
    \param dB the gain in decibels.
@@ -82,6 +95,17 @@ class CAEUtil
82 95
     return pow(10.0f, dB/20);
83 96
   }
84 97
 
  98
+  /*! \brief convert a scale factor to dB gain for audio manipulation
  99
+   Inverts GainToScale result
  100
+   \param the scale factor (equivalent to a voltage multiplier).
  101
+   \return dB the gain in decibels.
  102
+   \sa GainToScale
  103
+   */
  104
+  static inline const float ScaleToGain(const float scale)
  105
+  {
  106
+    return 20*log10(scale);
  107
+  }
  108
+
85 109
   #ifdef __SSE__
86 110
   static void SSEMulArray     (float *data, const float mul, uint32_t count);
87 111
   static void SSEMulAddArray  (float *data, float *add, const float mul, uint32_t count);

0 notes on commit c45b7fe

Please sign in to comment.
Something went wrong with that request. Please try again.