Skip to content

Commit

Permalink
Android: Added PlaylistActivity; not fully functional yet. Added play…
Browse files Browse the repository at this point in the history
…list/shuffle/repeat buttons to lock screen. Added shuffle/repeat commands to PlayerCommandMessage. Added new icon for playlist.

Related to issue #406.
  • Loading branch information
ycastonguay committed Aug 29, 2013
1 parent 8038d63 commit de138ca
Show file tree
Hide file tree
Showing 28 changed files with 969 additions and 498 deletions.
14 changes: 14 additions & 0 deletions MPfm/MPfm.Android/Classes/Activities/LockScreenActivity.cs
Expand Up @@ -19,6 +19,7 @@
using System.Threading.Tasks;
using System.Timers;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.Views;
Expand Down Expand Up @@ -51,6 +52,9 @@ public class LockScreenActivity : BaseActivity
ImageButton _btnPrevious;
ImageButton _btnPlayPause;
ImageButton _btnNext;
ImageButton _btnPlaylist;
ImageButton _btnShuffle;
ImageButton _btnRepeat;
Button _btnClose;
SeekBar _seekBar;
ImageView _imageAlbum;
Expand Down Expand Up @@ -79,6 +83,9 @@ protected override void OnCreate(Bundle bundle)
_btnPrevious = FindViewById<ImageButton>(Resource.Id.lockScreen_btnPrevious);
_btnPlayPause = FindViewById<ImageButton>(Resource.Id.lockScreen_btnPlayPause);
_btnNext = FindViewById<ImageButton>(Resource.Id.lockScreen_btnNext);
_btnPlaylist = FindViewById<ImageButton>(Resource.Id.lockScreen_btnPlaylist);
_btnShuffle = FindViewById<ImageButton>(Resource.Id.lockScreen_btnShuffle);
_btnRepeat = FindViewById<ImageButton>(Resource.Id.lockScreen_btnRepeat);
_btnClose = FindViewById<Button>(Resource.Id.lockScreen_btnClose);
_imageAlbum = FindViewById<ImageView>(Resource.Id.lockScreen_imageAlbum);
_seekBar = FindViewById<SeekBar>(Resource.Id.lockScreen_seekBar);
Expand Down Expand Up @@ -127,6 +134,13 @@ protected override void OnCreate(Bundle bundle)
_btnPrevious.Click += (sender, args) => _messengerHub.PublishAsync<PlayerCommandMessage>(new PlayerCommandMessage(this, PlayerCommandMessageType.Previous));
_btnPlayPause.Click += (sender, args) => _messengerHub.PublishAsync<PlayerCommandMessage>(new PlayerCommandMessage(this, PlayerCommandMessageType.PlayPause));
_btnNext.Click += (sender, args) => _messengerHub.PublishAsync<PlayerCommandMessage>(new PlayerCommandMessage(this, PlayerCommandMessageType.Next));
_btnShuffle.Click += (sender, args) => _messengerHub.PublishAsync<PlayerCommandMessage>(new PlayerCommandMessage(this, PlayerCommandMessageType.Shuffle));
_btnRepeat.Click += (sender, args) => _messengerHub.PublishAsync<PlayerCommandMessage>(new PlayerCommandMessage(this, PlayerCommandMessageType.Repeat));
_btnPlaylist.Click += (sender, args) => {
Intent intent = new Intent(this, typeof (PlaylistActivity));
intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
StartActivity(intent);
};

_timerSongPosition = new Timer();
_timerSongPosition.Interval = 100;
Expand Down
3 changes: 2 additions & 1 deletion MPfm/MPfm.Android/Classes/Activities/MainActivity.cs
Expand Up @@ -92,7 +92,7 @@ protected override void OnCreate(Bundle bundle)
RequestWindowFeature(WindowFeatures.ActionBar);
SetContentView(Resource.Layout.Main);
ActionBar.NavigationMode = ActionBarNavigationMode.List;
ActionBar.Title = "";
ActionBar.Title = string.Empty;
_spinnerAdapter = ArrayAdapter.CreateFromResource(this, Resource.Array.action_list, Resource.Layout.spinner_dropdown_item);
ActionBar.SetListNavigationCallbacks(_spinnerAdapter, this);

Expand Down Expand Up @@ -228,6 +228,7 @@ protected override void OnCreate(Bundle bundle)

public bool OnNavigationItemSelected(int itemPosition, long itemId)
{
Console.WriteLine("MainActivity - OnNavigationItemSelected - itemPosition: {0} - itemId: {1}", itemPosition, itemId);
return true;
}

Expand Down
9 changes: 6 additions & 3 deletions MPfm/MPfm.Android/Classes/Activities/PlayerActivity.cs
Expand Up @@ -257,17 +257,17 @@ private void BtnNextOnClick(object sender, EventArgs eventArgs)

private void BtnPlaylistOnClick(object sender, EventArgs eventArgs)
{

OnOpenPlaylist();
}

private void BtnShuffleOnClick(object sender, EventArgs eventArgs)
{

OnPlayerShuffle();
}

private void BtnRepeatOnClick(object sender, EventArgs eventArgs)
{

OnPlayerRepeat();
}

private void SeekBarOnProgressChanged(object sender, SeekBar.ProgressChangedEventArgs progressChangedEventArgs)
Expand Down Expand Up @@ -361,12 +361,15 @@ public bool OnTouch(View v, MotionEvent e)
public Action OnPlayerStop { get; set; }
public Action OnPlayerPrevious { get; set; }
public Action OnPlayerNext { get; set; }
public Action OnPlayerShuffle { get; set; }
public Action OnPlayerRepeat { get; set; }
public Action<float> OnPlayerSetVolume { get; set; }
public Action<float> OnPlayerSetPitchShifting { get; set; }
public Action<float> OnPlayerSetTimeShifting { get; set; }
public Action<float> OnPlayerSetPosition { get; set; }
public Func<float, PlayerPositionEntity> OnPlayerRequestPosition { get; set; }
public Action OnEditSongMetadata { get; set; }
public Action OnOpenPlaylist { get; set; }

public void PlayerError(Exception ex)
{
Expand Down
177 changes: 177 additions & 0 deletions MPfm/MPfm.Android/Classes/Activities/PlaylistActivity.cs
@@ -0,0 +1,177 @@
// Copyright © 2011-2013 Yanick Castonguay
//
// This file is part of MPfm.
//
// MPfm 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.
//
// MPfm 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 MPfm. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Views;
using Android.OS;
using Android.Widget;
using MPfm.Android.Classes.Adapters;
using MPfm.Android.Classes.Fragments;
using MPfm.Android.Classes.Navigation;
using MPfm.Library.Objects;
using MPfm.MVP.Bootstrap;
using MPfm.MVP.Navigation;
using MPfm.MVP.Views;
using MPfm.Player.Objects;
using MPfm.Sound.AudioFiles;
using MPfm.Sound.Playlists;

namespace MPfm.Android
{
[Activity(Label = "Playlist", ScreenOrientation = ScreenOrientation.Sensor, Theme = "@style/MyAppTheme", ConfigurationChanges = ConfigChanges.KeyboardHidden | ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class PlaylistActivity : BaseActivity, IPlaylistView
{
private MobileNavigationManager _navigationManager;
Button _btnNew;
Button _btnShuffle;
ListView _listView;
PlaylistListAdapter _listAdapter;
Playlist _playlist;

protected override void OnCreate(Bundle bundle)
{
Console.WriteLine("PlaylistActivity - OnCreate");
base.OnCreate(bundle);

_navigationManager = Bootstrapper.GetContainer().Resolve<MobileNavigationManager>();
SetContentView(Resource.Layout.Playlist);
ActionBar.SetDisplayHomeAsUpEnabled(true);
ActionBar.SetHomeButtonEnabled(true);

_btnNew = FindViewById<Button>(Resource.Id.playlist_btnNew);
_btnNew.Click += BtnNewOnClick;
_btnShuffle = FindViewById<Button>(Resource.Id.playlist_btnNew);
_btnShuffle.Click += BtnShuffleOnClick;

_listView = FindViewById<ListView>(Resource.Id.playlist_listView);
_listAdapter = new PlaylistListAdapter(this, new Playlist());
_listView.SetAdapter(_listAdapter);
_listView.ItemClick += ListViewOnItemClick;

// Since the onViewReady action could not be added to an intent, tell the NavMgr the view is ready
((AndroidNavigationManager)_navigationManager).SetPlaylistActivityInstance(this);
}

private void BtnNewOnClick(object sender, EventArgs eventArgs)
{
OnNewPlaylist();
}

private void BtnShuffleOnClick(object sender, EventArgs eventArgs)
{
OnShufflePlaylist();
}

private void ListViewOnItemClick(object sender, AdapterView.ItemClickEventArgs itemClickEventArgs)
{
}

protected override void OnStart()
{
Console.WriteLine("PlaylistActivity - OnStart");
base.OnStart();
}

protected override void OnRestart()
{
Console.WriteLine("PlaylistActivity - OnRestart");
base.OnRestart();
}

protected override void OnPause()
{
Console.WriteLine("PlaylistActivity - OnPause");
base.OnPause();
}

protected override void OnResume()
{
Console.WriteLine("PlaylistActivity - OnResume");
base.OnResume();
}

protected override void OnStop()
{
Console.WriteLine("PlaylistActivity - OnStop");
base.OnStop();
}

protected override void OnDestroy()
{
Console.WriteLine("PlaylistActivity - OnDestroy");
base.OnDestroy();
}

public override bool OnOptionsItemSelected(IMenuItem item)
{
switch (item.ItemId)
{
case global::Android.Resource.Id.Home:
var intent = new Intent(this, typeof (MainActivity));
intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
this.StartActivity(intent);
this.Finish();
return true;
break;
default:
return base.OnOptionsItemSelected(item);
break;
}
}

#region IPlaylistView implementation

public Action<Guid, int> OnChangePlaylistItemOrder { get; set; }
public Action<Guid> OnSelectPlaylistItem { get; set; }
public Action<List<Guid>> OnRemovePlaylistItems { get; set; }
public Action OnNewPlaylist { get; set; }
public Action<string> OnLoadPlaylist { get; set; }
public Action OnSavePlaylist { get; set; }
public Action OnShufflePlaylist { get; set; }

public void PlaylistError(Exception ex)
{
RunOnUiThread(() => {
AlertDialog ad = new AlertDialog.Builder(this).Create();
ad.SetCancelable(false);
ad.SetMessage(string.Format("An error has occured in Playlist: {0}", ex));
ad.SetButton("OK", (sender, args) => ad.Dismiss());
ad.Show();
});
}

public void RefreshPlaylist(Playlist playlist)
{
RunOnUiThread(() => {
_playlist = playlist;
_listAdapter.SetData(_playlist);
});
}

public void RefreshCurrentlyPlayingSong(int index, AudioFile audioFile)
{
}

#endregion

}
}
83 changes: 83 additions & 0 deletions MPfm/MPfm.Android/Classes/Adapters/PlaylistListAdapter.cs
@@ -0,0 +1,83 @@
// Copyright © 2011-2013 Yanick Castonguay
//
// This file is part of MPfm.
//
// MPfm 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.
//
// MPfm 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 MPfm. If not, see <http://www.gnu.org/licenses/>.

using System.Collections.Generic;
using Android.Graphics;
using Android.Views;
using Android.Views.Animations;
using Android.Widget;
using MPfm.Library.Objects;
using MPfm.Sound.AudioFiles;
using MPfm.Sound.Playlists;

namespace MPfm.Android.Classes.Adapters
{
public class PlaylistListAdapter : BaseAdapter<AudioFile>
{
readonly PlaylistActivity _context;
Playlist _playlist;

public PlaylistListAdapter(PlaylistActivity context, Playlist playlist)
{
_context = context;
_playlist = playlist;
}

public void SetData(Playlist playlist)
{
_playlist = playlist;
NotifyDataSetChanged();
}

public override long GetItemId(int position)
{
return position;
}

public override AudioFile this[int position]
{
get { return _playlist.Items[position].AudioFile; }
}

public override int Count
{
get { return _playlist.Items.Count; }
}

public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = _playlist.Items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = _context.LayoutInflater.Inflate(Resource.Layout.PlaylistCell, null);

if (item == null)
return view;

var index = view.FindViewById<TextView>(Resource.Id.playlistCell_lblIndex);
var title = view.FindViewById<TextView>(Resource.Id.playlistCell_lblTitle);
var subtitle = view.FindViewById<TextView>(Resource.Id.playlistCell_lblSubtitle);

//index.Text = item.AudioFile.TrackNumber.ToString();
index.Text = (position+1).ToString();
title.Text = item.AudioFile.ArtistName + " / " + item.AudioFile.Title;
subtitle.Text = item.AudioFile.Length;

return view;
}
}
}
1 change: 1 addition & 0 deletions MPfm/MPfm.Android/Classes/Application.cs
Expand Up @@ -72,6 +72,7 @@ public override void OnCreate()
container.Register<IPitchShiftingView, PitchShiftingFragment>().AsMultiInstance();
container.Register<IUpdateLibraryView, UpdateLibraryFragment>().AsMultiInstance();
container.Register<IMobileLibraryBrowserView, MobileLibraryBrowserFragment>().AsMultiInstance();
container.Register<IPlaylistView, PlaylistActivity>().AsMultiInstance();
container.Register<ISyncView, SyncActivity>().AsMultiInstance();
container.Register<ISyncDownloadView, SyncDownloadActivity>().AsMultiInstance();
container.Register<ISyncMenuView, SyncMenuActivity>().AsMultiInstance();
Expand Down
4 changes: 2 additions & 2 deletions MPfm/MPfm.Android/Classes/Fragments/PlayerMetadataFragment.cs
@@ -1,4 +1,4 @@
// Copyright © 2011-2013 Yanick Castonguay
// Copyright © 2011-2013 Yanick Castonguay
//
// This file is part of MPfm.
//
Expand Down Expand Up @@ -54,7 +54,7 @@ public override View OnCreateView(LayoutInflater inflater, ViewGroup container,

#region IPlayerMetadataView implementation

public Action OnClickPlaylist { get; set; }
public Action OnOpenPlaylist { get; set; }
public Action OnToggleShuffle { get; set; }
public Action OnToggleRepeat { get; set; }

Expand Down

0 comments on commit de138ca

Please sign in to comment.