Skip to content

Commit

Permalink
Refactoring and revision
Browse files Browse the repository at this point in the history
  • Loading branch information
mjarlund committed Nov 20, 2016
1 parent 96b0ee1 commit c7aaad4
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 198 deletions.
78 changes: 40 additions & 38 deletions API/MBQuickPlayOverlayDll.cs → MBQuickPlayOverlayDll.cs
Expand Up @@ -3,25 +3,25 @@
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Interop;
using System.ComponentModel;
using MusicBeePlugin.Views;
using MusicBeePlugin.ViewModels;
using System.Linq;
using System.Collections.ObjectModel;
using MusicBeePlugin.Models;

namespace MusicBeePlugin
{
public static class ApiInterface
{
public static Plugin.MusicBeeApiInterface mbApiInterface { get; set; }
}

public partial class Plugin
{
private MusicBeeApiInterface mbApiInterface;
private PluginInfo about = new PluginInfo();
private SearchWindowViewModel swViewModel = new SearchWindowViewModel();

public PluginInfo Initialise(IntPtr apiInterfacePtr)
{
mbApiInterface = new MusicBeeApiInterface();
mbApiInterface.Initialise(apiInterfacePtr);
ApiInterface.mbApiInterface = this.mbApiInterface;
about.PluginInfoVersion = PluginInfoVersion;
about.Name = "QuickPlay Overlay";
about.Description = "Bind to a global hotkey to quickly search for and play tracks in your NowPlayingList without having to open the MusicBee UI.";
Expand All @@ -30,7 +30,7 @@ public PluginInfo Initialise(IntPtr apiInterfacePtr)
about.Type = PluginType.General;
about.VersionMajor = 1; // your plugin version
about.VersionMinor = 0;
about.Revision = 1;
about.Revision = 3;
about.MinInterfaceVersion = MinInterfaceVersion;
about.MinApiRevision = MinApiRevision;
about.ReceiveNotifications = (ReceiveNotificationFlags.PlayerEvents | ReceiveNotificationFlags.TagEvents);
Expand All @@ -40,6 +40,16 @@ public PluginInfo Initialise(IntPtr apiInterfacePtr)
return about;
}

private void InitialisePlugin()
{
swViewModel.NowPlayingList = GetNowPlayingList();
swViewModel.PlaySelectedSong = new RelayCommand(x =>
{
PlayNow(swViewModel.SelectedSong);
}, x => swViewModel.SelectedSong != null);

}

private void createMenuItem()
{
mbApiInterface.MB_AddMenuItem("mnuTools/QuickPlay Overlay", "QuickPlay Overlay", openSearchWindow);
Expand All @@ -48,6 +58,7 @@ private void createMenuItem()
private void openSearchWindow(object sender, EventArgs args)
{
SearchWindow window = new SearchWindow();
window.DataContext = swViewModel;
WindowInteropHelper helper = new WindowInteropHelper(window);
ElementHost.EnableModelessKeyboardInterop(window);

Expand Down Expand Up @@ -87,8 +98,6 @@ public bool Configure(IntPtr panelHandle)
// its up to you to figure out whether anything has changed and needs updating
public void SaveSettings()
{
// save any persistent settings in a sub-folder of this path
string dataPath = mbApiInterface.Setting_GetPersistentStoragePath();
}

// MusicBee is closing the plugin (plugin is being disabled by user or MusicBee is shutting down)
Expand All @@ -110,44 +119,37 @@ public void ReceiveNotification(string sourceFileUrl, NotificationType type)
{
case NotificationType.PluginStartup:
// perform startup initialisation
switch (mbApiInterface.Player_GetPlayState())
{
case PlayState.Playing:
case PlayState.Paused:
// ...
break;
}
InitialisePlugin();
break;
case NotificationType.TrackChanged:
string artist = mbApiInterface.NowPlaying_GetFileTag(MetaDataType.Artist);
// ...
case NotificationType.NowPlayingListChanged:
swViewModel.NowPlayingList = GetNowPlayingList();
break;
}

}

// return an array of lyric or artwork provider names this plugin supports
// the providers will be iterated through one by one and passed to the RetrieveLyrics/ RetrieveArtwork function in order set by the user in the MusicBee Tags(2) preferences screen until a match is found
public string[] GetProviders()
private ObservableCollection<Song> GetNowPlayingList()
{
return null;
}
ObservableCollection<Song> instance = new ObservableCollection<Song>();

// return lyrics for the requested artist/title from the requested provider
// only required if PluginType = LyricsRetrieval
// return null if no lyrics are found
public string RetrieveLyrics(string sourceFileUrl, string artist, string trackTitle, string album, bool synchronisedPreferred, string provider)
{
return null;
string[] fileUrls = new string[0];
mbApiInterface.NowPlayingList_QueryFilesEx(null, ref fileUrls);

foreach (var url in fileUrls)
{
Song song = new Song();
song.Url = url;
song.Name = mbApiInterface.Library_GetFileTag(url, MetaDataType.TrackTitle);
instance.Add(song);
}

return new ObservableCollection<Song>(instance.OrderBy(x => x.Name));
}

// return Base64 string representation of the artwork binary data from the requested provider
// only required if PluginType = ArtworkRetrieval
// return null if no artwork is found
public string RetrieveArtwork(string sourceFileUrl, string albumArtist, string album, string provider)
private void PlayNow(Song target)
{
//Return Convert.ToBase64String(artworkBinaryData)
return null;
NowPlayingList_FileActionDelegate FileAction = mbApiInterface.NowPlayingList_PlayNow;
FileAction(target.Url);
}
}

}
}
6 changes: 3 additions & 3 deletions MBQuickPlayOverlayDll.csproj
Expand Up @@ -87,14 +87,14 @@
<Reference Include="WindowsFormsIntegration" />
</ItemGroup>
<ItemGroup>
<Compile Include="ViewModels\RelayCommand.cs" />
<Compile Include="RelayCommand.cs" />
<Compile Include="Views\SearchWindow.xaml.cs">
<DependentUpon>SearchWindow.xaml</DependentUpon>
</Compile>
<Compile Include="API\MusicBeeApiInterface.cs" />
<Compile Include="MusicBeeApiInterface.cs" />
<Compile Include="ViewModels\SearchWindowViewModel.cs" />
<Compile Include="Models\Song.cs" />
<Compile Include="API\MBQuickPlayOverlayDll.cs" />
<Compile Include="MBQuickPlayOverlayDll.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
25 changes: 4 additions & 21 deletions Models/Song.cs
@@ -1,25 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MusicBeePlugin.Models
namespace MusicBeePlugin.Models
{
public class Song : Plugin
public class Song
{
private MusicBeeApiInterface mbApiInterface
{
get { return ApiInterface.mbApiInterface; }
}

public Song(string sourceFileUrl)
{
Url = sourceFileUrl;
TrackTitle = mbApiInterface.Library_GetFileTag(Url, MetaDataType.TrackTitle);
}

public string Url { get; }
public string TrackTitle { get; }
public string Url { get; set; }
public string Name { get; set; }
}
}
File renamed without changes.
File renamed without changes.
130 changes: 4 additions & 126 deletions ViewModels/SearchWindowViewModel.cs
@@ -1,134 +1,12 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using MusicBeePlugin;
using System.Collections.ObjectModel;
using System.Collections.ObjectModel;
using MusicBeePlugin.Models;

namespace MusicBeePlugin.ViewModels
{
public class SearchWindowViewModel : Plugin, INotifyPropertyChanged
public class SearchWindowViewModel
{
#region Properties
private MusicBeeApiInterface mbApiInterface
{
get { return ApiInterface.mbApiInterface; }
}
public ObservableCollection<Song> NowPlayingList { get; set; }

public ObservableCollection<Song> SearchList
{
get
{
return GetSongsMatchingKey();
}
}

public Song SelectedSong
{
get; set;
}

private string _TextBoxSearch;
public string TextBoxSearch
{
get { return _TextBoxSearch; }
set
{
_TextBoxSearch = value;
OnPropertyChanged();
OnPropertyChanged("SearchList");
}
}

#endregion

#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

#endregion

#region Commands
public RelayCommand PlaySelectedSongCommand { get; }
public RelayCommand GetNextSearchResult { get; }
#endregion


public SearchWindowViewModel()
{
NowPlayingList = LoadNowPlayingQueue();

PlaySelectedSongCommand = new RelayCommand(x =>
{
PlayNow(SelectedSong);
}, x => this.SelectedSong != null);

GetNextSearchResult = new RelayCommand(x =>
{
SearchList.GetEnumerator().MoveNext();
}, x => SearchList.Count() != 0);
}

#region Methods
private void PlayNow(Song target)
{
NowPlayingList_FileActionDelegate FileAction = mbApiInterface.NowPlayingList_PlayNow;
FileAction(target.Url);
}

private ObservableCollection<Song> LoadNowPlayingQueue()
{
ObservableCollection<Song> instance = new ObservableCollection<Song>();

string[] fileUrls = new string[0];
mbApiInterface.NowPlayingList_QueryFilesEx(null, ref fileUrls);

foreach (var url in fileUrls)
{
instance.Add(new Song(url));
}

return instance;
}


private ObservableCollection<Song> GetSongsMatchingKey()
{
ObservableCollection<Song> instance = new ObservableCollection<Song>();
var query = TextBoxSearch;

if (NowPlayingList.Count() == 0 || string.IsNullOrEmpty(query))
{
return instance;
}

try
{
NowPlayingList.Any(x => x.TrackTitle.StartsWith(query, StringComparison.CurrentCultureIgnoreCase));
}
catch(ArgumentNullException)
{
return instance;
}

foreach(Song song in NowPlayingList)
{
if (song.TrackTitle.StartsWith(query, StringComparison.CurrentCultureIgnoreCase))
instance.Add(song);

}

return instance;
}

#endregion

public Song SelectedSong { get; set; }
public RelayCommand PlaySelectedSong { get; set; }
}
}
16 changes: 6 additions & 10 deletions Views/SearchWindow.xaml
Expand Up @@ -2,7 +2,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:vm="clr-namespace:MusicBeePlugin.ViewModels"
Title="MainWindow"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
Expand All @@ -12,9 +11,7 @@
Topmost="True"
AllowsTransparency="True"
Background="Transparent">
<Window.DataContext>
<vm:SearchWindowViewModel/>
</Window.DataContext>

<!-- Content -->
<Grid Background="White">
<Grid.Effect>
Expand All @@ -28,25 +25,24 @@
<ComboBox x:Name="TextBoxSearch"
IsEditable="True"
IsTextSearchEnabled="True"
TextSearch.TextPath="TrackTitle"
ItemsSource="{Binding SearchList, UpdateSourceTrigger=PropertyChanged}"
TextSearch.TextPath="Name"
ItemsSource="{Binding NowPlayingList}"
SelectedItem="{Binding SelectedSong}"
Text="{Binding TextBoxSearch}"
Height="40"
Width="500"
MaxWidth="500"
FontSize="20"
VerticalContentAlignment="Center"
Grid.Row="1"
>
<ComboBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding PlaySelectedSongCommand}"/>
<KeyBinding Key="Down" Command="{Binding GetNextSearchResult}"/>
<KeyBinding Key="Enter" Command="{Binding PlaySelectedSong}"/>
</ComboBox.InputBindings>

<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding TrackTitle}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
Expand Down

0 comments on commit c7aaad4

Please sign in to comment.