Audaspace:
[blender-staging.git] / intern / audaspace / intern / AUD_C-API.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * AudaSpace is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 #ifdef WITH_PYTHON
27 #include "AUD_PyAPI.h"
28
29 Device* g_device;
30 bool g_pyinitialized = false;
31 #endif
32
33 #include <cstdlib>
34 #include <cstring>
35 #include <cmath>
36
37 #ifndef __STDC_CONSTANT_MACROS
38 // needed for INT64_C
39 #define __STDC_CONSTANT_MACROS
40 #endif
41
42 #include "AUD_NULLDevice.h"
43 #include "AUD_I3DDevice.h"
44 #include "AUD_FileFactory.h"
45 #include "AUD_StreamBufferFactory.h"
46 #include "AUD_DelayFactory.h"
47 #include "AUD_LimiterFactory.h"
48 #include "AUD_PingPongFactory.h"
49 #include "AUD_LoopFactory.h"
50 #include "AUD_RectifyFactory.h"
51 #include "AUD_EnvelopeFactory.h"
52 #include "AUD_LinearResampleFactory.h"
53 #include "AUD_LowpassFactory.h"
54 #include "AUD_HighpassFactory.h"
55 #include "AUD_AccumulatorFactory.h"
56 #include "AUD_SumFactory.h"
57 #include "AUD_SquareFactory.h"
58 #include "AUD_ChannelMapperFactory.h"
59 #include "AUD_Buffer.h"
60 #include "AUD_ReadDevice.h"
61 #include "AUD_IReader.h"
62 #include "AUD_SequencerFactory.h"
63
64 #ifdef WITH_SDL
65 #include "AUD_SDLDevice.h"
66 #endif
67
68 #ifdef WITH_OPENAL
69 #include "AUD_OpenALDevice.h"
70 #endif
71
72 #ifdef WITH_JACK
73 #include "AUD_JackDevice.h"
74 #endif
75
76
77 #ifdef WITH_FFMPEG
78 extern "C" {
79 #include <libavformat/avformat.h>
80 }
81 #endif
82
83 #include <cassert>
84
85 typedef AUD_IFactory AUD_Sound;
86 typedef AUD_ReadDevice AUD_Device;
87 typedef AUD_Handle AUD_Channel;
88
89 #define AUD_CAPI_IMPLEMENTATION
90 #include "AUD_C-API.h"
91
92 #ifndef NULL
93 #define NULL 0
94 #endif
95
96 static AUD_IDevice* AUD_device = NULL;
97 static int AUD_available_devices[4];
98 static AUD_I3DDevice* AUD_3ddevice = NULL;
99
100 void AUD_initOnce()
101 {
102 #ifdef WITH_FFMPEG
103         av_register_all();
104 #endif
105 }
106
107 int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
108 {
109         AUD_IDevice* dev = NULL;
110
111         if(AUD_device)
112                 AUD_exit();
113
114         try
115         {
116                 switch(device)
117                 {
118                 case AUD_NULL_DEVICE:
119                         dev = new AUD_NULLDevice();
120                         break;
121 #ifdef WITH_SDL
122                 case AUD_SDL_DEVICE:
123                         dev = new AUD_SDLDevice(specs, buffersize);
124                         break;
125 #endif
126 #ifdef WITH_OPENAL
127                 case AUD_OPENAL_DEVICE:
128                         dev = new AUD_OpenALDevice(specs, buffersize);
129                         break;
130 #endif
131 #ifdef WITH_JACK
132                 case AUD_JACK_DEVICE:
133                         dev = new AUD_JackDevice(specs, buffersize);
134                         break;
135 #endif
136                 default:
137                         return false;
138                 }
139
140                 AUD_device = dev;
141                 AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device);
142
143 #ifdef WITH_PYTHON
144                 if(g_pyinitialized)
145                 {
146                         g_device = (Device*)Device_empty();
147                         if(g_device != NULL)
148                         {
149                                 g_device->device = dev;
150                         }
151                 }
152 #endif
153
154                 return true;
155         }
156         catch(AUD_Exception&)
157         {
158                 return false;
159         }
160 }
161
162 int* AUD_enumDevices()
163 {
164         int i = 0;
165 #ifdef WITH_SDL
166         AUD_available_devices[i++] = AUD_SDL_DEVICE;
167 #endif
168 #ifdef WITH_OPENAL
169         AUD_available_devices[i++] = AUD_OPENAL_DEVICE;
170 #endif
171 #ifdef WITH_JACK
172         AUD_available_devices[i++] = AUD_JACK_DEVICE;
173 #endif
174         AUD_available_devices[i++] = AUD_NULL_DEVICE;
175         return AUD_available_devices;
176 }
177
178 void AUD_exit()
179 {
180 #ifdef WITH_PYTHON
181         if(g_device)
182         {
183                 Py_XDECREF(g_device);
184                 g_device = NULL;
185         }
186         else
187 #endif
188         if(AUD_device)
189                 delete AUD_device;
190         AUD_device = NULL;
191         AUD_3ddevice = NULL;
192 }
193
194 #ifdef WITH_PYTHON
195 static PyObject* AUD_getCDevice(PyObject* self)
196 {
197         if(g_device)
198         {
199                 Py_INCREF(g_device);
200                 return (PyObject*)g_device;
201         }
202         Py_RETURN_NONE;
203 }
204
205 static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS,
206                                                                                   "device()\n\n"
207                                                                                   "Returns the application's Device.\n\n"
208                                                                                   ":return: The application's Device.\n"
209                                                                                   ":rtype: aud.Device"}};
210
211 PyObject* AUD_initPython()
212 {
213         PyObject* module = PyInit_aud();
214         PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL));
215         PyDict_SetItemString(PySys_GetObject("modules"), "aud", module);
216         if(AUD_device)
217         {
218                 g_device = (Device*)Device_empty();
219                 if(g_device != NULL)
220                 {
221                         g_device->device = AUD_device;
222                 }
223         }
224         g_pyinitialized = true;
225
226         return module;
227 }
228 #endif
229
230 void AUD_lock()
231 {
232         assert(AUD_device);
233         AUD_device->lock();
234 }
235
236 void AUD_unlock()
237 {
238         assert(AUD_device);
239         AUD_device->unlock();
240 }
241
242 AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
243 {
244         assert(sound);
245
246         AUD_IReader* reader = sound->createReader();
247
248         AUD_SoundInfo info;
249
250         if(reader)
251         {
252                 info.specs = reader->getSpecs();
253                 info.length = reader->getLength() / (float) info.specs.rate;
254         }
255         else
256         {
257                 info.specs.channels = AUD_CHANNELS_INVALID;
258                 info.specs.rate = AUD_RATE_INVALID;
259                 info.length = 0.0f;
260         }
261
262         return info;
263 }
264
265 AUD_Sound* AUD_load(const char* filename)
266 {
267         assert(filename);
268         return new AUD_FileFactory(filename);
269 }
270
271 AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size)
272 {
273         assert(buffer);
274         return new AUD_FileFactory(buffer, size);
275 }
276
277 AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
278 {
279         assert(sound);
280
281         try
282         {
283                 return new AUD_StreamBufferFactory(sound);
284         }
285         catch(AUD_Exception&)
286         {
287                 return NULL;
288         }
289 }
290
291 AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
292 {
293         assert(sound);
294
295         try
296         {
297                 return new AUD_DelayFactory(sound, delay);
298         }
299         catch(AUD_Exception&)
300         {
301                 return NULL;
302         }
303 }
304
305 AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
306 {
307         assert(sound);
308
309         try
310         {
311                 return new AUD_LimiterFactory(sound, start, end);
312         }
313         catch(AUD_Exception&)
314         {
315                 return NULL;
316         }
317 }
318
319 AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
320 {
321         assert(sound);
322
323         try
324         {
325                 return new AUD_PingPongFactory(sound);
326         }
327         catch(AUD_Exception&)
328         {
329                 return NULL;
330         }
331 }
332
333 AUD_Sound* AUD_loopSound(AUD_Sound* sound)
334 {
335         assert(sound);
336
337         try
338         {
339                 return new AUD_LoopFactory(sound);
340         }
341         catch(AUD_Exception&)
342         {
343                 return NULL;
344         }
345 }
346
347 int AUD_setLoop(AUD_Channel* handle, int loops)
348 {
349         if(handle)
350         {
351                 try
352                 {
353                         return AUD_device->setLoopCount(handle, loops);
354                 }
355                 catch(AUD_Exception&)
356                 {
357                 }
358         }
359         return false;
360 }
361
362 AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
363 {
364         assert(sound);
365
366         try
367         {
368                 return new AUD_RectifyFactory(sound);
369         }
370         catch(AUD_Exception&)
371         {
372                 return NULL;
373         }
374 }
375
376 void AUD_unload(AUD_Sound* sound)
377 {
378         assert(sound);
379         delete sound;
380 }
381
382 AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
383 {
384         assert(AUD_device);
385         assert(sound);
386         try
387         {
388                 return AUD_device->play(sound, keep);
389         }
390         catch(AUD_Exception&)
391         {
392                 return NULL;
393         }
394 }
395
396 int AUD_pause(AUD_Channel* handle)
397 {
398         assert(AUD_device);
399         return AUD_device->pause(handle);
400 }
401
402 int AUD_resume(AUD_Channel* handle)
403 {
404         assert(AUD_device);
405         return AUD_device->resume(handle);
406 }
407
408 int AUD_stop(AUD_Channel* handle)
409 {
410         if(AUD_device)
411                 return AUD_device->stop(handle);
412         return false;
413 }
414
415 int AUD_setKeep(AUD_Channel* handle, int keep)
416 {
417         assert(AUD_device);
418         return AUD_device->setKeep(handle, keep);
419 }
420
421 int AUD_seek(AUD_Channel* handle, float seekTo)
422 {
423         assert(AUD_device);
424         return AUD_device->seek(handle, seekTo);
425 }
426
427 float AUD_getPosition(AUD_Channel* handle)
428 {
429         assert(AUD_device);
430         return AUD_device->getPosition(handle);
431 }
432
433 AUD_Status AUD_getStatus(AUD_Channel* handle)
434 {
435         assert(AUD_device);
436         return AUD_device->getStatus(handle);
437 }
438
439 int AUD_setListenerLocation(const float* location)
440 {
441         assert(AUD_device);
442
443         if(AUD_3ddevice)
444         {
445                 AUD_Vector3 v(location[0], location[1], location[2]);
446                 AUD_3ddevice->setListenerLocation(v);
447                 return true;
448         }
449
450         return false;
451 }
452
453 int AUD_setListenerVelocity(const float* velocity)
454 {
455         assert(AUD_device);
456
457         if(AUD_3ddevice)
458         {
459                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
460                 AUD_3ddevice->setListenerVelocity(v);
461                 return true;
462         }
463
464         return false;
465 }
466
467 int AUD_setListenerOrientation(const float* orientation)
468 {
469         assert(AUD_device);
470
471         if(AUD_3ddevice)
472         {
473                 AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]);
474                 AUD_3ddevice->setListenerOrientation(q);
475                 return true;
476         }
477
478         return false;
479 }
480
481 int AUD_setSpeedOfSound(float speed)
482 {
483         assert(AUD_device);
484
485         if(AUD_3ddevice)
486         {
487                 AUD_3ddevice->setSpeedOfSound(speed);
488                 return true;
489         }
490
491         return false;
492 }
493
494 int AUD_setDopplerFactor(float factor)
495 {
496         assert(AUD_device);
497
498         if(AUD_3ddevice)
499         {
500                 AUD_3ddevice->setDopplerFactor(factor);
501                 return true;
502         }
503
504         return false;
505 }
506
507 int AUD_setDistanceModel(AUD_DistanceModel model)
508 {
509         assert(AUD_device);
510
511         if(AUD_3ddevice)
512         {
513                 AUD_3ddevice->setDistanceModel(model);
514                 return true;
515         }
516
517         return false;
518 }
519
520 int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
521 {
522         assert(AUD_device);
523         assert(handle);
524
525         if(AUD_3ddevice)
526         {
527                 AUD_Vector3 v(location[0], location[1], location[2]);
528                 return AUD_3ddevice->setSourceLocation(handle, v);
529         }
530
531         return false;
532 }
533
534 int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
535 {
536         assert(AUD_device);
537         assert(handle);
538
539         if(AUD_3ddevice)
540         {
541                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
542                 return AUD_3ddevice->setSourceVelocity(handle, v);
543         }
544
545         return false;
546 }
547
548 int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
549 {
550         assert(AUD_device);
551         assert(handle);
552
553         if(AUD_3ddevice)
554         {
555                 AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]);
556                 return AUD_3ddevice->setSourceOrientation(handle, q);
557         }
558
559         return false;
560 }
561
562 int AUD_setRelative(AUD_Channel* handle, int relative)
563 {
564         assert(AUD_device);
565         assert(handle);
566
567         if(AUD_3ddevice)
568         {
569                 return AUD_3ddevice->setRelative(handle, relative);
570         }
571
572         return false;
573 }
574
575 int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
576 {
577         assert(AUD_device);
578         assert(handle);
579
580         if(AUD_3ddevice)
581         {
582                 return AUD_3ddevice->setVolumeMaximum(handle, volume);
583         }
584
585         return false;
586 }
587
588 int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
589 {
590         assert(AUD_device);
591         assert(handle);
592
593         if(AUD_3ddevice)
594         {
595                 return AUD_3ddevice->setVolumeMinimum(handle, volume);
596         }
597
598         return false;
599 }
600
601 int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
602 {
603         assert(AUD_device);
604         assert(handle);
605
606         if(AUD_3ddevice)
607         {
608                 return AUD_3ddevice->setDistanceMaximum(handle, distance);
609         }
610
611         return false;
612 }
613
614 int AUD_setDistanceReference(AUD_Channel* handle, float distance)
615 {
616         assert(AUD_device);
617         assert(handle);
618
619         if(AUD_3ddevice)
620         {
621                 return AUD_3ddevice->setDistanceReference(handle, distance);
622         }
623
624         return false;
625 }
626
627 int AUD_setAttenuation(AUD_Channel* handle, float factor)
628 {
629         assert(AUD_device);
630         assert(handle);
631
632         if(AUD_3ddevice)
633         {
634                 return AUD_3ddevice->setAttenuation(handle, factor);
635         }
636
637         return false;
638 }
639
640 int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
641 {
642         assert(AUD_device);
643         assert(handle);
644
645         if(AUD_3ddevice)
646         {
647                 return AUD_3ddevice->setConeAngleOuter(handle, angle);
648         }
649
650         return false;
651 }
652
653 int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
654 {
655         assert(AUD_device);
656         assert(handle);
657
658         if(AUD_3ddevice)
659         {
660                 return AUD_3ddevice->setConeAngleInner(handle, angle);
661         }
662
663         return false;
664 }
665
666 int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
667 {
668         assert(AUD_device);
669         assert(handle);
670
671         if(AUD_3ddevice)
672         {
673                 return AUD_3ddevice->setConeVolumeOuter(handle, volume);
674         }
675
676         return false;
677 }
678
679 int AUD_setSoundVolume(AUD_Channel* handle, float volume)
680 {
681         if(handle)
682         {
683                 assert(AUD_device);
684
685                 try
686                 {
687                         return AUD_device->setVolume(handle, volume);
688                 }
689                 catch(AUD_Exception&) {}
690         }
691         return false;
692 }
693
694 int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
695 {
696         if(handle)
697         {
698                 assert(AUD_device);
699
700                 try
701                 {
702                         return AUD_device->setPitch(handle, pitch);
703                 }
704                 catch(AUD_Exception&) {}
705         }
706         return false;
707 }
708
709 AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
710 {
711         try
712         {
713                 return new AUD_ReadDevice(specs);
714         }
715         catch(AUD_Exception&)
716         {
717                 return NULL;
718         }
719 }
720
721 AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
722 {
723         assert(device);
724         assert(sound);
725
726         try
727         {
728                 AUD_Channel* handle = device->play(sound);
729                 device->seek(handle, seek);
730                 return handle;
731         }
732         catch(AUD_Exception&)
733         {
734                 return NULL;
735         }
736 }
737
738 int AUD_setDeviceVolume(AUD_Device* device, float volume)
739 {
740         assert(device);
741
742         try
743         {
744                 device->setVolume(volume);
745                 return true;
746         }
747         catch(AUD_Exception&) {}
748         
749         return false;
750 }
751
752 int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle,
753                                                          float volume)
754 {
755         if(handle)
756         {
757                 assert(device);
758
759                 try
760                 {
761                         return device->setVolume(handle, volume);
762                 }
763                 catch(AUD_Exception&) {}
764         }
765         return false;
766 }
767
768 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
769 {
770         assert(device);
771         assert(buffer);
772
773         try
774         {
775                 return device->read(buffer, length);
776         }
777         catch(AUD_Exception&)
778         {
779                 return false;
780         }
781 }
782
783 void AUD_closeReadDevice(AUD_Device* device)
784 {
785         assert(device);
786
787         try
788         {
789                 delete device;
790         }
791         catch(AUD_Exception&)
792         {
793         }
794 }
795
796 float* AUD_readSoundBuffer(const char* filename, float low, float high,
797                                                    float attack, float release, float threshold,
798                                                    int accumulate, int additive, int square,
799                                                    float sthreshold, int samplerate, int* length)
800 {
801         AUD_Buffer buffer;
802         AUD_DeviceSpecs specs;
803         specs.channels = AUD_CHANNELS_MONO;
804         specs.rate = (AUD_SampleRate)samplerate;
805         AUD_Sound* sound;
806
807         AUD_FileFactory file(filename);
808         AUD_ChannelMapperFactory mapper(&file, specs);
809         AUD_LowpassFactory lowpass(&mapper, high);
810         AUD_HighpassFactory highpass(&lowpass, low);
811         AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f);
812         AUD_LinearResampleFactory resampler(&envelope, specs);
813         sound = &resampler;
814         AUD_SquareFactory squaref(sound, sthreshold);
815         if(square)
816                 sound = &squaref;
817         AUD_AccumulatorFactory accumulator(sound, additive);
818         AUD_SumFactory sum(sound);
819         if(accumulate)
820                 sound = &accumulator;
821         else if(additive)
822                 sound = &sum;
823
824         AUD_IReader* reader = sound->createReader();
825
826         if(reader == NULL)
827                 return NULL;
828
829         int len;
830         int position = 0;
831         sample_t* readbuffer;
832         do
833         {
834                 len = samplerate;
835                 buffer.resize((position + len) * sizeof(float), true);
836                 reader->read(len, readbuffer);
837                 memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float));
838                 position += len;
839         } while(len != 0);
840         delete reader;
841
842         float* result = (float*)malloc(position * sizeof(float));
843         memcpy(result, buffer.getBuffer(), position * sizeof(float));
844         *length = position;
845         return result;
846 }
847
848 AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
849 {
850 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
851  * is initialized.
852
853         return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
854 */
855         AUD_Specs specs;
856         specs.channels = AUD_CHANNELS_STEREO;
857         specs.rate = AUD_RATE_44100;
858         return new AUD_SequencerFactory(specs, data, volume);
859 }
860
861 void AUD_destroySequencer(AUD_Sound* sequencer)
862 {
863         delete ((AUD_SequencerFactory*)sequencer);
864 }
865
866 AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
867                                                                  float begin, float end, float skip, void* data)
868 {
869         return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
870 }
871
872 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
873 {
874         ((AUD_SequencerFactory*)sequencer)->remove(entry);
875 }
876
877 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
878                                    float begin, float end, float skip)
879 {
880         ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
881 }
882
883 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
884 {
885         ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
886 }
887
888 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
889 {
890         AUD_DeviceSpecs specs;
891         sample_t* buf;
892
893         specs.rate = AUD_RATE_INVALID;
894         specs.channels = AUD_CHANNELS_MONO;
895         specs.format = AUD_FORMAT_INVALID;
896
897         AUD_ChannelMapperFactory mapper(sound, specs);
898
899         AUD_IReader* reader = mapper.createReader();
900
901         int len = reader->getLength();
902         float samplejump = (float)len / (float)length;
903         float min, max;
904
905         for(int i = 0; i < length; i++)
906         {
907                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
908                 reader->read(len, buf);
909
910                 if(len < 1)
911                 {
912                         length = i;
913                         break;
914                 }
915
916                 max = min = *buf;
917                 for(int j = 1; j < len; j++)
918                 {
919                         if(buf[j] < min)
920                                 min = buf[j];
921                         if(buf[j] > max)
922                                 max = buf[j];
923                         buffer[i * 2] = min;
924                         buffer[i * 2 + 1] = max;
925                 }
926         }
927
928         delete reader;
929
930         return length;
931 }
932
933 void AUD_startPlayback()
934 {
935 #ifdef WITH_JACK
936         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
937         if(device)
938                 device->startPlayback();
939 #endif
940 }
941
942 void AUD_stopPlayback()
943 {
944 #ifdef WITH_JACK
945         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
946         if(device)
947                 device->stopPlayback();
948 #endif
949 }
950
951 void AUD_seekSequencer(AUD_Channel* handle, float time)
952 {
953 #ifdef WITH_JACK
954         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
955         if(device)
956                 device->seekPlayback(time);
957         else
958 #endif
959         {
960                 AUD_device->seek(handle, time);
961         }
962 }
963
964 float AUD_getSequencerPosition(AUD_Channel* handle)
965 {
966 #ifdef WITH_JACK
967         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
968         if(device)
969                 return device->getPlaybackPosition();
970         else
971 #endif
972         {
973                 return AUD_device->getPosition(handle);
974         }
975 }
976
977 #ifdef WITH_JACK
978 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
979 {
980         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
981         if(device)
982                 device->setSyncCallback(function, data);
983 }
984 #endif
985
986 int AUD_doesPlayback()
987 {
988 #ifdef WITH_JACK
989         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
990         if(device)
991                 return device->doesPlayback();
992 #endif
993         return -1;
994 }