예제 #1
0
        /// <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);
                }
            }
        }
예제 #2
0
파일: MetaTag.cs 프로젝트: gageas/lutea
        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);
        }
예제 #3
0
        /// <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' });
                    }
                }
            }
        }