Some days ago saw the news that Windows10 's own Windows Media Player will support FLAC lossless playback, and the current player is using the Bass Audio Library to support lossless playback, the use of Bass Audio library not to say, not many documents, Encounter problems on-line search for half a day can not find the answer is really worried death, so intend to my music player to do some, this time back to the WMP kernel.
I believe that the development of the WPF Media application of the students know that the new one mediaplayer can achieve the operation of the media, and this mediaplayer is actually used in the current operating system of Windows Media Player, support play pause stop, Playback rate adjustment, volume settings (bass volume setting is very painful, will even the system volume is adjusted), provide media open, media end, play error 3 events, so if you want to do a music player, and then the media status of the judgment, as well as the addition of media status/playback progress changes in the event is almost. Because it is redo, so only to achieve a basic function (playback control, collection, playback mode) and a few personality features (music statistics, timing stop, the display of the progress of the show), while the bug is still a lot, still in development, if interested can be developed together Yo, the project has been uploaded to TFS, The address is http://llyn23.visualstudio.com.
Debug Catalog File Download: Http://yun.baidu.com/s/1xYWua
Solution Project Source code download: Http://yun.baidu.com/s/1mguWDCG
1. Build CoreHelper.cs
This player core class contains media playback, add cancel favorites, toggle playback mode, song file reading, Media Library/playlist/player configuration etc.
2. Saving and reading data
When the program starts (Onstartup), the loaded XML file is deserialized into an object, saved with a media library, a playlist, a playlist, a favorite song, and so on, when exiting (OnExit), the object is serialized into an XML file depending on whether the object has changed
String repository = System.IO.Path.Combine (new string[] {AppDomain.CurrentDomain.BaseDirectory, "repository" }); if (! System.IO.Directory.Exists (repository)) {return; }//load player Settings playerconfig = serializehelper.toentity<playerconfigmodel> (repository + "\\PlayerC Onfig.xml "); Load Media Library mediacollection = serializehelper.toentity<list<mediamodel>> (repository + "\\MediaCollectio N.xml "); Load Playlist playlists = serializehelper.toentity<list<playlistmodel>> (repository + "\\Playlists.xml"); Load Play Queue playqueues = serializehelper.toentity<list<playqueuemodel>> (repository + "\\Pl Ayqueues.xml "); Load playback Record playrecords = serializehelper.toentity<list<playrecordmodel>> (repository + "\\PlayRecords. XML "); Load Favorites list Favorites = Serializehelper.toentity<list<favoRitemodel>> (repository + "\\Favorites.xml"); Initialize counter autostopcounter = Playerconfig.autostoptimeset;
String repository = System.IO.Path.Combine (new string[] {AppDomain.CurrentDomain.BaseDirectory, "repository"}); if (! System.IO.Directory.Exists (repository)) { try { System.IO.Directory.CreateDirectory (repository ); } catch (Exception ex) { loghelper.error (ex. Message); return; } } Save Player Settings if (isplayerconfigchanged) { serializehelper.toxml<playerconfigmodel> ( Playerconfig, repository + "\\PlayerConfig.xml"); } Save Media Library if (ismediacollectionchanged) { serializehelper.toxml<list<mediamodel>> ( Mediacollection, repository + "\\MediaCollection.xml"); }
2. Style and Resource usage
The background image and color of the interface element, font color and font size are all stored in the application resource dictionary and can be dynamically updated by code
<ResourceDictionary> <ResourceDictionary.MergedDictionaries> <resourcedictionary source= "/resources/color.xaml" ></ResourceDictionary> <resourcedictionary source= "/resources/ Imagebrush.xaml "></ResourceDictionary> <resourcedictionary source="/resources/ Lineargradientbrush.xaml "></ResourceDictionary> <resourcedictionary source="/resources/ Solidbrush.xaml "></ResourceDictionary> <resourcedictionary source="/styles/border.xaml ">< /resourcedictionary> <resourcedictionary source= "/styles/textblock.xaml" ></resourcedictionary > </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
3. Playback Control Core Section
In fact, the handling of MediaPlayer 4 events, mediaopened,mediafailed,mediaended, as well as their own added events mediapositionchanging
private static void _mainplayer_mediaopened (object sender, EventArgs e) { //Set Current media Currentmedia = Mediacollection.where (w = W.fullname = = Httputility.urldecode (MainPlayer.Source.AbsolutePath). Replace ("/", "\ \")). FirstOrDefault (); }
private static void _mainplayer_mediafailed (object sender, Exceptioneventargs e) { Playerstatus = Playerstatusenum. has ceased; Loghelper.error (e.errorexception.message); }
private static void _mainplayer_mediaended (object sender, EventArgs e) {//Add play History IsP Layrecordschanged = true; Playrecords.add (new Playrecordmodel {createdat = DateTime.Now, Media = Currentme Dia. FullName}); Set player Status Playerstatus = Playerstatusenum. stopped; Depending on the playback mode, decide which song to play with switch (Playerconfig.playmode) {case (int) playmodeenum. Single loop: {playbyrepeat (); Break } case (int) playmodeenum. List loop: {playbyrecycle (); Break } case (int) playmodeenum. Sequential playback: {Playbyorder (); Break } case (int) playmodeenum. Random Play: { Playbyrandom (); Break } } }
CoreHelper.cs Trigger Media playback Progress Change event private static void _maintimer1_tick () {if (isautostopopene D && autostopcounter <= 0) {//Stop play (cross-threading) MainPlayer.Dispatcher.Invok E (New Action () = {Stop (); })); Autostopcounter = Playerconfig.autostoptimeset; isautostopopened = false; Return } if (Playerstatus = = Playerstatusenum. Play) {autostopcounter-= 1; Mediapositionchanging (); }}//Handle media playback Progress events in the UI thread corehelper.mediapositionchanging + = corehelper_mediapositionchanging; private void Corehelper_mediapositionchanging () {this. Dispatcher.invoke (new Action () = {displayautostop (); TimeSpan Duration = timespan.fromseconds (0); if (coreheLper. MainPlayer.NaturalDuration.HasTimeSpan) {duration = CoreHelper.MainPlayer.NaturalDurati On. TimeSpan; } double percent = 0; if (duration. TotalSeconds > 0) {percent = Corehelper.mainplayer.position.totalseconds/duration. TotalSeconds; }//Display the media playback progress background GS2. Offset = percent; Gs3. Offset = percent; Displays the media playback progress and total duration text _mediapositiontextblock.text = String.Format ("{0}/{1}", Stringhelper.gettimespanstring (C oreHelper.MainPlayer.Position), stringhelper.gettimespanstring (duration)); })); }
5. Update the Media Library
This mainly involves reading the song information from the file, so one step is to read the files in the folder recursively, the second step is to read the song information (through the third-party class library Id3.dll,taglib.dll), the third step is to read the status in real time on the UI
public static void Findmatchedfile (string folder, list<string> extensions, double minfilelength, double MAXF Ilelength, Updatemediacollectioneventhandler callback) {string[] files = System.IO.Directory.GetFiles (f Older, "* *", searchoption.topdirectoryonly); FileInfo info = null; foreach (string file in files) {info = new FileInfo (file); if (!extensions. Contains (System.IO.Path.GetExtension (file). ToLower ())) {continue; } if (info. Length < Minfilelength) {continue; } if (info. Length > Maxfilelength) {continue; }//through a delegate to notify the front-end UI callback (file, Addtomediacollection (info)); } string[] directories = System.IO.Directory.GetDirectories (folder, "", Searchoption.topdirecTORYONLY); foreach (string directory in directories) {findmatchedfile (directory, extensions, minfilelength , Maxfilelength, callback); } }
public static int addtomediacollection (FileInfo file) {Id3info ID3 = null; try {id3 = new Id3info (file. FullName, True); } catch (Exception ex) {Loghelper.error (ex. Message); return-1; } Mediamodel Media = new Mediamodel (); The time media that was created. Createdtime = DateTime.Now; File length media. Filelength = file. Length; File full path media. FullName = file. FullName; Song of the album Media. Album = ID3. Id3v2info.gettextframe ("Talb")?? "Unknown album"; The artist media of the song. Artists = ID3. Id3v2info.gettextframe ("TPE1")?? "Unknown singer"; The title of the song media. Title = ID3. Id3v2info.gettextframe ("TIT2")?? System.IO.Path.GetFileNameWithoutExtension (file. FullName); Taglib.file f = null; try {f = TagLib.File.Create (File. FullName); Duration of the song media. Duration = F.properties.duration.totalseconds; Save song cover if (F.tag.pictures.length > 0) {string folder = System.IO.Pa Th. Combine (new string[] {AppDomain.CurrentDomain.BaseDirectory, "Repository", "Cover"}); if (! System.IO.Directory.Exists (folder)) {System.IO.Directory.CreateDirectory (folder) ); } byte[] bytes = F.tag.pictures[0]. Data.data; String cover = System.IO.Path.Combine (new string[] {folder, stringhelper.removespecialcharacters (media. Album) + ". jpg"}); using (FileStream fs = new FileStream (cover, FileMode.Create)) {fs. Write (bytes, 0, bytes. Length); }}} catch (Exception ex) {Loghelper.debug (ex). Message); } Mediamodel model = mediacollection.where (w = w.fullname = = file. FullName). FirstOrDefault (); if (model = = NULL | | String.IsNullOrEmpty (model. FullName)) {mediacollection.add (media); Loghelper.debug ("added a media:" + file.) FullName); return 1; }//Update media information model. Album = media. Album; Model. Artists = media. Artists; Model. Duration = media. Duration; Model. filelength = media. Filelength; Model. Title = media. Title; Loghelper.debug ("Updated a media:" + file.) FullName); return 0; }
Private list<int> _operations = null; private void Updatemediacollectiontextblock_mouseleftbuttondown (object sender, MouseButtonEventArgs e) { updatemediacollectiontextblock.isenabled = false; processingmediatextblock.visibility = visibility.visible; _operations = new list<int> (); Turn on thread Update Media Library BackgroundWorker worker = new BackgroundWorker (); Worker. DoWork + = Worker_dowork; Worker. runworkercompleted + = worker_runworkercompleted; Worker. RunWorkerAsync (); private void Worker_runworkercompleted (object sender, Runworkercompletedeventargs e) {Updateme Diacollectiontextblock.isenabled = true; processingmediatextblock.visibility = visibility.collapsed; int succeed = _operations. Count (c = = c = 1); int updated = _operations. Count (c = = c = 0); int failed = _operations. Count (c + = c < 0); if (Succeed > 0 | | Updated > 0) {corehelper.ismediacollectionchanged = true; } uihelper.showprompt (String.Format ("NEW: {0}, update: {1}, failed: {2}", succeed, updated, failed)); _operations = null; }
I did a little bit of my music player again.