/// <summary> /// Read MP4 structure recursively and make a list of meta data. /// </summary> private void ReadRecurse(long length) { long p = 0; while (true) { // read ATOM header byte[] buffer = new byte[NODE_LIST_HEADER_SIZE]; strm.Read(buffer, 0, NODE_LIST_HEADER_SIZE); long atom_size = BEUInt32(buffer, 0); UInt32 atom_name = BEUInt32(buffer, 4); var headerSize = NODE_LIST_HEADER_SIZE; if (atom_size == 1) { byte[] large_size_buf = new byte[sizeof(UInt64)]; strm.Read(large_size_buf, 0, sizeof(UInt64)); var large_size = BEUInt64(large_size_buf, 0); atom_size = (long)large_size; headerSize = NODE_LIST_HEADER_SIZE + sizeof(UInt64); } else if (atom_size == 0) { throw new System.IO.FileFormatException("atom_size is zero"); } atom_size -= headerSize; if ((atom_size > (length - p)) || (atom_size < 0)) { return; } long initial_pos = strm.Position; switch (atom_name) { case 0x6D646174: // mdat // メタ情報が取得済みと思われる場合、mdatが見つかった時点で処理終了 if (tags.Count != 0) { throw new EndOfStreamException(); } break; case 0x64617461: // data if (tagValue == null) { ReadData((int)atom_size); } break; case 0x6E616D65: // name tagKey = ReadName((int)atom_size).ToUpper(); break; case 0x676E7265: // gnre tagValue = null; try { ReadRecurse(atom_size); if (tagValue == null) { break; } if (!(tagValue is int)) { break; } var genreStr = ID3.GetGenreString((int)tagValue - 1); if (genreStr == null) { break; } tags.Add(new KeyValuePair <string, object>("GENRE", genreStr)); } catch (ArgumentException) { } catch (IOException) { } catch (FormatException) { } break; case 0x6D703461: // mp4a ReadMp4a((int)atom_size); break; case 0x616C6163: // alac ReadAlac((int)atom_size); break; case 0x6D766864: // mvhd ReadMvhd((int)atom_size); break; case 0x2D2D2D2D: // ---- Read____((int)atom_size); break; case 0x70696E66: // pinf tags.Add(new KeyValuePair <string, object>("PURCHASED", "true")); break; default: if (KnownListAtoms.ContainsKey(atom_name)) { var offset = KnownListAtoms[atom_name]; if (offset != 0) { strm.Seek(offset, SeekOrigin.Current); } ReadRecurse(atom_size - offset); } else if (KnownItunesTagAtoms.ContainsKey(atom_name)) { tagValue = null; ReadRecurse(atom_size); if ((tagValue != null) || (tagValuePicture != null)) { AddToTag(KnownItunesTagAtoms[atom_name]); } } else { strm.Seek(atom_size, SeekOrigin.Current); } break; } p += atom_size + headerSize; initial_pos += atom_size; if (p >= length) { return; } if (strm.Position != initial_pos) { strm.Seek(initial_pos, SeekOrigin.Begin); } } }
public static List <KeyValuePair <string, object> > readTagByFilename(string filename, bool createImageObject) { List <KeyValuePair <string, object> > tag = null; try { using (System.IO.FileStream fs = System.IO.File.Open(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read)) { switch (System.IO.Path.GetExtension(filename).ToLower()) { case ".flac": tag = FlacTag.Read(fs, createImageObject); break; case ".ogg": tag = Ogg.Read(fs); break; case ".m4a": case ".m4v": case ".mp4": case ".aac": tag = MP4.Read(fs, createImageObject); break; case ".wma": case ".asf": case ".wmv": tag = ASF.Read(fs, createImageObject); break; case ".ape": case ".tak": case ".wv": tag = ApeTag.Read(fs, createImageObject); break; case ".tta": case ".mp3": case ".mp2": try { tag = ApeTag.Read(fs, createImageObject); if (tag == null) { tag = new List <KeyValuePair <string, object> >(); } } catch (IOException) { } try { fs.Seek(0, System.IO.SeekOrigin.Begin); var tag_id3v2 = ID3ToTag(ID3V2Tag.readID3tag(fs, createImageObject)); if (tag_id3v2 != null) { tag.AddRange(tag_id3v2); } } catch (IOException ex) { Logger.Error(ex); } try { fs.Seek(0, System.IO.SeekOrigin.Begin); var tag_id3v1 = ID3.Read(fs); if (tag_id3v1 != null) { foreach (var v1tag in tag_id3v1) { if (tag.Find((e) => e.Key == v1tag.Key).Key == null) { tag.Add(v1tag); } } } } catch (IOException) { } break; default: return(null); } } } catch (IOException) { } if (tag == null) { return(null); } // BANDをALBUM ARTISTとして扱う var band = tag.Find((e) => { return(e.Key == "BAND"); }); if (band.Value != null) { tag.Add(new KeyValuePair <string, object>("ALBUM ARTIST", band.Value)); } // TRACKNUMBERをTRACKとして扱う var tracknumber = tag.Find((e) => { return(e.Key == "TRACKNUMBER"); }); if (tracknumber.Value != null) { tag.Add(new KeyValuePair <string, object>("TRACK", tracknumber.Value)); } // ARTISTがないとき、ALBUM ARTISTをARTISTとして扱う if (tag.Find((e) => { return(e.Key == "ARTIST"); }).Value == null) { var albumartist = tag.Find((e) => { return(e.Key == "ALBUM ARTIST"); }); if (albumartist.Value != null) { tag.Add(new KeyValuePair <string, object>("ARTIST", albumartist.Value)); } } return(tag); }
/// <summary> /// ID3V2フレームのデータを読む /// </summary> /// <param name="sr"></param> /// <param name="fr"></param> /// <param name="createImageObject"></param> private static void readFrameBody(Stream sr, Frame fr, bool createImageObject) { if (fr.ID.Type == FRAME_TYPE.FR_APIC) { if (!createImageObject) { sr.Seek(sr.Length, SeekOrigin.Current); return; } var tmp = sr.ReadBytes((int)sr.Length); int offset = 0; string imgtype = Encoding.ASCII.GetString(tmp, 1, 3); if ((imgtype == "JPG") || (imgtype == "PNG")) { fr.Picture_type = tmp[4]; offset = tmp.IndexOf(5, 0) + 1; } else // mime { int pictureTypeIndex = tmp.IndexOf(1, 0) + 1; fr.Picture_type = tmp[pictureTypeIndex]; offset = tmp.IndexOf(pictureTypeIndex + 1, 0) + 1; } MemoryStream ms = new MemoryStream(tmp, offset, tmp.Length - offset); try { fr.Image = System.Drawing.Image.FromStream(ms); } catch (ArgumentException) { } } else { var tmp = sr.ReadBytes((int)sr.Length); Encoding enc = ID32Encodings[0]; // default int offset = 0; if (tmp[0] < ID32Encodings.Length) { offset += 1; if (fr.ID.Type == FRAME_TYPE.FR_TXT_EX_LNG) { offset += 3; } enc = ID32Encodings[tmp[0]]; } fr.Value = enc.GetString(tmp, offset, tmp.Length - offset).Replace("\ufeff", "").Trim().TrimEnd(new char[] { '\0' }); //genreのとき if (fr.ID.Name4 == "TCON") { var match = GenreRegex.Match(fr.Value); if (match.Success) { fr.Value = ID3.GetGenreString(int.Parse(match.Groups[1].Value)) ?? match.Groups[2].Value; } } // TXXX,COMMなどのとき if (fr.ID.Type == FRAME_TYPE.FR_TXT_EX || fr.ID.Type == FRAME_TYPE.FR_TXT_EX_LNG) { int idx = fr.Value.IndexOf('\0'); if (idx == -1) { fr.Extid = ""; fr.Value = ""; } else { fr.Extid = fr.Value.Substring(0, idx).ToUpper(); fr.Value = fr.Value.Substring(idx + 1).TrimEnd(new char[] { '\0' }); } } } }