public string Title;
public string Artist;
public string AlbumCover;
+ public string AlbumName;
+ }
+
+ /// <summary>
+ /// A custom EventArgs with bool field
+ /// </summary>
+ public class MusicPlayerStateEventArgs : EventArgs
+ {
+ public bool IsPlaying;
}
/// <summary>
private EventHandler<MusicPlayerInfoEventArgs> MusicPlayerInfoListener;
/// <summary>
+ /// An event handler for handling music player state change event
+ /// </summary>
+ private EventHandler<MusicPlayerStateEventArgs> MusicPlayerStateChanged;
+
+ /// <summary>
/// An event handler for handling the percentage of the progressbar
/// </summary>
private EventHandler<MusicPlayerProgressEventArgs> MusicPlayerProgressListener;
currentMusic = value;
/// 1. Stop the player
- if (playerInstance.State == PlayerState.Playing)
+ if (playerInstance.State == PlayerState.Playing || playerInstance.State == PlayerState.Paused)
{
StopPlayer();
}
/// 2. Play the current music
- StartPlayerAsync((currentMusic.MediaContentInformation as AudioInformation).FilePath);
+ StartPlayerAsync((currentMusic.MediaContentInformation as AudioInformation).FilePath);
/// 3. Update the information of the current music
MusicPlayerInfoListener?.Invoke(this, new MusicPlayerInfoEventArgs()
Title = (currentMusic.MediaContentInformation as AudioInformation).Title,
Artist = (currentMusic.MediaContentInformation as AudioInformation).Artist,
AlbumCover = ((currentMusic.MediaContentInformation as AudioInformation).ThumbnailPath.Length != 0) ? (currentMusic.MediaContentInformation as AudioInformation).ThumbnailPath : "img_media_no_contents.png",
+ AlbumName = (currentMusic.MediaContentInformation as AudioInformation).Album
});
/// 4. Update the progressbar of the current music
{
Progress = (playerInstance.State == PlayerState.Idle || playerInstance.State == PlayerState.Preparing) ? 0 : Convert.ToDouble(playerInstance.GetPlayPosition()) / (currentMusic.MediaContentInformation as AudioInformation).Duration,
});
+
+ MusicPlayerStateChanged?.Invoke(this, new MusicPlayerStateEventArgs()
+ {
+ IsPlaying = true
+ });
}
}
}
private void InitializePlayer()
{
playerInstance = new Player();
-
playerInstance.PlaybackCompleted += ((s, e) =>
{
StopPlayer();
+
+ MusicPlayerStateChanged?.Invoke(this, new MusicPlayerStateEventArgs()
+ {
+ IsPlaying = false
+ });
});
playerInstance.PlaybackInterrupted += ((s, e) =>
DbgPort.E("Error : " + Enum.GetName(typeof(PlayerError), e.Reason));
StopPlayer();
+
+ MusicPlayerStateChanged?.Invoke(this, new MusicPlayerStateEventArgs()
+ {
+ IsPlaying = false
+ });
});
playerInstance.ErrorOccurred += ((s, e) =>
DbgPort.E("Error : " + Enum.GetName(typeof(PlayerError), e.Error));
StopPlayer();
+
+ MusicPlayerStateChanged?.Invoke(this, new MusicPlayerStateEventArgs()
+ {
+ IsPlaying = false
+ });
});
}
}
/// <summary>
+ /// Toggles pause and play the current music
+ /// </summary>
+ public void TogglePausePlay()
+ {
+ if (playerInstance.State == PlayerState.Playing)
+ {
+ try
+ {
+ playerInstance.Pause();
+
+ MusicPlayerStateChanged?.Invoke(this, new MusicPlayerStateEventArgs()
+ {
+ IsPlaying = false
+ });
+ }
+ catch (Exception e)
+ {
+ DbgPort.E("Error : " + e.Message);
+ }
+ StopProgressbarTimer();
+ }
+ else if (playerInstance.State == PlayerState.Paused)
+ {
+ try
+ {
+ playerInstance.Start();
+
+ MusicPlayerStateChanged?.Invoke(this, new MusicPlayerStateEventArgs()
+ {
+ IsPlaying = true
+ });
+ }
+ catch (Exception e)
+ {
+ DbgPort.E("Error : " + e.Message);
+ }
+ StartProgressbarTimer();
+ }
+ }
+
+ /// <summary>
/// Stops the current music
/// </summary>
public void StopPlayer()
{
MusicPlayerProgressListener += listener;
}
+
+ /// <summary>
+ /// A method adds EventHandler to SetCurrentMusicProgressListener
+ /// </summary>
+ /// <param name="listener">The EventHandler for adding</param>
+ public void SetMusicPlayerStateChangedListener(EventHandler<MusicPlayerStateEventArgs> listener)
+ {
+ MusicPlayerStateChanged += listener;
+ }
}
}
using System.ComponentModel;
using TVMediaHub.Tizen.Models;
+using TVMediaHub.Tizen.Utils;
+using Xamarin.Forms;
namespace TVMediaHub.Tizen.ViewModels
{
public string AlbumArtist { get; private set; }
/// <summary>
+ /// The album name to be shown
+ /// </summary>
+ public string AlbumName { get; private set; }
+
+ /// <summary>
/// The album cover to be shown
/// </summary>
public string AlbumCover { get; private set; }
+ public Command MusicPlayerButtonClickCommand { get; private set; }
+
+ public string IconPath { get; private set; }
+
/// <summary>
/// An event that is occurred when property of ViewModel is changed
/// </summary>
AlbumTitle = "Title";
AlbumArtist = "Artist";
AlbumCover = "img_media_no_contents.png";
+ AlbumName = "Album";
+
+ MusicPlayerButtonClickCommand = new Command(() =>
+ {
+ MusicPlayerModel.Instance.TogglePausePlay();
+ });
+
+ IconPath = "btn_music_info_play.png";
MusicPlayerModel.Instance.SetCurrentMusicInfoListener((e, args) =>
{
AlbumCover = args.AlbumCover;
OnPropertyChanged("AlbumCover");
+
+ AlbumName = args.AlbumName;
+ OnPropertyChanged("AlbumName");
});
MusicPlayerModel.Instance.SetCurrentMusicProgressListener((e, arg) =>
}
ProgressBarPercentage = arg.Progress;
-
OnPropertyChanged("ProgressBarPercentage");
});
+
+ MusicPlayerModel.Instance.SetMusicPlayerStateChangedListener((e, arg) => {
+ if(arg == null)
+ {
+ return;
+ }
+
+ if (arg.IsPlaying)
+ {
+ IconPath = "btn_music_info_pause.png";
+ }
+ else
+ {
+ IconPath = "btn_music_info_play.png";
+ }
+ OnPropertyChanged("IconPath");
+ });
}
}
}
<Grid x:Name="GroupContentArea"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.926}"
- RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.085}">
- </Grid>
+ RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.0737}">
+ </Grid>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" ?>
-<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="TVMediaHub.Tizen.Views.MusicPlayer">
+<RelativeLayout xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:Utils="clr-namespace:TVMediaHub.Tizen.Utils"
+ x:Class="TVMediaHub.Tizen.Views.MusicPlayer">
+ <Utils:NinePatch x:Name="MusicPlayerShadowImage"
+ Source="img_music_list_focused_shadow.9.png" />
<Image x:Name="MusicPlayerAlbumArt"
- Source="{Binding AlbumCover}"
- WidthRequest="300"
- HeightRequest="300"
- HorizontalOptions="Center"/>
+ Source="{Binding AlbumCover}" />
+ <Image x:Name="MusicPlayerPausePlayButton"
+ Source="{Binding IconPath}" />
+ <Button x:Name="MusicPlayerFocusArea"
+ Command="{Binding MusicPlayerButtonClickCommand}"
+ Focused="MusicPlayerFocusAreaFocused"
+ Unfocused="MusicPlayerFocusAreaUnfocused"
+ Opacity="0" />
<Label x:Name="MusicPlayerTitle"
Text="{Binding AlbumTitle}"
- HorizontalOptions="Center"/>
+ LineBreakMode="TailTruncation" />
<Label x:Name="MusicPlayerArtist"
Text="{Binding AlbumArtist}"
- HorizontalOptions="Center"/>
- <ProgressBar x:Name="MusicPlayerProgressbar"
- Progress="{Binding ProgressBarPercentage}"/>
-</StackLayout>
\ No newline at end of file
+ LineBreakMode="TailTruncation" />
+ <Label x:Name="MusicPlayerAlbum"
+ Text="{Binding AlbumName}"
+ LineBreakMode="TailTruncation" />
+</RelativeLayout>
\ No newline at end of file
* limitations under the License.
*/
+using System;
+using Tizen.Xamarin.Forms.Extension;
+using TVMediaHub.Tizen.Utils;
using TVMediaHub.Tizen.ViewModels;
using Xamarin.Forms;
/// <summary>
/// A custom ContentPage for displaying the music player
/// </summary>
- public partial class MusicPlayer : StackLayout
+ public partial class MusicPlayer : RelativeLayout
{
+ private bool IsInitailized;
+ private Rectangle ShadowImageFocusedBounds;
+ private Rectangle ShadowImageNormalBounds;
+
+ private Rectangle AlbumImageFocusedBounds;
+ private Rectangle AlbumImageNormalBounds;
+
+ private Rectangle PausePlayButtonBounds;
+
+ private Rectangle TitleBounds;
+ private Rectangle ArtistBounds;
+ private Rectangle AlbumNameBounds;
+
/// <summary>
/// A constructor
/// </summary>
public MusicPlayer()
{
BindingContext = MusicPlayerViewModelLocator.ViewModel;
-
+ IsInitailized = false;
InitializeComponent();
+ InitializeSize();
+ }
+
+ private void MusicPlayerFocusAreaFocused(object sender, FocusEventArgs e)
+ {
+ MusicPlayerShadowImage.LayoutTo(ShadowImageFocusedBounds);
+ MusicPlayerAlbumArt.LayoutTo(AlbumImageFocusedBounds);
+ }
+
+ private void MusicPlayerFocusAreaUnfocused(object sender, FocusEventArgs e)
+ {
+ MusicPlayerShadowImage.LayoutTo(ShadowImageNormalBounds);
+ MusicPlayerAlbumArt.LayoutTo(AlbumImageNormalBounds);
+ }
+
+ private void InitializeSize()
+ {
+ WidthRequest = SizeUtils.GetWidthSize(546);
+ HeightRequest = SizeUtils.GetHeightSize(546);
+ Margin = new Thickness(SizeUtils.GetWidthSize(-14), SizeUtils.GetHeightSize(-14), 0, 0);
+
+
+ MusicPlayerShadowImage.BorderTop = SizeUtils.GetHeightSize(67);
+ MusicPlayerShadowImage.BorderBottom = SizeUtils.GetHeightSize(67);
+ MusicPlayerShadowImage.BorderLeft = SizeUtils.GetWidthSize(67);
+ MusicPlayerShadowImage.BorderRight = SizeUtils.GetWidthSize(67);
+
+ ShadowImageFocusedBounds = new Rectangle(0, 0, SizeUtils.GetWidthSize(546), SizeUtils.GetHeightSize(546));
+ ShadowImageNormalBounds = new Rectangle(SizeUtils.GetWidthSize(6), SizeUtils.GetHeightSize(6), SizeUtils.GetWidthSize(532), SizeUtils.GetHeightSize(532));
+
+ AlbumImageFocusedBounds = new Rectangle(SizeUtils.GetWidthSize(64), SizeUtils.GetHeightSize(64), SizeUtils.GetWidthSize(418), SizeUtils.GetHeightSize(418));
+ AlbumImageNormalBounds = new Rectangle(SizeUtils.GetWidthSize(70), SizeUtils.GetHeightSize(70), SizeUtils.GetWidthSize(406), SizeUtils.GetHeightSize(406));
+
+ PausePlayButtonBounds = new Rectangle(SizeUtils.GetWidthSize(223), SizeUtils.GetHeightSize(223), SizeUtils.GetWidthSize(100), SizeUtils.GetHeightSize(100));
+
+ TitleBounds = new Rectangle(SizeUtils.GetWidthSize(72), SizeUtils.GetHeightSize(498), SizeUtils.GetWidthSize(406), SizeUtils.GetHeightSize(32));
+ ArtistBounds = new Rectangle(SizeUtils.GetWidthSize(72), SizeUtils.GetHeightSize(542), SizeUtils.GetWidthSize(418), SizeUtils.GetHeightSize(28));
+ AlbumNameBounds = new Rectangle(SizeUtils.GetWidthSize(72), SizeUtils.GetHeightSize(572), SizeUtils.GetWidthSize(418), SizeUtils.GetHeightSize(28));
+
+ MusicPlayerTitle.FontSize = SizeUtils.GetFontSize(28);
+
+ MusicPlayerArtist.FontSize = SizeUtils.GetFontSize(24);
+ MusicPlayerArtist.Opacity = 0.5;
+
+ MusicPlayerAlbum.FontSize = SizeUtils.GetFontSize(24);
+ MusicPlayerAlbum.Opacity = 0.25;
+ }
+
+ protected override void LayoutChildren(double x, double y, double width, double height)
+ {
+ if (IsInitailized == false)
+ {
+ base.LayoutChildren(x, y, width, height);
+ MusicPlayerAlbumArt.Layout(AlbumImageNormalBounds);
+ MusicPlayerTitle.Layout(TitleBounds);
+ MusicPlayerArtist.Layout(ArtistBounds);
+ MusicPlayerAlbum.Layout(AlbumNameBounds);
+ MusicPlayerShadowImage.Layout(ShadowImageNormalBounds);
+ MusicPlayerPausePlayButton.Layout(PausePlayButtonBounds);
+ MusicPlayerFocusArea.Layout(PausePlayButtonBounds);
+ IsInitailized = true;
+ }
}
}
}
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
<RelativeLayout RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
- <Views:FooterDeleteStatus x:Name="FooterDelete" IsVisible="False"
+ <Views:FooterDeleteStatus x:Name="FooterDelete"
+ IsVisible="False"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
- SelectedCount="{Binding SelectedCount}"/>
- <Views:FooterNormalStatus x:Name="FooterNormal" IsVisible="True"
+ SelectedCount="{Binding SelectedCount}" />
+ <Views:FooterNormalStatus x:Name="FooterNormal"
+ IsVisible="True"
IsFooterEnabled="True"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
SourceList="{Binding SourceList}"
SortOptions="{Binding SortOptions}"
- OptionList="{Binding OptionList}"/>
+ OptionList="{Binding OptionList}" />
</RelativeLayout>
- <Views:MusicPlayer x:Name="MusicPlayer"
- RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.855}"
- RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.3}"
- RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.0}">
- </Views:MusicPlayer>
- <ScrollView x:Name="MusicTabScrollView"
- RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.8545}"
- RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.7386}"
- RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.2614}"
- Orientation="Horizontal" IsVisible="False">
- <StackLayout x:Name="MusicContentView"
- Orientation="Horizontal"
- HorizontalOptions="Start"
- RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.1}">
- </StackLayout>
- </ScrollView>
- <StackLayout x:Name="MusicNoContents" Orientation="Vertical" IsVisible="True"
+
+ <StackLayout x:Name="MusicTabContents"
+ RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.855}"
+ RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}"
+ Orientation="Horizontal">
+ <Views:MusicPlayer x:Name="MusicPlayer" />
+ <ScrollView x:Name="MusicTabScrollView"
+ Orientation="Horizontal"
+ IsVisible="False">
+ <StackLayout x:Name="MusicContentView"
+ Orientation="Horizontal"
+ HorizontalOptions="Start"
+ RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.1}">
+ </StackLayout>
+ </ScrollView>
+ </StackLayout>
+
+ <StackLayout x:Name="MusicNoContents"
+ Orientation="Vertical"
+ IsVisible="True"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
- <Image x:Name="ImgNoContents" Source="img_media_no_contents.png" HorizontalOptions="Center"/>
- <Label x:Name="LabelNoContents" Text="No content" FontFamily="BreezeSans" HorizontalOptions="Center"/>
+ <Image x:Name="ImgNoContents"
+ Source="img_media_no_contents.png"
+ HorizontalOptions="Center" />
+ <Label x:Name="LabelNoContents"
+ Text="No content"
+ FontFamily="BreezeSans"
+ HorizontalOptions="Center" />
</StackLayout>
</RelativeLayout>
</mh:ContentPageEx>
\ No newline at end of file
* limitations under the License.
*/
-using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
-using System.ComponentModel;
-using System.Threading;
using System.Windows.Input;
using TVMediaHub.Tizen.Controls;
using TVMediaHub.Tizen.DataModels;
ImgNoContents.WidthRequest = SizeUtils.GetWidthSize(68);
LabelNoContents.HeightRequest = SizeUtils.GetHeightSize(32);
LabelNoContents.FontSize = SizeUtils.GetFontSize(28);
- MusicContentView.Padding = new Thickness(0, SizeUtils.GetHeightSize(74));
MusicContentView.Spacing = SizeUtils.GetWidthSize(60);
+ MusicTabContents.Padding = new Thickness(0, SizeUtils.GetHeightSize(74), 0, 0);
}
/// <summary>
/// <param name="e">A SelectedItemChanged event's argument</param>
private void OnSourceChanged(object sender, SelectedItemChangedEventArgs e)
{
- String storageName = e.SelectedItem as String;
+ string storageName = e.SelectedItem as string;
//BottomButtonList.Clear();
ChangeSourceCommand?.Execute(storageName);