~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/maccore/src/AudioToolbox/AudioFile.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
//
4
4
// Authors:
5
5
//    Miguel de Icaza (miguel@xamarin.com)
 
6
//    Marek Safar (marek.safar@gmail.com)
6
7
//     
7
8
// Copyright 2009 Novell, Inc
 
9
// Copyright 2011, 2012 Xamarin Inc.
8
10
//
9
11
// Permission is hereby granted, free of charge, to any person obtaining
10
12
// a copy of this software and associated documentation files (the
51
53
                AAC_ADTS = 0x61647473, // adts
52
54
                MPEG4 = 0x6d703466, // mp4f
53
55
                M4A = 0x6d346166, // m4af
 
56
                M4B = 0x6d346266, // m4bf
54
57
                CAF = 0x63616666, // caff
55
58
                ThreeGP = 0x33677070, // 3gpp
56
59
                ThreeGP2 = 0x33677032, // 3gp2
57
60
                AMR = 0x616d7266, // amrf
58
61
        }
59
62
 
60
 
        enum AudioFileError {
 
63
        public enum AudioFileError {
61
64
                Unspecified = 0x7768743f, // wht?
62
65
                UnsupportedFileType = 0x7479703f, // typ?
63
66
                UnsupportedDataFormat = 0x666d743f, // fmt?
129
132
                Backward = 3
130
133
        }
131
134
 
 
135
        public enum AudioFileChunkType : uint
 
136
        {
 
137
                CAFStreamDescription    = 0x64657363,   // 'desc'
 
138
                CAFAudioData                    = 0x64617461,   // 'data'
 
139
                CAFChannelLayout                = 0x6368616e,   // 'chan'
 
140
                CAFFiller                               = 0x66726565,   // 'free'
 
141
                CAFMarker                               = 0x6d61726b,   // 'mark'
 
142
                CAFRegion                               = 0x7265676e,   // 'regn'
 
143
                CAFInstrument                   = 0x696e7374,   // 'inst'
 
144
                CAFMagicCookieID                = 0x6b756b69,   // 'kuki'
 
145
                CAFInfoStrings                  = 0x696e666f,   // 'info'
 
146
                CAFEditComments                 = 0x65646374,   // 'edct'
 
147
                CAFPacketTable                  = 0x70616b74,   // 'pakt'
 
148
                CAFStrings                              = 0x73747267,   // 'strg'
 
149
                CAFUUID                                 = 0x75756964,   // 'uuid'
 
150
                CAFPeak                                 = 0x7065616b,   // 'peak'
 
151
                CAFOverview                             = 0x6f767677,   // 'ovvw'
 
152
                CAFMIDI                                 = 0x6d696469,   // 'midi'
 
153
                CAFUMID                                 = 0x756d6964,   // 'umid'
 
154
                CAFFormatListID                 = 0x6c647363,   // 'ldsc'
 
155
                CAFiXML                                 = 0x69584d4c,   // 'iXML'
 
156
        }
 
157
 
132
158
        [StructLayout(LayoutKind.Sequential)]
133
159
        struct AudioFramePacketTranslation {
134
160
                public long Frame;
141
167
                public long Byte;
142
168
                public long Packet;
143
169
                public int ByteOffsetInPacket;
144
 
                public uint Flags;
145
 
        };
 
170
                public BytePacketTranslationFlags Flags;
 
171
        }
 
172
 
 
173
        [Flags]
 
174
        enum BytePacketTranslationFlags : uint
 
175
        {
 
176
                IsEstimate = 1
 
177
        }
146
178
        
147
179
        [StructLayout(LayoutKind.Sequential)]
148
 
        struct AudioFileSmpteTime {
 
180
        public struct AudioFileSmpteTime {
149
181
                public sbyte Hours;
150
182
                public byte  Minutes;
151
183
                public byte  Seconds;
154
186
        }
155
187
 
156
188
        [StructLayout(LayoutKind.Sequential)]
157
 
        struct AudioFileMarker
 
189
        public struct AudioFileMarker
158
190
        {
159
191
                public double FramePosition;
160
 
                public IntPtr Name_cfstringref;
 
192
                internal IntPtr Name_cfstringref;
161
193
                public int    MarkerID;
162
194
                public AudioFileSmpteTime SmpteTime;
163
 
                public uint Type;
 
195
                public AudioFileMarkerType Type;
164
196
                public ushort Reserved;
165
197
                public ushort Channel;
166
198
 
171
203
                }
172
204
        }
173
205
 
174
 
        [StructLayout(LayoutKind.Sequential)]
175
 
        struct AudioFileMarkerList {
176
 
                public uint SmpteTimeType;
177
 
                public uint NumberMarkers;
178
 
                public AudioFileMarker Markers; // this is a variable length array of mNumberMarkers elements
179
 
 
180
 
                public static int RecordsThatFitIn (int n)
181
 
                {
182
 
                        unsafe {
183
 
                                if (n <= sizeof (AudioFileMarker))
184
 
                                        return 0;
185
 
                                n -= 8;
186
 
                                return n / sizeof (AudioFileMarker);
187
 
                        }
188
 
                }
189
 
 
190
 
                public static int SizeForMarkers (int markers)
191
 
                {
192
 
                        unsafe {
193
 
                                return 8 + markers * sizeof (AudioFileMarker);
194
 
                        }
195
 
                }
196
 
        }
197
 
 
198
 
        [StructLayout(LayoutKind.Sequential)]
199
 
        struct AudioFileRegion {
200
 
                public uint RegionID;
201
 
                public IntPtr Name_cfstringref;
202
 
                public uint Flags;
203
 
                public int Count;
204
 
                public AudioFileMarker Markers; // this is a variable length array of mNumberMarkers elements
205
 
        }
206
 
 
207
 
        [StructLayout(LayoutKind.Sequential)]
208
 
        struct AudioFileRegionList {
209
 
                public uint SmpteTimeType;
210
 
                public int Count;
211
 
                public AudioFileRegion Regions; // this is a variable length array of mNumberRegions elements
 
206
        public enum AudioFileMarkerType : uint
 
207
        {
 
208
                Generic = 0,
 
209
 
 
210
                CAFProgramStart                         = 0x70626567,   // 'pbeg'
 
211
                CAFProgramEnd                           = 0x70656e64,   // 'pend'
 
212
                CAFTrackStart                           = 0x74626567,   // 'tbeg'
 
213
                CAFTrackEnd                                     = 0x74656e54,   // 'tend'
 
214
                CAFIndex                                        = 0x696e6478,   // 'indx'
 
215
                CAFRegionStart                          = 0x72626567,   // 'rbeg'
 
216
                CAFRegionEnd                            = 0x72626567,   // 'rend'
 
217
                CAFRegionSyncPoint                      = 0x72737963,   // 'rsyc'
 
218
                CAFSelectionStart                       = 0x73626567,   // 'sbeg'
 
219
                CAFSelectionEnd                         = 0x73626567,   // 'send'
 
220
                CAFEditSourceBegin                      = 0x63626567,   // 'cbeg'
 
221
                CAFEditSourceEnd                        = 0x63626567,   // 'cend'
 
222
                CAFEditDestinationBegin         = 0x64626567,   // 'dbeg'
 
223
                CAFEditDestinationEnd           = 0x64626567,   // 'dend'
 
224
                CAFSustainLoopStart                     = 0x736c6267,   // 'slbg'
 
225
                CAFSustainLoopEnd                       = 0x736c6265,   // 'slen'
 
226
                CAFReleaseLoopStart                     = 0x726c6267,   // 'rlbg'
 
227
                CAFReleaseLoopEnd                       = 0x726c6265,   // 'rlen'
 
228
                CAFSavedPlayPosition            = 0x73706c79,   // 'sply'
 
229
                CAFTempo                                        = 0x746d706f,   // 'tmpo'
 
230
                CAFTimeSignature                        = 0x74736967,   // 'tsig'
 
231
                CAFKeySignature                         = 0x6b736967,   // 'ksig'
 
232
        }
 
233
 
 
234
        public class AudioFileMarkerList : IDisposable
 
235
        {
 
236
                IntPtr ptr;
 
237
                readonly bool owns;
 
238
 
 
239
                public AudioFileMarkerList (IntPtr ptr, bool owns)
 
240
                {
 
241
                        this.ptr = ptr;
 
242
                        this.owns = owns;
 
243
                }
 
244
 
 
245
                ~AudioFileMarkerList ()
 
246
                {
 
247
                        Dispose (false);
 
248
                        GC.SuppressFinalize (this);
 
249
                }
 
250
 
 
251
                public SmpteTimeType SmpteTimeType {
 
252
                        get {
 
253
                                return (SmpteTimeType) Marshal.ReadInt32 (ptr);
 
254
                        }
 
255
                }
 
256
 
 
257
                public uint Count {
 
258
                        get {
 
259
                                return (uint) Marshal.ReadInt32 (ptr, 4);
 
260
                        }
 
261
                }
 
262
 
 
263
                public AudioFileMarker this [int index] {
 
264
                        get {
 
265
                                if (index >= Count || index < 0)
 
266
                                        throw new ArgumentOutOfRangeException ("index");
 
267
 
 
268
                                //
 
269
                                // Decodes
 
270
                                //
 
271
                                // struct AudioFileMarkerList
 
272
                                // {
 
273
                                //      UInt32                          mSMPTE_TimeType;
 
274
                                //      UInt32                          mNumberMarkers;
 
275
                                //      AudioFileMarker         mMarkers[1]; // this is a variable length array of mNumberMarkers elements
 
276
                                // }
 
277
                                //
 
278
                                unsafe {
 
279
                                        var ptr = (AudioFileMarker *) this.ptr + 2 * sizeof (int) + index * sizeof (AudioFileMarker);
 
280
                                        return *ptr;
 
281
                                }
 
282
                        }
 
283
                }
 
284
 
 
285
                public void Dispose ()
 
286
                {
 
287
                        Dispose (true);
 
288
                }
 
289
 
 
290
                protected virtual void Dispose (bool disposing)
 
291
                {
 
292
                        if (!owns || ptr == IntPtr.Zero)
 
293
                                return;
 
294
 
 
295
                        for (int i = 0; i < Count; ++i) {
 
296
                                CFObject.CFRelease (this [i].Name_cfstringref);
 
297
                        }
 
298
 
 
299
                        Marshal.FreeHGlobal (ptr);
 
300
                        ptr = IntPtr.Zero;
 
301
                }
 
302
        }
 
303
 
 
304
        [StructLayout(LayoutKind.Sequential)]
 
305
        public struct AudioFilePacketTableInfo
 
306
        {
 
307
                public long ValidFrames;
 
308
                public int PrimingFrames;
 
309
                public int RemainderFrames;
 
310
        }
 
311
 
 
312
        [StructLayout(LayoutKind.Sequential)]
 
313
        public struct AudioFileRegion {
 
314
                readonly IntPtr ptr;
 
315
                //
 
316
                // Wraps
 
317
                //
 
318
                // struct AudioFileRegion
 
319
                // {
 
320
                //      UInt32                          mRegionID;
 
321
                //      CFStringRef                     mName;
 
322
                //      UInt32                          mFlags;
 
323
                //      UInt32                          mNumberMarkers;
 
324
                //      AudioFileMarker         mMarkers[1]; // this is a variable length array of mNumberMarkers elements
 
325
                // }
 
326
 
 
327
                public AudioFileRegion (IntPtr ptr)
 
328
                {
 
329
                        this.ptr = ptr;
 
330
                }
 
331
 
 
332
                public uint RegionID {
 
333
                        get {
 
334
                                return (uint) Marshal.ReadInt32 (ptr);
 
335
                        }
 
336
                }
 
337
 
 
338
                public string Name {
 
339
                        get {
 
340
                                return CFString.FetchString (NameWeak);
 
341
                        }
 
342
                }
 
343
 
 
344
                internal IntPtr NameWeak {
 
345
                        get {
 
346
                                return Marshal.ReadIntPtr (ptr, sizeof (uint));                         
 
347
                        }
 
348
                }
 
349
 
 
350
                public unsafe AudioFileRegionFlags Flags {
 
351
                        get {
 
352
                                return (AudioFileRegionFlags) Marshal.ReadInt32 (ptr, sizeof (uint) + sizeof (IntPtr));
 
353
                        }
 
354
                }
 
355
 
 
356
                public unsafe int Count {
 
357
                        get {
 
358
                                return Marshal.ReadInt32 (ptr, 2 * sizeof (uint) + sizeof (IntPtr));
 
359
                        }
 
360
                }
 
361
 
 
362
                public AudioFileMarker this [int index] {
 
363
                        get {
 
364
                                if (index >= Count || index < 0)
 
365
                                        throw new ArgumentOutOfRangeException ("index");
 
366
 
 
367
                                unsafe {
 
368
                                        var ptr = (AudioFileMarker *) this.ptr + 3 * sizeof (int) + sizeof (IntPtr) + index * sizeof (AudioFileMarker);
 
369
                                        return *ptr;
 
370
                                }
 
371
                        }
 
372
                }
 
373
 
 
374
                internal unsafe int TotalSize {
 
375
                        get {
 
376
                                return Count * sizeof (AudioFileMarker);
 
377
                        }
 
378
                }
 
379
        }
 
380
 
 
381
        [Flags]
 
382
        public enum AudioFileRegionFlags : uint
 
383
        {
 
384
                LoopEnable = 1,
 
385
                PlayForward = 2,
 
386
                PlayBackward = 4
 
387
        }
 
388
 
 
389
        public class AudioFileRegionList : IDisposable
 
390
        {
 
391
                IntPtr ptr;
 
392
                readonly bool owns;
 
393
 
 
394
                public AudioFileRegionList (IntPtr ptr, bool owns)
 
395
                {
 
396
                        this.ptr = ptr;
 
397
                        this.owns = owns;
 
398
                }
 
399
 
 
400
                ~AudioFileRegionList ()
 
401
                {
 
402
                        Dispose (false);
 
403
                        GC.SuppressFinalize (this);
 
404
                }
 
405
 
 
406
                public SmpteTimeType SmpteTimeType {
 
407
                        get {
 
408
                                return (SmpteTimeType) Marshal.ReadInt32 (ptr);
 
409
                        }
 
410
                }
 
411
 
 
412
                public uint Count {
 
413
                        get {
 
414
                                return (uint) Marshal.ReadInt32 (ptr, sizeof (uint));
 
415
                        }
 
416
                }
 
417
 
 
418
                public AudioFileRegion this [int index] {
 
419
                        get {
 
420
                                if (index >= Count || index < 0)
 
421
                                        throw new ArgumentOutOfRangeException ("index");
 
422
 
 
423
                                //
 
424
                                // Decodes
 
425
                                //
 
426
                                // struct AudioFileRegionList
 
427
                                // {
 
428
                                //      UInt32                          mSMPTE_TimeType;
 
429
                                //      UInt32                          mNumberRegions;
 
430
                                //      AudioFileRegion         mRegions[1]; // this is a variable length array of mNumberRegions elements
 
431
                                // }
 
432
                                //
 
433
                                unsafe {
 
434
                                        var ptr = (byte *) this.ptr + 2 * sizeof (uint);
 
435
                                        for (int i = 0; i < index; ++i) {
 
436
                                                var region = new AudioFileRegion ((IntPtr) ptr);
 
437
                                                ptr += region.TotalSize;
 
438
                                        }
 
439
 
 
440
                                        return new AudioFileRegion ((IntPtr) ptr);
 
441
                                }
 
442
                        }
 
443
                }
 
444
 
 
445
                public void Dispose ()
 
446
                {
 
447
                        Dispose (true);
 
448
                }
 
449
 
 
450
                protected virtual void Dispose (bool disposing)
 
451
                {
 
452
                        if (!owns || ptr == IntPtr.Zero)
 
453
                                return;
 
454
 
 
455
                        for (int i = 0; i < Count; ++i) {
 
456
                                CFObject.CFRelease (this [i].NameWeak);
 
457
                        }
 
458
 
 
459
                        Marshal.FreeHGlobal (ptr);
 
460
                        ptr = IntPtr.Zero;
 
461
                }
212
462
        }
213
463
 
214
464
        public class AudioFile : IDisposable {
296
546
                [DllImport (Constants.AudioToolboxLibrary)]
297
547
                extern static OSStatus AudioFileOpenURL  (IntPtr cfurlref_infile, byte permissions, AudioFileType fileTypeHint, out IntPtr file_id);
298
548
 
299
 
                public static AudioFile OpenRead (string url, AudioFileType fileTypeHint)
 
549
                public static AudioFile OpenRead (string url, AudioFileType fileTypeHint = 0)
300
550
                {
301
551
                        return Open (url, AudioFilePermission.Read, fileTypeHint);
302
552
                }
303
553
                
304
 
                public static AudioFile OpenRead (CFUrl url, AudioFileType fileTypeHint)
 
554
                public static AudioFile OpenRead (CFUrl url, AudioFileType fileTypeHint = 0)
305
555
                {
306
556
                        return Open (url, AudioFilePermission.Read, fileTypeHint);
307
557
                }
308
558
 
309
 
                public static AudioFile OpenRead (NSUrl url, AudioFileType fileTypeHint)
 
559
                public static AudioFile OpenRead (NSUrl url, AudioFileType fileTypeHint = 0)
310
560
                {
311
561
                        return Open (url, AudioFilePermission.Read, fileTypeHint);
312
562
                }
313
563
                
314
 
                public static AudioFile Open (string url, AudioFilePermission permissions, AudioFileType fileTypeHint)
 
564
                public static AudioFile Open (string url, AudioFilePermission permissions, AudioFileType fileTypeHint = 0)
315
565
                {
316
566
                        if (url == null)
317
567
                                throw new ArgumentNullException ("url");
320
570
                                return Open (cfurl, permissions, fileTypeHint);
321
571
                }
322
572
 
323
 
                public static AudioFile Open (CFUrl url, AudioFilePermission permissions, AudioFileType fileTypeHint)
 
573
                public static AudioFile Open (CFUrl url, AudioFilePermission permissions, AudioFileType fileTypeHint = 0)
324
574
                {
325
575
                        if (url == null)
326
576
                                throw new ArgumentNullException ("url");
331
581
                        return null;
332
582
                }
333
583
 
334
 
                public static AudioFile Open (NSUrl url, AudioFilePermission permissions, AudioFileType fileTypeHint)
 
584
                public static AudioFile Open (NSUrl url, AudioFilePermission permissions, AudioFileType fileTypeHint = 0)
335
585
                {
336
586
                        if (url == null)
337
587
                                throw new ArgumentNullException ("url");
443
693
                        return ReadPacketData (useCache, inStartingPacket, ref nPackets, buffer, offset, ref count);
444
694
                }
445
695
 
 
696
                [DllImport (Constants.AudioToolboxLibrary)]
 
697
                extern static AudioFileError AudioFileReadPackets (IntPtr inAudioFile, bool inUseCache, out int numBytes,
 
698
                        [MarshalAs (UnmanagedType.LPArray)] AudioStreamPacketDescription[] packetDescriptions, long startingPacket, ref int numPackets, IntPtr buffer);
 
699
 
 
700
                public AudioFileError ReadPackets (bool useCache, out int numBytes,
 
701
                        AudioStreamPacketDescription[] packetDescriptions, long startingPacket, ref int numPackets, IntPtr buffer)
 
702
                {
 
703
                        if (buffer == IntPtr.Zero)
 
704
                                throw new ArgumentException ("buffer");
 
705
 
 
706
                        return AudioFileReadPackets (handle, useCache, out numBytes, packetDescriptions, startingPacket, ref numPackets, buffer);
 
707
                }
 
708
 
446
709
                static internal AudioStreamPacketDescription [] PacketDescriptionFrom (int nPackets, IntPtr b)
447
710
                {
448
711
                        if (b == IntPtr.Zero)
548
811
                }
549
812
 
550
813
                [DllImport (Constants.AudioToolboxLibrary)]
551
 
                extern static OSStatus AudioFileWritePackets (
 
814
                extern static AudioFileError AudioFileWritePackets (
552
815
                        AudioFileID audioFile, bool useCache, int inNumBytes, AudioStreamPacketDescription [] inPacketDescriptions,
553
816
                        long inStartingPacket, ref int numPackets, IntPtr buffer);
554
817
 
555
 
                public int WritePackets (bool useCache, long inStartingPacket, int numPackets, IntPtr buffer, int count)
 
818
                public int WritePackets (bool useCache, long startingPacket, int numPackets, IntPtr buffer, int count)
556
819
                {
557
820
                        if (buffer == IntPtr.Zero)
558
821
                                throw new ArgumentNullException ("buffer");
559
822
 
560
 
                        if (AudioFileWritePackets (handle, useCache, count, null, inStartingPacket, ref numPackets, buffer) == 0)
 
823
                        if (AudioFileWritePackets (handle, useCache, count, null, startingPacket, ref numPackets, buffer) == 0)
561
824
                                return numPackets;
562
825
 
563
826
                        return -1;
564
827
                }
565
828
 
566
 
                unsafe public int WritePackets (bool useCache, long inStartingPacket, AudioStreamPacketDescription [] inPacketDescriptions, IntPtr buffer, int count)
 
829
                public int WritePackets (bool useCache, long startingPacket, AudioStreamPacketDescription [] packetDescriptions, IntPtr buffer, int count)
567
830
                {
568
 
                        if (inPacketDescriptions == null)
569
 
                                throw new ArgumentNullException ("inPacketDescriptions");
 
831
                        if (packetDescriptions == null)
 
832
                                throw new ArgumentNullException ("packetDescriptions");
570
833
                        if (buffer == IntPtr.Zero)
571
834
                                throw new ArgumentNullException ("buffer");
572
 
                        int nPackets = inPacketDescriptions.Length;
573
 
                        if (AudioFileWritePackets (handle, useCache, count, inPacketDescriptions, inStartingPacket, ref nPackets, buffer) == 0)
 
835
                        int nPackets = packetDescriptions.Length;
 
836
                        if (AudioFileWritePackets (handle, useCache, count, packetDescriptions, startingPacket, ref nPackets, buffer) == 0)
574
837
                                return nPackets;
575
838
                        return -1;
576
839
                }
596
859
                        }
597
860
                }
598
861
 
599
 
                unsafe public int WritePackets (bool useCache, long inStartingPacket, AudioStreamPacketDescription [] inPacketDescriptions, IntPtr buffer, int count, out int errorCode)
 
862
                public int WritePackets (bool useCache, long startingPacket, AudioStreamPacketDescription [] packetDescriptions, IntPtr buffer, int count, out int errorCode)
600
863
                {
601
 
                        if (inPacketDescriptions == null)
602
 
                                throw new ArgumentNullException ("inPacketDescriptions");
 
864
                        if (packetDescriptions == null)
 
865
                                throw new ArgumentNullException ("packetDescriptions");
603
866
                        if (buffer == IntPtr.Zero)
604
 
                                throw new ArgumentNullException ("buffer");
605
 
                        int nPackets = inPacketDescriptions.Length;
 
867
                                throw new ArgumentException ("buffer");
 
868
                        int nPackets = packetDescriptions.Length;
606
869
                        
607
 
                        errorCode = AudioFileWritePackets (handle, useCache, count, inPacketDescriptions, inStartingPacket, ref nPackets, buffer);
 
870
                        errorCode = (int) AudioFileWritePackets (handle, useCache, count, packetDescriptions, startingPacket, ref nPackets, buffer);
608
871
                        if (errorCode == 0)
609
872
                                return nPackets;
610
873
                        return -1;
625
888
 
626
889
                        int nPackets = packetDescriptions.Length;
627
890
                        fixed (byte *bop = &buffer [offset]){
628
 
                                errorCode = AudioFileWritePackets (handle, useCache, count, packetDescriptions, startingPacket, ref nPackets, (IntPtr) bop);
 
891
                                errorCode = (int) AudioFileWritePackets (handle, useCache, count, packetDescriptions, startingPacket, ref nPackets, (IntPtr) bop);
629
892
                                if (errorCode == 0)
630
893
                                        return nPackets;
631
894
                                return -1;
632
895
                        }
633
896
                }
634
897
 
 
898
                public AudioFileError WritePackets (bool useCache, int numBytes, AudioStreamPacketDescription[] packetDescriptions, long startingPacket, ref int numPackets, IntPtr buffer)
 
899
                {
 
900
                        if (buffer == IntPtr.Zero)
 
901
                                throw new ArgumentException ("buffer");
 
902
                        
 
903
                        return AudioFileWritePackets (handle, useCache, numBytes, packetDescriptions, startingPacket, ref numPackets, buffer);
 
904
                }
 
905
 
635
906
                [DllImport (Constants.AudioToolboxLibrary)]
636
907
                extern static OSStatus AudioFileCountUserData (AudioFileID handle, uint userData, out int count);
637
908
 
685
956
                {
686
957
                        return AudioFileGetPropertyInfo (handle, property, out size, out writable) == 0;
687
958
                }
 
959
 
 
960
                public bool IsPropertyWritable (AudioFileProperty property)
 
961
                {
 
962
                        int writable;
 
963
                        int size;
 
964
                        return AudioFileGetPropertyInfo (handle, property, out size, out writable) == 0 && writable != 0;
 
965
                }
688
966
                
689
967
                [DllImport (Constants.AudioToolboxLibrary)]
690
968
                extern static OSStatus AudioFileGetProperty (AudioFileID audioFile, AudioFileProperty property, ref int dataSize, IntPtr outdata);
713
991
                        return IntPtr.Zero;
714
992
                }
715
993
 
716
 
                T GetProperty<T> (AudioFileProperty property)
 
994
                unsafe T? GetProperty<T> (AudioFileProperty property) where T : struct
717
995
                {
718
996
                        int size, writable;
719
997
 
720
998
                        if (AudioFileGetPropertyInfo (handle, property, out size, out writable) != 0)
721
 
                                return default (T);
 
999
                                return null;
722
1000
                        var buffer = Marshal.AllocHGlobal (size);
723
1001
                        if (buffer == IntPtr.Zero)
724
 
                                return default(T);
 
1002
                                return null;
725
1003
                        try {
726
1004
                                var r = AudioFileGetProperty (handle, property, ref size, buffer);
727
 
                                if (r == 0)
728
 
                                        return (T) Marshal.PtrToStructure (buffer, typeof (T));
 
1005
                                if (r == 0){
 
1006
                                        T t = *(T*) buffer;
 
1007
                                        return t;
 
1008
                                }
729
1009
 
730
 
                                return default(T);
 
1010
                                return null;
731
1011
                        } finally {
732
1012
                                Marshal.FreeHGlobal (buffer);
733
1013
                        }
778
1058
                }
779
1059
                
780
1060
                [DllImport (Constants.AudioToolboxLibrary)]
781
 
                extern static OSStatus AudioFileSetProperty (AudioFileID audioFile, AudioFileProperty property, int dataSize, IntPtr propertyData);
 
1061
                extern static AudioFileError AudioFileSetProperty (AudioFileID audioFile, AudioFileProperty property, int dataSize, IntPtr propertyData);
 
1062
 
 
1063
                [DllImport (Constants.AudioToolboxLibrary)]
 
1064
                extern static AudioFileError AudioFileSetProperty (AudioFileID audioFile, AudioFileProperty property, int dataSize, ref AudioFilePacketTableInfo propertyData);
782
1065
 
783
1066
                public bool SetProperty (AudioFileProperty property, int dataSize, IntPtr propertyData)
784
1067
                {
791
1074
                                AudioFileSetProperty (handle, property, 4, (IntPtr) (&value));
792
1075
                        }
793
1076
                }
 
1077
 
 
1078
                unsafe AudioFileError SetDouble (AudioFileProperty property, double value)
 
1079
                {
 
1080
                        return AudioFileSetProperty (handle, property, sizeof (double), (IntPtr) (&value));
 
1081
                }
794
1082
                
795
1083
                public AudioFileType FileType {
796
1084
                        get {
798
1086
                        }
799
1087
                }
800
1088
 
 
1089
                [Advice ("Use DataFormat instead")]
801
1090
                public AudioStreamBasicDescription StreamBasicDescription {
802
1091
                        get {
 
1092
                                return GetProperty<AudioStreamBasicDescription> (AudioFileProperty.DataFormat) ?? default (AudioStreamBasicDescription);
 
1093
                        }
 
1094
                }
 
1095
 
 
1096
                public AudioStreamBasicDescription? DataFormat {
 
1097
                        get {
803
1098
                                return GetProperty<AudioStreamBasicDescription> (AudioFileProperty.DataFormat);
804
1099
                        }
805
1100
                }
923
1218
                        }
924
1219
                }
925
1220
 
 
1221
                public double ReserveDuration {
 
1222
                        get {
 
1223
                                return GetDouble (AudioFileProperty.ReserveDuration);
 
1224
                        }
 
1225
                }
 
1226
 
 
1227
                public AudioFileMarkerList MarkerList {
 
1228
                        get {
 
1229
                                int size;
 
1230
                                int writable;
 
1231
                                var res = GetPropertyInfo (AudioFileProperty.MarkerList, out size, out writable);
 
1232
                                if (size == 0)
 
1233
                                        return null;
 
1234
 
 
1235
                                IntPtr ptr = Marshal.AllocHGlobal (size);
 
1236
                                if (AudioFileGetProperty (handle, AudioFileProperty.MarkerList, ref size, (IntPtr) ptr) != 0) {
 
1237
                                        Marshal.FreeHGlobal (ptr);
 
1238
                                        return null;
 
1239
                                }
 
1240
 
 
1241
                                return new AudioFileMarkerList (ptr, true);
 
1242
                        }
 
1243
                }
 
1244
 
 
1245
                public AudioFileRegionList RegionList {
 
1246
                        get {
 
1247
                                int size;
 
1248
                                int writable;
 
1249
                                var res = GetPropertyInfo (AudioFileProperty.RegionList, out size, out writable);
 
1250
                                if (size == 0)
 
1251
                                        return null;
 
1252
 
 
1253
                                IntPtr ptr = Marshal.AllocHGlobal (size);
 
1254
                                if (AudioFileGetProperty (handle, AudioFileProperty.RegionList, ref size, (IntPtr) ptr) != 0) {
 
1255
                                        Marshal.FreeHGlobal (ptr);
 
1256
                                        return null;
 
1257
                                }
 
1258
 
 
1259
                                return new AudioFileRegionList (ptr, true);
 
1260
                        }
 
1261
                }
 
1262
 
 
1263
                public unsafe AudioFilePacketTableInfo? PacketTableInfo {
 
1264
                        get {
 
1265
                                return GetProperty<AudioFilePacketTableInfo> (AudioFileProperty.PacketTableInfo);
 
1266
                        }
 
1267
                        set {
 
1268
                                if (value == null)
 
1269
                                        throw new ArgumentNullException ("value");
 
1270
 
 
1271
                                AudioFilePacketTableInfo afpti = value.Value;
 
1272
                                var res = AudioFileSetProperty (handle, AudioFileProperty.PacketTableInfo, sizeof (AudioFilePacketTableInfo), ref afpti);
 
1273
                                if (res != 0)
 
1274
                                        throw new ArgumentException (res.ToString ());
 
1275
                        }
 
1276
                }
 
1277
 
 
1278
                public unsafe AudioFileChunkType[] ChunkIDs {
 
1279
                        get {
 
1280
                                int size;
 
1281
                                int writable;
 
1282
                                var res = GetPropertyInfo (AudioFileProperty.ChunkIDs, out size, out writable);
 
1283
                                if (size == 0)
 
1284
                                        return null;
 
1285
 
 
1286
                                var data = new AudioFileChunkType[size / sizeof (AudioFileChunkType)];
 
1287
                                fixed (AudioFileChunkType* ptr = data) {
 
1288
                                        if (AudioFileGetProperty (handle, AudioFileProperty.ChunkIDs, ref size, (IntPtr) ptr) != 0)
 
1289
                                                return null;
 
1290
 
 
1291
                                        return data;
 
1292
                                }
 
1293
                        }
 
1294
                }
 
1295
 
 
1296
                public unsafe byte[] ID3Tag {
 
1297
                        get {
 
1298
                                int size;
 
1299
                                int writable;
 
1300
                                var res = GetPropertyInfo (AudioFileProperty.ID3Tag, out size, out writable);
 
1301
                                if (size == 0)
 
1302
                                        return null;
 
1303
 
 
1304
                                var data = new byte[size];
 
1305
                                fixed (byte* ptr = data) {
 
1306
                                        if (AudioFileGetProperty (handle, AudioFileProperty.ID3Tag, ref size, (IntPtr) ptr) != 0)
 
1307
                                                return null;
 
1308
 
 
1309
                                        return data;
 
1310
                                }
 
1311
                        }
 
1312
                }
 
1313
 
 
1314
                public AudioFileInfoDictionary InfoDictionary {
 
1315
                        get {
 
1316
                                var ptr = GetIntPtr (AudioFileProperty.InfoDictionary);
 
1317
                                if (ptr == IntPtr.Zero)
 
1318
                                        return null;
 
1319
 
 
1320
                                return new AudioFileInfoDictionary(new NSMutableDictionary (ptr, true));
 
1321
                        }
 
1322
                }               
 
1323
 
926
1324
                public long PacketToFrame (long packet)
927
1325
                {
928
1326
                        AudioFramePacketTranslation buffer;
930
1328
 
931
1329
                        unsafe {
932
1330
                                AudioFramePacketTranslation *p = &buffer;
933
 
                                int size = Marshal.SizeOf (buffer);
 
1331
                                int size = sizeof (AudioFramePacketTranslation);
934
1332
                                if (AudioFileGetProperty (handle, AudioFileProperty.PacketToFrame, ref size, (IntPtr) p) == 0)
935
1333
                                        return buffer.Frame;
936
1334
                                return -1;
944
1342
 
945
1343
                        unsafe {
946
1344
                                AudioFramePacketTranslation *p = &buffer;
947
 
                                int size = Marshal.SizeOf (buffer);
 
1345
                                int size = sizeof (AudioFramePacketTranslation);
948
1346
                                if (AudioFileGetProperty (handle, AudioFileProperty.FrameToPacket, ref size, (IntPtr) p) == 0){
949
1347
                                        frameOffsetInPacket = buffer.FrameOffsetInPacket;
950
1348
                                        return buffer.Packet;
961
1359
 
962
1360
                        unsafe {
963
1361
                                AudioBytePacketTranslation *p = &buffer;
964
 
                                int size = Marshal.SizeOf (buffer);
 
1362
                                int size = sizeof (AudioBytePacketTranslation);
965
1363
                                if (AudioFileGetProperty (handle, AudioFileProperty.PacketToByte, ref size, (IntPtr) p) == 0){
966
 
                                        isEstimate = (buffer.Flags & 1) == 1;
 
1364
                                        isEstimate = (buffer.Flags & BytePacketTranslationFlags.IsEstimate) != 0;
967
1365
                                        return buffer.Byte;
968
1366
                                }
969
1367
                                isEstimate = false;
978
1376
 
979
1377
                        unsafe {
980
1378
                                AudioBytePacketTranslation *p = &buffer;
981
 
                                int size = Marshal.SizeOf (buffer);
 
1379
                                int size = sizeof (AudioBytePacketTranslation);
982
1380
                                if (AudioFileGetProperty (handle, AudioFileProperty.ByteToPacket, ref size, (IntPtr) p) == 0){
983
 
                                        isEstimate = (buffer.Flags & 1) == 1;
 
1381
                                        isEstimate = (buffer.Flags & BytePacketTranslationFlags.IsEstimate) != 0;
984
1382
                                        byteOffsetInPacket = buffer.ByteOffsetInPacket;
985
1383
                                        return buffer.Packet;
986
1384
                                }
989
1387
                                return -1;
990
1388
                        }
991
1389
                }
992
 
                
993
 
//              MarkerList = 0x6d6b6c73,
994
 
//              RegionList = 0x72676c73,
995
 
//              ChunkIDs = 0x63686964,
996
 
//              InfoDictionary = 0x696e666f,
997
 
//              PacketTableInfo = 0x706e666f,
998
 
//              FormatList = 0x666c7374,
999
 
//              ReserveDuration = 0x72737276,
1000
 
//              EstimatedDuration = 0x65647572,
1001
 
//              ID3Tag = 0x69643374,
1002
 
//              
 
1390
        }
 
1391
 
 
1392
        public class AudioFileInfoDictionary : DictionaryContainer
 
1393
        {
 
1394
                internal AudioFileInfoDictionary (NSDictionary dict)
 
1395
                        : base (dict)
 
1396
                {
 
1397
                }
 
1398
 
 
1399
                public string Album {
 
1400
                        get {
 
1401
                                return GetStringValue ("album");
 
1402
                        }
 
1403
                }
 
1404
 
 
1405
                public string ApproximateDurationInSeconds {
 
1406
                        get {
 
1407
                                return GetStringValue ("approximate duration in seconds");
 
1408
                        }
 
1409
                }
 
1410
 
 
1411
                public string Artist {
 
1412
                        get {
 
1413
                                return GetStringValue ("artist");
 
1414
                        }
 
1415
                }
 
1416
 
 
1417
                public string ChannelLayout      {
 
1418
                        get {
 
1419
                                return GetStringValue ("channel layout");                               
 
1420
                        }
 
1421
                }
 
1422
 
 
1423
                public string Composer {
 
1424
                        get {
 
1425
                                return GetStringValue ("composer");
 
1426
                        }
 
1427
                }
 
1428
 
 
1429
                public string Comments {
 
1430
                        get {
 
1431
                                return GetStringValue ("comments");
 
1432
                        }
 
1433
                }
 
1434
 
 
1435
                public string Copyright {
 
1436
                        get {
 
1437
                                return GetStringValue ("copyright");
 
1438
                        }
 
1439
                }
 
1440
 
 
1441
                public string EncodingApplication {
 
1442
                        get {
 
1443
                                return GetStringValue ("encoding application");
 
1444
                        }
 
1445
                }
 
1446
 
 
1447
                public string Genre {
 
1448
                        get {
 
1449
                                return GetStringValue ("genre");
 
1450
                        }
 
1451
                }
 
1452
 
 
1453
                public string ISRC {
 
1454
                        get {
 
1455
                                return GetStringValue ("ISRC");
 
1456
                        }
 
1457
                }
 
1458
 
 
1459
                public string KeySignature {
 
1460
                        get {
 
1461
                                return GetStringValue ("key signature");
 
1462
                        }
 
1463
                }
 
1464
 
 
1465
                public string Lyricist {
 
1466
                        get {
 
1467
                                return GetStringValue ("lyricist");
 
1468
                        }
 
1469
                }
 
1470
 
 
1471
                public string NominalBitRate {
 
1472
                        get {
 
1473
                                return GetStringValue ("nominal bit rate");                             
 
1474
                        }
 
1475
                }
 
1476
 
 
1477
                public string RecordedDate {
 
1478
                        get {
 
1479
                                return GetStringValue ("recorded date");
 
1480
                        }
 
1481
                }
 
1482
 
 
1483
                public string SourceBitDepth {
 
1484
                        get {
 
1485
                                return GetStringValue ("source bit depth");
 
1486
                        }
 
1487
                }
 
1488
 
 
1489
                public string SourceEncoder {
 
1490
                        get {
 
1491
                                return GetStringValue ("source encoder");
 
1492
                        }
 
1493
                }
 
1494
 
 
1495
                public string SubTitle {
 
1496
                        get {
 
1497
                                return GetStringValue ("subtitle");
 
1498
                        }
 
1499
                }
 
1500
 
 
1501
                public string Tempo {
 
1502
                        get {
 
1503
                                return GetStringValue ("tempo");
 
1504
                        }
 
1505
                }
 
1506
 
 
1507
                public string TimeSignature {
 
1508
                        get {
 
1509
                                return GetStringValue ("time signature");
 
1510
                        }
 
1511
                }
 
1512
 
 
1513
                public string Title {
 
1514
                        get {
 
1515
                                return GetStringValue ("title");
 
1516
                        }
 
1517
                }
 
1518
 
 
1519
                public string TrackNumber {
 
1520
                        get {
 
1521
                                return GetStringValue ("track number");
 
1522
                        }
 
1523
                }
 
1524
 
 
1525
                public string Year {
 
1526
                        get {
 
1527
                                return GetStringValue ("year");
 
1528
                        }
 
1529
                }
1003
1530
        }
1004
1531
 
1005
1532
        delegate int ReadProc (IntPtr clientData, long position, int requestCount, IntPtr buffer, out int actualCount);