/* * Copyright (C) 2014 Fastboot Mobile, LLC. * * This program 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. * * This program 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 this program; * if not, see <http://www.gnu.org/licenses>. */ package com.fastbootmobile.encore.service; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; import com.fastbootmobile.encore.framework.PluginsLookup; import com.fastbootmobile.encore.providers.DSPConnection; import com.fastbootmobile.encore.providers.ProviderIdentifier; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; /** * Class responsible for grabbing the audio from a provider, pushing it through the DSP chain, * and playing it to a sink */ public class DSPProcessor { private static final String TAG = "DSPProcessor"; private static final boolean DEBUG = false; private static final String PREFS_DSP_CHAIN = "DSP_Chain"; private static final String PREF_KEY_CHAIN = "chain"; private List<ProviderIdentifier> mDSPChain; private PlaybackService mPlaybackService; /** * Default constructor */ public DSPProcessor(PlaybackService pbs) { mPlaybackService = pbs; mDSPChain = new ArrayList<>(); } /** * Returns the current RMS level of the last 1/60 * sampleRate frames * @return The RMS level */ public int getRms() { // TODO: reimplement return 0; } /** * Sets the current active DSP plugins chain and saves it * @param ctx A valid context * @param chain The chain of plugins to use */ public void setActiveChain(Context ctx, List<ProviderIdentifier> chain, NativeHub hub) { // We make a copy to avoid any external modification mDSPChain = new ArrayList<>(chain); // Save it SharedPreferences prefs = ctx.getSharedPreferences(PREFS_DSP_CHAIN, 0); Set<String> identifiers = new TreeSet<>(); for (ProviderIdentifier identifier : chain) { identifiers.add(identifier.serialize()); } SharedPreferences.Editor editor = prefs.edit(); editor.putStringSet(PREF_KEY_CHAIN, identifiers); editor.apply(); // Bind (if necessary) the new services, and unbind unused DSP services final PluginsLookup plugins = PluginsLookup.getDefault(); final List<DSPConnection> list = new ArrayList<>(plugins.getAvailableDSPs()); for (ProviderIdentifier id : chain) { DSPConnection conn = plugins.getDSP(id); conn.bindService(); list.remove(conn); } for (DSPConnection conn : list) { Log.e(TAG, "Unbinding: " + conn.getProviderName()); conn.unbindService(hub); } updateHubDspChain(); } /** * @return The current active chain of DSP plugins */ public List<ProviderIdentifier> getActiveChain() { return mDSPChain; } /** * Restores the saved chain * @param ctx A valid context */ public void restoreChain(Context ctx) { final SharedPreferences prefs = ctx.getSharedPreferences(PREFS_DSP_CHAIN, 0); final Set<String> identifiers = prefs.getStringSet(PREF_KEY_CHAIN, null); final PluginsLookup plugins = PluginsLookup.getDefault(); mDSPChain = new ArrayList<>(); if (identifiers != null) { for (String id : identifiers) { ProviderIdentifier identifier = ProviderIdentifier.fromSerialized(id); if (identifier != null) { DSPConnection connection = plugins.getDSP(identifier); if (connection != null) { mDSPChain.add(identifier); connection.bindService(); } } else { Log.e(TAG, "Cannot restore from serialized string " + id); } } } // Push the new chain to the NativeHub new Thread() { public void run() { updateHubDspChain(); } }.start(); } /** * Updates the DSP chain on the native hub */ private void updateHubDspChain() { NativeHub hub = mPlaybackService.getNativeHub(); String[] sockets = new String[mDSPChain.size()]; int index = 0; for (ProviderIdentifier id : mDSPChain) { DSPConnection conn = PluginsLookup.getDefault().getDSP(id); if (conn != null) { String socketName = conn.getAudioSocketName(); if (socketName == null) { socketName = mPlaybackService.assignProviderAudioSocket(conn); } if (socketName == null) { Log.e(TAG, "======== SOCKET NAME STILL NULL AFTER ASSIGNPROVIDERAUDIOSOCKET"); } else if (DEBUG) { Log.d(TAG, "SOCKET " + index + ": " + socketName); } sockets[index] = socketName; } else { Log.e(TAG, "============================================"); Log.e(TAG, "= FIXMEFIXMEFIXMEFIXMEFIXMEFIXMEFIXMEFIXME ="); Log.e(TAG, "= DSP in the chain, but not yet connected! ="); Log.e(TAG, "= FIXMEFIXMEFIXMEFIXMEFIXMEFIXMEFIXMEFIXME ="); Log.e(TAG, "============================================"); } index++; } hub.setDSPChain(sockets); } }