/* This file is part of the Android Clementine Remote. * Copyright (C) 2014, Andreas Muttscheller <asfa194@gmail.com> * * 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 de.qspool.clementineremote.backend.mediasession; import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.Build; import de.qspool.clementineremote.App; import de.qspool.clementineremote.backend.Clementine; import de.qspool.clementineremote.backend.ClementinePlayerConnection; import de.qspool.clementineremote.backend.listener.PlayerConnectionListener; import de.qspool.clementineremote.backend.pb.ClementineMessage; import de.qspool.clementineremote.backend.player.MySong; import de.qspool.clementineremote.backend.receivers.ClementineMediaButtonEventReceiver; import de.qspool.clementineremote.widget.ClementineWidgetProvider; import de.qspool.clementineremote.widget.WidgetIntent; public class MediaSessionController { private final String PLAYSTATE_CHANGED = "com.android.music.playstatechanged"; private final String META_CHANGED = "com.android.music.metachanged"; private Context mContext; private ClementinePlayerConnection mClementinePlayerConnection; private ClementineMediaSession mClementineMediaSession; private ClementineMediaSessionNotification mMediaSessionNotification; private AudioManager mAudioManager; private BroadcastReceiver mMediaButtonBroadcastReceiver; public MediaSessionController(Context context, ClementinePlayerConnection clementinePlayerConnection) { mContext = context; mClementinePlayerConnection = clementinePlayerConnection; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mMediaButtonBroadcastReceiver = new ClementineMediaButtonEventReceiver(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { mClementineMediaSession = new ClementineMediaSessionV20(mContext); } else { mClementineMediaSession = new ClementineMediaSessionV21(mContext); } mMediaSessionNotification = new ClementineMediaSessionNotification(mContext); } public void registerMediaSession() { mClementinePlayerConnection.addPlayerConnectionListener(new PlayerConnectionListener() { @Override public void onConnectionStatusChanged( ClementinePlayerConnection.ConnectionStatus status) { switch (status) { case IDLE: break; case CONNECTING: break; case NO_CONNECTION: break; case CONNECTED: // Request AudioFocus, so the widget is shown on the lock-screen mAudioManager.requestAudioFocus(mOnAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); // Register MediaButtonReceiver IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON); mContext.registerReceiver(mMediaButtonBroadcastReceiver, filter); mClementineMediaSession.registerSession(); mMediaSessionNotification.registerSession(); mMediaSessionNotification.setMediaSessionCompat( mClementineMediaSession.getMediaSession()); break; case DISCONNECTED: mAudioManager.abandonAudioFocus(mOnAudioFocusChangeListener); mContext.unregisterReceiver(mMediaButtonBroadcastReceiver); mClementineMediaSession.unregisterSession(); mMediaSessionNotification.unregisterSession(); break; } sendWidgetUpdateIntent(WidgetIntent.ClementineAction.CONNECTION_STATUS, status); } @Override public void onClementineMessageReceived(ClementineMessage clementineMessage) { if (clementineMessage.isErrorMessage()) { return; } switch (clementineMessage.getMessageType()) { case CURRENT_METAINFO: mClementineMediaSession.updateSession(); mMediaSessionNotification.updateSession(); sendMetachangedIntent(META_CHANGED); sendWidgetUpdateIntent(WidgetIntent.ClementineAction.STATE_CHANGE, ClementinePlayerConnection.ConnectionStatus.CONNECTED); break; case PLAY: case PAUSE: case STOP: mClementineMediaSession.updateSession(); mMediaSessionNotification.updateSession(); sendMetachangedIntent(PLAYSTATE_CHANGED); sendWidgetUpdateIntent(WidgetIntent.ClementineAction.STATE_CHANGE, ClementinePlayerConnection.ConnectionStatus.CONNECTED); break; case FIRST_DATA_SENT_COMPLETE: sendWidgetUpdateIntent(WidgetIntent.ClementineAction.STATE_CHANGE, ClementinePlayerConnection.ConnectionStatus.CONNECTED); break; default: break; } } }); } private void sendMetachangedIntent(String what) { MySong currentSong = App.Clementine.getCurrentSong(); Intent i = new Intent(what); i.putExtra("playing", App.Clementine.getState() == Clementine.State.PLAY); if (null != currentSong) { i.putExtra("id", Long.valueOf(currentSong.getId())); i.putExtra("artist", currentSong.getArtist()); i.putExtra("album", currentSong.getAlbum()); i.putExtra("track", currentSong.getTitle()); } mContext.sendBroadcast(i); } private void sendWidgetUpdateIntent(WidgetIntent.ClementineAction action, ClementinePlayerConnection.ConnectionStatus connectionStatus) { // Get widget ids ComponentName widgetComponent = new ComponentName(mContext.getPackageName(), ClementineWidgetProvider.class.getName()); int[] widgetIds = AppWidgetManager.getInstance(mContext).getAppWidgetIds(widgetComponent); if (widgetIds.length > 0) { Intent intent = new Intent(mContext, ClementineWidgetProvider.class); intent.setAction(WidgetIntent.ACTION_APPWIDGET_UPDATE); intent.putExtra(WidgetIntent.EXTRA_APPWIDGET_IDS, widgetIds); intent.putExtra(WidgetIntent.EXTRA_CLEMENTINE_ACTION, action.ordinal()); intent.putExtra(WidgetIntent.EXTRA_CLEMENTINE_CONNECTION_STATE, connectionStatus.ordinal()); mContext.sendBroadcast(intent); } } private AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { } }; }