Added base classes to encapsulate metadata in media

This commit is contained in:
watsonb8 2019-05-24 15:59:26 -04:00
parent 93be6dc100
commit 80e9a4543d
12 changed files with 222 additions and 97 deletions

View File

@ -0,0 +1,35 @@
using System;
namespace Aurora.Backend.Models.Media
{
public class AudioMetadata : BaseMetadata
{
public void AutioMetadata()
{
}
/// <summary>
/// The title of the song.
/// </summary>
/// <value></value>
public string Title { get; set; }
/// <summary>
/// The artist of the song.
/// </summary>
/// <value></value>
public string Artist { get; set; }
/// <summary>
/// The album from which the song belongs.
/// </summary>
/// <value></value>
public string Album { get; set; }
/// <summary>
/// The duration of the song.
/// </summary>
/// <value></value>
public string Duration { get; set; }
}
}

View File

@ -1,7 +1,7 @@
using System; using System;
using System.IO; using System.IO;
namespace Aurora.Backend.Models namespace Aurora.Backend.Models.Media
{ {
public abstract class BaseMedia public abstract class BaseMedia
{ {
@ -17,36 +17,6 @@ namespace Aurora.Backend.Models
#region Properties #region Properties
public string Id { get; private set; } public string Id { get; private set; }
/// <summary>
/// The title of the song.
/// </summary>
/// <value></value>
public string Title { get; set; }
/// <summary>
/// The artist of the song.
/// </summary>
/// <value></value>
public string Artist { get; set; }
/// <summary>
/// The album from which the song belongs.
/// </summary>
/// <value></value>
public string Album { get; set; }
/// <summary>
/// The duration of the song.
/// </summary>
/// <value></value>
public string Duration { get; set; }
/// <summary>
/// Extra data associated with a song.
/// </summary>
/// <value></value>
public object Metadata { get; set; }
#endregion Properties #endregion Properties
public virtual void Load() public virtual void Load()
@ -59,6 +29,9 @@ namespace Aurora.Backend.Models
_loaded = false; _loaded = false;
} }
public abstract MediaTypeEnum MediaType { get; }
/// <summary> /// <summary>
/// Gets or sets the data stream that holds the song. /// Gets or sets the data stream that holds the song.
/// </summary> /// </summary>
@ -67,10 +40,6 @@ namespace Aurora.Backend.Models
{ {
get get
{ {
//if (!_loaded)
//{
// throw new InvalidOperationException("Must be loaded first");
//}
return _stream; return _stream;
} }
protected set protected set
@ -81,7 +50,5 @@ namespace Aurora.Backend.Models
} }
} }
} }
} }
} }

View File

@ -0,0 +1,17 @@
using System;
namespace Aurora.Backend.Models.Media
{
public class BaseMetadata
{
public BaseMetadata()
{
}
/// <summary>
/// Extra data associated with a song.
/// </summary>
/// <value></value>
public object ExtraData { get; set; }
}
}

View File

@ -1,18 +1,26 @@
using System; using System;
using System.IO; using System.IO;
namespace Aurora.Backend.Models namespace Aurora.Backend.Models.Media
{ {
public class LocalAudio : BaseMedia public class LocalAudio : BaseMedia
{ {
public LocalAudio(FileInfo fileInfo) public LocalAudio(FileInfo fileInfo)
{ {
File = fileInfo; File = fileInfo;
LoadMetadata();
} }
#region Properties #region Properties
public FileInfo File { get; private set; } public FileInfo File { get; private set; }
public AudioMetadata Metadata { get; private set; }
public override MediaTypeEnum MediaType
{
get { return MediaTypeEnum.Audio; }
}
#endregion Properties #endregion Properties
/// <summary> /// <summary>
@ -41,5 +49,18 @@ namespace Aurora.Backend.Models
} }
base.Unload(); base.Unload();
} }
private void LoadMetadata()
{
TagLib.File tagFile = TagLib.File.Create(File.FullName);
Metadata = new AudioMetadata()
{
Title = tagFile.Tag.Title,
Album = tagFile.Tag.Album,
Artist = tagFile.Tag.FirstAlbumArtist,
ExtraData = tagFile.Tag
};
}
} }
} }

View File

@ -0,0 +1,9 @@
using System;
namespace Aurora.Backend.Models.Media
{
public enum MediaTypeEnum
{
Audio,
Video,
}
}

View File

@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using Aurora.Backend.Models; using Aurora.Backend.Models.Media;
using Aurora.Backend.Utils; using Aurora.Backend.Utils;
namespace Aurora.Backend.Services namespace Aurora.Backend.Services
@ -14,7 +14,6 @@ namespace Aurora.Backend.Services
private string _extensions = ".wav,.mp3,.aiff,.flac,.m4a,.m4b,.wma"; private string _extensions = ".wav,.mp3,.aiff,.flac,.m4a,.m4b,.wma";
private Dictionary<string, BaseMedia> _library; private Dictionary<string, BaseMedia> _library;
#endregion Fields #endregion Fields
public LibraryService() public LibraryService()
@ -50,13 +49,7 @@ namespace Aurora.Backend.Services
{ {
TagLib.File tagFile = TagLib.File.Create(file.FullName); TagLib.File tagFile = TagLib.File.Create(file.FullName);
BaseMedia song = new LocalAudio(file) BaseMedia song = new LocalAudio(file);
{
Title = tagFile.Tag.Title,
Album = tagFile.Tag.Album,
Artist = tagFile.Tag.FirstAlbumArtist
};
_library.Add(song.Id, song); _library.Add(song.Id, song);
} }
} }

View File

@ -1,5 +1,5 @@
using System; using System;
using Aurora.Backend.Models; using Aurora.Backend.Models.Media;
using LibVLCSharp.Shared; using LibVLCSharp.Shared;
namespace Aurora.Backend.Services.PlayerService namespace Aurora.Backend.Services.PlayerService
@ -54,10 +54,10 @@ namespace Aurora.Backend.Services.PlayerService
/// </summary> /// </summary>
public void Play() public void Play()
{ {
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(_state, PlaybackState.Playing)); PlaybackState oldState = _state;
_state = PlaybackState.Playing; _state = PlaybackState.Playing;
_mediaPlayer.Play(); _mediaPlayer.Play();
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
} }
/// <summary> /// <summary>
@ -65,9 +65,10 @@ namespace Aurora.Backend.Services.PlayerService
/// </summary> /// </summary>
public void Pause() public void Pause()
{ {
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(_state, PlaybackState.Buffering)); PlaybackState oldState = _state;
_state = PlaybackState.Buffering; _state = PlaybackState.Buffering;
_mediaPlayer.Pause(); _mediaPlayer.Pause();
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
} }
/// <summary> /// <summary>
@ -75,9 +76,10 @@ namespace Aurora.Backend.Services.PlayerService
/// </summary> /// </summary>
public void Stop() public void Stop()
{ {
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(_state, PlaybackState.Stopped)); PlaybackState oldState = _state;
_state = PlaybackState.Stopped; _state = PlaybackState.Stopped;
_mediaPlayer.Stop(); _mediaPlayer.Stop();
PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
} }
public void Enqueue(BaseMedia song) public void Enqueue(BaseMedia song)

View File

@ -1,10 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Aurora.Frontend.Components.MediaPlayer.Player"> <ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Aurora.Frontend.Components.MediaPlayer.Player">
<ContentView.Content> <ContentView.Content>
<StackLayout Orientation="Horizontal"> <Grid>
<Button Text="Previous" Command="{Binding PreviousCommand}" WidthRequest="100" HeightRequest="50"/> <Grid.ColumnDefinitions>
<Button Text="{Binding PlayButtonText}" Command="{Binding PlayCommand}" WidthRequest="100" HeightRequest="50"/> <ColumnDefinition
<Button Text="Next" Command="{Binding NextCommand}" WidthRequest="100" HeightRequest="50"/> Width="100"/>
</StackLayout> <ColumnDefinition
Width="*"/>
</Grid.ColumnDefinitions>
<StackLayout
Grid.Column="0">
<Label
Text="{Binding SongName}"/>
<Label
Text="{Binding ArtistName}"/>
</StackLayout>
<StackLayout
Grid.Column="1"
Orientation="Horizontal">
<Button
Text="Previous"
Command="{Binding PreviousCommand}"
WidthRequest="100"
HeightRequest="50"/>
<Button
Text="{Binding PlayButtonText}"
Command="{Binding PlayCommand}"
WidthRequest="100"
HeightRequest="50"/>
<Button
Text="Next"
Command="{Binding NextCommand}"
WidthRequest="100"
HeightRequest="50"/>
</StackLayout>
</Grid>
</ContentView.Content> </ContentView.Content>
</ContentView> </ContentView>

View File

@ -17,12 +17,11 @@ namespace Aurora.Frontend.Views.Main
BindingContext = new MainViewModel(); BindingContext = new MainViewModel();
MasterPage.ListView.ItemSelected += ListView_ItemSelected; MasterPage.ListView.ItemSelected += ListView_ItemSelected;
//Set initial view from first item in list Appearing += OnAppearing;
ObservableCollection<NavigationGroupItem> screenList = (ObservableCollection<NavigationGroupItem>)MasterPage.ListView.ItemsSource; }
var view = (View)Activator.CreateInstance(screenList.FirstOrDefault().FirstOrDefault().TargetType); ~MainView()
{
ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent"); Appearing -= OnAppearing;
viewContent.Content = view;
} }
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e) private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
@ -38,6 +37,23 @@ namespace Aurora.Frontend.Views.Main
MasterPage.ListView.SelectedItem = null; MasterPage.ListView.SelectedItem = null;
} }
/// <summary>
/// Event handler for page appearing.
/// </summary>
/// <param name="sender">The object that fired the event.</param>
/// <param name="args">The event arguments</param>
private void OnAppearing(object sender, EventArgs args)
{
//Set initial view from first item in list
ObservableCollection<NavigationGroupItem> screenList = (ObservableCollection<NavigationGroupItem>)MasterPage.ListView.ItemsSource;
var view = (View)Activator.CreateInstance(screenList.FirstOrDefault().FirstOrDefault().TargetType);
ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent");
viewContent.Content = view;
MasterPage.ListView.SelectedItem = screenList.FirstOrDefault();
}
} }
} }

View File

@ -1,9 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:components="clr-namespace:Aurora.Frontend.Components" xmlns:mp="clr-namespace:Aurora.Frontend.Components.MediaPlayer" x:Class="Aurora.Frontend.Views.MainView.PageContainer"> <ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:components="clr-namespace:Aurora.Frontend.Components"
xmlns:mp="clr-namespace:Aurora.Frontend.Components.MediaPlayer"
x:Class="Aurora.Frontend.Views.MainView.PageContainer">
<ContentPage.Content> <ContentPage.Content>
<StackLayout> <Grid>
<ContentPresenter x:Name="ViewContent"/> <Grid.RowDefinitions>
<mp:Player HorizontalOptions="CenterAndExpand" VerticalOptions="End" HeightRequest="200"/> <RowDefinition
</StackLayout> Height="*"/>
<RowDefinition
Height="50"/>
</Grid.RowDefinitions>
<ContentPresenter
Grid.Row="0"
x:Name="ViewContent"/>
<mp:Player
Grid.Row="1"
HorizontalOptions="CenterAndExpand"
VerticalOptions="End"
HeightRequest="200"/>
</Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View File

@ -1,50 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" <ContentView
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:songs="clr-namespace:Aurora.Frontend.Views.Songs" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid" xmlns:songs="clr-namespace:Aurora.Frontend.Views.Songs"
x:Class="Aurora.Frontend.Views.Songs.SongsView"> xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid"
x:Class="Aurora.Frontend.Views.Songs.SongsView">
<ContentPage.BindingContext> <ContentPage.BindingContext>
<songs:SongsViewModel x:Name="songsViewModel"/> <songs:SongsViewModel
x:Name="songsViewModel"/>
</ContentPage.BindingContext> </ContentPage.BindingContext>
<ContentPage.Content> <ContentPage.Content>
<dg:DataGrid ItemsSource="{Binding SongsList}" SelectionEnabled="True" SelectedItem="{Binding SelectedSong}" <dg:DataGrid
RowHeight="30" HeaderHeight="50" BorderColor="#CCCCCC" HeaderBackground="#E0E6F8" > ItemsSource="{Binding SongsList}"
SelectionEnabled="True"
<!-- Header --> SelectedItem="{Binding SelectedSong}"
RowHeight="30"
HeaderHeight="50"
BorderColor="#CCCCCC"
HeaderBackground="#E0E6F8"><!-- Header -->
<dg:DataGrid.HeaderFontSize> <dg:DataGrid.HeaderFontSize>
<OnIdiom x:TypeArguments="x:Double"> <OnIdiom
x:TypeArguments="x:Double">
<OnIdiom.Tablet>15</OnIdiom.Tablet> <OnIdiom.Tablet>15</OnIdiom.Tablet>
<OnIdiom.Phone>13</OnIdiom.Phone> <OnIdiom.Phone>13</OnIdiom.Phone>
<OnIdiom.Desktop>20</OnIdiom.Desktop> <OnIdiom.Desktop>20</OnIdiom.Desktop>
</OnIdiom> </OnIdiom>
</dg:DataGrid.HeaderFontSize> </dg:DataGrid.HeaderFontSize><!-- Columns -->
<!-- Columns -->
<dg:DataGrid.Columns> <dg:DataGrid.Columns>
<dg:DataGridColumn Title="" Width="40"> <dg:DataGridColumn
Title=""
Width="40">
<dg:DataGridColumn.CellTemplate> <dg:DataGridColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Button Text="Play" Command="{Binding PlayCommand}" BindingContext="{x:Reference songsViewModel}" /> <Button
Text="Play"
Command="{Binding PlayCommand}"
BindingContext="{x:Reference songsViewModel}"/>
</DataTemplate> </DataTemplate>
</dg:DataGridColumn.CellTemplate> </dg:DataGridColumn.CellTemplate>
</dg:DataGridColumn> </dg:DataGridColumn>
<dg:DataGridColumn Title="Title" PropertyName="Title" Width="2*" /> <dg:DataGridColumn
<dg:DataGridColumn Title="Album" PropertyName="Album" Width="0.95*"/> Title="Title"
<dg:DataGridColumn Title="Artist" PropertyName="Artist" Width="1*"/> PropertyName="Metadata.Title"
<dg:DataGridColumn Title="Duration" PropertyName="Duration"/> Width="2*"/>
</dg:DataGrid.Columns> <dg:DataGridColumn
Title="Album"
<!-- Row Colors --> PropertyName="Metadata.Album"
Width="0.95*"/>
<dg:DataGridColumn
Title="Artist"
PropertyName="Metadata.Artist"
Width="1*"/>
<dg:DataGridColumn
Title="Duration"
PropertyName="Metadata.Duration"/>
</dg:DataGrid.Columns><!-- Row Colors -->
<dg:DataGrid.RowsBackgroundColorPalette> <dg:DataGrid.RowsBackgroundColorPalette>
<dg:PaletteCollection> <dg:PaletteCollection>
<Color>#F2F2F2</Color> <Color>#F2F2F2</Color>
<Color>#FFFFFF</Color> <Color>#FFFFFF</Color>
</dg:PaletteCollection> </dg:PaletteCollection>
</dg:DataGrid.RowsBackgroundColorPalette> </dg:DataGrid.RowsBackgroundColorPalette>
</dg:DataGrid> </dg:DataGrid>
</ContentPage.Content> </ContentPage.Content>
</ContentView> </ContentView>

View File

@ -1,5 +1,5 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Aurora.Backend.Models; using Aurora.Backend.Models.Media;
using Aurora.Backend.Services; using Aurora.Backend.Services;
using Aurora.Backend.Services.PlayerService; using Aurora.Backend.Services.PlayerService;
using Xamarin.Forms; using Xamarin.Forms;