diff options
Diffstat (limited to 'src')
11 files changed, 539 insertions, 229 deletions
diff --git a/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java index a55abfc0..5aee380f 100644 --- a/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java +++ b/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java @@ -511,7 +511,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity { private void showInfoDialog() {
if (!infoDialogDisplayed) {
infoDialogDisplayed = true;
- Log.i(TAG, Util.getRestUrl(this, null));
if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) {
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
}
diff --git a/src/github/daneren2005/dsub/audiofx/AudioEffectsController.java b/src/github/daneren2005/dsub/audiofx/AudioEffectsController.java new file mode 100644 index 00000000..f53a4dff --- /dev/null +++ b/src/github/daneren2005/dsub/audiofx/AudioEffectsController.java @@ -0,0 +1,82 @@ +/* + This file is part of Subsonic. + + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see <http://www.gnu.org/licenses/>. + + Copyright 2014 (C) Scott Jackson +*/ +package github.daneren2005.dsub.audiofx; + +import android.content.Context; +import android.media.MediaPlayer; +import android.media.audiofx.AudioEffect; +import android.media.audiofx.LoudnessEnhancer; +import android.os.Build; +import android.util.Log; + +public class AudioEffectsController { + private static final String TAG = AudioEffectsController.class.getSimpleName(); + + private final Context context; + private int audioSessionId = 0; + + private boolean available = false; + + private EqualizerController equalizerController; + private VisualizerController visualizerController; + + public AudioEffectsController(Context context, int audioSessionId) { + this.context = context; + this.audioSessionId = audioSessionId; + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + available = true; + } + } + + public boolean isAvailable() { + return available; + } + + public void release() { + if(equalizerController != null) { + equalizerController.release(); + } + if(visualizerController != null) { + visualizerController.release(); + } + } + + public EqualizerController getEqualizerController() { + if (available && equalizerController == null) { + equalizerController = new EqualizerController(context, audioSessionId); + if (!equalizerController.isAvailable()) { + equalizerController = null; + } else { + equalizerController.loadSettings(); + } + } + return equalizerController; + } + public VisualizerController getVisualizerController() { + if (available && visualizerController == null) { + visualizerController = new VisualizerController(context, audioSessionId); + if (!visualizerController.isAvailable()) { + visualizerController = null; + } + } + return visualizerController; + } +} + diff --git a/src/github/daneren2005/dsub/audiofx/EqualizerController.java b/src/github/daneren2005/dsub/audiofx/EqualizerController.java index 0e1c49b5..254f168d 100644 --- a/src/github/daneren2005/dsub/audiofx/EqualizerController.java +++ b/src/github/daneren2005/dsub/audiofx/EqualizerController.java @@ -21,8 +21,9 @@ package github.daneren2005.dsub.audiofx; import java.io.Serializable; import android.content.Context; -import android.media.MediaPlayer; +import android.media.audiofx.BassBoost; import android.media.audiofx.Equalizer; +import android.os.Build; import android.util.Log; import github.daneren2005.dsub.util.FileUtil; @@ -34,125 +35,170 @@ import github.daneren2005.dsub.util.FileUtil; */ public class EqualizerController { - private static final String TAG = EqualizerController.class.getSimpleName(); + private static final String TAG = EqualizerController.class.getSimpleName(); - private final Context context; - private Equalizer equalizer; + private final Context context; + private Equalizer equalizer; + private BassBoost bass; + private boolean loudnessAvailable = false; + private LoudnessEnhancerController loudnessEnhancerController; private boolean released = false; private int audioSessionId = 0; - // Class initialization fails when this throws an exception. - static { - try { - Class.forName("android.media.audiofx.Equalizer"); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - /** - * Throws an exception if the {@link Equalizer} class is not available. - */ - public static void checkAvailable() throws Throwable { - // Calling here forces class initialization. - } - - public EqualizerController(Context context, MediaPlayer mediaPlayer) { - this.context = context; - try { - audioSessionId = mediaPlayer.getAudioSessionId(); - equalizer = new Equalizer(0, audioSessionId); - } catch (Throwable x) { - Log.w(TAG, "Failed to create equalizer.", x); - } - } - - public void saveSettings() { - try { - if (isAvailable()) { - FileUtil.serialize(context, new EqualizerSettings(equalizer), "equalizer.dat"); - } - } catch (Throwable x) { - Log.w(TAG, "Failed to save equalizer settings.", x); - } - } - - public void loadSettings() { - try { - if (isAvailable()) { - EqualizerSettings settings = FileUtil.deserialize(context, "equalizer.dat", EqualizerSettings.class); - if (settings != null) { - settings.apply(equalizer); - } - } - } catch (Throwable x) { - Log.w(TAG, "Failed to load equalizer settings.", x); - } - } - - public boolean isAvailable() { - return equalizer != null; - } - - public boolean isEnabled() { - try { - return isAvailable() && equalizer.getEnabled(); - } catch(Exception e) { - return false; - } - } - - public void release() { - if (isAvailable()) { + public EqualizerController(Context context, int audioSessionId) { + this.context = context; + try { + this.audioSessionId = audioSessionId; + init(); + } catch (Throwable x) { + Log.w(TAG, "Failed to create equalizer.", x); + } + } + + private void init() { + equalizer = new Equalizer(0, audioSessionId); + bass = new BassBoost(0, audioSessionId); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + loudnessAvailable = true; + loudnessEnhancerController = new LoudnessEnhancerController(context, audioSessionId); + } + } + + public void saveSettings() { + try { + if (isAvailable()) { + FileUtil.serialize(context, new EqualizerSettings(equalizer, bass, loudnessEnhancerController), "equalizer.dat"); + } + } catch (Throwable x) { + Log.w(TAG, "Failed to save equalizer settings.", x); + } + } + + public void loadSettings() { + try { + if (isAvailable()) { + EqualizerSettings settings = FileUtil.deserialize(context, "equalizer.dat", EqualizerSettings.class); + if (settings != null) { + settings.apply(equalizer, bass, loudnessEnhancerController); + } + } + } catch (Throwable x) { + Log.w(TAG, "Failed to load equalizer settings.", x); + } + } + + public boolean isAvailable() { + return equalizer != null && bass != null; + } + + public boolean isEnabled() { + try { + return isAvailable() && equalizer.getEnabled(); + } catch(Exception e) { + return false; + } + } + + public void release() { + if (isAvailable()) { released = true; - equalizer.release(); - } - } + equalizer.release(); + bass.release(); + if(loudnessEnhancerController != null && loudnessEnhancerController.isAvailable()) { + loudnessEnhancerController.release(); + } + } + } - public Equalizer getEqualizer() { + public Equalizer getEqualizer() { if(released) { released = false; try { - equalizer = new Equalizer(0, audioSessionId); + init(); } catch (Throwable x) { equalizer = null; Log.w(TAG, "Failed to create equalizer.", x); } } - return equalizer; - } + return equalizer; + } + public BassBoost getBassBoost() { + if(released) { + released = false; + try { + init(); + } catch (Throwable x) { + bass = null; + Log.w(TAG, "Failed to create bass booster.", x); + } + } + return bass; + } + public LoudnessEnhancerController getLoudnessEnhancerController() { + if(loudnessAvailable && released) { + released = false; + try { + init(); + } catch (Throwable x) { + loudnessEnhancerController = null; + Log.w(TAG, "Failed to create loudness enhancer.", x); + } + } + return loudnessEnhancerController; + } - private static class EqualizerSettings implements Serializable { + private static class EqualizerSettings implements Serializable { - private short[] bandLevels; - private short preset; - private boolean enabled; + private short[] bandLevels; + private short preset; + private boolean enabled; + private short bass; + private int loudness; public EqualizerSettings() { } - public EqualizerSettings(Equalizer equalizer) { - enabled = equalizer.getEnabled(); - bandLevels = new short[equalizer.getNumberOfBands()]; - for (short i = 0; i < equalizer.getNumberOfBands(); i++) { - bandLevels[i] = equalizer.getBandLevel(i); - } - try { - preset = equalizer.getCurrentPreset(); - } catch (Exception x) { - preset = -1; - } - } - - public void apply(Equalizer equalizer) { - for (short i = 0; i < bandLevels.length; i++) { - equalizer.setBandLevel(i, bandLevels[i]); - } - if (preset >= 0 && preset < equalizer.getNumberOfPresets()) { - equalizer.usePreset(preset); - } - equalizer.setEnabled(enabled); - } - } + public EqualizerSettings(Equalizer equalizer, BassBoost boost, LoudnessEnhancerController loudnessEnhancerController) { + enabled = equalizer.getEnabled(); + bandLevels = new short[equalizer.getNumberOfBands()]; + for (short i = 0; i < equalizer.getNumberOfBands(); i++) { + bandLevels[i] = equalizer.getBandLevel(i); + } + try { + preset = equalizer.getCurrentPreset(); + } catch (Exception x) { + preset = -1; + } + try { + bass = boost.getRoundedStrength(); + } catch(Exception e) { + bass = 0; + } + + try { + loudness = (int) loudnessEnhancerController.getGain(); + } catch(Exception e) { + loudness = 0; + } + } + + public void apply(Equalizer equalizer, BassBoost boost, LoudnessEnhancerController loudnessController) { + for (short i = 0; i < bandLevels.length; i++) { + equalizer.setBandLevel(i, bandLevels[i]); + } + if (preset >= 0 && preset < equalizer.getNumberOfPresets()) { + equalizer.usePreset(preset); + } + equalizer.setEnabled(enabled); + if(bass != 0) { + boost.setEnabled(true); + boost.setStrength(bass); + } + if(loudness != 0) { + loudnessController.enable(); + loudnessController.setGain(loudness); + } + } + } } diff --git a/src/github/daneren2005/dsub/audiofx/LoudnessEnhancerController.java b/src/github/daneren2005/dsub/audiofx/LoudnessEnhancerController.java new file mode 100644 index 00000000..df6fdb1c --- /dev/null +++ b/src/github/daneren2005/dsub/audiofx/LoudnessEnhancerController.java @@ -0,0 +1,77 @@ +/* + This file is part of Subsonic. + + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see <http://www.gnu.org/licenses/>. + + Copyright 2014 (C) Scott Jackson +*/ +package github.daneren2005.dsub.audiofx; + +import android.content.Context; +import android.media.audiofx.LoudnessEnhancer; +import android.util.Log; + +public class LoudnessEnhancerController { + private static final String TAG = LoudnessEnhancerController.class.getSimpleName(); + + private final Context context; + private LoudnessEnhancer enhancer; + private boolean released = false; + private int audioSessionId = 0; + + public LoudnessEnhancerController(Context context, int audioSessionId) { + this.context = context; + try { + this.audioSessionId = audioSessionId; + enhancer = new LoudnessEnhancer(audioSessionId); + } catch (Throwable x) { + Log.w(TAG, "Failed to create enhancer", x); + } + } + + public boolean isAvailable() { + return enhancer != null; + } + + public boolean isEnabled() { + try { + return isAvailable() && enhancer.getEnabled(); + } catch(Exception e) { + return false; + } + } + + public void enable() { + enhancer.setEnabled(true); + } + public void disable() { + enhancer.setEnabled(false); + } + + public float getGain() { + return enhancer.getTargetGain(); + } + public void setGain(int gain) { + enhancer.setTargetGain(gain); + } + + public void release() { + if (isAvailable()) { + enhancer.release(); + released = true; + } + } + +} + diff --git a/src/github/daneren2005/dsub/audiofx/VisualizerController.java b/src/github/daneren2005/dsub/audiofx/VisualizerController.java index b32245f4..92e3712c 100644 --- a/src/github/daneren2005/dsub/audiofx/VisualizerController.java +++ b/src/github/daneren2005/dsub/audiofx/VisualizerController.java @@ -19,7 +19,6 @@ package github.daneren2005.dsub.audiofx; import android.content.Context; -import android.media.MediaPlayer; import android.media.audiofx.Visualizer; import android.util.Log; @@ -31,63 +30,63 @@ import android.util.Log; */ public class VisualizerController { - private static final String TAG = VisualizerController.class.getSimpleName(); - private static final int PREFERRED_CAPTURE_SIZE = 128; // Must be a power of two. + private static final String TAG = VisualizerController.class.getSimpleName(); + private static final int PREFERRED_CAPTURE_SIZE = 128; // Must be a power of two. - private final Context context; - private Visualizer visualizer; + private final Context context; + private Visualizer visualizer; private boolean released = false; private int audioSessionId = 0; - // Class initialization fails when this throws an exception. - static { - try { - Class.forName("android.media.audiofx.Visualizer"); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - /** - * Throws an exception if the {@link Visualizer} class is not available. - */ - public static void checkAvailable() throws Throwable { - // Calling here forces class initialization. - } - - public VisualizerController(Context context, MediaPlayer mediaPlayer) { - this.context = context; - try { - audioSessionId = mediaPlayer.getAudioSessionId(); - visualizer = new Visualizer(audioSessionId); - } catch (Throwable x) { - Log.w(TAG, "Failed to create visualizer.", x); - } - - if (visualizer != null) { - int[] captureSizeRange = Visualizer.getCaptureSizeRange(); - int captureSize = Math.max(PREFERRED_CAPTURE_SIZE, captureSizeRange[0]); - captureSize = Math.min(captureSize, captureSizeRange[1]); - visualizer.setCaptureSize(captureSize); - } - } - - public boolean isAvailable() { - return visualizer != null; - } - - public boolean isEnabled() { - return isAvailable() && visualizer.getEnabled(); - } - - public void release() { - if (isAvailable()) { - visualizer.release(); + // Class initialization fails when this throws an exception. + static { + try { + Class.forName("android.media.audiofx.Visualizer"); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + /** + * Throws an exception if the {@link Visualizer} class is not available. + */ + public static void checkAvailable() throws Throwable { + // Calling here forces class initialization. + } + + public VisualizerController(Context context, int audioSessionId) { + this.context = context; + try { + this.audioSessionId = audioSessionId; + visualizer = new Visualizer(audioSessionId); + } catch (Throwable x) { + Log.w(TAG, "Failed to create visualizer.", x); + } + + if (visualizer != null) { + int[] captureSizeRange = Visualizer.getCaptureSizeRange(); + int captureSize = Math.max(PREFERRED_CAPTURE_SIZE, captureSizeRange[0]); + captureSize = Math.min(captureSize, captureSizeRange[1]); + visualizer.setCaptureSize(captureSize); + } + } + + public boolean isAvailable() { + return visualizer != null; + } + + public boolean isEnabled() { + return isAvailable() && visualizer.getEnabled(); + } + + public void release() { + if (isAvailable()) { + visualizer.release(); released = true; - } - } + } + } - public Visualizer getVisualizer() { + public Visualizer getVisualizer() { if(released) { released = false; try { @@ -97,8 +96,8 @@ public class VisualizerController { Log.w(TAG, "Failed to create visualizer.", x); } } - - return visualizer; - } + + return visualizer; + } } diff --git a/src/github/daneren2005/dsub/fragments/DownloadFragment.java b/src/github/daneren2005/dsub/fragments/DownloadFragment.java index 835394ae..d9091b55 100644 --- a/src/github/daneren2005/dsub/fragments/DownloadFragment.java +++ b/src/github/daneren2005/dsub/fragments/DownloadFragment.java @@ -464,13 +464,10 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe downloadService.setShufflePlayEnabled(true);
}
- boolean visualizerAvailable = downloadService != null && downloadService.getVisualizerAvailable();
boolean equalizerAvailable = downloadService != null && downloadService.getEqualizerAvailable();
if (!equalizerAvailable) {
equalizerButton.setVisibility(View.GONE);
- }
- if (!visualizerAvailable) {
visualizerButton.setVisibility(View.GONE);
} else {
visualizerView = new VisualizerView(context);
diff --git a/src/github/daneren2005/dsub/fragments/EqualizerFragment.java b/src/github/daneren2005/dsub/fragments/EqualizerFragment.java index 71067d7c..1475ccdd 100644 --- a/src/github/daneren2005/dsub/fragments/EqualizerFragment.java +++ b/src/github/daneren2005/dsub/fragments/EqualizerFragment.java @@ -19,8 +19,10 @@ package github.daneren2005.dsub.fragments;
import android.content.SharedPreferences;
+import android.media.audiofx.BassBoost;
import android.media.audiofx.Equalizer;
import android.os.Bundle;
+import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
@@ -37,6 +39,7 @@ import java.util.Map; import github.daneren2005.dsub.R;
import github.daneren2005.dsub.audiofx.EqualizerController;
+import github.daneren2005.dsub.audiofx.LoudnessEnhancerController;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.Util;
@@ -50,20 +53,28 @@ public class EqualizerFragment extends SubsonicFragment { private static final int MENU_GROUP_PRESET = 100;
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
+ private SeekBar bassBar;
+ private SeekBar loudnessBar;
private EqualizerController equalizerController;
private Equalizer equalizer;
+ private BassBoost bass;
+ private LoudnessEnhancerController loudnessEnhancer;
private short masterLevel = 0;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
rootView = inflater.inflate(R.layout.equalizer, container, false);
- equalizerController = DownloadService.getInstance().getEqualizerController();
+ DownloadService service = DownloadService.getInstance();
+ equalizerController = service.getEqualizerController();
equalizer = equalizerController.getEqualizer();
+ bass = equalizerController.getBassBoost();
+ loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
try {
initEqualizer();
} catch(Exception e) {
+ Log.e(TAG, "Failed to initialize EQ", e);
Util.toast(context, "Failed to initialize EQ");
context.onBackPressed();
}
@@ -106,6 +117,7 @@ public class EqualizerFragment extends SubsonicFragment { super.onResume();
equalizerController = DownloadService.getInstance().getEqualizerController();
equalizer = equalizerController.getEqualizer();
+ bass = equalizerController.getBassBoost();
}
@Override
@@ -180,6 +192,11 @@ public class EqualizerFragment extends SubsonicFragment { }
}
+ bassBar.setEnabled(isEnabled);
+ if(loudnessBar != null) {
+ loudnessBar.setEnabled(isEnabled);
+ }
+
if(!isEnabled) {
masterLevel = 0;
SharedPreferences prefs = Util.getPreferences(context);
@@ -240,6 +257,98 @@ public class EqualizerFragment extends SubsonicFragment { });
layout.addView(bandBar);
}
+
+ LinearLayout specialLayout = (LinearLayout) rootView.findViewById(R.id.special_effects_layout);
+
+ // Setup bass booster
+ View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
+ TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
+ final TextView bassTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
+ bassBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
+
+ freqTextView.setText(R.string.equalizer_bass_booster);
+ bassBar.setEnabled(equalizer.getEnabled());
+ short bassLevel = 0;
+ if(bass.getEnabled()) {
+ bassLevel = bass.getRoundedStrength();
+ }
+ bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, bassLevel));
+ bassBar.setMax(1000);
+ bassBar.setProgress(bassLevel);
+ bassBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, progress));
+ if(fromUser) {
+ if(progress > 0) {
+ if(!bass.getEnabled()) {
+ bass.setEnabled(true);
+ }
+ bass.setStrength((short) progress);
+ } else if(progress == 0 && bass.getEnabled()) {
+ bass.setStrength((short) progress);
+ bass.setEnabled(false);
+ }
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+
+ }
+ });
+ specialLayout.addView(bandBar);
+
+ if(loudnessEnhancer != null && loudnessEnhancer.isAvailable()) {
+ // Setup loudness enhancer
+ bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
+ freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
+ final TextView loudnessTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
+ loudnessBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
+
+ freqTextView.setText(R.string.equalizer_voice_booster);
+ loudnessBar.setEnabled(equalizer.getEnabled());
+ int loudnessLevel = 0;
+ if(loudnessEnhancer.isEnabled()) {
+ loudnessLevel = (int) loudnessEnhancer.getGain();
+ }
+ loudnessBar.setProgress(loudnessLevel / 100);
+ loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, loudnessLevel / 100));
+ loudnessBar.setMax(15);
+ loudnessBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, progress));
+ if(fromUser) {
+ if(progress > 0) {
+ if(!loudnessEnhancer.isEnabled()) {
+ loudnessEnhancer.enable();
+ }
+ loudnessEnhancer.setGain(progress * 100);
+ } else if(progress == 0 && loudnessEnhancer.isEnabled()) {
+ loudnessEnhancer.setGain(progress * 100);
+ loudnessEnhancer.disable();
+ }
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+
+ }
+ });
+ specialLayout.addView(bandBar);
+ }
}
private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) {
@@ -285,6 +394,6 @@ public class EqualizerFragment extends SubsonicFragment { }
private void updateLevelText(TextView levelTextView, short level) {
- levelTextView.setText((level > 0 ? "+" : "") + level / 100 + " dB");
+ levelTextView.setText((level > 0 ? "+" : "") + context.getResources().getString(R.string.equalizer_db_size, level / 100));
}
}
diff --git a/src/github/daneren2005/dsub/receiver/MediaButtonIntentReceiver.java b/src/github/daneren2005/dsub/receiver/MediaButtonIntentReceiver.java index 89a4a87b..8119ef2d 100644 --- a/src/github/daneren2005/dsub/receiver/MediaButtonIntentReceiver.java +++ b/src/github/daneren2005/dsub/receiver/MediaButtonIntentReceiver.java @@ -36,18 +36,22 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT); + if(DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP || + event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) { + Log.w(TAG, "Ignore keycode event because downloadService is off"); + return; + } Log.i(TAG, "Got MEDIA_BUTTON key event: " + event); Intent serviceIntent = new Intent(context, DownloadService.class); serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event); context.startService(serviceIntent); - if (isOrderedBroadcast()) - { - try { - abortBroadcast(); - } catch (Exception x) { - // Ignored. + if (isOrderedBroadcast()) { + try { + abortBroadcast(); + } catch (Exception x) { + // Ignored. + } } - } } } diff --git a/src/github/daneren2005/dsub/service/ChromeCastController.java b/src/github/daneren2005/dsub/service/ChromeCastController.java index 02661f14..9ff0f54a 100644 --- a/src/github/daneren2005/dsub/service/ChromeCastController.java +++ b/src/github/daneren2005/dsub/service/ChromeCastController.java @@ -245,7 +245,6 @@ public class ChromeCastController extends RemoteController { } url = fixURLs(url); - Log.i(TAG, "Cast url: " + url); } // Setup song/video information @@ -271,7 +270,6 @@ public class ChromeCastController extends RemoteController { meta.addImage(new WebImage(Uri.parse(coverArt))); } } - Log.i(TAG, "Cover art: " + coverArt); } String contentType; diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 76ec8396..7b4ddf31 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -27,7 +27,10 @@ import static github.daneren2005.dsub.domain.PlayerState.PREPARED; import static github.daneren2005.dsub.domain.PlayerState.PREPARING; import static github.daneren2005.dsub.domain.PlayerState.STARTED; import static github.daneren2005.dsub.domain.PlayerState.STOPPED; + +import github.daneren2005.dsub.audiofx.AudioEffectsController; import github.daneren2005.dsub.audiofx.EqualizerController; +import github.daneren2005.dsub.audiofx.LoudnessEnhancerController; import github.daneren2005.dsub.audiofx.VisualizerController; import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.MusicDirectory; @@ -94,6 +97,7 @@ public class DownloadService extends Service { private Looper mediaPlayerLooper; private MediaPlayer mediaPlayer; private MediaPlayer nextMediaPlayer; + private int audioSessionId; private boolean nextSetup = false; private boolean isPartial = true; private final List<DownloadFile> downloadList = new ArrayList<DownloadFile>(); @@ -128,10 +132,7 @@ public class DownloadService extends Service { private boolean downloadOngoing = false; private DownloadFile lastDownloaded = null; - private static boolean equalizerAvailable; - private static boolean visualizerAvailable; - private EqualizerController equalizerController; - private VisualizerController visualizerController; + private AudioEffectsController effectsController; private boolean showVisualization; private RemoteControlState remoteState = RemoteControlState.LOCAL; private PositionCache positionCache; @@ -143,23 +144,18 @@ public class DownloadService extends Service { private MediaRouteManager mediaRouter; - static { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - equalizerAvailable = true; - visualizerAvailable = true; - } - } - @Override public void onCreate() { super.onCreate(); + final SharedPreferences prefs = Util.getPreferences(this); new Thread(new Runnable() { public void run() { Looper.prepare(); mediaPlayer = new MediaPlayer(); mediaPlayer.setWakeMode(DownloadService.this, PowerManager.PARTIAL_WAKE_LOCK); + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override @@ -168,16 +164,27 @@ public class DownloadService extends Service { return false; } }); + audioSessionId = mediaPlayer.getAudioSessionId(); + Log.d(TAG, "id: " + audioSessionId); try { Intent i = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); - i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, mediaPlayer.getAudioSessionId()); + i.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId); i.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName()); sendBroadcast(i); } catch(Throwable e) { // Froyo or lower } + effectsController = new AudioEffectsController(DownloadService.this, audioSessionId); + if(prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false)) { + getEqualizerController(); + } + if(prefs.getBoolean(Constants.PREFERENCES_VISUALIZER_ON, false)) { + getVisualizerController(); + showVisualization = true; + } + mediaPlayerLooper = Looper.myLooper(); mediaPlayerHandler = new Handler(mediaPlayerLooper); Looper.loop(); @@ -197,7 +204,6 @@ public class DownloadService extends Service { wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName()); wakeLock.setReferenceCounted(false); - SharedPreferences prefs = Util.getPreferences(this); try { timerDuration = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_SLEEP_TIMER_DURATION, "5")); } catch(Throwable e) { @@ -211,14 +217,6 @@ public class DownloadService extends Service { instance = this; lifecycleSupport.onCreate(); - - if(prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false)) { - getEqualizerController(); - } - if(prefs.getBoolean(Constants.PREFERENCES_VISUALIZER_ON, false)) { - getVisualizerController(); - showVisualization = true; - } } @Override @@ -255,12 +253,7 @@ public class DownloadService extends Service { } mediaPlayerLooper.quit(); shufflePlayBuffer.shutdown(); - if (equalizerController != null) { - equalizerController.release(); - } - if (visualizerController != null) { - visualizerController.release(); - } + effectsController.release(); if (mRemoteControl != null) { mRemoteControl.unregister(this); mRemoteControl = null; @@ -1079,33 +1072,15 @@ public class DownloadService extends Service { } public boolean getEqualizerAvailable() { - return equalizerAvailable; - } - - public boolean getVisualizerAvailable() { - return visualizerAvailable; + return effectsController.isAvailable(); } public EqualizerController getEqualizerController() { - if (equalizerAvailable && equalizerController == null) { - equalizerController = new EqualizerController(this, mediaPlayer); - if (!equalizerController.isAvailable()) { - equalizerController = null; - } else { - equalizerController.loadSettings(); - } - } - return equalizerController; + return effectsController.getEqualizerController(); } public VisualizerController getVisualizerController() { - if (visualizerAvailable && visualizerController == null) { - visualizerController = new VisualizerController(this, mediaPlayer); - if (!visualizerController.isAvailable()) { - visualizerController = null; - } - } - return visualizerController; + return effectsController.getVisualizerController(); } public MediaRouteSelector getRemoteSelector() { @@ -1251,7 +1226,11 @@ public class DownloadService extends Service { mediaPlayer.setOnCompletionListener(null); mediaPlayer.reset(); setPlayerState(IDLE); - mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + try { + mediaPlayer.setAudioSessionId(audioSessionId); + } catch(Exception e) { + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + } String dataSource = file.getPath(); if(isPartial) { if (proxy == null) { @@ -1334,7 +1313,7 @@ public class DownloadService extends Service { nextMediaPlayer = new MediaPlayer(); nextMediaPlayer.setWakeMode(DownloadService.this, PowerManager.PARTIAL_WAKE_LOCK); try { - nextMediaPlayer.setAudioSessionId(mediaPlayer.getAudioSessionId()); + nextMediaPlayer.setAudioSessionId(audioSessionId); } catch(Throwable e) { nextMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } @@ -1465,7 +1444,7 @@ public class DownloadService extends Service { } public void setVolume(float volume) { - if(mediaPlayer != null) { + if(mediaPlayer != null && (playerState == STARTED || playerState == PAUSED || playerState == STOPPED)) { mediaPlayer.setVolume(volume, volume); } } @@ -1500,7 +1479,11 @@ public class DownloadService extends Service { } private void handleErrorNext(Exception x) { Log.w(TAG, "Next Media player error: " + x, x); - nextMediaPlayer.reset(); + try { + nextMediaPlayer.reset(); + } catch(Exception e) { + Log.e(TAG, "Failed to reset next media player", x); + } setNextPlayerState(IDLE); } diff --git a/src/github/daneren2005/dsub/service/RESTMusicService.java b/src/github/daneren2005/dsub/service/RESTMusicService.java index 879339cc..6c4872e9 100644 --- a/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -203,6 +203,18 @@ public class RESTMusicService implements MusicService { return cachedIndexes; } + // If manual refresh, try to start server scan for madsonic servers + if(refresh) { + Reader reader = getReader(context, progressListener, "startRescan", null); + try { + new ErrorParser(context).parse(reader); + } catch(Exception e) { + // Probably not madsonic, don't care + } finally { + Util.close(reader); + } + } + long lastModified = (cachedIndexes == null || refresh) ? 0L : cachedIndexes.getLastModified(); List<String> parameterNames = new ArrayList<String>(); @@ -715,7 +727,7 @@ public class RESTMusicService implements MusicService { builder.append("&maxBitRate=").append(maxBitrate); String url = rewriteUrlWithRedirect(context, builder.toString()); - Log.i(TAG, "Using music URL: " + url); + Log.i(TAG, "Using music URL: " + stripUrlInfo(url)); return url; } @@ -727,7 +739,7 @@ public class RESTMusicService implements MusicService { builder.append("&autoplay=true"); String url = rewriteUrlWithRedirect(context, builder.toString()); - Log.i(TAG, "Using video URL: " + url); + Log.i(TAG, "Using video URL: " + stripUrlInfo(url)); return url; } @@ -742,7 +754,7 @@ public class RESTMusicService implements MusicService { builder.append("&format=").append(format); String url = rewriteUrlWithRedirect(context, builder.toString()); - Log.i(TAG, "Using video URL: " + url); + Log.i(TAG, "Using video URL: " + stripUrlInfo(url)); return url; } @@ -757,7 +769,7 @@ public class RESTMusicService implements MusicService { } String url = rewriteUrlWithRedirect(context, builder.toString()); - Log.i(TAG, "Using hls URL: " + url); + Log.i(TAG, "Using hls URL: " + stripUrlInfo(url)); return url; } @@ -1341,8 +1353,8 @@ public class RESTMusicService implements MusicService { List<String> parameterNames, List<Object> parameterValues, List<Header> headers, ProgressListener progressListener, CancellableTask task) throws IOException { // Strip out sensitive information from log - Log.i(TAG, "Using URL " + url.substring(0, url.indexOf("?u=") + 1) + url.substring(url.indexOf("&v=") + 1)); - + Log.i(TAG, stripUrlInfo(url)); + SharedPreferences prefs = Util.getPreferences(context); int networkTimeout = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_NETWORK_TIMEOUT, "15000")); HttpParams newParams = httpClient.getParams(); @@ -1476,6 +1488,10 @@ public class RESTMusicService implements MusicService { return url.replace(redirectFrom, redirectTo); } + private String stripUrlInfo(String url) { + return url.substring(0, url.indexOf("?u=") + 1) + url.substring(url.indexOf("&v=") + 1); + } + private int getCurrentNetworkType(Context context) { ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = manager.getActiveNetworkInfo(); |