Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

mfkl
mfkl

Posted on • Originally published atmfkl.github.io

     

PulseMusic - music player design with Skia and LibVLC

In February 2015,Anish Chandran, a Microsoft UX and Visual designer, posted onDribble andBehance an original music player UX concept.

In August 2018,Javier Suárez Ruiz implemented andpublished on GitHub a Xamarin.Forms (iOS/Android) UI implementation of the audio player view of the PulseMusic concept by Anish.

As mentioned in thereadme:

The main objective of the sample is to show the creation of the Player's UI (circular progress, rotating cover, etc.). This App is NOT a real player.

So... let's turn it into a real player withLibVLCSharp.

This is an extract from the existingPlayerView.xaml:

<controls:CircleProgressGrid.Row="0"VerticalOptions="FillAndExpand"HorizontalOptions="FillAndExpand"Progress="{Binding Progress}"LineBackgroundColor ="{StaticResource BlackColor}"ProgressColor="{StaticResource PlayerRedColor}"StrokeWidth="12"Margin="12"/><buttonCircle:CircleButtonCommand="{Binding PlayCommand}"FontIcon="FontAwesome"Icon="{Binding Icon}"FontSize="{StaticResource FontSize16}"TextColor="{StaticResource WhiteColor}"HeightRequest="60"WidthRequest="60"BackgroundColor="{StaticResource PlayerRedColor}"HorizontalOptions="Center"VerticalOptions="Center"/><GridGrid.Row="1"Margin="70, -24, 70, 0"><Grid.ColumnDefinitions><ColumnDefinitionWidth="Auto"/><ColumnDefinitionWidth="Auto"/><ColumnDefinitionWidth="Auto"/><ColumnDefinitionWidth="Auto"/></Grid.ColumnDefinitions><LabelGrid.Column="0"Text="{Binding StartTime, Converter={StaticResource TimeSpanToStringConverter}}"Style="{StaticResource TimeTextStyle}"/><controls:ToggleButtonGrid.Column="1"Checked="False"Animate="False"CheckedImage="playonce_on"UnCheckedImage="playonce_off"/><controls:TapImageGrid.Column="2"Source="shuffle"/><LabelGrid.Column="3"Text="{Binding RemainTime, Converter={StaticResource TimeSpanToStringConverter}}"Style="{StaticResource TimeTextStyle}"/></Grid>
Enter fullscreen modeExit fullscreen mode

TheBinding XAML keyword indicates the value is databinded to the corresponding ViewModel. For the demo code, Javier had used an artificial countdown to make the UI seem alive (ticks for position and time). Let's hook up a real player!

Xamarin.Forms has a pub/sub concept calledMessagingCenter, we will use it to propagate LibVLCSharp's playback events in the app.

readonlyMediaPlayer_mp;conststringURL="https://archive.org/download/ImagineDragons_201410/imagine%20dragons.mp4";publicvoidInit(){// create a libvlc media_mp.Media=newMedia(_libVLC,URL,Media.FromType.FromLocation);// disable video output, we only need audio_mp.Media.AddOption(":no-video");// subscribe to libvlc playback events_mp.TimeChanged+=TimeChanged;_mp.PositionChanged+=PositionChanged;_mp.LengthChanged+=LengthChanged;_mp.EndReached+=EndReached;_mp.Playing+=Playing;_mp.Paused+=Paused;}// when the libvlc mediaplayer events fire, publish an event with the MessagingCenterprivatevoidPositionChanged(objectsender,MediaPlayerPositionChangedEventArgse)=>MessagingCenter.Send(MessengerKeys.App,MessengerKeys.Position,e.Position);privatevoidPaused(objectsender,System.EventArgse)=>MessagingCenter.Send(MessengerKeys.App,MessengerKeys.Play,false);privatevoidPlaying(objectsender,System.EventArgse)=>MessagingCenter.Send(MessengerKeys.App,MessengerKeys.Play,true);privatevoidEndReached(objectsender,System.EventArgse)=>MessagingCenter.Send(MessengerKeys.App,MessengerKeys.EndReached);privatevoidLengthChanged(objectsender,MediaPlayerLengthChangedEventArgse)=>MessagingCenter.Send(MessengerKeys.App,MessengerKeys.Length,e.Length);privatevoidTimeChanged(objectsender,MediaPlayerTimeChangedEventArgse)=>MessagingCenter.Send(MessengerKeys.App,MessengerKeys.Time,e.Time);
Enter fullscreen modeExit fullscreen mode

Wecould also use the reverse event stream to control playback (one of several ways to do so).

constlongOFFSET=5000;// subscribe to UI app events for seeking.MessagingCenter.Subscribe<string>(MessengerKeys.App,MessengerKeys.Rewind,vm=>_mp.Time-=OFFSET);MessagingCenter.Subscribe<string>(MessengerKeys.App,MessengerKeys.Forward,vm=>_mp.Time+=OFFSET);
Enter fullscreen modeExit fullscreen mode

Now that our playback service is up and running, we need to use it from the ViewModel (which is bound to the UI). This is one way of doing so:

publicoverrideTaskLoadAsync(){_playbackService.Init();MessagingCenter.Subscribe<string,float>(MessengerKeys.App,MessengerKeys.Position,(app,position)=>Progress=position);MessagingCenter.Subscribe<string,long>(MessengerKeys.App,MessengerKeys.Time,(app,time)=>{RemainTime=TimeSpan.FromMilliseconds((double)newdecimal(_length-time));StartTime=TimeSpan.FromMilliseconds((double)newdecimal(time));});MessagingCenter.Subscribe<string,long>(MessengerKeys.App,MessengerKeys.Length,(app,length)=>_length=length);MessagingCenter.Subscribe<string>(MessengerKeys.App,MessengerKeys.EndReached,app=>EndReached());LoadSong();_playbackService.Play(true);returnbase.LoadAsync();}
Enter fullscreen modeExit fullscreen mode

Updating ViewModel properties such asProgress,RemainTime andStartTime will automatically refresh the UI and trigger Skia animations accordingly.

Play andPause, as well as seeking, has also been bound from the UI to the libvlc engine usingLibVLCSharp.

Credits:

Note: I deliberately picked a Creative Commons licensed version of the song "Imagine Dragons - Radioactive" (remix). Seehttps://archive.org/details/ImagineDragons_201410 and itslicense for more information.

This sample is available on theVideoLAN GitLab.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

.NET @ VideoLAN
  • Joined

More frommfkl

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp