示例#1
0
		//Creates the ByteBuffer for the ogg tag
		public ByteBuffer Create(Tag tag, int paddingSize) {
			ByteBuffer ogg = creator.Create(tag);
			int tagLength = ogg.Capacity + 4;
			
			ByteBuffer buf = new ByteBuffer( tagLength + paddingSize );

			//CREATION OF CVORBIS COMMENT METADATA BLOCK HEADER
			//If we have padding, the comment is not the last block (bit[0] = 0)
			//If there is no padding, the comment is the last block (bit[0] = 1)
			byte type =  (paddingSize > 0) ? (byte)0x04 : (byte) 0x84;
			buf.Put(type);
			int commentLength = tagLength - 4; //Comment length
			buf.Put( new byte[] { (byte)((commentLength & 0xFF0000) >> 16), (byte)((commentLength & 0xFF00) >> 8) , (byte)(commentLength&0xFF)  } );

			//The actual tag
			buf.Put(ogg);
			
			//PADDING
			if(paddingSize >=4) {
				int paddingDataSize = paddingSize - 4;
				buf.Put((byte)0x81); //Last frame, padding 0x81
				buf.Put(new byte[]{ (byte)((paddingDataSize&0xFF0000)>>16),(byte)((paddingDataSize&0xFF00)>>8),(byte)(paddingDataSize&0xFF) });
				for(int i = 0; i< paddingDataSize; i++)
					buf.Put((byte)0);
			}
			buf.Rewind();
			
			return buf;
		}
示例#2
0
 public ByteBuffer Create(Tag tag, int padding) 
 {
     IList fields = CreateFields(tag);
     int tagSize = ComputeTagLength(tag, fields);
     
     ByteBuffer buf = new ByteBuffer(tagSize + padding);
     Create(tag, buf, fields, tagSize, padding);
     buf.Rewind();
     
     return buf;
 }
示例#3
0
		protected override void Create(Tag tag, ByteBuffer buf, IList fields, int tagSize, int paddingSize) {
			//APETAGEX------------------
			buf.Put(Utils.GetBytes("APETAGEX"));
			
			//Version 2.0 (aka 2000)
			buf.Put( new byte[] {(byte)0xD0,0x07,0x00,0x00} );
			
			//Tag size
			int size = tagSize - 32;
			buf.Put(Utils.GetNumber(size));
			
			//Number of fields
			int listLength = fields.Count;
			buf.Put(Utils.GetNumber(listLength));
			
			//Flags
			buf.Put( new byte[] {0x00,0x00,0x00,(byte)0xA0} );
			//means: We have a header and a footer, this is the header
			
			//Reserved 8-bytes 0x00
			buf.Put( new byte[] {0,0,0,0,0,0,0,0} );
			
			//Now each field is saved:
			foreach(byte[] field in fields) {
				buf.Put(field);
			}
			
			//APETAGEX------------------
			buf.Put(Utils.GetBytes("APETAGEX"));  //APETAGEX
			
			//Version 2.0 (aka 2000)
			buf.Put( new byte[] {(byte)0xD0,0x07,0x00,0x00} );
			
			//Tag size
			buf.Put(Utils.GetNumber(size));
			
			//Number of fields
			buf.Put(Utils.GetNumber(listLength));
			
			//Flags
			buf.Put( new byte[] {0x00,0x00,0x00,(byte)0x80} );
			//means: We have a header and a footer, this is the footer
			
			//Reserved 8-bytes 0x00
			buf.Put( new byte[] {0,0,0,0,0,0,0,0} );
			
			//----------------------------------------------------------------------------
		}
        public Id3v2Tag Read(ByteBuffer data, bool[] ID3Flags, byte version)
        {
            int tagSize = data.Limit;
            byte[] b;
            Id3v2Tag tag = new Id3v2Tag();
            //----------------------------------------------------------------------------
            //Traitement en cas d'Header Etendu==true (A COMPLETER)
            if (version == Id3v2Tag.ID3V23 && ID3Flags[1])
                ProcessExtendedHeader(data);
            //----------------------------------------------------------------------------
            //Extraction des champs de texte
            int specSize = (version == Id3v2Tag.ID3V22) ? 3 : 4;
            for (int a = 0; a < tagSize; a++) {
                //Nom de la Frame
                b = new byte[specSize];

                if(data.Remaining <= specSize)
                    break;

                data.Get(b);

                string field = new string(System.Text.Encoding.ASCII.GetChars(b));
                if (b[0] == 0)
                    break;

                //La longueur du texte contenu dans la Frame
                int frameSize = ReadInteger(data, version);

                if ((frameSize > data.Remaining) || frameSize <= 0){
                //ignore empty frames
                    break;
                }

                b = new byte[ frameSize + ((version == Id3v2Tag.ID3V23) ? 2 : 0) ];
                data.Get(b);

                if( "" != field) {
                    Id3Frame f = CreateId3Frame(field, b, version);
                    if(f != null)
                        tag.Add(f);
                }
            }

            return tag;
        }
示例#5
0
		//Creates the ByteBuffer for the ogg tag
		public ByteBuffer Convert(Tag tag) {
			ByteBuffer ogg = creator.Create(tag);
			int tagLength = ogg.Capacity + 8;
			
			ByteBuffer buf = new ByteBuffer(tagLength);
			
			//[packet type=comment0x03]['vorbis']
			buf.Put( new byte[]{(byte) 0x03, (byte) 0x76, (byte) 0x6f, (byte) 0x72, (byte) 0x62, (byte) 0x69, (byte) 0x73} );
			
			//The actual tag
			buf.Put(ogg);

			//Framing bit = 1
			buf.Put( (byte) 0x01 );

			buf.Rewind();
			return buf;
		}
示例#6
0
		//Creates the ByteBuffer for the ogg tag
		protected override void Create(Tag tag, ByteBuffer buf, IList fields, int tagSize, int padding) {
			string vendorstring;
			if (tag.HasField("vendor"))
				vendorstring = tag.Get("vendor")[0] as string;
			else
				//FIXME: Do something about this
				vendorstring = "DefaultVendor";
				
			byte[] vendorBytes = Utils.GetBytes(vendorstring, "UTF-8");
			buf.Put( new byte[]{(byte)(vendorBytes.Length&0xFF), (byte)((vendorBytes.Length & 0xFF00) >> 8) , (byte)((vendorBytes.Length & 0xFF0000) >> 16), (byte)((vendorBytes.Length & 0xFF000000) >> 24)  } );
			buf.Put( vendorBytes );

			//[user comment list length]
			buf.Put( Utils.GetNumber(fields.Count) );
			
			foreach(byte[] field in fields) {
				buf.Put(field);
			}
		}
示例#7
0
	    public ByteBuffer synchronize(ByteBuffer b)
	    {
	        ByteBuffer bb = new ByteBuffer(b.Capacity);
	        
	        while(b.Remaining >= 1) {
	        	byte cur = b.Get();
	            bb.Put(cur);
	            
	            if((cur&0xFF) == 0xFF && b.Remaining >=1 && b.Peek() == 0x00) {
	            	//First part of synchronization
	                b.Get();
	            }
	        }
	        
	        //We have finished filling the new bytebuffer, so set the limit, and rewind
	        bb.Limit = bb.Position;
	        bb.Rewind();
	        
	        return bb;
	    }
示例#8
0
		public void Write(Tag tag, Stream raf, Stream rafTemp) {
			//Read firstPage----------------------------------------------------
			raf.Seek(26, SeekOrigin.Begin);
			byte[] b = new byte[4];
			int pageSegments = raf.ReadByte()&0xFF; //Unsigned
			raf.Seek(0, SeekOrigin.Begin);

			b = new byte[27 + pageSegments];
			raf.Read(b, 0, b.Length);

			OggPageHeader firstPage = new OggPageHeader(b);
			//------------------------------------------------------------------

			raf.Seek(0, SeekOrigin.Begin);
			//write 1st page (unchanged)----------------------------------------
			byte[] pageBytes = new byte[firstPage.PageLength + 27 + pageSegments];
			raf.Read(pageBytes, 0, pageBytes.Length);
			rafTemp.Write(pageBytes, 0, pageBytes.Length);
			//rafTemp.Seek(firstPage.PageLength + raf.Position, SeekOrigin.Current);
			//------------------------------------------------------------------
			
			//Read 2nd page-----------------------------------------------------
			long pos = raf.Position;
			raf.Seek(raf.Position + 26, SeekOrigin.Begin);
			pageSegments = raf.ReadByte()&0xFF; //Unsigned
			raf.Seek(pos, SeekOrigin.Begin);
			
			b = new byte[27 + pageSegments];
			raf.Read(b, 0, b.Length);
			OggPageHeader secondPage = new OggPageHeader(b);
			long secondPageEndPos = raf.Position;
			//------------------------------------------------------------------

			//Compute old comment length----------------------------------------
			int oldCommentLength = 7; // [.vorbis]
			raf.Seek(raf.Position + 7, SeekOrigin.Begin);

			b = new byte[4];
			raf.Read(b, 0, b.Length);
			int vendorstringLength = Utils.GetNumber(b, 0,3);
			oldCommentLength += 4 + vendorstringLength;

			raf.Seek(raf.Position + vendorstringLength, SeekOrigin.Begin);

			b = new byte[4];
			raf.Read(b, 0, b.Length);
			int userComments = Utils.GetNumber(b, 0,3);
			oldCommentLength += 4;

			for (int i = 0; i < userComments; i++) {
				b = new byte[4];
				raf.Read(b, 0, b.Length);
				int commentLength = Utils.GetNumber(b, 0,3);
				oldCommentLength += 4 + commentLength;

				raf.Seek(raf.Position + commentLength, SeekOrigin.Begin);
			}

			int isValid = raf.ReadByte();
			oldCommentLength += 1;
			if (isValid != 1)
				throw new CannotWriteException("Unable to retreive old tag informations");
			//------------------------------------------------------------------

			//Get the new comment and create the container bytebuffer for 2nd page---
			ByteBuffer newComment = tc.Convert(tag);

			int newCommentLength = newComment.Capacity;
			int newSecondPageLength = secondPage.PageLength - oldCommentLength + newCommentLength;

			byte[] segmentTable = CreateSegmentTable(oldCommentLength,newCommentLength,secondPage);
			int newSecondPageHeaderLength = 27 + segmentTable.Length;

			ByteBuffer secondPageBuffer = new ByteBuffer(newSecondPageLength + newSecondPageHeaderLength);
			//------------------------------------------------------------------

			//Build the new second page header----------------------------------
			//OggS capture
			secondPageBuffer.Put(Utils.GetBytes("OggS"));
			//Stream struct revision
			secondPageBuffer.Put((byte) 0);
			//header_type_flag
			secondPageBuffer.Put((byte) 0);
			//absolute granule position
			secondPageBuffer.Put(
				new byte[] {
					(byte) 0,
					(byte) 0,
					(byte) 0,
					(byte) 0,
					(byte) 0,
					(byte) 0,
					(byte) 0,
					(byte) 0 });

			//stream serial number
			secondPageBuffer.Put(Utils.GetNumber(secondPage.SerialNumber));

			//page sequence no
			secondPageBuffer.Put(Utils.GetNumber(secondPage.PageSequence));

			//CRC (to be computed later)
			secondPageBuffer.Put(new byte[] {(byte) 0, (byte) 0, (byte) 0, (byte) 0 });
			int crcOffset = 22;
			
			if (segmentTable.Length > 255) {
			    throw new CannotWriteException ("In this special case we need to " +
			    		"create a new page, since we still hadn't the time for that " +
			    		"we won't write because it wouldn't create an ogg file.");
			}
			//page_segments nb.
			secondPageBuffer.Put((byte)segmentTable.Length);

			//page segment table
			for (int i = 0; i < segmentTable.Length; i++)
				secondPageBuffer.Put(segmentTable[i]);
			//------------------------------------------------------------------

			//Add to the new second page the new comment------------------------
			secondPageBuffer.Put(newComment);
			//------------------------------------------------------------------

			//Add the remaining old second page (encoding infos, etc)-----------
			raf.Seek(secondPageEndPos+oldCommentLength, SeekOrigin.Begin);
			secondPageBuffer.Put(raf);
			//------------------------------------------------------------------

			//Compute CRC over the new second page------------------------------
			byte[] crc = OggCRCFactory.ComputeCRC(secondPageBuffer.Data);
			for (int i = 0; i < crc.Length; i++) {
				secondPageBuffer.Put(crcOffset + i, crc[i]);
			}
			//------------------------------------------------------------------

			//Transfer the second page bytebuffer content-----------------------
			secondPageBuffer.Rewind();
			rafTemp.Write(secondPageBuffer.Data, 0, secondPageBuffer.Data.Length);
			//------------------------------------------------------------------

			//Write the rest of the original file-------------------------------
			byte[] buf = new byte[65536];
			int read = raf.Read(buf, 0, buf.Length);
			while (read != 0) {
				rafTemp.Write(buf, 0, read);
				read = raf.Read(buf, 0, buf.Length);
			}
			//rafTemp.getChannel().transferFrom(raf.getChannel(), 	rafTemp.Position, raf.Length() - raf.Position);
			//------------------------------------------------------------------
		}
示例#9
0
 public void Put(ByteBuffer buf) 
 {
     Put(buf.Data);
 }
        private int ReadInteger(ByteBuffer bb, int version)
        {
            int value = 0;

            if(version == Id3v2Tag.ID3V23)
                value += (bb.Get()& 0xFF) << 24;
            value += (bb.Get()& 0xFF) << 16;
            value += (bb.Get()& 0xFF) << 8;
            value += (bb.Get()& 0xFF);

            return value;
        }
 //Process the Extended Header in the ID3v2 Tag, returns the number of bytes to skip
 private int ProcessExtendedHeader(ByteBuffer data)
 {
     //TODO Verify that we have an syncsfe int
     byte[] exthead = new byte [4];
     data.Get(exthead);
     int extsize = ReadInteger(data, Id3v2Tag.ID3V23);
     // The extended header size includes those first four bytes.
     data.Position = data.Position + extsize;
     return extsize;
 }
        public Id3v2Tag Read(Stream mp3Stream)
        {
            Id3v2Tag tag;

            byte[] b = new byte[3];

            mp3Stream.Read(b, 0, b.Length);
            mp3Stream.Seek(0, SeekOrigin.Begin);

            string ID3 = new string(System.Text.Encoding.ASCII.GetChars(b));

            if (ID3 != "ID3") {
                throw new CannotReadException("Not an ID3 tag");
            }
            //Begins tag parsing ---------------------------------------------
            mp3Stream.Seek(3, SeekOrigin.Begin);
            //----------------------------------------------------------------------------
            //Version du tag ID3v2.xx.xx
            string versionHigh=mp3Stream.ReadByte() +"";
            string versionID3 =versionHigh+ "." + mp3Stream.ReadByte();
            //------------------------------------------------------------------------- ---
            //D?tection de certains flags (A COMPLETER)
            this.ID3Flags = ProcessID3Flags( (byte) mp3Stream.ReadByte() );
            //----------------------------------------------------------------------------

            //			On extrait la taille du tag ID3
            int tagSize = ReadSyncsafeInteger(mp3Stream);
            //System.err.println("TagSize: "+tagSize);

            //			------------------NEWNEWNWENENEWNENWEWN-------------------------------
            //Fill a byte buffer, then process according to correct version
            b = new byte[tagSize+2];
            mp3Stream.Read(b, 0, b.Length);
            ByteBuffer bb = new ByteBuffer(b);

            if (ID3Flags[0]==true) {
                //We have unsynchronization, first re-synchronize
                bb = synchronizer.synchronize(bb);
            }

            if(versionHigh == "2") {
                tag = v23.Read(bb, ID3Flags, Id3v2Tag.ID3V22);
            }
            else if(versionHigh == "3") {
                tag = v23.Read(bb, ID3Flags, Id3v2Tag.ID3V23);
            }
            else if(versionHigh == "4") {
                throw new CannotReadException("ID3v2 tag version "+ versionID3 + " not supported !");
            }
            else {
                throw new CannotReadException("ID3v2 tag version "+ versionID3 + " not supported !");
            }

            return tag;
        }
示例#13
0
 protected abstract void Create(Tag tag, ByteBuffer buf, IList fields, int tagSize, int padding);