Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/esau/ptarmigan/impl/filter/VorbisCommentFilter.java


1   /* $Header: /cvsroot/ptarmigan/ptarmigan/src/java/org/esau/ptarmigan/impl/filter/VorbisCommentFilter.java,v 1.2 2002/09/19 03:50:48 reedesau Exp $ */
2   
3   package org.esau.ptarmigan.impl.filter;
4   
5   import java.io.IOException;
6   import java.text.ParseException;
7   
8   import org.xml.sax.SAXException;
9   
10  import org.apache.commons.logging.Log;
11  import org.apache.commons.logging.LogFactory;
12  
13  import org.esau.ptarmigan.util.MultiMap;
14  
15  /**
16   * Extract metadata from an OGG Vorbis native tag format
17   *
18   * Following the three header packets, all packets in a Vorbis I stream
19   * are audio.
20   *
21   * @author Reed Esau
22   * @author Philip Gladstone
23   * @version $Revision: 1.2 $ $Date: 2002/09/19 03:50:48 $
24   */
25  public abstract class VorbisCommentFilter extends BinaryFilter {
26  
27      public VorbisCommentFilter() throws SAXException  {
28  
29          //NOTE: don't declare mime-type in ctor because we might be reading
30          // vorbis tags from FLAC or some other format
31      }
32  
33      /** shared with FLAC to read comment packet */
34      int readCommentSubPacket() throws IOException, SAXException, ParseException {
35  
36          if (log.isDebugEnabled())
37              log.debug("readCommentSubPacket: counter=" + counter());
38  
39          final String local_name = "comments";
40          final String q_name = NS_PREFIX + ":" + local_name;
41  
42          startElement(NS_URI, local_name, q_name, EMPTY_ATTRS);
43  
44          int total = 0;
45  
46          byte[] buf = new byte[2048];
47  
48          int bytes_read = readComment(buf);   // vendor string
49  
50          total += (4+bytes_read);
51  
52          write(NS_URI, NS_PREFIX, "vendor", buf, 0, bytes_read, ENCODING);
53  
54          int comment_count = readInt32LE();
55          total += 4;
56  
57          MultiMap content_map = new MultiMap();     // map of keys, each with a list of values
58  
59          for (int i = 0; i < comment_count; i++) {
60              bytes_read = readComment(buf);
61              total += (4+bytes_read);
62  
63              int j;
64              for (j = 0; j < bytes_read; j++)
65                  if (buf[j] == '=')
66                      break;
67              if (j < bytes_read) {
68                  String key = new String(buf, 0, j).toLowerCase();
69                  String value = new String(buf, j+1, bytes_read-j-1, ENCODING);
70                  content_map.put(key, value);
71              }
72              else {   // if no key=value, treat as a comment (may be more than one!)
73                  write(NS_URI, NS_PREFIX, "user-comment", buf, 0, bytes_read, ENCODING);
74              }
75          }
76  
77          // dump the Content in the sequence required by the schema
78          writeContentMap(content_map);
79  
80          endElement(NS_URI, local_name, q_name);
81  
82          return total;
83      }
84  
85  //
86  // internal
87  //
88  
89      /**
90       * consume a comment string prefixed by an UNSIGNED length integer (4-bytes)
91       *
92       * @return number of bytes read into buffer for the comment
93       */
94      private int readComment(byte[] buf) throws IOException, ParseException {
95  
96          int len = readInt32LE();
97  
98          if (len > MAX_COMMENT_SIZE)
99              throw new ParseException("allowable comment size exceeded", 0);  //TODO: supply the position
100 
101         read(buf, 0, len);
102 
103         return len;
104     }
105 
106     /** write those items available in content_map as elements in the order prescribed by the schema */
107     private void writeContentMap(MultiMap content_map) throws SAXException {
108 
109         final int DEFAULT_LIMIT = 100;
110 
111         final String local_name = "content";
112         final String q_name = NS_PREFIX + ":" + local_name;
113 
114         startElement(NS_URI, local_name, q_name, EMPTY_ATTRS);
115 
116         // Track/Work name
117         writeString(NS_URI, NS_PREFIX, content_map, "title", DEFAULT_LIMIT);
118 
119         // The version field may be used to differentiate multiple versions of the same track title in a single collection. (e.g. remix info)
120         writeString(NS_URI, NS_PREFIX, content_map, "version", 1);
121 
122         // The collection name to which this track belongs
123         writeString(NS_URI, NS_PREFIX, content_map, "album", DEFAULT_LIMIT);
124 
125         // The track number of this piece if part of a specific larger collection or album
126         writeInteger(NS_URI, NS_PREFIX, content_map, "tracknumber", 1);
127 
128         // The artist generally considered responsible for the work. In popular music this is usually the performing band or singer. For classical music it would be the composer. For an audio book it would be the author of the original text.
129         writeString(NS_URI, NS_PREFIX, content_map, "artist", DEFAULT_LIMIT);
130 
131         // The artist(s) who performed the work. In classical music this would be the conductor, orchestra, soloists. In an audio book it would be the actor who did the reading. In popular music this is typically the same as the ARTIST and is omitted.
132         writeString(NS_URI, NS_PREFIX, content_map, "performer", DEFAULT_LIMIT);
133 
134         // Copyright attribution, e.g., '2001 Nobody's Band' or '1999 Jack Moffitt'
135         writeString(NS_URI, NS_PREFIX, content_map, "copyright", DEFAULT_LIMIT);
136 
137         // License information, eg, 'All Rights Reserved', 'Any Use Permitted', a URL to a license such as a Creative Commons license ("www.creativecommons.org/blahblah/license.html") or the EFF Open Audio License ('distributed under the terms of the Open Audio License. see http://www.eff.org/IP/Open_licenses/eff_oal.html for details'), etc.
138         writeString(NS_URI, NS_PREFIX, content_map, "license", DEFAULT_LIMIT);
139 
140         // Name of the organization producing the track (i.e. the 'record label')
141         writeString(NS_URI, NS_PREFIX, content_map, "organization", DEFAULT_LIMIT);
142 
143         // A short text description of the contents
144         writeString(NS_URI, NS_PREFIX, content_map, "description", DEFAULT_LIMIT);
145 
146         // A short text indication of music genre
147         writeString(NS_URI, NS_PREFIX, content_map, "genre", DEFAULT_LIMIT);
148 
149         // Date the track was recorded
150         writeDate(NS_URI, NS_PREFIX, content_map, "date", DEFAULT_LIMIT);
151 
152         // Location where track was recorded
153         writeString(NS_URI, NS_PREFIX, content_map, "location", DEFAULT_LIMIT);
154 
155         // Contact information for the creators or distributors of the track. This could be a URL, an email address, the physical address of the producing label.
156         writeString(NS_URI, NS_PREFIX, content_map, "contact", DEFAULT_LIMIT);
157 
158         // ISRC number for the track; see the ISRC intro page for more information on ISRC numbers.
159         writeString(NS_URI, NS_PREFIX, content_map, "isrc", DEFAULT_LIMIT);
160 
161         writeString(NS_URI, NS_PREFIX, content_map, "replaygain_album_gain", 1);
162         writeString(NS_URI, NS_PREFIX, content_map, "replaygain_album_peak", 1);
163         writeString(NS_URI, NS_PREFIX, content_map, "replaygain_track_gain", 1);
164         writeString(NS_URI, NS_PREFIX, content_map, "replaygain_track_peak", 1);
165 
166         endElement(NS_URI, local_name, q_name);
167     }
168 
169 //
170 // constants
171 //
172 
173     static final String NS_URI = "http://esau.org/ns/ptarmigan/vorbis";
174     static final String NS_PREFIX = "ogg";
175 
176     static final int MAX_COMMENT_SIZE = 10000;      // arbitrary limit to prevent OOM exceptions
177 
178     static final String ENCODING = "UTF-8";
179 
180     /**
181      * logging object
182      */
183     static Log log = LogFactory.getLog(VorbisCommentFilter.class);
184 }
185 
186 /*
187 PTARMIGAN MODIFIED BSD LICENSE
188 
189 Copyright (c) 2002, Reed Esau (reed.esau@pobox.com) All rights reserved.
190 
191 Redistribution and use in source and binary forms, with or without
192 modification, are permitted provided that the following conditions are
193 met:
194 
195 Redistributions of source code must retain the above copyright notice,
196 this list of conditions and the following disclaimer.
197 
198 Redistributions in binary form must reproduce the above copyright notice,
199 this list of conditions and the following disclaimer in the documentation
200 and/or other materials provided with the distribution.
201 
202 Neither the name of the Ptarmigan Project
203 (http://ptarmigan.sourceforge.net) nor the names of its contributors may
204 be used to endorse or promote products derived from this software without
205 specific prior written permission.
206 
207 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
208 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
209 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
210 PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
211 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
212 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
213 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
214 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
215 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
216 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
217 POSSIBILITY OF SUCH DAMAGE.
218 */