private void musicListStore_SelectedIndexChanged(object sender, EventArgs e) { ListView.SelectedListViewItemCollection filename = this.musicListStore.SelectedItems; string temp = ""; cleartextbox(); pictureBox.Image = null; LABimage.Text = ""; try { foreach (ListViewItem item in filename) { if (item.SubItems.Count > 1) { temp += item.SubItems[1].Text + "\\" + item.SubItems[0].Text; } } if (File.Exists(temp)) { if (ID3v2Tag.DoesTagExist(temp)) { poptextboxV2(temp); } else if (ID3v1Tag.DoesTagExist(temp)) { poptextboxV1(temp); } } }//end of try catch (Exception ex) { MessageBox.Show("Error " + ex.Message); } }
public Audiofile GetTag(string filePath) { var hasTag = ID3v1Tag.DoesTagExist(filePath); var filename = Path.GetFileName(filePath); var genres = genreService.GetID3v1Genres(); if (hasTag) { var tag = new ID3v1Tag(filePath); var audioFile = mapper.Map(tag, new Audiofile(Guid.NewGuid())); audioFile.HasTag = true; audioFile.Filename = filename; audioFile.TagType = TagType.ID3V1; audioFile.TagVersion = GetTagVersion(filePath); audioFile.Genre = genres[tag.GenreIndex]; return(audioFile); } else { return(new Audiofile(Guid.NewGuid()) { HasTag = false, Filename = filename }); } }
internal static ID3v1Tag DecodeTag(Stream s) { byte[] buffer = new byte[ID3v1Tag.TagLength]; ID3v1Tag tag; Util.ReadFully(s, buffer); if (!HasID3v1Tag(buffer)) { return null; } tag = new ID3v1Tag(); tag.Title = StringDecoder.DecodeLatin1String(buffer, 3, ID3v1Tag.MaxTitleLength); tag.Artist = StringDecoder.DecodeLatin1String(buffer, 33, ID3v1Tag.MaxArtistLength); tag.Album = StringDecoder.DecodeLatin1String(buffer, 63, ID3v1Tag.MaxAlbumLength); tag.Year = StringDecoder.DecodeLatin1String(buffer, 93, ID3v1Tag.MaxYearLength); if (buffer[125] == 0x00 && buffer[126] != 0x00) { /* ID3v1.1 tag */ tag.Comment = StringDecoder.DecodeLatin1String(buffer, 97, ID3v1Tag.MaxCommentLengthVersion1_1); tag.TrackNumber = (buffer[126] == 0x00 ? String.Empty : Convert.ToString(buffer[126])); } else { /* ID3v1.0 tag */ tag.Comment = StringDecoder.DecodeLatin1String(buffer, 97, ID3v1Tag.MaxCommentLengthVersion1_0); } tag.Genre = (ID3v1Genre)buffer[127]; return tag; }
// 同期実行版。いるかな? // 01/08/2008 by aldente : ~Accessorに移植. // 05/24/2007 by aldente : static化 // 05/15/2007 by aldente #region *[static]ファイルからID3タグを読み込み(ReadFile) /// <summary> /// mp3ファイルからID3タグを読み込みます. /// タグが見つからなければnullを返します. /// </summary> /// <param name="filename">読み込むファイル名.</param> /// <returns>該当するバージョンのタグオブジェクト.</returns> public static async Task <IID3Tag> ReadFile(string fileName) { IID3Tag tag; //SongInfo info = new SongInfo(); if (!File.Exists(fileName)) { // ファイルがないぞ! return(null); } // 拡張子が"rmp"の場合は,RIFFとして開く. if (Path.GetExtension(fileName).ToLower().EndsWith("rmp")) { return(await RIFFMP3Tag.ReadFromFileAsync(fileName) as RIFFMP3Tag); } else { // ID3v2をチェック. tag = await ID3v2Tag.ReadFile(fileName); ID3v1Tag tag1 = await ID3v1Tag.ReadFile(fileName); if (tag != null) { if (tag1 != null) { tag.Merge(tag1); } return(tag); } return(tag1); } }
private void btnRemoveID3v1_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(m_Filename)) { MessageBox.Show("No file loaded", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); } else { DialogResult result = MessageBox.Show(string.Format("Remove ID3v1 tag from '{0}'?", Path.GetFileName(m_Filename)), "", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { Boolean success = ID3v1Tag.RemoveTag(m_Filename); if (success) { MessageBox.Show("ID3v1 tag successfully removed", "", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show("ID3v1 tag not found", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } } btnRemoveID3v1.Enabled = ID3v1Tag.DoesTagExist(m_Filename); ucID3v1.LoadFile(m_Filename); }
public void Updaterecord(string filename) { string tagstring = ""; if (ID3v2Tag.DoesTagExist(filename)) { tagstring = "/V2"; if (ID3v1Tag.DoesTagExist(filename)) { tagstring = "V1" + tagstring; } var id3 = new ID3v2Tag(filename); var mytrack = new Track(id3.Artist, id3.Title, id3.Album, id3.Year, id3.TrackNumber, id3.Genre, filename, tagstring); ModifyRecord(mytrack); } if (ID3v1Tag.DoesTagExist(filename) && tagstring == "") { tagstring = "V1"; var id3 = new ID3v1Tag(filename); var mytrack = new Track(id3.Artist, id3.Title, id3.Album, id3.Year, id3.TrackNumber.ToString(), GenreHelper.GenreByIndex[id3.GenreIndex], filename, tagstring); ModifyRecord(mytrack); } if (tagstring == "No Tag") { var mytrack = new Track("", "", "", "", "", "", filename, "No Tag"); ModifyRecord(mytrack); } }
private void LoadFile(string path) { m_Filename = path; ucID3v2.LoadFile(m_Filename); ucID3v1.LoadFile(m_Filename); btnSave.Enabled = true; btnRemoveID3v2.Enabled = ID3v2Tag.DoesTagExist(m_Filename); btnRemoveID3v1.Enabled = ID3v1Tag.DoesTagExist(m_Filename); }
public void RemoveTag(string filePath) { try { ID3v1Tag.RemoveTag(filePath); } catch (Exception e) { throw new Exception("Removing ID3v1 error"); } }
// 02/04/2013 by aldentea : 一時ファイルの名前をAPIから取得。 // 05/17/2007 by aldente #region *ファイルに書き込む(WriteTo) /// <summary> /// 指定したファイルにタグを書き込みます. /// 既存のタグは上書きされます. /// </summary> /// <param name="dstFilename">書き込み先のファイル名.</param> public async Task WriteTo(string dstFilename) { if (!File.Exists(dstFilename)) { // どうしてくれよう? } bool v1_exists = await ID3v1Tag.Exists(dstFilename); //string tempFilename = "namunamu.mp3"; string tempFilename = Path.GetTempFileName(); using (var reader = new ID3Reader(dstFilename)) { bool exists = await Exists(reader); int old_tag_size = exists ? (await Generate(reader, true)).GetTotalSize() : 0; // 11/10/2008 by aldente // FileModeをCreateNewからCreateに変更. using (var writer = new FileStream(tempFilename, FileMode.Create, FileAccess.Write)) { ID3v1Tag v1Tag = new ID3v1Tag(); // タグを書き込む. await writer.WriteAsync(this.GetBytes(this.char_code, 0x100)); // 本体を書き込む. reader.Seek(old_tag_size, SeekOrigin.Begin); if (v1_exists) { var contents = await reader.ReadBytes((int)reader.Length - old_tag_size - 128); await writer.WriteAsync(contents); await v1Tag.Initialize(reader, false); } else { var contents = await reader.ReadBytes((int)reader.Length - old_tag_size); await writer.WriteAsync(contents); } // ID3v1タグを書き込む. v1Tag.Title = this.Title; v1Tag.Artist = this.Artist; byte[] buf = v1Tag.GetBytes(); await writer.WriteAsync(buf, 0, buf.Length); } } File.Delete(dstFilename); File.Move(tempFilename, dstFilename); }
public void DemoBasicUsageForID3v1() { // Create a new ID3v1 tag. ID3v1Tag v1Tag = new ID3v1Tag(); v1Tag.Album = "My Track Album"; v1Tag.Artist = "My Track Artist"; v1Tag.Comments = "My Track Comments"; v1Tag.Genre = "Rock"; // this has to be a genre from the ID3v1 genre list (see ID3Genre.cs) v1Tag.Title = "My Track Title"; v1Tag.TrackNumber = 1; v1Tag.Year = "2004"; // Write our new tag out to a file as ID3v1.1 (for example; v1.0 would work too) v1Tag.WriteTag("basic.tag", ID3Versions.V1_1); // Read the tag back from the file. v1Tag = null; if (!ID3v1Tag.HasTag("basic.tag")) { Console.WriteLine("Hmmmm....something didn't go right here."); } else { v1Tag = ID3v1Tag.ReadTag("basic.tag"); // Some usage possibilities: Console.WriteLine("Album: " + v1Tag.Album); if (v1Tag.HasArtist) // checks to see if Artist isn't null or empty { Console.WriteLine("Artist: " + v1Tag.Artist); } // Make a change and write it back out to the file. v1Tag.Comments = null; v1Tag.WriteTag("basic.tag", ID3Versions.V1_1); // Show that the change worked. v1Tag = ID3v1Tag.ReadTag("basic.tag"); if (v1Tag.HasComments) { Console.WriteLine("Hmmmm....something didn't go right here."); } else { Console.WriteLine("See! This library really does work."); } } }
public static Track Getv1tags(string fname) { Track mytrack = new Track("", "", "", "", "", "", "", ""); if (File.Exists(fname)) { var id3 = new ID3v1Tag(fname); mytrack.Album = id3.Album; mytrack.Artist = id3.Artist; mytrack.Title = id3.Title; mytrack.Trackno = id3.TrackNumber.ToString(); mytrack.Year = id3.Year; } return(mytrack); }
public static Boolean removeID3v1(string fname) { Boolean success = false; var trackxml = new XMLutils(appPath + "\\trackxml.xml"); if (!String.IsNullOrEmpty(fname) && File.Exists(fname)) { success = ID3v1Tag.RemoveTag(fname); } if (success) { trackxml.Updaterecord(fname); } return(success); }
public static Boolean Savev1tag(Track mytrack) { if (!File.Exists(mytrack.Filename)) { MessageBox.Show("File Does not exist " + mytrack.Filename); return(false); } try { var trackxml = new XMLutils(appPath + "\\trackxml.xml"); removeID3v1(mytrack.Filename); var id3 = new ID3v1Tag(mytrack.Filename); if (!String.IsNullOrEmpty(mytrack.Filename) && File.Exists(mytrack.Filename)) { id3.Album = mytrack.Album; id3.Artist = mytrack.Artist; id3.Title = mytrack.Title; if (mytrack.Trackno.Contains("/")) { id3.TrackNumber = Convert.ToInt16(mytrack.Trackno.Substring(0, mytrack.Trackno.IndexOf("/"))); } else { id3.TrackNumber = Convert.ToInt16(mytrack.Trackno); } id3.Year = mytrack.Year; id3.GenreIndex = GenreHelper.GetGenreIndex(mytrack.Genre); // id3.Comment = comment; id3.Save(mytrack.Filename); trackxml.ModifyRecord(mytrack); } if (ID3v1Tag.DoesTagExist(mytrack.Filename)) { trackxml.Updaterecord(mytrack.Filename); return(true); } else { return(false); } } catch (Exception ex) { MessageBox.Show(ex.Message); return(false); } }
public TagVersion GetTagVersion(string filePath) { if (HasTag(filePath)) { var tag = new ID3v1Tag(filePath); switch (tag.TagVersion) { case ID3v1TagVersion.ID3v10: return(TagVersion.ID3V10); case ID3v1TagVersion.ID3v11: return(TagVersion.ID3V11); } } return(TagVersion.none); }
private void poptextboxV1(string fdir) { TXTfilename.Text = fdir; if (ID3v1Tag.DoesTagExist(fdir)) { RDOver1.Checked = true; var id3v1 = new ID3v1Tag(fdir); CMBartist.Text = id3v1.Artist; CMBtitle.Text = id3v1.Title; CMBalbum.Text = id3v1.Album; CMBgenre.Text = GenreHelper.GenreByIndex[id3v1.GenreIndex]; CMBtrack.Text = id3v1.TrackNumber.ToString(); CMByear.Text = id3v1.Year; CMBcomment.Text = id3v1.Comment; } }
public APEv2Tag(FileStream fs, ID3v1Tag id3v1, Lyrics3Tag lyrics3, bool afterAudioData) { Appended = false; Exists = false; Valid = false; long lngOffset = 32; //Size of footer tag of APEv2 if (id3v1.Exists) { lngOffset += id3v1.TagSize; //128 Bytes for ID3v1 } if (lyrics3.Exists) { lngOffset += lyrics3.TagSize; } RawFooter = new byte[32]; fs.Position = fs.Length - lngOffset; fs.Read(RawFooter, 0, 32); if (Encoding.ASCII.GetString(RawFooter, 0, 8) == "APETAGEX") { Exists = true; Appended = true; //Version uint v = ID3Base.expand(RawFooter[11], RawFooter[10], RawFooter[9], RawFooter[8]); TagSize = ID3Base.expand(RawFooter[15], RawFooter[14], RawFooter[13], RawFooter[12]); uint numOfItems = ID3Base.expand(RawFooter[19], RawFooter[18], RawFooter[17], RawFooter[16]); //Detect Header fs.Position = fs.Length - (lngOffset + TagSize); RawHeader = new byte[32]; fs.Read(RawHeader, 0, 32); if (Encoding.ASCII.GetString(RawHeader, 0, 8) == "APETAGEX") { //WERE GOOD ProcessFlags(); } } }
private string Getnewtrack(string fname) { string ntn = COMBrename.Text; Track mytrack = new Track("", "", "", "", "", "", "", ""); string extn = Path.GetExtension(fname); if (ID3v1Tag.DoesTagExist(fname)) { mytrack = Miscutils.Getv1tags(fname); } else if (ID3v2Tag.DoesTagExist(fname)) { mytrack = Miscutils.Getv2tags(fname); } if (ntn.Contains("%TRACKNUMBER%")) { ntn = ntn.Replace("%TRACKNUMBER%", Miscutils.PaddedNumber(mytrack.Trackno)); } if (ntn.Contains("%ARTIST%")) { ntn = ntn.Replace("%ARTIST%", mytrack.Artist); } if (ntn.Contains("%ALBUM%")) { ntn = ntn.Replace("%ALBUM%", mytrack.Album); } if (ntn.Contains("%TITLE%")) { ntn = ntn.Replace("%TITLE%", mytrack.Title); } if (ntn.Contains("%FILENAME%")) { ntn = ntn.Replace("%FILENAME%", Path.GetFileNameWithoutExtension(fname)); } ntn = Miscutils.stripchar(ntn); if (TXTrepbefore.Text != "") { ntn = ntn.Replace(TXTrepbefore.Text, TXTrepafter.Text); } return(ntn + extn); }
private void BTNcopy_Click(object sender, EventArgs e) { if (musicListStore.SelectedItems.Count > 0) { var copywin = new FRMcopy(); string temp = ""; ListView.SelectedListViewItemCollection filename = this.musicListStore.SelectedItems; copywin.GetGenre = musicListStore.SelectedItems[0].SubItems[8].Text; if (copywin.ShowDialog(this) == DialogResult.OK) { if (copywin.CopyV1) { foreach (ListViewItem item in filename) { temp = item.SubItems[1].Text + "\\" + item.SubItems[0].Text; if (File.Exists(temp) & ID3v1Tag.DoesTagExist(temp)) { var id3 = new ID3v1Tag(temp); Miscutils.Savev2tag(new Track(id3.Artist, id3.Title, id3.Album, id3.Year, id3.TrackNumber.ToString(), GenreHelper.GenreByIndex[id3.GenreIndex], temp, "V1/V2")); ReloadlistviewV2(item); } } } if (copywin.CopyV2) { foreach (ListViewItem item in filename) { temp = item.SubItems[1].Text + "\\" + item.SubItems[0].Text; if (File.Exists(temp) & ID3v2Tag.DoesTagExist(temp)) { var id3 = new ID3v2Tag(temp); string gen = copywin.GetGenre; Miscutils.Savev1tag(new Track(id3.Artist, id3.Title, id3.Album, id3.Year, id3.TrackNumber.ToString(), gen, temp, "V1/V2")); ReloadlistviewV1(item); } } } } }//end musicstore setected }
/// <summary>Serialzes an <see cref="ID3v1Tag" /> to a byte array.</summary> /// <param name="tag">The <see cref="ID3v1Tag" /> to bew serialized.</param> /// <returns>A byte array containing the encoded tag</returns> internal static byte[] EncodeTag(ID3v1Tag tag) { byte[] buffer = new byte[ID3v1Tag.TagLength]; StringEncoder.WriteLatin1String(buffer, 0, 3, "TAG"); StringEncoder.WriteLatin1String(buffer, 3, ID3v1Tag.MaxTitleLength, tag.Title); StringEncoder.WriteLatin1String(buffer, 33, ID3v1Tag.MaxArtistLength, tag.Artist); StringEncoder.WriteLatin1String(buffer, 63, ID3v1Tag.MaxAlbumLength, tag.Album); StringEncoder.WriteLatin1String(buffer, 93, ID3v1Tag.MaxYearLength, tag.Year); if (String.IsNullOrEmpty(tag.TrackNumber)) { /* ID3v1 tag */ StringEncoder.WriteLatin1String(buffer, 97, ID3v1Tag.MaxCommentLengthVersion1_0, tag.Comment); } else { /* ID3v1.1 tag */ StringEncoder.WriteLatin1String(buffer, 97, ID3v1Tag.MaxCommentLengthVersion1_1, tag.Comment); buffer[126] = (byte)Convert.ToInt32(tag.TrackNumber); } buffer[127] = (byte)tag.Genre; return buffer; }
public void ReloadlistviewV1(ListViewItem item) { string tagstring = "No Tag"; if (ID3v2Tag.DoesTagExist(item.SubItems[1].Text + "\\" + item.SubItems[0].Text)) { tagstring = "/V2"; } if (ID3v1Tag.DoesTagExist(item.SubItems[1].Text + "\\" + item.SubItems[0].Text)) { var id3 = new ID3v1Tag(item.SubItems[1].Text + "\\" + item.SubItems[0].Text); item.SubItems[2].Text = "V1" + tagstring; item.SubItems[3].Text = id3.Title; item.SubItems[4].Text = id3.Artist; item.SubItems[5].Text = id3.Album; item.SubItems[7].Text = id3.Year; item.SubItems[6].Text = id3.TrackNumber.ToString(); item.SubItems[8].Text = GenreHelper.GenreByIndex[id3.GenreIndex]; // Miscutils.Updaterecord(item.SubItems[1].Text + "\\" + item.SubItems[0].Text, id3.Album, // id3.Artist, id3.GenreIndex.ToString(), id3.Title, id3.TrackNumber.ToString(), id3.Year); } else { item.SubItems[2].Text = tagstring; item.SubItems[3].Text = ""; item.SubItems[4].Text = ""; item.SubItems[5].Text = ""; item.SubItems[7].Text = ""; item.SubItems[6].Text = ""; item.SubItems[8].Text = ""; if (tagstring == "No Tag") { // Miscutils.Updaterecord(item.SubItems[1].Text + "\\" + item.SubItems[0].Text, item.SubItems[1].Text, // "No Tag", "", "", "", ""); } } }
public ID3v1ViewModel(IEventAggregator eventAggregator) : base(eventAggregator) { GetDirectoryControllerEvent args = new GetDirectoryControllerEvent(); eventAggregator.Publish(args); var file = args.DirectoryController.SelectedItems.Where(p => Path.GetExtension(p.FullName).ToLower() == ".mp3").FirstOrDefault(); if (file != null) { FileName = Path.GetFileName(file.FullName); ID3v1 = new ID3v1Tag(file.FullName); CanSave = true; } else { ID3v1 = new ID3v1Tag(); CanSave = false; } }
private void ReadTagsFromFile() { if (Status != ItemStatus.Complete) { return; } if (!CompleteDestination.EndsWith(".mp3", StringComparison.CurrentCultureIgnoreCase)) { return; } try { ID3Tag tag = ID3v2Tag.ReadTag(CompleteDestination); if (tag == null) { tag = ID3v1Tag.ReadTag(CompleteDestination); if (tag == null) { tag = new ID3v2Tag(); } } TrackTitleTag = tag.Title; AlbumTag = tag.Album; ArtistTag = tag.Artist; GenreTag = tag.Genre; _tagsSet = true; } catch (Exception ex) { Trace.TraceError("Error: unable to read ID3 Tag for file: " + CompleteDestination + ". " + ex.Message); } }
static void Main(string[] args) { string fileName = GetFileName(args); if (fileName == null) { return; } Console.WriteLine(); Console.WriteLine(string.Format("File: {0}", fileName)); Console.WriteLine(); IAudioFile audioFile = AudioFile.Create(fileName, true); Console.WriteLine("Audio Info"); Console.WriteLine(); Console.WriteLine(string.Format("Type: {0}", EnumUtils.GetDescription(audioFile.FileType))); Console.WriteLine(string.Format("Length: {0}:{1:00}", (int)audioFile.TotalSeconds / 60, (int)audioFile.TotalSeconds % 60)); Console.WriteLine(string.Format("Bitrate: {0:#,0} kbps", (int)audioFile.Bitrate)); Console.WriteLine(string.Format("Frequency: {0:#,0} Hz", audioFile.Frequency)); Console.WriteLine(string.Format("Channels: {0}", audioFile.Channels)); Console.WriteLine(); if (ID3v2Tag.DoesTagExist(fileName)) { IID3v2Tag id3v2 = new ID3v2Tag(fileName); Console.WriteLine(EnumUtils.GetDescription(id3v2.Header.TagVersion)); Console.WriteLine(); Console.WriteLine(string.Format("Artist: {0}", id3v2.Artist)); Console.WriteLine(string.Format("Title: {0}", id3v2.Title)); Console.WriteLine(string.Format("Album: {0}", id3v2.Album)); Console.WriteLine(string.Format("Year: {0}", id3v2.Year)); Console.WriteLine(string.Format("Track: {0}", id3v2.TrackNumber)); Console.WriteLine(string.Format("Genre: {0}", id3v2.Genre)); Console.WriteLine(string.Format("Pictures: {0}", id3v2.PictureList.Count)); Console.WriteLine(string.Format("Comments: {0}", id3v2.CommentsList.Count)); Console.WriteLine(); // Example of saving an ID3v2 tag // // id3v2.Title = "New song title"; // id3v2.Save(fileName); } if (ID3v1Tag.DoesTagExist(fileName)) { IID3v1Tag id3v1 = new ID3v1Tag(fileName); Console.WriteLine(EnumUtils.GetDescription(id3v1.TagVersion)); Console.WriteLine(); Console.WriteLine(string.Format("Artist: {0}", id3v1.Artist)); Console.WriteLine(string.Format("Title: {0}", id3v1.Title)); Console.WriteLine(string.Format("Album: {0}", id3v1.Album)); Console.WriteLine(string.Format("Year: {0}", id3v1.Year)); Console.WriteLine(string.Format("Comment: {0}", id3v1.Comment)); Console.WriteLine(string.Format("Track: {0}", id3v1.TrackNumber)); Console.WriteLine(string.Format("Genre: {0}", GenreHelper.GenreByIndex[id3v1.GenreIndex])); Console.WriteLine(); // Example of saving an ID3v1 tag // // id3v1.Title = "New song title"; // id3v1.Save(fileName); } if (audioFile.FileType == AudioFileType.Flac) { VorbisComment vorbis = new VorbisComment(fileName); Console.WriteLine("Vorbis Comment"); Console.WriteLine(); Console.WriteLine(string.Format("Artist: {0}", vorbis.Artist)); Console.WriteLine(string.Format("Title: {0}", vorbis.Title)); Console.WriteLine(string.Format("Album: {0}", vorbis.Album)); Console.WriteLine(string.Format("Year: {0}", vorbis.Year)); Console.WriteLine(string.Format("Comment: {0}", vorbis.Comment)); Console.WriteLine(string.Format("Track: {0}", vorbis.TrackNumber)); Console.WriteLine(string.Format("Genre: {0}", vorbis.Genre)); Console.WriteLine(string.Format("Vendor: {0}", vorbis.Vendor)); Console.WriteLine(); // Example of saving a Vorbis Comment // // vorbis.Title = "New song title"; // vorbis.Save(fileName); } }
public bool WriteTags(AudioMetaData metaData, string filename, bool force = false) { try { if (!metaData.IsValid) { this.Logger.LogWarning($"Invalid MetaData `{ metaData }` to save to file [{ filename }]"); return(false); } ID3v1Tag.RemoveTag(filename); var trackNumber = metaData.TrackNumber ?? 1; var totalTrackNumber = metaData.TotalTrackNumbers ?? trackNumber; var disc = metaData.Disk ?? 1; var discCount = metaData.TotalDiscCount ?? disc; IID3v2Tag id3v2 = new ID3v2Tag(filename) { Artist = metaData.Artist, Album = metaData.Release, Title = metaData.Title, Year = metaData.Year.Value.ToString(), TrackNumber = totalTrackNumber < 99 ? $"{trackNumber.ToString("00")}/{totalTrackNumber.ToString("00")}" : $"{trackNumber.ToString()}/{totalTrackNumber.ToString()}", DiscNumber = discCount < 99 ? $"{disc.ToString("00")}/{discCount.ToString("00")}" : $"{disc.ToString()}/{discCount.ToString()}" }; if (metaData.TrackArtists.Any()) { id3v2.OriginalArtist = string.Join("/", metaData.TrackArtists); } if (this.Configuration.Processing.DoClearComments) { if (id3v2.CommentsList.Any()) { for (var i = 0; i < id3v2.CommentsList.Count; i++) { id3v2.CommentsList[i].Description = null; id3v2.CommentsList[i].Value = null; } } } id3v2.Save(filename); //// Delete first embedded picture (let's say it exists) //theTrack.EmbeddedPictures.RemoveAt(0); //// Add 'CD' embedded picture //PictureInfo newPicture = new PictureInfo(Commons.ImageFormat.Gif, PictureInfo.PIC_TYPE.CD); //newPicture.PictureData = System.IO.File.ReadAllBytes("E:/temp/_Images/pic1.gif"); //theTrack.EmbeddedPictures.Add(newPicture); //// Save modifications on the disc //theTrack.Save(); //tagFile.Tag.Pictures = metaData.Images == null ? null : metaData.Images.Select(x => new TagLib.Picture //{ // Data = new TagLib.ByteVector(x.Data), // Description = x.Description, // MimeType = x.MimeType, // Type = (TagLib.PictureType)x.Type //}).ToArray(); //tagFile.Save(); return(true); } catch (Exception ex) { this.Logger.LogError(ex, string.Format("MetaData [{0}], Filename [{1}]", metaData.ToString(), filename)); } return(false); }
private OperationResult <AudioMetaData> MetaDataForFileFromIdSharp(string fileName) { var sw = new Stopwatch(); sw.Start(); AudioMetaData result = new AudioMetaData(); var isSuccess = false; try { result.Filename = fileName; IAudioFile audioFile = AudioFile.Create(fileName, true); if (ID3v2Tag.DoesTagExist(fileName)) { IID3v2Tag id3v2 = new ID3v2Tag(fileName); result.Release = id3v2.Album; result.Artist = id3v2.AlbumArtist ?? id3v2.Artist; result.ArtistRaw = id3v2.AlbumArtist ?? id3v2.Artist; result.Genres = id3v2.Genre?.Split(new char[] { ',', '\\' }); result.TrackArtist = id3v2.OriginalArtist ?? id3v2.Artist ?? id3v2.AlbumArtist; result.TrackArtistRaw = id3v2.OriginalArtist; result.AudioBitrate = (int?)audioFile.Bitrate; result.AudioChannels = audioFile.Channels; result.AudioSampleRate = (int)audioFile.Bitrate; result.Disk = ID3TagsHelper.ParseDiscNumber(id3v2.DiscNumber); result.DiskSubTitle = id3v2.SetSubtitle; result.Images = id3v2.PictureList?.Select(x => new AudioMetaDataImage { Data = x.PictureData, Description = x.Description, MimeType = x.MimeType, Type = (AudioMetaDataImageType)x.PictureType }).ToArray(); result.Time = audioFile.TotalSeconds > 0 ? ((decimal?)audioFile.TotalSeconds).ToTimeSpan() : null; result.Title = id3v2.Title.ToTitleCase(false); result.TrackNumber = ID3TagsHelper.ParseTrackNumber(id3v2.TrackNumber); result.TotalTrackNumbers = ID3TagsHelper.ParseTotalTrackNumber(id3v2.TrackNumber); var year = id3v2.Year ?? id3v2.RecordingTimestamp ?? id3v2.ReleaseTimestamp ?? id3v2.OriginalReleaseTimestamp; result.Year = ID3TagsHelper.ParseYear(year); isSuccess = result.IsValid; } if (!isSuccess) { if (ID3v1Tag.DoesTagExist(fileName)) { IID3v1Tag id3v1 = new ID3v1Tag(fileName); result.Release = id3v1.Album; result.Artist = id3v1.Artist; result.ArtistRaw = id3v1.Artist; result.AudioBitrate = (int?)audioFile.Bitrate; result.AudioChannels = audioFile.Channels; result.AudioSampleRate = (int)audioFile.Bitrate; result.Time = audioFile.TotalSeconds > 0 ? ((decimal?)audioFile.TotalSeconds).ToTimeSpan() : null; result.Title = id3v1.Title.ToTitleCase(false); result.TrackNumber = SafeParser.ToNumber <short?>(id3v1.TrackNumber); var date = SafeParser.ToDateTime(id3v1.Year); result.Year = date?.Year ?? SafeParser.ToNumber <int?>(id3v1.Year); isSuccess = result.IsValid; } } } catch (Exception ex) { this.Logger.LogError(ex, "MetaDataForFileFromTagLib Filename [" + fileName + "] Error [" + ex.Serialize() + "]"); } sw.Stop(); return(new OperationResult <AudioMetaData> { IsSuccess = isSuccess, OperationTime = sw.ElapsedMilliseconds, Data = result }); }
public EditID3v1Tag(ID3v1Tag parent) { this.Parent = parent; }
public AlbumTrack(string path) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("path"); } _path = path; if (ID3v2Tag.DoesTagExist(path)) { ID3v2Tag id3v2 = new ID3v2Tag(path); DiscNumber = id3v2.DiscNumber; TrackNumber = id3v2.TrackNumber; Artist = id3v2.Artist; Title = id3v2.Title; ReleaseDate = id3v2.Year; Album = id3v2.Album; Genre = id3v2.Genre; if (id3v2.PictureList != null && id3v2.PictureList.Count == 1) { Picture = id3v2.PictureList[0]; } } if (ID3v1Tag.DoesTagExist(path)) { ID3v1Tag id3v1 = new ID3v1Tag(path); if (string.IsNullOrWhiteSpace(TrackNumber)) { TrackNumber = string.Format("{0}", id3v1.TrackNumber); } if (string.IsNullOrWhiteSpace(Artist)) { Artist = id3v1.Artist; } if (string.IsNullOrWhiteSpace(Title)) { Title = id3v1.Title; } if (string.IsNullOrWhiteSpace(ReleaseDate)) { ReleaseDate = id3v1.Year; } if (string.IsNullOrWhiteSpace(Album)) { Album = id3v1.Album; } if (string.IsNullOrWhiteSpace(Genre)) { Genre = GenreHelper.GenreByIndex[id3v1.GenreIndex]; } } IAudioFile audioFile = AudioFile.Create(_path, throwExceptionIfUnknown: true); Bitrate = audioFile.Bitrate; TotalSeconds = audioFile.TotalSeconds; // TODO: APE, Lyrics3 // TODO: When no tags, try to guess from path and file names // TODO: Parse Tracks for TotalTracks // TODO: Parse Disc for TotalDiscs // Parse track # from TrackNumber including total tracks if (!string.IsNullOrWhiteSpace(TrackNumber)) { if (TrackNumber.Contains('/')) { TrackNumber = TrackNumber.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)[0]; // TODO: Set total tracks? } } // Parse disc # from DiscNumber including total discs if (!string.IsNullOrWhiteSpace(DiscNumber)) { if (DiscNumber.Contains('/')) { DiscNumber = DiscNumber.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)[0]; // TODO: Set total discs? } } else { DiscNumber = "1"; } }
/// <summary>Reads the tag from the specified stream.</summary> /// <param name="stream">The stream.</param> private void Read(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } bool id3v2Found = false; string tagVersion = string.Empty; // ID3v2 if (ID3v2Tag.DoesTagExist(stream)) { ID3v2Tag id3v2 = new ID3v2Tag(stream); Title = id3v2.Title; Artist = id3v2.Artist; Album = id3v2.Album; Year = id3v2.Year; Genre = id3v2.Genre; TrackNumber = id3v2.TrackNumber; if (id3v2.CommentsList.Count > 0) { Comment = id3v2.CommentsList[0].Description; } else { Comment = null; } tagVersion = EnumUtils.GetDescription(id3v2.Header.TagVersion); id3v2Found = true; } // ID3v1 if (ID3v1Tag.DoesTagExist(stream)) { ID3v1Tag id3v1 = new ID3v1Tag(stream); // Use ID3v1 fields if ID3v2 doesn't exist or field is blank if (!id3v2Found || string.IsNullOrEmpty(Title)) { Title = id3v1.Title; } if (!id3v2Found || string.IsNullOrEmpty(Artist)) { Artist = id3v1.Artist; } if (!id3v2Found || string.IsNullOrEmpty(Album)) { Album = id3v1.Album; } if (!id3v2Found || string.IsNullOrEmpty(Year)) { Year = id3v1.Year; } if (!id3v2Found || string.IsNullOrEmpty(Genre)) { Genre = GenreHelper.GenreByIndex[id3v1.GenreIndex]; } if (!id3v2Found || string.IsNullOrEmpty(TrackNumber)) { TrackNumber = id3v1.TrackNumber.ToString(); } if (!id3v2Found || string.IsNullOrEmpty(Comment)) { Comment = id3v1.Comment; } tagVersion += (!string.IsNullOrEmpty(tagVersion) ? ", " : "") + EnumUtils.GetDescription(id3v1.TagVersion); } // Vorbis Comment if (VorbisComment.VorbisComment.IsFlac(stream)) { VorbisComment.VorbisComment vc = new VorbisComment.VorbisComment(stream); Title = vc.Title; Artist = vc.Artist; Album = vc.Album; Year = vc.Year; Genre = vc.Genre; TrackNumber = vc.TrackNumber; Comment = vc.Comment; tagVersion = (!string.IsNullOrEmpty(tagVersion) ? ", " : "") + "Vorbis Comment"; } // No tag found if (string.IsNullOrEmpty(tagVersion)) { Title = null; Artist = null; Album = null; Year = null; Genre = null; TrackNumber = null; Comment = null; tagVersion = "None"; } // Set TagVersion TagVersion = tagVersion; }
public void Load(Stream s, ReadMode mode) { if (s == null) { throw new ArgumentNullException("s"); } if (!s.CanRead) { throw new ArgumentException("Cannot read from Stream.", "s"); } if (!Enum.IsDefined(typeof(ReadMode), mode)) { throw new InvalidEnumArgumentException("mode", (int)mode, typeof(ReadMode)); } try { id3v2Tag = ID3v2TagDecoder.DecodeTag(s, mode); } catch { if (mode == ReadMode.ThrowOnError) { throw; } id3v2Tag = null; } if (s.CanSeek && s.Length >= ID3v1Tag.TagLength) { s.Seek(-ID3v1Tag.TagLength, SeekOrigin.End); try { id3v1Tag = ID3v1TagDecoder.DecodeTag(s); } catch { if (mode == ReadMode.ThrowOnError) { throw; } id3v1Tag = null; } } else { id3v1Tag = null; } }
public bool WriteTagsToFile(bool overwriteExistingTags) { if (Status != ItemStatus.Complete) { return(false); } if (!CompleteDestination.EndsWith(".mp3", StringComparison.CurrentCultureIgnoreCase)) { return(false); } try { ID3Tag tag = null; switch (ID3v2Tag.LookForTag(CompleteDestination)) { case ID3Versions.None: case ID3Versions.Unknown: default: tag = new ID3v2Tag(); SetTagContent(tag, overwriteExistingTags); tag.WriteTag(CompleteDestination, ID3Versions.V2_4); break; case ID3Versions.V1: case ID3Versions.V1_0: case ID3Versions.V1_1: tag = ID3v1Tag.ReadTag(CompleteDestination); SetTagContent(tag, overwriteExistingTags); tag.WriteTag(CompleteDestination, ID3Versions.V1_1); break; case ID3Versions.V2: case ID3Versions.V2_2: case ID3Versions.V2_3: tag = ID3v2Tag.ReadTag(CompleteDestination); SetTagContent(tag, overwriteExistingTags); tag.WriteTag(CompleteDestination, ID3Versions.V2_3); break; case ID3Versions.V2_4: tag = ID3v2Tag.ReadTag(CompleteDestination); SetTagContent(tag, overwriteExistingTags); tag.WriteTag(CompleteDestination, ID3Versions.V2_4); break; } } catch (Exception ex) { Trace.TraceError("Error writing tags to: " + CompleteDestination + ". " + ex.Message); return(false); } return(true); }
/// <summary>Saves the tag to the specified path.</summary> /// <param name="path">The full path of the file.</param> private void Save(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } if (VorbisComment.VorbisComment.IsFlac(path)) { VorbisComment.VorbisComment vc = new VorbisComment.VorbisComment(path); vc.Title = Title; vc.Artist = Artist; vc.Album = Album; vc.Year = Year; vc.Genre = Genre; vc.TrackNumber = TrackNumber; vc.Comment = Comment; vc.Save(path); ID3v2Tag.RemoveTag(path); ID3v1Tag.RemoveTag(path); } else { ID3v2Tag id3v2 = new ID3v2Tag(path); id3v2.Title = Title; id3v2.Artist = Artist; id3v2.Album = Album; id3v2.Year = Year; id3v2.Genre = Genre; id3v2.TrackNumber = TrackNumber; if (id3v2.CommentsList.Count > 0) { id3v2.CommentsList[0].Description = Comment; } else { if (!string.IsNullOrEmpty(Comment)) { id3v2.CommentsList.AddNew().Description = Comment; } } ID3v1Tag id3v1 = new ID3v1Tag(path); id3v1.Title = Title; id3v1.Artist = Artist; id3v1.Album = Album; id3v1.Year = Year; id3v1.GenreIndex = GenreHelper.GetGenreIndex(Genre); id3v1.Comment = Comment; int trackNumber; if (int.TryParse(TrackNumber, out trackNumber)) { id3v1.TrackNumber = trackNumber; } else { // Handle ##/## format if (TrackNumber.Contains("/")) { if (int.TryParse(TrackNumber.Split('/')[0], out trackNumber)) { id3v1.TrackNumber = trackNumber; } else { id3v1.TrackNumber = 0; } } else { id3v1.TrackNumber = 0; } } id3v2.Save(path); id3v1.Save(path); } Read(path); }
public MP3(string FileName) { Console.WriteLine(FileName); FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read); Valid = false; // Set the filename not including the path information strFileName = @fs.Name; char[] chrSeparators = new char[] { '\\', '/' }; string[] strSeparator = strFileName.Split(chrSeparators); int intUpper = strSeparator.GetUpperBound(0); strFileName = strSeparator[intUpper]; // Replace ' with '' for the SQL INSERT statement strFileName = strFileName.Replace("'", "''"); // Set the file size lngFileSize = fs.Length; byte[] bytHeader = new byte[4]; byte[] bytVBitRate = new byte[12]; int intPos = 0; // Keep reading 4 bytes from the header until we know for sure that in // fact it's an MP3 int nextFrame = 0; //Jeff - Location in stream to next Frame (current position + framesize) //Read if id3v1 exists id3v1 = new ID3v1Tag(fs); //Read if id3v2 exists id3v2 = new ID3v2Tag(fs); //Read if lyrics3 exists lyrics3 = new Lyrics3Tag(fs, id3v1.Exists); //Read if APEv2 exists apev2 = new APEv2Tag(fs, id3v1, lyrics3, true); //Pass up the ID3v2 tag (if it exists) if (id3v2.Exists) { if (!id3v2.FooterExists) { intPos = (int)id3v2.TagSize + 10; //+10 for header } else { intPos = (int)id3v2.TagSize + 20; //+20 for header and footer } } fs.Position = intPos; fs.Read(bytHeader, 0, 4); MPEGAudioFrame temp = new MPEGAudioFrame(bytHeader, 0); if (temp.Valid == false) { if (Encoding.ASCII.GetString(bytHeader, 0, 3) == "ID3") { //Another ID3v2 Tag? Console.WriteLine("Another ID3v2 tag was found after the initial one"); Console.WriteLine(); } else if (Encoding.ASCII.GetString(bytHeader, 0, 3) == "APE") { //APETAGEX has appeared before audio data Console.WriteLine("APEv2 Tag Found after ID3v2 tag"); Console.WriteLine(); } else { //Unknown - Somthing is here that is not supposed to be Console.WriteLine("Garbage found after ID3v2 tag"); Console.WriteLine(); } } //ID3v2 Tag was not valid, so the reported size may not be the actual size. Search backwards to try and find the first mpeg audio frame. if (!id3v2.Valid) { //Search Backwards (Max Search 16384) int intPosPrev = intPos; int maxPos = intPos - 16384; if (maxPos < 0) { maxPos = 0; } do { fs.Position = intPos; fs.Read(bytHeader, 0, 4); firstFrame = new MPEGAudioFrame(bytHeader, intPos); if (firstFrame.Valid) { nextFrame = intPos + firstFrame.FrameSize; fs.Position = nextFrame; bytHeader = new byte[4]; //Reset bytHeader array fs.Read(bytHeader, 0, 4); MPEGAudioFrame SecondHeader = new MPEGAudioFrame(bytHeader, nextFrame); if (SecondHeader.Valid) { Valid = true; break; } else { //The next frame did not appear valid - reset stream position fs.Position = intPos; } } intPos--; } while (!Valid && (fs.Position >= maxPos) && intPos >= 0); if (!Valid) { intPos = intPosPrev; } } //Search Forwards do { fs.Position = intPos; fs.Read(bytHeader, 0, 4); firstFrame = new MPEGAudioFrame(bytHeader, intPos); if (firstFrame.Valid) { nextFrame = intPos + firstFrame.FrameSize; fs.Position = nextFrame; bytHeader = new byte[4]; //Reset bytHeader array fs.Read(bytHeader, 0, 4); MPEGAudioFrame SecondHeader = new MPEGAudioFrame(bytHeader, nextFrame); if (SecondHeader.Valid) { Valid = true; break; } else { //The next frame did not appear valid - reset stream position fs.Position = intPos; } } intPos++; }while (!Valid && (fs.Position != fs.Length)); // If the current file stream position is equal to the length, // that means that we've read the entire file and it's not a valid MP3 file if (Valid && (fs.Position != fs.Length)) { intPos += 4; //Bypass the 4 byte header //The following is retrieved from XING SDK //http://www.mp3-tech.org/programmer/decoding.html if (firstFrame.getVersion() == 1.0) //MPEG Version 1 { if (firstFrame.ChannelModeIndex == 3) //Single Channel (Mono) { intPos += 17; } else { intPos += 32; } } else //MPEG Version 2.0 or 2.5 { if (firstFrame.ChannelModeIndex == 3) //Single Channel (Mono) { intPos += 9; } else { intPos += 17; } } // Check to see if the MP3 has a variable bitrate fs.Position = intPos; //fs.Read(bytVBitRate,0,12); //bVBR = LoadVBRHeader(bytVBitRate); vbrFrameInfo = new VBRHeader(fs, (long)intPos); // Find the last Audio Frame of the MP3 findLastFrame(fs); // Once the file's read in, then assign the properties of the file to the public variables intBitRate = getBitrate(); intFrequency = firstFrame.getFrequency(); strMode = firstFrame.getChannelMode(); intLength = getLengthInSeconds(); strLengthFormatted = getFormattedLength(); fs.Close(); } }
private static void Writev1Tag(Stream s, ID3v1Tag id3v1tag) { byte[] encodedTag; bool streamHasID3v1Tag; if (s.Length >= ID3v1Tag.TagLength) { byte[] tagHeader = new byte[ID3v1TagDecoder.TagHeaderSize]; s.Seek(-ID3v1Tag.TagLength, SeekOrigin.End); s.Read(tagHeader, 0, ID3v1TagDecoder.TagHeaderSize); streamHasID3v1Tag = ID3v1TagDecoder.HasID3v1Tag(tagHeader); } else { streamHasID3v1Tag = false; } if (id3v1tag != null) { /* write/overwrite Tag in Stream */ encodedTag = ID3v1TagEncoder.EncodeTag(id3v1tag); s.Seek(streamHasID3v1Tag ? -ID3v1Tag.TagLength : 0, SeekOrigin.End); s.Write(encodedTag, 0, encodedTag.Length); } else { /* delete Tag in Stream if exists */ if (streamHasID3v1Tag) { s.SetLength(s.Length - ID3v1Tag.TagLength); } } }
/// <summary> /// Main output routine. /// </summary> public void Output(int storageId) { // Get correctly formed output folder. string outputFolderName = OutputFolder; if (string.IsNullOrEmpty(outputFolderName)) { throw new InvalidOperationException("An output folder has not been specified."); } // Add a slash on to the output folder so that all file processing works correctly. if (!outputFolderName.EndsWith("\\")) { outputFolderName += "\\"; } // Check that the output folder exists. if (!Directory.Exists(outputFolderName)) { throw new InvalidOperationException($"The output folder '{outputFolderName}' does not exist."); } // Notify that we've started. StatusChangedEventArgs startArgs = new StatusChangedEventArgs(0, "Starting...", false); StatusChanged?.Invoke(startArgs); // Set up error handling so that events can be raised OutputErrorEventArgs outputErrorEventArgs; // Find card so we know what playlists to export. Storage storage = new Storage(); if (storage.Find(storageId)) { // Add on name of storage. outputFolderName += FileSystem.ValidWindowsFileName(storage.StorageDescription); // If the folder doesn't exist, create it. if (!Directory.Exists(outputFolderName)) { try { Directory.CreateDirectory(outputFolderName); } catch (Exception ex) { outputErrorEventArgs = new OutputErrorEventArgs($"There was a problem creating the folder at '{outputFolderName}': {ex.Message}."); OutputError?.Invoke(outputErrorEventArgs); if (outputErrorEventArgs.Cancel) { return; } } } // Check if stuff exists in the folder, if it does then warn. DirectoryInfo outputFolder = new DirectoryInfo(outputFolderName); if (outputFolder.GetDirectories().Any() | outputFolder.GetFiles().Any()) { // Files and/or folders exist in the output folder therefore offer to delete them first. DeleteFilesEventArgs deleteFilesEventArgs = new DeleteFilesEventArgs(outputFolderName); DeleteFiles?.Invoke(deleteFilesEventArgs); if (deleteFilesEventArgs.Response == DeleteFilesResponse.Yes) { // Delete everything in the folder (recursively). foreach (DirectoryInfo directory in outputFolder.GetDirectories()) { try { directory.Delete(true); } catch (Exception ex) { outputErrorEventArgs = new OutputErrorEventArgs(string.Format("Sorry, there was a problem deleting '{0}' : {1}{2}{2}", directory.FullName, ex.Message, Environment.NewLine)); OutputError?.Invoke(outputErrorEventArgs); if (outputErrorEventArgs.Cancel) { return; } } } foreach (FileInfo file in outputFolder.GetFiles()) { try { file.Delete(); } catch (Exception ex) { outputErrorEventArgs = new OutputErrorEventArgs(string.Format("Sorry, there was a problem deleting '{0}' : {1}{2}{2}", file.FullName, ex.Message, Environment.NewLine)); OutputError?.Invoke(outputErrorEventArgs); if (outputErrorEventArgs.Cancel) { return; } } } } else if (deleteFilesEventArgs.Response == DeleteFilesResponse.Cancel) { // Cancel the export altogether. return; } } // In the output handler, the tracks needed to be added first, and then the playlists after. foreach (string playlistId in storage.Playlists) { Playlist playlist = AppMusicLibrary.PlaylistDictionary[playlistId]; if (playlist != null) { // Add MP3 music. foreach (Track track in playlist.AllTracks.Where(t => t.FileName.ToLower().EndsWith(".mp3"))) { if (track.InLibrary) { AddTrack(track.Id, track.Artist, track.Name, track.TrackTime, AppMusicLibrary.MusicFolder + track.Location); } else { AddTrack(track.Id, track.Artist, track.Name, track.TrackTime, track.Location); } } AddPlaylist(playlist.PersistentId, playlist.Name, playlist.AllTracks); } } } // Check for sensible limits. if (FileNameLengthLimit < 64) { throw new InvalidOperationException("File name length limit must be 64 characters or more."); } if (FolderTrackLimit < 0) { throw new InvalidOperationException("Folder Track limit must be 0 or more."); } if (PlaylistTrackLimit < 0) { throw new InvalidOperationException("Playlist Track limit must be 0 or more."); } // To work out a percentage, look at the total tracks to output. int totalOutputTracks = TotalOutputTracks(); int totalOutputTracksSoFar = 0; // Set up a counter to count number of tracks output so far. // Get a divisor (first 95% = the music)... double divisor = 95.0 / totalOutputTracks; if (totalOutputTracks > 0) { // Apply names, e.g. just "Music", or "Music 1", "Music 2" etc. ApplyOutputMusicFolderNames(); // Deal with one music folder at a time. foreach (OutputMusicFolder outputMusicFolder in _outputMusicFolders) { // Establish the name of the music folder string musicFolderPath = $"{outputFolderName}\\{outputMusicFolder.Name}\\"; // Folder should not exist already because whole output folder should have been wiped. if (!Directory.Exists(musicFolderPath)) { try { Directory.CreateDirectory(musicFolderPath); } catch (Exception ex) { outputErrorEventArgs = new OutputErrorEventArgs($"There was a problem creating the folder at '{musicFolderPath}': {ex.Message}."); OutputError?.Invoke(outputErrorEventArgs); // If the user pressed cancel then exit. if (outputErrorEventArgs.Cancel) { return; } } } foreach (OutputTrack outputTrack in outputMusicFolder.Tracks.Values) { // Copy all the music into this folder. string sourceFileName = outputTrack.SourceFileName; // Eliminate any characters that the RNS-E might not agree with. string destinationBaseFileName = FileSystem.ValidRnseFileName(outputTrack.Name + " - " + outputTrack.Artist); // Make sure that full path in M3U is no longer than the specified limit. // // e.g. 64 characters minus the Folder name + slash + .mp3 int maximumFileNameLength = FileNameLengthLimit - (outputMusicFolder.Name.Length + 5); // If necessary, truncate the base file name (i.e. the Name - Artist) to the maximum allowed. if (destinationBaseFileName.Length > maximumFileNameLength) { destinationBaseFileName = destinationBaseFileName.Substring(0, maximumFileNameLength); } // Test for some files being the same name when truncated. string destinationFileName = musicFolderPath + destinationBaseFileName + ".mp3"; int fileNameSuffixCount = 0; // If the file doesn't exist already, then this loop will be skipped over. while (File.Exists(destinationFileName)) { // If file does exist there may be some tracks which are lengthy in name, but only different in the last few characters.. this may have been // truncated before we get to here. Therefore we still need to give them a different file name by applying a "1", "2" etc. on the end. fileNameSuffixCount += 1; // Get a proposed file name for when the suffix is added. Just trim off however many characters needed at the end, and add number. string amendedDestinationBaseFileName = destinationBaseFileName.Substring(0, destinationBaseFileName.Length - fileNameSuffixCount.ToString().Length); // Append number so now overall filename should still be no more than the limit. destinationFileName = musicFolderPath + amendedDestinationBaseFileName + fileNameSuffixCount + ".mp3"; } outputTrack.DestinationFileName = destinationFileName; // Check that the source file exists before trying to copy it. if (File.Exists(sourceFileName)) { // Check whether destination file exists. It shouldn't because of logic further up, but still... if (File.Exists(outputTrack.DestinationFileName)) { outputErrorEventArgs = new OutputErrorEventArgs($"The file '{outputTrack.DestinationFileName}' already exists. Continue the export?"); OutputError?.Invoke(outputErrorEventArgs); // If the user pressed cancel then exit. if (outputErrorEventArgs.Cancel) { return; } } // Work out a percentage complete figure. int percentProgress = Convert.ToInt32(totalOutputTracksSoFar * divisor); // Check for cancellation. StatusChangedEventArgs exportingFileArgs = new StatusChangedEventArgs(percentProgress, "Exporting '" + Path.GetFileName(outputTrack.DestinationFileName) + "'...", false); StatusChanged?.Invoke(exportingFileArgs); if (exportingFileArgs.Cancel) { return; } try { File.Copy(sourceFileName, outputTrack.DestinationFileName, true); } catch (Exception) { outputErrorEventArgs = new OutputErrorEventArgs("There was a problem copying from '" + sourceFileName + "' to '" + outputTrack.DestinationFileName + "'."); OutputError?.Invoke(outputErrorEventArgs); // If the user pressed cancel then exit. if (outputErrorEventArgs.Cancel) { return; } } if (StripId3V1Tags) { // Should Remove ID3V1 tag for two reasons: // (a) Just in case any "helpful" Windows software comes along and tries to automatically add a V2 tag back. // (b) The description output in the M3U playlist is recognised and shown by the RNS-E on the DIS and so this makes any tag redundant anyway. try { ID3v1Tag.RemoveTag(outputTrack.DestinationFileName); } catch (Exception) { // Ignore any error (e.g. if no tag there anyway). } } if (StripId3V2Tags) { // Should Remove any ID3V2 tag because my RNS-E doesn't play any MP3 with this tag (contrary to the Audi instruction manual). try { ID3v2Tag.RemoveTag(outputTrack.DestinationFileName); } catch (Exception) { // Ignore any error (e.g. if no tag there anyway). } } } else { outputErrorEventArgs = new OutputErrorEventArgs($"The file '{sourceFileName}' does not exist."); OutputError?.Invoke(outputErrorEventArgs); // If the user pressed cancel then exit/ if (outputErrorEventArgs.Cancel) { return; } } // Add to value so that percentage can update properly/ totalOutputTracksSoFar += 1; } } // Check for cancellation. StatusChangedEventArgs exportingPlaylistsArgs = new StatusChangedEventArgs(97, "Exporting Playlists...", false); StatusChanged?.Invoke(exportingPlaylistsArgs); if (exportingPlaylistsArgs.Cancel) { return; } // Apply names to playlists before they are output. ApplyOutputPlaylistNames(); // Create all the playlists on disk. foreach (OutputPlaylist outputPlaylist in _outputPlaylists) { if (outputPlaylist.Tracks.Any()) { // Create an M3U file for the playlist in the output folder (make sure this is OK within RNS-E rules). FileStream fileM3U = null; string m3UFileName = Path.Combine(outputFolderName, FileSystem.ValidRnseFileName(outputPlaylist.Name) + ".m3u"); try { fileM3U = File.Create(m3UFileName); } catch (Exception) { outputErrorEventArgs = new OutputErrorEventArgs("There was a problem creating the '" + m3UFileName + "' file."); OutputError?.Invoke(outputErrorEventArgs); // If the user pressed cancel then exit. if (outputErrorEventArgs.Cancel) { return; } } if (fileM3U != null) { // Open the file for writing based upon this stream. StreamWriter writeM3U = new StreamWriter(fileM3U); writeM3U.WriteLine("#EXTM3U"); foreach (string outputTrack in outputPlaylist.Tracks) { // Find which music folder we put the track into, in the end. OutputMusicFolder trackOutputMusicFolder = FindOutputMusicFolderByTrack(outputTrack); if (trackOutputMusicFolder != null && trackOutputMusicFolder.Tracks.ContainsKey(outputTrack)) { // Get the exact file being referred to by the Id. OutputTrack track = trackOutputMusicFolder.Tracks[outputTrack]; // Write an entry in the M3U. writeM3U.WriteLine("#EXTINF:{0},{1} - {2}", track.TrackTime, track.Name, track.Artist); writeM3U.WriteLine("{0}\\{1}", trackOutputMusicFolder.Name, Path.GetFileName(track.DestinationFileName)); } } // Clean up. writeM3U.Flush(); writeM3U.Close(); fileM3U.Close(); } } } } StatusChanged?.Invoke(new StatusChangedEventArgs(100, "Completed.", false)); }