diff options
author | Björn Stenberg <bjorn@haxx.se> | 2011-03-14 12:25:48 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2011-03-14 12:25:48 +0000 |
commit | e50cc0e3d760d4fdb99f971070a6943ee15a9a98 (patch) | |
tree | 9d22cde7d39a2aefbc75cd970916fbc161f53cac | |
parent | 606bed035ed898df1d1bf4a8c7be904f76b118ff (diff) | |
download | rockbox-e50cc0e3d760d4fdb99f971070a6943ee15a9a98.tar.gz rockbox-e50cc0e3d760d4fdb99f971070a6943ee15a9a98.zip |
Listen to and follow external Android volume changes. (Based on FS#11914 by Maurus Cuelenaere)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29586 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | android/src/org/rockbox/RockboxPCM.java | 52 | ||||
-rw-r--r-- | apps/misc.c | 9 | ||||
-rw-r--r-- | apps/playback.c | 2 | ||||
-rw-r--r-- | apps/settings.c | 2 | ||||
-rw-r--r-- | firmware/export/config/android.h | 3 | ||||
-rw-r--r-- | firmware/export/kernel.h | 1 | ||||
-rw-r--r-- | firmware/export/system.h | 4 | ||||
-rw-r--r-- | firmware/target/hosted/android/pcm-android.c | 25 |
8 files changed, 95 insertions, 3 deletions
diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java index 5a8354abee..7d01da6150 100644 --- a/android/src/org/rockbox/RockboxPCM.java +++ b/android/src/org/rockbox/RockboxPCM.java | |||
@@ -23,8 +23,10 @@ package org.rockbox; | |||
23 | 23 | ||
24 | import java.util.Arrays; | 24 | import java.util.Arrays; |
25 | 25 | ||
26 | import android.content.BroadcastReceiver; | ||
26 | import android.content.Context; | 27 | import android.content.Context; |
27 | import android.content.Intent; | 28 | import android.content.Intent; |
29 | import android.content.IntentFilter; | ||
28 | import android.media.AudioFormat; | 30 | import android.media.AudioFormat; |
29 | import android.media.AudioManager; | 31 | import android.media.AudioManager; |
30 | import android.media.AudioTrack; | 32 | import android.media.AudioTrack; |
@@ -52,8 +54,10 @@ public class RockboxPCM extends AudioTrack | |||
52 | 54 | ||
53 | private AudioManager audiomanager; | 55 | private AudioManager audiomanager; |
54 | private int maxstreamvolume; | 56 | private int maxstreamvolume; |
57 | private int setstreamvolume = -1; | ||
55 | private float minpcmvolume; | 58 | private float minpcmvolume; |
56 | private float pcmrange; | 59 | private float pcmrange; |
60 | private RockboxService rbservice; | ||
57 | 61 | ||
58 | private void LOG(CharSequence text) | 62 | private void LOG(CharSequence text) |
59 | { | 63 | { |
@@ -72,15 +76,55 @@ public class RockboxPCM extends AudioTrack | |||
72 | l = new PCMListener(buf_len); | 76 | l = new PCMListener(buf_len); |
73 | 77 | ||
74 | /* find cleaner way to get context? */ | 78 | /* find cleaner way to get context? */ |
75 | final RockboxService rb = RockboxService.get_instance(); | 79 | rbservice = RockboxService.get_instance(); |
76 | audiomanager = | 80 | audiomanager = |
77 | (AudioManager) rb.getSystemService(Context.AUDIO_SERVICE); | 81 | (AudioManager) rbservice.getSystemService(Context.AUDIO_SERVICE); |
78 | maxstreamvolume = audiomanager.getStreamMaxVolume(streamtype); | 82 | maxstreamvolume = audiomanager.getStreamMaxVolume(streamtype); |
79 | 83 | ||
80 | minpcmvolume = getMinVolume(); | 84 | minpcmvolume = getMinVolume(); |
81 | pcmrange = getMaxVolume() - minpcmvolume; | 85 | pcmrange = getMaxVolume() - minpcmvolume; |
86 | |||
87 | setupVolumeHandler(); | ||
82 | } | 88 | } |
83 | 89 | ||
90 | private native void postVolumeChangedEvent(int volume); | ||
91 | private void setupVolumeHandler() | ||
92 | { | ||
93 | BroadcastReceiver broadcastReceiver = new BroadcastReceiver() | ||
94 | { | ||
95 | @Override | ||
96 | public void onReceive(Context context, Intent intent) | ||
97 | { | ||
98 | int streamType = intent.getIntExtra( | ||
99 | "android.media.EXTRA_VOLUME_STREAM_TYPE", -1); | ||
100 | int volume = intent.getIntExtra( | ||
101 | "android.media.EXTRA_VOLUME_STREAM_VALUE", -1); | ||
102 | |||
103 | if (streamType == RockboxPCM.streamtype && | ||
104 | volume != -1 && | ||
105 | volume != setstreamvolume && | ||
106 | rbservice.isRockboxRunning()) | ||
107 | { | ||
108 | int rbvolume = ((maxstreamvolume - volume) * -99) / | ||
109 | maxstreamvolume; | ||
110 | postVolumeChangedEvent(rbvolume); | ||
111 | } | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | /* at startup, change the internal rockbox volume to what the global | ||
116 | android music stream volume is */ | ||
117 | int volume = audiomanager.getStreamVolume(streamtype); | ||
118 | int rbvolume = ((maxstreamvolume - volume) * -99) / maxstreamvolume; | ||
119 | postVolumeChangedEvent(rbvolume); | ||
120 | |||
121 | /* We're relying on internal API's here, | ||
122 | this can break in the future! */ | ||
123 | rbservice.registerReceiver( | ||
124 | broadcastReceiver, | ||
125 | new IntentFilter("android.media.VOLUME_CHANGED_ACTION")); | ||
126 | } | ||
127 | |||
84 | private int bytes2frames(int bytes) | 128 | private int bytes2frames(int bytes) |
85 | { | 129 | { |
86 | /* 1 sample is 2 bytes, 2 samples are 1 frame */ | 130 | /* 1 sample is 2 bytes, 2 samples are 1 frame */ |
@@ -164,8 +208,10 @@ public class RockboxPCM extends AudioTrack | |||
164 | } | 208 | } |
165 | 209 | ||
166 | int oldstreamvolume = audiomanager.getStreamVolume(streamtype); | 210 | int oldstreamvolume = audiomanager.getStreamVolume(streamtype); |
167 | if (streamvolume != oldstreamvolume) | 211 | if (streamvolume != oldstreamvolume) { |
212 | setstreamvolume = streamvolume; | ||
168 | audiomanager.setStreamVolume(streamtype, streamvolume, 0); | 213 | audiomanager.setStreamVolume(streamtype, streamvolume, 0); |
214 | } | ||
169 | } | 215 | } |
170 | 216 | ||
171 | public native void pcmSamplesToByteArray(byte[] dest); | 217 | public native void pcmSamplesToByteArray(byte[] dest); |
diff --git a/apps/misc.c b/apps/misc.c index fa34c21f4e..995d65644e 100644 --- a/apps/misc.c +++ b/apps/misc.c | |||
@@ -636,6 +636,15 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame | |||
636 | resume = false; | 636 | resume = false; |
637 | return SYS_CALL_HUNG_UP; | 637 | return SYS_CALL_HUNG_UP; |
638 | #endif | 638 | #endif |
639 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) && defined(PLATFORM_HAS_VOLUME_CHANGE) | ||
640 | case SYS_VOLUME_CHANGED: | ||
641 | { | ||
642 | int volume = hosted_get_volume(); | ||
643 | if (global_settings.volume != volume) | ||
644 | global_settings.volume = volume; | ||
645 | return 0; | ||
646 | } | ||
647 | #endif | ||
639 | #ifdef HAVE_MULTIMEDIA_KEYS | 648 | #ifdef HAVE_MULTIMEDIA_KEYS |
640 | /* multimedia keys on keyboards, headsets */ | 649 | /* multimedia keys on keyboards, headsets */ |
641 | case BUTTON_MULTIMEDIA_PLAYPAUSE: | 650 | case BUTTON_MULTIMEDIA_PLAYPAUSE: |
diff --git a/apps/playback.c b/apps/playback.c index b72ed8a3b8..fb79c4d382 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -1834,7 +1834,9 @@ static void audio_play_start(size_t offset) | |||
1834 | ci.seek_time = 0; | 1834 | ci.seek_time = 0; |
1835 | wps_offset = 0; | 1835 | wps_offset = 0; |
1836 | 1836 | ||
1837 | #ifndef PLAFORM_HAS_VOLUME_CHANGE | ||
1837 | sound_set_volume(global_settings.volume); | 1838 | sound_set_volume(global_settings.volume); |
1839 | #endif | ||
1838 | track_widx = track_ridx = 0; | 1840 | track_widx = track_ridx = 0; |
1839 | buf_set_base_handle(-1); | 1841 | buf_set_base_handle(-1); |
1840 | 1842 | ||
diff --git a/apps/settings.c b/apps/settings.c index e9458dc601..623bc5b2a0 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -726,7 +726,9 @@ void sound_settings_apply(void) | |||
726 | sound_set(SOUND_TREBLE, global_settings.treble); | 726 | sound_set(SOUND_TREBLE, global_settings.treble); |
727 | #endif | 727 | #endif |
728 | sound_set(SOUND_BALANCE, global_settings.balance); | 728 | sound_set(SOUND_BALANCE, global_settings.balance); |
729 | #ifndef PLATFORM_HAS_VOLUME_CHANGE | ||
729 | sound_set(SOUND_VOLUME, global_settings.volume); | 730 | sound_set(SOUND_VOLUME, global_settings.volume); |
731 | #endif | ||
730 | sound_set(SOUND_CHANNELS, global_settings.channel_config); | 732 | sound_set(SOUND_CHANNELS, global_settings.channel_config); |
731 | sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width); | 733 | sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width); |
732 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) | 734 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) |
diff --git a/firmware/export/config/android.h b/firmware/export/config/android.h index ed1a283c7d..69a758d69b 100644 --- a/firmware/export/config/android.h +++ b/firmware/export/config/android.h | |||
@@ -79,6 +79,9 @@ | |||
79 | /* define this if the target has volume keys which can be used in the lists */ | 79 | /* define this if the target has volume keys which can be used in the lists */ |
80 | #define HAVE_VOLUME_IN_LIST | 80 | #define HAVE_VOLUME_IN_LIST |
81 | 81 | ||
82 | /* define this if the host platform can change volume outside of rockbox */ | ||
83 | #define PLATFORM_HAS_VOLUME_CHANGE | ||
84 | |||
82 | #define HAVE_SW_TONE_CONTROLS | 85 | #define HAVE_SW_TONE_CONTROLS |
83 | 86 | ||
84 | /* Define current usage levels. */ | 87 | /* Define current usage levels. */ |
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 6aaf11ddb9..66efce33f6 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h | |||
@@ -83,6 +83,7 @@ | |||
83 | #define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2) | 83 | #define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2) |
84 | #define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3) | 84 | #define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3) |
85 | #define SYS_CALL_HUNG_UP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 4) | 85 | #define SYS_CALL_HUNG_UP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 4) |
86 | #define SYS_VOLUME_CHANGED MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 5) | ||
86 | 87 | ||
87 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) | 88 | #define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT) |
88 | 89 | ||
diff --git a/firmware/export/system.h b/firmware/export/system.h index 78bddae387..3f626c3688 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h | |||
@@ -137,6 +137,10 @@ int get_cpu_boost_counter(void); | |||
137 | #undef htobe32 | 137 | #undef htobe32 |
138 | #endif | 138 | #endif |
139 | 139 | ||
140 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) && defined(PLATFORM_HAS_VOLUME_CHANGE) | ||
141 | int hosted_get_volume(void); | ||
142 | #endif | ||
143 | |||
140 | /* Get the byte offset of a type's member */ | 144 | /* Get the byte offset of a type's member */ |
141 | #define OFFSETOF(type, membername) ((off_t)&((type *)0)->membername) | 145 | #define OFFSETOF(type, membername) ((off_t)&((type *)0)->membername) |
142 | 146 | ||
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c index 4c34e3cd91..24881bd3df 100644 --- a/firmware/target/hosted/android/pcm-android.c +++ b/firmware/target/hosted/android/pcm-android.c | |||
@@ -179,3 +179,28 @@ void pcm_set_mixer_volume(int volume) | |||
179 | 179 | ||
180 | (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume); | 180 | (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume); |
181 | } | 181 | } |
182 | |||
183 | /* Due to limitations of default_event_handler(), parameters gets swallowed when | ||
184 | * being posted with queue_broadcast(), so workaround this by caching the last | ||
185 | * value. | ||
186 | */ | ||
187 | static int lastPostedVolume = -1; | ||
188 | int hosted_get_volume(void) | ||
189 | { | ||
190 | return lastPostedVolume; | ||
191 | } | ||
192 | |||
193 | JNIEXPORT void JNICALL | ||
194 | Java_org_rockbox_RockboxPCM_postVolumeChangedEvent(JNIEnv *env, | ||
195 | jobject this, | ||
196 | jint volume) | ||
197 | { | ||
198 | (void) env; | ||
199 | (void) this; | ||
200 | |||
201 | if (volume != lastPostedVolume) | ||
202 | { | ||
203 | lastPostedVolume = volume; | ||
204 | queue_broadcast(SYS_VOLUME_CHANGED, 0); | ||
205 | } | ||
206 | } | ||