~ubuntu-branches/debian/sid/hipo/sid

« back to all changes in this revision

Viewing changes to taglib-sharp/TagLib/Id3v2/FrameFactory.cs

  • Committer: Bazaar Package Importer
  • Author(s): Arthur Loiret
  • Date: 2008-04-02 15:37:34 UTC
  • mfrom: (1.1.3 upstream) (2.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080402153734-hnz2ia2tj3zox4z8
Tags: 0.6.1-2
* 0001-Remove-deprecated-Encoding-field-from-hipo.desktop.i.patch: Add,
  taken from Ubuntu.
* Let's hope Ubuntu maintainer Miguel Ruiz will send its patches back to
  Debian next time.
* debian/copyright: Rewrite.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
    copyright            : (C) 2005 by Brian Nickel
3
 
    email                : brian.nickel@gmail.com
4
 
    based on             : id3v2framefactory.cpp from TagLib
5
 
 ***************************************************************************/
6
 
 
7
 
/***************************************************************************
8
 
 *   This library is free software; you can redistribute it and/or modify  *
9
 
 *   it  under the terms of the GNU Lesser General Public License version  *
10
 
 *   2.1 as published by the Free Software Foundation.                     *
11
 
 *                                                                         *
12
 
 *   This library is distributed in the hope that it will be useful, but   *
13
 
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
14
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
15
 
 *   Lesser General Public License for more details.                       *
16
 
 *                                                                         *
17
 
 *   You should have received a copy of the GNU Lesser General Public      *
18
 
 *   License along with this library; if not, write to the Free Software   *
19
 
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
20
 
 *   USA                                                                   *
21
 
 ***************************************************************************/
22
 
 
23
 
using System.Collections.Generic;
24
 
 
25
 
namespace TagLib.Id3v2
26
 
{
27
 
   public class FrameFactory
28
 
   {
29
 
      public delegate Frame FrameCreator (ByteVector data, int offset, FrameHeader header, uint version);
30
 
 
31
 
      //////////////////////////////////////////////////////////////////////////
32
 
      // private properties
33
 
      //////////////////////////////////////////////////////////////////////////
34
 
      private static StringType          default_encoding     = StringType.UTF8;
35
 
      private static bool                use_default_encoding = false;
36
 
      private static List<FrameCreator>  frame_creators       = new List<FrameCreator> ();
37
 
      
38
 
      //////////////////////////////////////////////////////////////////////////
39
 
      // public members
40
 
      //////////////////////////////////////////////////////////////////////////
41
 
      public static Frame CreateFrame (ByteVector data, int offset, uint version)
42
 
      {
43
 
         FrameHeader header = new FrameHeader (data.Mid (offset, (int) FrameHeader.Size (version)), version);
44
 
         ByteVector frame_id = header.FrameId;
45
 
         // A quick sanity check -- make sure that the frame_id is 4 uppercase
46
 
         // Latin1 characters.  Also make sure that there is data in the frame.
47
 
         
48
 
         if(frame_id == null || frame_id.Count != (version < 3 ? 3 : 4) || header.FrameSize < 0)
49
 
            return null;
50
 
         
51
 
         foreach (byte b in frame_id)
52
 
         {
53
 
            char c = (char) b;
54
 
            if ((c < 'A' || c > 'Z') && (c < '1' || c > '9'))
55
 
               return null;
56
 
         }
57
 
         
58
 
         // Windows Media Player may create zero byte frames. Just send them
59
 
         // off as unknown and delete them.
60
 
         if (header.FrameSize == 0)
61
 
         {
62
 
            header.TagAlterPreservation = true;
63
 
            return new UnknownFrame (data, offset, header, version);
64
 
         }
65
 
         
66
 
         // TagLib doesn't mess with encrypted frames, so just treat them
67
 
         // as unknown frames.
68
 
 
69
 
         if (header.Compression)
70
 
         {
71
 
            Debugger.Debug ("Compressed frames are currently not supported.");
72
 
            return new UnknownFrame (data, offset, header, version);
73
 
         }
74
 
         
75
 
         if (header.Encryption)
76
 
         {
77
 
            Debugger.Debug ("Encrypted frames are currently not supported.");
78
 
            return new UnknownFrame (data, offset, header, version);
79
 
         }
80
 
 
81
 
         if (!UpdateFrame (header, version))
82
 
         {
83
 
            header.TagAlterPreservation = true;
84
 
            return new UnknownFrame (data, offset, header, version);
85
 
         }
86
 
         
87
 
         foreach (FrameCreator creator in frame_creators)
88
 
         {
89
 
            Frame frame = creator (data, offset, header, version);
90
 
            if (frame != null)
91
 
               return frame;
92
 
         }
93
 
         
94
 
         
95
 
         // UpdateFrame () might have updated the frame ID.
96
 
 
97
 
         frame_id = header.FrameId;
98
 
         
99
 
         // This is where things get necissarily nasty.  Here we determine which
100
 
         // Frame subclass (or if none is found simply an Frame) based
101
 
         // on the frame ID.  Since there are a lot of possibilities, that means
102
 
         // a lot of if blocks.
103
 
         
104
 
         // Text Identification (frames 4.2)
105
 
         
106
 
         if(frame_id.StartsWith ("T"))
107
 
         {
108
 
            TextIdentificationFrame f = frame_id != "TXXX"
109
 
            ? new TextIdentificationFrame (data, offset, header, version)
110
 
            : new UserTextIdentificationFrame (data, offset, header, version);
111
 
            
112
 
            if(use_default_encoding)
113
 
               f.TextEncoding = default_encoding;
114
 
            
115
 
            if (frame_id == "TCON" && version < 4)
116
 
               UpdateGenre (f);
117
 
            
118
 
            return f;
119
 
         }
120
 
         
121
 
         // Unsynchronized Lyrics (frames 4.8)
122
 
 
123
 
         if (frame_id == "USLT")
124
 
         {
125
 
            UnsynchronisedLyricsFrame f = new UnsynchronisedLyricsFrame (data, offset, header, version);
126
 
            
127
 
            if(use_default_encoding)
128
 
               f.TextEncoding = default_encoding;
129
 
            
130
 
            return f;
131
 
         }
132
 
 
133
 
         // Comments (frames 4.10)
134
 
 
135
 
         if (frame_id == "COMM")
136
 
         {
137
 
            CommentsFrame f = new CommentsFrame (data, offset, header, version);
138
 
            
139
 
            if(use_default_encoding)
140
 
               f.TextEncoding = default_encoding;
141
 
            
142
 
            return f;
143
 
         }
144
 
 
145
 
         // Attached Picture (frames 4.14)
146
 
 
147
 
         if (frame_id == "APIC")
148
 
         {
149
 
            AttachedPictureFrame f = new AttachedPictureFrame (data, offset, header, version);
150
 
            
151
 
            if(use_default_encoding)
152
 
               f.TextEncoding = default_encoding;
153
 
            
154
 
            return f;
155
 
         }
156
 
 
157
 
         // Relative Volume Adjustment (frames 4.11)
158
 
 
159
 
         if (frame_id == "RVA2")
160
 
            return new RelativeVolumeFrame (data, offset, header, version);
161
 
 
162
 
         // Unique File Identifier (frames 4.1)
163
 
 
164
 
         if (frame_id == "UFID")
165
 
            return new UniqueFileIdentifierFrame (data, offset, header, version);
166
 
 
167
 
         // Private (frames 4.27)
168
 
 
169
 
         if (frame_id == "PRIV")
170
 
            return new PrivateFrame (data, offset, header, version);
171
 
         
172
 
         // General Encapsulated Object (frames 4.15)
173
 
         
174
 
         if(frame_id == "GEOB")
175
 
            return new GeneralEncapsulatedObjectFrame (data, offset, header, version);
176
 
         
177
 
         return new UnknownFrame (data, offset, header, version);
178
 
      }
179
 
 
180
 
      public static StringType DefaultTextEncoding
181
 
      {
182
 
         get
183
 
         {
184
 
            return default_encoding;
185
 
         }
186
 
         set
187
 
         {
188
 
            use_default_encoding = true;
189
 
            default_encoding = value;
190
 
         }
191
 
      }
192
 
      
193
 
      public static void AddFrameCreator (FrameCreator creator)
194
 
      {
195
 
         if (creator != null)
196
 
            frame_creators.Insert (0, creator);
197
 
      }
198
 
      
199
 
      public static void UpdateGenre (TextIdentificationFrame frame)
200
 
      {
201
 
         StringList fields = new StringList ();
202
 
         string s = frame.ToString ();
203
 
         
204
 
         while (s.Length > 1 && s [0] == '(')
205
 
         {
206
 
            int closing = s.IndexOf (')');
207
 
            if (closing < 0)
208
 
               break;
209
 
            
210
 
            fields.Add (s.Substring (1, closing - 1));
211
 
            
212
 
            s = s.Substring (closing + 1);
213
 
         }
214
 
         
215
 
         if(s != string.Empty)
216
 
            fields.Add (s);
217
 
            
218
 
         if (fields.IsEmpty)
219
 
            fields.Add (s);
220
 
         
221
 
         frame.SetText (fields);
222
 
      }
223
 
      
224
 
      
225
 
      //////////////////////////////////////////////////////////////////////////
226
 
      // private members
227
 
      //////////////////////////////////////////////////////////////////////////
228
 
      private FrameFactory () {}
229
 
      
230
 
      private static bool UpdateFrame (FrameHeader header, uint version)
231
 
      {
232
 
         ByteVector frame_id = header.FrameId;
233
 
 
234
 
         switch (version)
235
 
         {
236
 
            case 2: // ID3v2.2
237
 
            {
238
 
               if(frame_id == "CRM" ||
239
 
                  frame_id == "EQU" ||
240
 
                  frame_id == "LNK" ||
241
 
                  frame_id == "RVA" ||
242
 
                  frame_id == "TIM" ||
243
 
                  frame_id == "TSI")
244
 
               {
245
 
                  Debugger.Debug ("ID3v2.4 no longer supports the frame type "
246
 
                  + frame_id.ToString () + ".  It will be discarded from the tag.");
247
 
                  
248
 
                  return false;
249
 
               }
250
 
 
251
 
               // ID3v2.2 only used 3 bytes for the frame ID, so we need to convert all of
252
 
               // the frames to their 4 byte ID3v2.4 equivalent.
253
 
 
254
 
               ConvertFrame ("BUF", "RBUF", header);
255
 
               ConvertFrame ("CNT", "PCNT", header);
256
 
               ConvertFrame ("COM", "COMM", header);
257
 
               ConvertFrame ("CRA", "AENC", header);
258
 
               ConvertFrame ("ETC", "ETCO", header);
259
 
               ConvertFrame ("GEO", "GEOB", header);
260
 
               ConvertFrame ("IPL", "TIPL", header);
261
 
               ConvertFrame ("MCI", "MCDI", header);
262
 
               ConvertFrame ("MLL", "MLLT", header);
263
 
               ConvertFrame ("PIC", "APIC", header);
264
 
               ConvertFrame ("POP", "POPM", header);
265
 
               ConvertFrame ("REV", "RVRB", header);
266
 
               ConvertFrame ("SLT", "SYLT", header);
267
 
               ConvertFrame ("STC", "SYTC", header);
268
 
               ConvertFrame ("TAL", "TALB", header);
269
 
               ConvertFrame ("TBP", "TBPM", header);
270
 
               ConvertFrame ("TCM", "TCOM", header);
271
 
               ConvertFrame ("TCO", "TCON", header);
272
 
               ConvertFrame ("TCR", "TCOP", header);
273
 
               ConvertFrame ("TDA", "TDRC", header);
274
 
               ConvertFrame ("TDY", "TDLY", header);
275
 
               ConvertFrame ("TEN", "TENC", header);
276
 
               ConvertFrame ("TFT", "TFLT", header);
277
 
               ConvertFrame ("TKE", "TKEY", header);
278
 
               ConvertFrame ("TLA", "TLAN", header);
279
 
               ConvertFrame ("TLE", "TLEN", header);
280
 
               ConvertFrame ("TMT", "TMED", header);
281
 
               ConvertFrame ("TOA", "TOAL", header);
282
 
               ConvertFrame ("TOF", "TOFN", header);
283
 
               ConvertFrame ("TOL", "TOLY", header);
284
 
               ConvertFrame ("TOR", "TDOR", header);
285
 
               ConvertFrame ("TOT", "TOAL", header);
286
 
               ConvertFrame ("TP1", "TPE1", header);
287
 
               ConvertFrame ("TP2", "TPE2", header);
288
 
               ConvertFrame ("TP3", "TPE3", header);
289
 
               ConvertFrame ("TP4", "TPE4", header);
290
 
               ConvertFrame ("TPA", "TPOS", header);
291
 
               ConvertFrame ("TPB", "TPUB", header);
292
 
               ConvertFrame ("TRC", "TSRC", header);
293
 
               ConvertFrame ("TRD", "TDRC", header);
294
 
               ConvertFrame ("TRK", "TRCK", header);
295
 
               ConvertFrame ("TSS", "TSSE", header);
296
 
               ConvertFrame ("TT1", "TIT1", header);
297
 
               ConvertFrame ("TT2", "TIT2", header);
298
 
               ConvertFrame ("TT3", "TIT3", header);
299
 
               ConvertFrame ("TXT", "TOLY", header);
300
 
               ConvertFrame ("TXX", "TXXX", header);
301
 
               ConvertFrame ("TYE", "TDRC", header);
302
 
               ConvertFrame ("UFI", "UFID", header);
303
 
               ConvertFrame ("ULT", "USLT", header);
304
 
               ConvertFrame ("WAF", "WOAF", header);
305
 
               ConvertFrame ("WAR", "WOAR", header);
306
 
               ConvertFrame ("WAS", "WOAS", header);
307
 
               ConvertFrame ("WCM", "WCOM", header);
308
 
               ConvertFrame ("WCP", "WCOP", header);
309
 
               ConvertFrame ("WPB", "WPUB", header);
310
 
               ConvertFrame ("WXX", "WXXX", header);
311
 
 
312
 
            }
313
 
            break;
314
 
 
315
 
            case 3: // ID3v2.3
316
 
            {
317
 
               if(frame_id == "EQUA" ||
318
 
                  frame_id == "RVAD" ||
319
 
                  frame_id == "TIME" ||
320
 
                  frame_id == "TRDA" ||
321
 
                  frame_id == "TSIZ" ||
322
 
                  frame_id == "TDAT")
323
 
               {
324
 
                  Debugger.Debug ("ID3v2.4 no longer supports the frame type "
325
 
                  + frame_id.ToString () + ".  It will be discarded from the tag.");
326
 
                  
327
 
                  return false;
328
 
               }
329
 
 
330
 
               ConvertFrame ("TORY", "TDOR", header);
331
 
               ConvertFrame ("TYER", "TDRC", header);
332
 
 
333
 
            }
334
 
            break;
335
 
 
336
 
            default:
337
 
            {
338
 
               // This should catch a typo that existed in TagLib up to and including
339
 
               // version 1.1 where TRDC was used for the year rather than TDRC.
340
 
 
341
 
               ConvertFrame ("TRDC", "TDRC", header);
342
 
            }
343
 
            break;
344
 
         }
345
 
 
346
 
         return true;
347
 
      }
348
 
 
349
 
      private static void ConvertFrame (string from, string to, FrameHeader header)
350
 
      {
351
 
         if (header.FrameId != from)
352
 
            return;
353
 
         
354
 
         header.FrameId = to;
355
 
      }
356
 
   }
357
 
}