1 /**
2  * @file
3  *
4  * Audiere Sound System
5  * Version 1.9.4
6  * (c) 2001-2003 Chad Austin
7  *
8  * This API uses principles explained at
9  * http://aegisknight.org/cppinterface.html
10  *
11  * This code licensed under the terms of the LGPL.  See doc/license.txt.
12  *
13  *
14  * Note: When compiling this header in gcc, you may want to use the
15  * -Wno-non-virtual-dtor flag to get rid of those annoying "class has
16  * virtual functions but no virtual destructor" warnings.
17  *
18  * This file is structured as follows:
19  * - includes, macro definitions, other general setup
20  * - interface definitions
21  * - DLL-safe entry points (not for general use)
22  * - inline functions that use those entry points
23  */
24 
25 #ifndef AUDIERE_H
26 #define AUDIERE_H
27 
28 
29 #include <vector>
30 #include <string>
31 #include <cstring> // strlen memcpy etc
32 #include <cstdio>  // for sprintf
33 
34 #ifdef _MSC_VER
35 #pragma warning(disable : 4786)
36 #endif
37 
38 
39 #ifndef __cplusplus
40   #error Audiere requires C++
41 #endif
42 
43 
44 // DLLs in Windows should use the standard (Pascal) calling convention
45 #ifndef ADR_CALL
46   #if defined(WIN32) || defined(_WIN32)
47     #define ADR_CALL __stdcall
48   #else
49     #define ADR_CALL
50   #endif
51 #endif
52 
53 // Export functions from the DLL
54 #ifndef ADR_DECL
55 #  if defined(WIN32) || defined(_WIN32)
56 #    ifdef AUDIERE_EXPORTS
57 #      define ADR_DECL __declspec(dllexport)
58 #    else
59 #      define ADR_DECL __declspec(dllimport)
60 #    endif
61 #  else
62 #    define ADR_DECL
63 #  endif
64 #endif
65 
66 
67 
68 #define ADR_FUNCTION(ret) extern "C" ADR_DECL ret ADR_CALL
69 #define ADR_METHOD(ret) virtual ret ADR_CALL
70 
71 
72 namespace audiere {
73 
74   class RefCounted {
75   protected:
76     /**
77      * Protected so users of refcounted classes don't use std::auto_ptr
78      * or the delete operator.
79      *
80      * Interfaces that derive from RefCounted should define an inline,
81      * empty, protected destructor as well.
82      */
~RefCounted()83     ~RefCounted() { }
84 
85   public:
86     /**
87      * Add a reference to the internal reference count.
88      */
89     ADR_METHOD(void) ref() = 0;
90 
91     /**
92      * Remove a reference from the internal reference count.  When this
93      * reaches 0, the object is destroyed.
94      */
95     ADR_METHOD(void) unref() = 0;
96   };
97 
98 
99   template<typename T>
100   class RefPtr {
101   public:
102     RefPtr(T* ptr = 0) {
103       m_ptr = 0;
104       *this = ptr;
105     }
106 
RefPtr(const RefPtr<T> & ptr)107     RefPtr(const RefPtr<T>& ptr) {
108       m_ptr = 0;
109       *this = ptr;
110     }
111 
~RefPtr()112     ~RefPtr() {
113       if (m_ptr) {
114         m_ptr->unref();
115         m_ptr = 0;
116       }
117     }
118 
119     RefPtr<T>& operator=(T* ptr) {
120       if (ptr != m_ptr) {
121         if (m_ptr) {
122           m_ptr->unref();
123         }
124         m_ptr = ptr;
125         if (m_ptr) {
126           m_ptr->ref();
127         }
128       }
129       return *this;
130     }
131 
132     RefPtr<T>& operator=(const RefPtr<T>& ptr) {
133       *this = ptr.m_ptr;
134       return *this;
135     }
136 
137     T* operator->() const {
138       return m_ptr;
139     }
140 
141     T& operator*() const {
142       return *m_ptr;
143     }
144 
145     operator bool() const {
146       return (m_ptr != 0);
147     }
148 
get()149     T* get() const {
150       return m_ptr;
151     }
152 
153   private:
154     T* m_ptr;
155   };
156 
157 
158   template<typename T, typename U>
159   bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) {
160       return (a.get() == b.get());
161   }
162 
163   template<typename T>
164   bool operator==(const RefPtr<T>& a, const T* b) {
165       return (a.get() == b);
166   }
167 
168   template<typename T>
169   bool operator==(const T* a, const RefPtr<T>& b) {
170       return (a == b.get());
171   }
172 
173 
174   template<typename T, typename U>
175   bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) {
176       return (a.get() != b.get());
177   }
178 
179   template<typename T>
180   bool operator!=(const RefPtr<T>& a, const T* b) {
181       return (a.get() != b);
182   }
183 
184   template<typename T>
185   bool operator!=(const T* a, const RefPtr<T>& b) {
186       return (a != b.get());
187   }
188 
189 
190   /**
191    * A basic implementation of the RefCounted interface.  Derive
192    * your implementations from RefImplementation<YourInterface>.
193    */
194   template<class Interface>
195   class RefImplementation : public Interface {
196   protected:
RefImplementation()197     RefImplementation() {
198       m_ref_count = 0;
199     }
200 
201     /**
202      * So the implementation can put its destruction logic in the destructor,
203      * as natural C++ code does.
204      */
~RefImplementation()205     virtual ~RefImplementation() { }
206 
207   public:
ref()208     void ADR_CALL ref() {
209       ++m_ref_count;
210     }
211 
unref()212     void ADR_CALL unref() {
213       if (--m_ref_count == 0) {
214         delete this;
215       }
216     }
217 
218   private:
219     int m_ref_count;
220   };
221 
222 
223   /**
224    * Represents a random-access file, usually stored on a disk.  Files
225    * are always binary: that is, they do no end-of-line
226    * transformations.  File objects are roughly analogous to ANSI C
227    * FILE* objects.
228    *
229    * This interface is not synchronized.
230    */
231   class File : public RefCounted {
232   protected:
~File()233     ~File() { }
234 
235   public:
236     /**
237      * The different ways you can seek within a file.
238      */
239     enum SeekMode {
240       BEGIN,
241       CURRENT,
242       END,
243     };
244 
245     /**
246      * Read size bytes from the file, storing them in buffer.
247      *
248      * @param buffer  buffer to read into
249      * @param size    number of bytes to read
250      *
251      * @return  number of bytes successfully read
252      */
253     ADR_METHOD(int) read(void* buffer, int size) = 0;
254 
255     /**
256      * Jump to a new position in the file, using the specified seek
257      * mode.  Remember: if mode is END, the position must be negative,
258      * to seek backwards from the end of the file into its contents.
259      * If the seek fails, the current position is undefined.
260      *
261      * @param position  position relative to the mode
262      * @param mode      where to seek from in the file
263      *
264      * @return  true on success, false otherwise
265      */
266     ADR_METHOD(bool) seek(int position, SeekMode mode) = 0;
267 
268     /**
269      * Get current position within the file.
270      *
271      * @return  current position
272      */
273     ADR_METHOD(int) tell() = 0;
274   };
275   typedef RefPtr<File> FilePtr;
276 
277 
278   /// Storage formats for sample data.
279   enum SampleFormat {
280     SF_U8,  ///< unsigned 8-bit integer [0,255]
281     SF_S16, ///< signed 16-bit integer in host endianness [-32768,32767]
282   };
283 
284 
285   /// Supported audio file formats.
286   enum FileFormat {
287     FF_AUTODETECT,
288     FF_WAV,
289     FF_OGG,
290     FF_FLAC,
291     FF_MP3,
292     FF_MOD,
293     FF_AIFF,
294     FF_SPEEX,
295   };
296 
297 
298   /**
299    * Source of raw PCM samples.  Sample sources have an intrinsic format
300    * (@see SampleFormat), sample rate, and number of channels.  They can
301    * be read from or reset.
302    *
303    * Some sample sources are seekable.  Seekable sources have two additional
304    * properties: length and position.  Length is read-only.
305    *
306    * This interface is not synchronized.
307    */
308   class SampleSource : public RefCounted {
309   protected:
~SampleSource()310     ~SampleSource() { }
311 
312   public:
313     /**
314      * Retrieve the number of channels, sample rate, and sample format of
315      * the sample source.
316      */
317     ADR_METHOD(void) getFormat(
318       int& channel_count,
319       int& sample_rate,
320       SampleFormat& sample_format) = 0;
321 
322     /**
323      * Read frame_count samples into buffer.  buffer must be at least
324      * |frame_count * GetSampleSize(format) * channel_count| bytes long.
325      *
326      * @param frame_count  number of frames to read
327      * @param buffer       buffer to store samples in
328      *
329      * @return  number of frames actually read
330      */
331     ADR_METHOD(int) read(int frame_count, void* buffer) = 0;
332 
333     /**
334      * Reset the sample source.  This has the same effect as setPosition(0)
335      * on a seekable source.  On an unseekable source, it resets all internal
336      * state to the way it was when the source was first created.
337      */
338     ADR_METHOD(void) reset() = 0;
339 
340     /**
341      * @return  true if the stream is seekable, false otherwise
342      */
343     ADR_METHOD(bool) isSeekable() = 0;
344 
345     /**
346      * @return  number of frames in the stream, or 0 if the stream is not
347      *          seekable
348      */
349     ADR_METHOD(int) getLength() = 0;
350 
351     /**
352      * Sets the current position within the sample source.  If the stream
353      * is not seekable, this method does nothing.
354      *
355      * @param position  current position in frames
356      */
357     ADR_METHOD(void) setPosition(int position) = 0;
358 
359     /**
360      * Returns the current position within the sample source.
361      *
362      * @return  current position in frames
363      */
364     ADR_METHOD(int) getPosition() = 0;
365 
366     /**
367      * @return  true if the sample source is set to repeat
368      */
369     ADR_METHOD(bool) getRepeat() = 0;
370 
371     /**
372      * Sets whether the sample source should repeat or not.  Note that not
373      * all sample sources repeat by starting again at the beginning of the
374      * sound.  For example MOD files can contain embedded loop points.
375      *
376      * @param repeat  true if the source should repeat, false otherwise
377      */
378     ADR_METHOD(void) setRepeat(bool repeat) = 0;
379 
380     /// Returns number of metadata tags present in this sample source.
381     ADR_METHOD(int) getTagCount() = 0;
382 
383     /**
384      * Returns the key of the i'th tag in the source.  If the tag is
385      * "author=me", the key is "author".
386      */
387     virtual const char* ADR_CALL getTagKey(int i) = 0;
388 
389     /**
390      * Returns the value of the i'th tag in the source.  If the tag is
391      * "author=me", the value is "me".
392      */
393     virtual const char* ADR_CALL getTagValue(int i) = 0;
394 
395     /**
396      * Returns the type of the i'th tag in the source.  The type is where
397      * the tag comes from, i.e. "ID3v1", "ID3v2", or "vorbis".
398      */
399     virtual const char* ADR_CALL getTagType(int i) = 0;
400   };
401   typedef RefPtr<SampleSource> SampleSourcePtr;
402 
403 
404   /**
405    * LoopPointSource is a wrapper around another SampleSource, providing
406    * custom loop behavior.  LoopPointSource maintains a set of links
407    * within the sample stream and whenever the location of one of the links
408    * (i.e. a loop point) is reached, the stream jumps to that link's target.
409    * Each loop point maintains a count.  Every time a loop point comes into
410    * effect, the count is decremented.  Once it reaches zero, that loop point
411    * is temporarily disabled.  If a count is not a positive value, it
412    * cannot be disabled.  Calling reset() resets all counts to their initial
413    * values.
414    *
415    * Loop points only take effect when repeating has been enabled via the
416    * setRepeat() method.
417    *
418    * Loop points are stored in sorted order by their location.  Each one
419    * has an index based on its location within the list.  A loop point's
420    * index will change if another is added before it.
421    *
422    * There is always one implicit loop point after the last sample that
423    * points back to the first.  That way, this class's default looping
424    * behavior is the same as a standard SampleSource.  This loop point
425    * does not show up in the list.
426    */
427   class LoopPointSource : public SampleSource {
428   protected:
~LoopPointSource()429     ~LoopPointSource() { }
430 
431   public:
432     /**
433      * Adds a loop point to the stream.  If a loop point at 'location'
434      * already exists, the new one replaces it.  Location and target are
435      * clamped to the actual length of the stream.
436      *
437      * @param location   frame where loop occurs
438      * @param target     frame to jump to after loop point is hit
439      * @param loopCount  number of times to execute this jump.
440      */
441     ADR_METHOD(void) addLoopPoint(
442       int location, int target, int loopCount) = 0;
443 
444     /**
445      * Removes the loop point at index 'index' from the stream.
446      *
447      * @param index  index of the loop point to remove
448      */
449     ADR_METHOD(void) removeLoopPoint(int index) = 0;
450 
451     /**
452      * Returns the number of loop points in this stream.
453      */
454     ADR_METHOD(int) getLoopPointCount() = 0;
455 
456     /**
457      * Retrieves information about a specific loop point.
458      *
459      * @param index      index of the loop point
460      * @param location   frame where loop occurs
461      * @param target     loop point's target frame
462      * @param loopCount  number of times to loop from this particular point
463      *
464      * @return  true if the index is valid and information is returned
465      */
466     ADR_METHOD(bool) getLoopPoint(
467       int index, int& location, int& target, int& loopCount) = 0;
468   };
469   typedef RefPtr<LoopPointSource> LoopPointSourcePtr;
470 
471 
472   /**
473    * A connection to an audio device.  Multiple output streams are
474    * mixed by the audio device to produce the final waveform that the
475    * user hears.
476    *
477    * Each output stream can be independently played and stopped.  They
478    * also each have a volume from 0.0 (silence) to 1.0 (maximum volume).
479    */
480   class OutputStream : public RefCounted {
481   protected:
~OutputStream()482     ~OutputStream() { }
483 
484   public:
485     /**
486      * Start playback of the output stream.  If the stream is already
487      * playing, this does nothing.
488      */
489     ADR_METHOD(void) play() = 0;
490 
491     /**
492      * Stop playback of the output stream.  If the stream is already
493      * stopped, this does nothing.
494      */
495     ADR_METHOD(void) stop() = 0;
496 
497     /**
498      * @return  true if the output stream is playing, false otherwise
499      */
500     ADR_METHOD(bool) isPlaying() = 0;
501 
502     /**
503      * Reset the sample source or buffer to the beginning. On seekable
504      * streams, this operation is equivalent to setPosition(0).
505      *
506      * On some output streams, this operation can be moderately slow, as up to
507      * several seconds of PCM buffer must be refilled.
508      */
509     ADR_METHOD(void) reset() = 0;
510 
511     /**
512      * Set whether the output stream should repeat.
513      *
514      * @param repeat  true if the stream should repeat, false otherwise
515      */
516     ADR_METHOD(void) setRepeat(bool repeat) = 0;
517 
518     /**
519      * @return  true if the stream is repeating
520      */
521     ADR_METHOD(bool) getRepeat() = 0;
522 
523     /**
524      * Sets the stream's volume.
525      *
526      * @param  volume  0.0 = silence, 1.0 = maximum volume (default)
527      */
528     ADR_METHOD(void) setVolume(float volume) = 0;
529 
530     /**
531      * Gets the current volume.
532      *
533      * @return  current volume of the output stream
534      */
535     ADR_METHOD(float) getVolume() = 0;
536 
537     /**
538      * Set current pan.
539      *
540      * @param pan  -1.0 = left, 0.0 = center (default), 1.0 = right
541      */
542     ADR_METHOD(void) setPan(float pan) = 0;
543 
544     /**
545      * Get current pan.
546      */
547     ADR_METHOD(float) getPan() = 0;
548 
549     /**
550      * Set current pitch shift.
551      *
552      * @param shift  can range from 0.5 to 2.0.  default is 1.0.
553      */
554     ADR_METHOD(void) setPitchShift(float shift) = 0;
555 
556     /**
557      * Get current pitch shift.  Defaults to 1.0.
558      */
559     ADR_METHOD(float) getPitchShift() = 0;
560 
561     /**
562      * @return  true if the stream is seekable, false otherwise
563      */
564     ADR_METHOD(bool) isSeekable() = 0;
565 
566     /**
567      * @return  number of frames in the stream, or 0 if the stream is not
568      *          seekable
569      */
570     ADR_METHOD(int) getLength() = 0;
571 
572     /**
573      * Sets the current position within the sample source.  If the stream
574      * is not seekable, this method does nothing.
575      *
576      * @param position  current position in frames
577      */
578     ADR_METHOD(void) setPosition(int position) = 0;
579 
580     /**
581      * Returns the current position within the sample source.
582      *
583      * @return  current position in frames
584      */
585     ADR_METHOD(int) getPosition() = 0;
586   };
587   typedef RefPtr<OutputStream> OutputStreamPtr;
588 
589 
590   /// An integral code representing a specific type of event.
591   enum EventType {
592     ET_STOP, ///< See StopEvent and StopCallback
593   };
594 
595 
596   /// Base interface for event-specific data passed to callbacks.
597   class Event : public RefCounted {
598   protected:
~Event()599     ~Event() { }
600 
601   public:
602     /// Returns the EventType code for this event.
603     ADR_METHOD(EventType) getType() = 0;
604   };
605   typedef RefPtr<Event> EventPtr;
606 
607 
608   /**
609    * An event object that gets passed to implementations of StopCallback
610    * when a stream has stopped playing.
611    */
612   class StopEvent : public Event {
613   protected:
~StopEvent()614     ~StopEvent() { }
615 
616   public:
getType()617     EventType ADR_CALL getType() { return ET_STOP; }
618 
619     /// A code representing the reason the stream stopped playback.
620     enum Reason {
621       STOP_CALLED,  ///< stop() was called from an external source.
622       STREAM_ENDED, ///< The stream reached its end.
623     };
624 
625     /**
626      * @return Pointer to the OutputStream that stopped playback.
627      */
628     ADR_METHOD(OutputStream*) getOutputStream() = 0;
629 
630     /**
631      * @return Reason for the stop event.
632      */
633     ADR_METHOD(Reason) getReason() = 0;
634   };
635   typedef RefPtr<StopEvent> StopEventPtr;
636 
637 
638   /**
639    * Base interface for all callbacks.  See specific callback implementations
640    * for descriptions.
641    */
642   class Callback : public RefCounted {
643   protected:
~Callback()644     ~Callback() { }
645 
646   public:
647     /**
648      * Returns the event type that this callback knows how to handle.
649      */
650     ADR_METHOD(EventType) getType() = 0;
651 
652     /**
653      * Actually executes the callback with event-specific data.  This is
654      * only called if event->getType() == this->getType().
655      */
656     ADR_METHOD(void) call(Event* event) = 0;
657   };
658   typedef RefPtr<Callback> CallbackPtr;
659 
660 
661   /**
662    * To listen for stream stopped events on a device, implement this interface
663    * and call registerStopCallback() on the device, passing your
664    * implementation.  streamStopped() will be called whenever a stream on that
665    * device stops playback.
666    *
667    * WARNING: StopCallback is called from another thread.  Make sure your
668    * callback is thread-safe.
669    */
670   class StopCallback : public Callback {
671   protected:
~StopCallback()672     ~StopCallback() { }
673 
674   public:
getType()675     EventType ADR_CALL getType() { return ET_STOP; }
call(Event * event)676     void ADR_CALL call(Event* event) {
677       streamStopped(static_cast<StopEvent*>(event));
678     }
679 
680     /**
681      * Called when a stream has stopped.
682      *
683      * @param event  Information pertaining to the event.
684      */
685     ADR_METHOD(void) streamStopped(StopEvent* event) = 0;
686   };
687   typedef RefPtr<StopCallback> StopCallbackPtr;
688 
689 
690   /**
691    * AudioDevice represents a device on the system which is capable
692    * of opening and mixing multiple output streams.  In Windows,
693    * DirectSound is such a device.
694    *
695    * This interface is synchronized.  update() and openStream() may
696    * be called on different threads.
697    */
698   class AudioDevice : public RefCounted {
699   protected:
~AudioDevice()700     ~AudioDevice() { }
701 
702   public:
703     /**
704      * Tell the device to do any internal state updates.  Some devices
705      * update on an internal thread.  If that is the case, this method
706      * does nothing.
707      */
708     ADR_METHOD(void) update() = 0;
709 
710     /**
711      * Open an output stream with a given sample source.  If the sample
712      * source ever runs out of data, the output stream automatically stops
713      * itself.
714      *
715      * The output stream takes ownership of the sample source, even if
716      * opening the output stream fails (in which case the source is
717      * immediately deleted).
718      *
719      * @param  source  the source used to feed the output stream with samples
720      *
721      * @return  new output stream if successful, 0 if failure
722      */
723     ADR_METHOD(OutputStream*) openStream(SampleSource* source) = 0;
724 
725     /**
726      * Open a single buffer with the specified PCM data.  This is sometimes
727      * more efficient than streaming and works on a larger variety of audio
728      * devices.  In some implementations, this may download the audio data
729      * to the sound card's memory itself.
730      *
731      * @param samples  Buffer containing sample data.  openBuffer() does
732      *                 not take ownership of the memory.  The application
733      *                 is responsible for freeing it.  There must be at
734      *                 least |frame_count * channel_count *
735      *                 GetSampleSize(sample_format)| bytes in the buffer.
736      *
737      * @param frame_count  Number of frames in the buffer.
738      *
739      * @param channel_count  Number of audio channels.  1 = mono, 2 = stereo.
740      *
741      * @param sample_rate  Number of samples per second.
742      *
743      * @param sample_format  Format of samples in buffer.
744      *
745      * @return  new output stream if successful, 0 if failure
746      */
747     ADR_METHOD(OutputStream*) openBuffer(
748       void* samples,
749       int frame_count,
750       int channel_count,
751       int sample_rate,
752       SampleFormat sample_format) = 0;
753 
754     /**
755      * Gets the name of the audio device.  For example "directsound" or "oss".
756      *
757      * @return name of audio device
758      */
759     ADR_METHOD(const char*) getName() = 0;
760 
761     /**
762      * Registers 'callback' to receive events.  Callbacks can be
763      * registered multiple times.
764      */
765     ADR_METHOD(void) registerCallback(Callback* callback) = 0;
766 
767     /**
768      * Unregisters 'callback' once.  If it is registered multiple times,
769      * each unregisterStopCallback call unregisters one of the instances.
770      */
771     ADR_METHOD(void) unregisterCallback(Callback* callback) = 0;
772 
773     /// Clears all of the callbacks from the device.
774     ADR_METHOD(void) clearCallbacks() = 0;
775   };
776   typedef RefPtr<AudioDevice> AudioDevicePtr;
777 
778 
779   /**
780    * A readonly sample container which can open sample streams as iterators
781    * through the buffer.  This is commonly used in cases where a very large
782    * sound effect is loaded once into memory and then streamed several times
783    * to the audio device.  This is more efficient memory-wise than loading
784    * the effect multiple times.
785    *
786    * @see CreateSampleBuffer
787    */
788   class SampleBuffer : public RefCounted {
789   protected:
~SampleBuffer()790     ~SampleBuffer() { }
791 
792   public:
793 
794     /**
795      * Return the format of the sample data in the sample buffer.
796      * @see SampleSource::getFormat
797      */
798     ADR_METHOD(void) getFormat(
799       int& channel_count,
800       int& sample_rate,
801       SampleFormat& sample_format) = 0;
802 
803     /**
804      * Get the length of the sample buffer in frames.
805      */
806     ADR_METHOD(int) getLength() = 0;
807 
808     /**
809      * Get a readonly pointer to the samples contained within the buffer.  The
810      * buffer is |channel_count * frame_count * GetSampleSize(sample_format)|
811      * bytes long.
812      */
813     virtual const void* ADR_CALL getSamples() = 0;
814 
815     /**
816      * Open a seekable sample source using the samples contained in the
817      * buffer.
818      */
819     ADR_METHOD(SampleSource*) openStream() = 0;
820   };
821   typedef RefPtr<SampleBuffer> SampleBufferPtr;
822 
823 
824   /**
825    * Defines the type of SoundEffect objects.  @see SoundEffect
826    */
827   enum SoundEffectType {
828     SINGLE,
829     MULTIPLE,
830   };
831 
832 
833   /**
834    * SoundEffect is a convenience class which provides a simple
835    * mechanism for basic sound playback.  There are two types of sound
836    * effects: SINGLE and MULTIPLE.  SINGLE sound effects only allow
837    * the sound to be played once at a time.  MULTIPLE sound effects
838    * always open a new stream to the audio device for each time it is
839    * played (cleaning up or reusing old streams if possible).
840    */
841   class SoundEffect : public RefCounted {
842   protected:
~SoundEffect()843     ~SoundEffect() { }
844 
845   public:
846     /**
847      * Trigger playback of the sound.  If the SoundEffect is of type
848      * SINGLE, this plays the sound if it isn't playing yet, and
849      * starts it again if it is.  If the SoundEffect is of type
850      * MULTIPLE, play() simply starts playing the sound again.
851      */
852     ADR_METHOD(void) play() = 0;
853 
854     /**
855      * If the sound is of type SINGLE, stop the sound.  If it is of
856      * type MULTIPLE, stop all playing instances of the sound.
857      */
858     ADR_METHOD(void) stop() = 0;
859 
860     /**
861      * Sets the sound's volume.
862      *
863      * @param  volume  0.0 = silence, 1.0 = maximum volume (default)
864      */
865     ADR_METHOD(void) setVolume(float volume) = 0;
866 
867     /**
868      * Gets the current volume.
869      *
870      * @return  current volume of the output stream
871      */
872     ADR_METHOD(float) getVolume() = 0;
873 
874     /**
875      * Set current pan.
876      *
877      * @param pan  -1.0 = left, 0.0 = center (default), 1.0 = right
878      */
879     ADR_METHOD(void) setPan(float pan) = 0;
880 
881     /**
882      * Get current pan.
883      */
884     ADR_METHOD(float) getPan() = 0;
885 
886     /**
887      * Set current pitch shift.
888      *
889      * @param shift  can range from 0.5 to 2.0.  default is 1.0.
890      */
891     ADR_METHOD(void) setPitchShift(float shift) = 0;
892 
893     /**
894      * Get current pitch shift.  Defaults to 1.0.
895      */
896     ADR_METHOD(float) getPitchShift() = 0;
897   };
898   typedef RefPtr<SoundEffect> SoundEffectPtr;
899 
900 
901   /**
902    * Represents a device capable of playing CD audio. Internally, this
903    * uses the MCI subsystem in windows and libcdaudio on other platforms.
904    * MCI subsystem: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_multimedia_command_strings.asp
905    * libcdaudio: http://cdcd.undergrid.net/libcdaudio/
906    */
907   class CDDevice : public RefCounted {
908   protected:
~CDDevice()909     virtual ~CDDevice() { }
910 
911   public:
912     /**
913      * Returns the name of this CD Device, often just the device name
914      * it was created with.
915      */
916     virtual const char* ADR_CALL getName() = 0;
917 
918     /**
919      * Returns the number of audio tracks on the disc.
920      */
921     ADR_METHOD(int) getTrackCount() = 0;
922 
923     /**
924      * Starts playback of the given track. If another track was
925      * already playing, the previous track is stopped.  IMPORTANT: Tracks are
926      * indexed from 0 to getTrackCount() - 1.
927      */
928     ADR_METHOD(void) play(int track) = 0;
929 
930     /**
931      * Stops the playback, if the playback was already stopped, this
932      * does nothing.
933      */
934     ADR_METHOD(void) stop() = 0;
935 
936     /**
937      * pauses playback of the track that is currently playing (if any)
938      * This does nothing if no track is playing
939      */
940     ADR_METHOD(void) pause() = 0;
941 
942     /**
943      * Resumes playback of the track that is currently paused (if any).
944      * This does nothing if no track is paused.
945      */
946     ADR_METHOD(void) resume() = 0;
947 
948     /**
949      * Returns true if the CD is currently playing a sound, this could
950      * be through us, or through some other program.
951      */
952     ADR_METHOD(bool) isPlaying() = 0;
953 
954     /**
955      * Returns true if the drive contains a cd. This might be slow
956      * on some systems, use with care.
957      */
958     ADR_METHOD(bool) containsCD() = 0;
959 
960     /// Returns true if the door is open.
961     ADR_METHOD(bool) isDoorOpen() = 0;
962 
963     /// Opens this device's door.
964     ADR_METHOD(void) openDoor() = 0;
965 
966     /// Closes this device's door.
967     ADR_METHOD(void) closeDoor() = 0;
968   };
969   typedef RefPtr<CDDevice> CDDevicePtr;
970 
971 
972   /**
973    * An opened MIDI song that can be played, stopped, and seeked within.
974    * Uses MCI under Windows and is not supported in other platforms.
975    */
976   class MIDIStream : public RefCounted {
977   protected:
~MIDIStream()978     virtual ~MIDIStream() { }
979 
980   public:
981     /**
982      * Begins playback of the song and does nothing if the song is already
983      * playing.
984      */
985     ADR_METHOD(void) play() = 0;
986 
987     /// Stops playback of the song and seeks to the beginning.
988     ADR_METHOD(void) stop() = 0;
989 
990     /**
991      * Stops playback of the song and does not change its current position.
992      * A subsequent play() will resume the song where it left off.
993      */
994     ADR_METHOD(void) pause() = 0;
995 
996     /// Returns true if the song is currently playing, false otherwise.
997     ADR_METHOD(bool) isPlaying() = 0;
998 
999     /// Returns the length of the song in milliseconds.
1000     ADR_METHOD(int) getLength() = 0;
1001 
1002     /// Returns the current position of the song in milliseconds.
1003     ADR_METHOD(int) getPosition() = 0;
1004 
1005     /// Sets the current position of the song.
1006     ADR_METHOD(void) setPosition(int position) = 0;
1007 
1008     /// Returns true if this song is set to repeat.
1009     ADR_METHOD(bool) getRepeat() = 0;
1010 
1011     /// Sets whether the song should repeat on completion.  Defaults to false.
1012     ADR_METHOD(void) setRepeat(bool repeat) = 0;
1013   };
1014   typedef RefPtr<MIDIStream> MIDIStreamPtr;
1015 
1016 
1017   /**
1018    * A MIDIDevice must be instantiated in order to open MIDIStreams.
1019    */
1020   class MIDIDevice : public RefCounted {
1021   protected:
~MIDIDevice()1022     virtual ~MIDIDevice() { }
1023 
1024   public:
1025     /**
1026      * Returns the name of the device.
1027      */
1028     ADR_METHOD(const char*) getName() = 0;
1029 
1030     /**
1031      * openStream() creates and returns a new MIDIStream object from the
1032      * file with the specified name, which then can be queried and played.
1033      * This method returns NULL if the stream cannot be opened.
1034      *
1035      * Note: MCI subsystem limitations do not allow loading MIDIStream
1036      * objects from an audiere File implementation.  This may be addressed
1037      * in future versions of this API.
1038      */
1039     ADR_METHOD(MIDIStream*) openStream(const char* filename) = 0;
1040   };
1041   typedef RefPtr<MIDIDevice> MIDIDevicePtr;
1042 
1043 
1044   /// PRIVATE API - for internal use only
1045   namespace hidden {
1046 
1047     // these are extern "C" so we don't mangle the names
1048 
1049     ADR_FUNCTION(const char*) AdrGetVersion();
1050 
1051     /**
1052      * Returns a formatted string that lists the file formats that Audiere
1053      * supports.  This function is DLL-safe.
1054      *
1055      * It is formatted in the following way:
1056      *
1057      * description1:ext1,ext2,ext3;description2:ext1,ext2,ext3
1058      */
1059     ADR_FUNCTION(const char*) AdrGetSupportedFileFormats();
1060 
1061     /**
1062      * Returns a formatted string that lists the audio devices Audiere
1063      * supports.  This function is DLL-safe.
1064      *
1065      * It is formatted in the following way:
1066      *
1067      * name1:description1;name2:description2;...
1068      */
1069     ADR_FUNCTION(const char*) AdrGetSupportedAudioDevices();
1070 
1071     ADR_FUNCTION(int) AdrGetSampleSize(SampleFormat format);
1072 
1073     ADR_FUNCTION(AudioDevice*) AdrOpenDevice(
1074       const char* name,
1075       const char* parameters);
1076 
1077     ADR_FUNCTION(SampleSource*) AdrOpenSampleSource(
1078       const char* filename,
1079       FileFormat file_format);
1080     ADR_FUNCTION(SampleSource*) AdrOpenSampleSourceFromFile(
1081       File* file,
1082       FileFormat file_format);
1083     ADR_FUNCTION(SampleSource*) AdrCreateTone(double frequency);
1084     ADR_FUNCTION(SampleSource*) AdrCreateSquareWave(double frequency);
1085     ADR_FUNCTION(SampleSource*) AdrCreateWhiteNoise();
1086     ADR_FUNCTION(SampleSource*) AdrCreatePinkNoise();
1087 
1088     ADR_FUNCTION(LoopPointSource*) AdrCreateLoopPointSource(
1089       SampleSource* source);
1090 
1091     ADR_FUNCTION(OutputStream*) AdrOpenSound(
1092       AudioDevice* device,
1093       SampleSource* source,
1094       bool streaming);
1095 
1096     ADR_FUNCTION(SampleBuffer*) AdrCreateSampleBuffer(
1097       void* samples,
1098       int frame_count,
1099       int channel_count,
1100       int sample_rate,
1101       SampleFormat sample_format);
1102     ADR_FUNCTION(SampleBuffer*) AdrCreateSampleBufferFromSource(
1103       SampleSource* source);
1104 
1105     ADR_FUNCTION(SoundEffect*) AdrOpenSoundEffect(
1106       AudioDevice* device,
1107       SampleSource* source,
1108       SoundEffectType type);
1109 
1110     ADR_FUNCTION(File*) AdrOpenFile(
1111       const char* name,
1112       bool writeable);
1113 
1114     ADR_FUNCTION(File*) AdrCreateMemoryFile(
1115       const void* buffer,
1116       int size);
1117 
1118     ADR_FUNCTION(const char*) AdrEnumerateCDDevices();
1119 
1120     ADR_FUNCTION(CDDevice*) AdrOpenCDDevice(
1121       const char* name);  // Parameters?
1122 
1123     ADR_FUNCTION(MIDIDevice*) AdrOpenMIDIDevice(
1124       const char* name);  // Parameters?
1125   }
1126 
1127 
1128 
1129 
1130   /*-------- PUBLIC API FUNCTIONS --------*/
1131 
1132 
1133   /**
1134    * Returns the Audiere version string.
1135    *
1136    * @return  Audiere version information
1137    */
GetVersion()1138   inline const char* GetVersion() {
1139     return hidden::AdrGetVersion();
1140   }
1141 
1142 
SplitString(std::vector<std::string> & out,const char * in,char delim)1143   inline void SplitString(
1144     std::vector<std::string>& out,
1145     const char* in,
1146     char delim)
1147   {
1148     out.clear();
1149     while (*in) {
1150       const char* next = strchr(in, delim);
1151       if (next) {
1152         out.push_back(std::string(in, next));
1153       } else {
1154         out.push_back(in);
1155       }
1156 
1157       in = (next ? next + 1 : "");
1158     }
1159   }
1160 
1161 
1162   /// Describes a file format that Audiere supports.
1163   struct FileFormatDesc {
1164     /// Short description of format, such as "MP3 Files" or "Mod Files"
1165     std::string description;
1166 
1167     /// List of support extensions, such as {"mod", "it", "xm"}
1168     std::vector<std::string> extensions;
1169   };
1170 
1171   /// Populates a vector of FileFormatDesc structs.
GetSupportedFileFormats(std::vector<FileFormatDesc> & formats)1172   inline void GetSupportedFileFormats(std::vector<FileFormatDesc>& formats) {
1173     std::vector<std::string> descriptions;
1174     SplitString(descriptions, hidden::AdrGetSupportedFileFormats(), ';');
1175 
1176     formats.resize(descriptions.size());
1177     for (unsigned i = 0; i < descriptions.size(); ++i) {
1178       const char* d = descriptions[i].c_str();
1179       const char* colon = strchr(d, ':');
1180       formats[i].description.assign(d, colon);
1181 
1182       SplitString(formats[i].extensions, colon + 1, ',');
1183     }
1184   }
1185 
1186 
1187   /// Describes a supported audio device.
1188   struct AudioDeviceDesc {
1189     /// Name of device, i.e. "directsound", "winmm", or "oss"
1190     std::string name;
1191 
1192     // Textual description of device.
1193     std::string description;
1194   };
1195 
1196   /// Populates a vector of AudioDeviceDesc structs.
GetSupportedAudioDevices(std::vector<AudioDeviceDesc> & devices)1197   inline void GetSupportedAudioDevices(std::vector<AudioDeviceDesc>& devices) {
1198     std::vector<std::string> descriptions;
1199     SplitString(descriptions, hidden::AdrGetSupportedAudioDevices(), ';');
1200 
1201     devices.resize(descriptions.size());
1202     for (unsigned i = 0; i < descriptions.size(); ++i) {
1203       std::vector<std::string> d;
1204       SplitString(d, descriptions[i].c_str(), ':');
1205       devices[i].name        = d[0];
1206       devices[i].description = d[1];
1207     }
1208   }
1209 
1210 
1211   /**
1212    * Get the size of a sample in a specific sample format.
1213    * This is commonly used to determine how many bytes a chunk of
1214    * PCM data will take.
1215    *
1216    * @return  Number of bytes a single sample in the specified format
1217    *          takes.
1218    */
GetSampleSize(SampleFormat format)1219   inline int GetSampleSize(SampleFormat format) {
1220     return hidden::AdrGetSampleSize(format);
1221   }
1222 
1223   /**
1224    * Open a new audio device. If name or parameters are not specified,
1225    * defaults are used. Each platform has its own set of audio devices.
1226    * Every platform supports the "null" audio device.
1227    *
1228    * @param  name  name of audio device that should be used
1229    * @param  parameters  comma delimited list of audio-device parameters;
1230    *                     for example, "buffer=100,rate=44100"
1231    *
1232    * @return  new audio device object if OpenDevice succeeds, and 0 in case
1233    *          of failure
1234    */
1235   inline AudioDevice* OpenDevice(
1236     const char* name = 0,
1237     const char* parameters = 0)
1238   {
1239     return hidden::AdrOpenDevice(name, parameters);
1240   }
1241 
1242   /**
1243    * Create a streaming sample source from a sound file.  This factory simply
1244    * opens a default file from the system filesystem and calls
1245    * OpenSampleSource(File*).
1246    *
1247    * @see OpenSampleSource(File*)
1248    */
1249   inline SampleSource* OpenSampleSource(
1250     const char* filename,
1251     FileFormat file_format = FF_AUTODETECT)
1252   {
1253     return hidden::AdrOpenSampleSource(filename, file_format);
1254   }
1255 
1256   /**
1257    * Opens a sample source from the specified file object.  If the sound file
1258    * cannot be opened, this factory function returns 0.
1259    *
1260    * @note  Some sound files support seeking, while some don't.
1261    *
1262    * @param file         File object from which to open the decoder
1263    * @param file_format  Format of the file to load.  If FF_AUTODETECT,
1264    *                     Audiere will try opening the file in each format.
1265    *
1266    * @return  new SampleSource if OpenSampleSource succeeds, 0 otherwise
1267    */
1268   inline SampleSource* OpenSampleSource(
1269     const FilePtr& file,
1270     FileFormat file_format = FF_AUTODETECT)
1271   {
1272     return hidden::AdrOpenSampleSourceFromFile(file.get(), file_format);
1273   }
1274 
1275   /**
1276    * Create a tone sample source with the specified frequency.
1277    *
1278    * @param  frequency  Frequency of the tone in Hz.
1279    *
1280    * @return  tone sample source
1281    */
CreateTone(double frequency)1282   inline SampleSource* CreateTone(double frequency) {
1283     return hidden::AdrCreateTone(frequency);
1284   }
1285 
1286   /**
1287    * Create a square wave with the specified frequency.
1288    *
1289    * @param  frequency  Frequency of the wave in Hz.
1290    *
1291    * @return  wave sample source
1292    */
CreateSquareWave(double frequency)1293   inline SampleSource* CreateSquareWave(double frequency) {
1294     return hidden::AdrCreateSquareWave(frequency);
1295   }
1296 
1297   /**
1298    * Create a white noise sample source.  White noise is just random
1299    * data.
1300    *
1301    * @return  white noise sample source
1302    */
CreateWhiteNoise()1303   inline SampleSource* CreateWhiteNoise() {
1304     return hidden::AdrCreateWhiteNoise();
1305   }
1306 
1307   /**
1308    * Create a pink noise sample source.  Pink noise is noise with equal
1309    * power distribution among octaves (logarithmic), not frequencies.
1310    *
1311    * @return  pink noise sample source
1312    */
CreatePinkNoise()1313   inline SampleSource* CreatePinkNoise() {
1314     return hidden::AdrCreatePinkNoise();
1315   }
1316 
1317   /**
1318    * Create a LoopPointSource from a SampleSource.  The SampleSource must
1319    * be seekable.  If it isn't, or the source isn't valid, this function
1320    * returns 0.
1321    */
CreateLoopPointSource(const SampleSourcePtr & source)1322   inline LoopPointSource* CreateLoopPointSource(
1323     const SampleSourcePtr& source)
1324   {
1325     return hidden::AdrCreateLoopPointSource(source.get());
1326   }
1327 
1328   /**
1329    * Creates a LoopPointSource from a source loaded from a file.
1330    */
1331   inline LoopPointSource* CreateLoopPointSource(
1332     const char* filename,
1333     FileFormat file_format = FF_AUTODETECT)
1334   {
1335     return CreateLoopPointSource(OpenSampleSource(filename, file_format));
1336   }
1337 
1338   /**
1339    * Creates a LoopPointSource from a source loaded from a file.
1340    */
1341   inline LoopPointSource* CreateLoopPointSource(
1342     const FilePtr& file,
1343     FileFormat file_format = FF_AUTODETECT)
1344   {
1345     return CreateLoopPointSource(OpenSampleSource(file, file_format));
1346   }
1347 
1348   /**
1349    * Try to open a sound buffer using the specified AudioDevice and
1350    * sample source.  If the specified sample source is seekable, it
1351    * loads it into memory and uses AudioDevice::openBuffer to create
1352    * the output stream.  If the stream is not seekable, it uses
1353    * AudioDevice::openStream to create the output stream.  This means
1354    * that certain file types must always be streamed, and therefore,
1355    * OpenSound will hold on to the file object.  If you must guarantee
1356    * that the file on disk is no longer referenced, you must create
1357    * your own memory file implementation and load your data into that
1358    * before calling OpenSound.
1359    *
1360    * @param device  AudioDevice in which to open the output stream.
1361    *
1362    * @param source  SampleSource used to generate samples for the sound
1363    *                object.  OpenSound takes ownership of source, even
1364    *                if it returns 0.  (In that case, OpenSound immediately
1365    *                deletes the SampleSource.)
1366    *
1367    * @param streaming  If false or unspecified, OpenSound attempts to
1368    *                   open the entire sound into memory.  Otherwise, it
1369    *                   streams the sound from the file.
1370    *
1371    * @return  new output stream if successful, 0 otherwise
1372    */
1373   inline OutputStream* OpenSound(
1374     const AudioDevicePtr& device,
1375     const SampleSourcePtr& source,
1376     bool streaming = false)
1377   {
1378     return hidden::AdrOpenSound(device.get(), source.get(), streaming);
1379   }
1380 
1381   /**
1382    * Calls OpenSound(AudioDevice*, SampleSource*) with a sample source
1383    * created via OpenSampleSource(const char*).
1384    */
1385   inline OutputStream* OpenSound(
1386     const AudioDevicePtr& device,
1387     const char* filename,
1388     bool streaming = false,
1389     FileFormat file_format = FF_AUTODETECT)
1390   {
1391     SampleSource* source = OpenSampleSource(filename, file_format);
1392     return OpenSound(device, source, streaming);
1393   }
1394 
1395   /**
1396    * Calls OpenSound(AudioDevice*, SampleSource*) with a sample source
1397    * created via OpenSampleSource(File* file).
1398    */
1399   inline OutputStream* OpenSound(
1400     const AudioDevicePtr& device,
1401     const FilePtr& file,
1402     bool streaming = false,
1403     FileFormat file_format = FF_AUTODETECT)
1404   {
1405     SampleSource* source = OpenSampleSource(file, file_format);
1406     return OpenSound(device, source, streaming);
1407   }
1408 
1409   /**
1410    * Create a SampleBuffer object using the specified samples and formats.
1411    *
1412    * @param samples  Pointer to a buffer of samples used to initialize the
1413    *                 new object.  If this is 0, the sample buffer contains
1414    *                 just silence.
1415    *
1416    * @param frame_count  Size of the sample buffer in frames.
1417    *
1418    * @param channel_count  Number of channels in each frame.
1419    *
1420    * @param sample_rate  Sample rate in Hz.
1421    *
1422    * @param sample_format  Format of each sample.  @see SampleFormat.
1423    *
1424    * @return  new SampleBuffer object
1425    */
CreateSampleBuffer(void * samples,int frame_count,int channel_count,int sample_rate,SampleFormat sample_format)1426   inline SampleBuffer* CreateSampleBuffer(
1427     void* samples,
1428     int frame_count,
1429     int channel_count,
1430     int sample_rate,
1431     SampleFormat sample_format)
1432   {
1433     return hidden::AdrCreateSampleBuffer(
1434       samples, frame_count,
1435       channel_count, sample_rate, sample_format);
1436   }
1437 
1438   /**
1439    * Create a SampleBuffer object from a SampleSource.
1440    *
1441    * @param source  Seekable sample source used to create the buffer.
1442    *                If the source is not seekable, then the function
1443    *                fails.
1444    *
1445    * @return  new sample buffer if success, 0 otherwise
1446    */
CreateSampleBuffer(const SampleSourcePtr & source)1447   inline SampleBuffer* CreateSampleBuffer(const SampleSourcePtr& source) {
1448     return hidden::AdrCreateSampleBufferFromSource(source.get());
1449   }
1450 
1451   /**
1452    * Open a SoundEffect object from the given sample source and sound
1453    * effect type.  @see SoundEffect
1454    *
1455    * @param device  AudioDevice on which the sound is played.
1456    *
1457    * @param source  The sample source used to feed the sound effect
1458    *                with data.
1459    *
1460    * @param type  The type of the sound effect.  If type is MULTIPLE,
1461    *              the source must be seekable.
1462    *
1463    * @return  new SoundEffect object if successful, 0 otherwise
1464    */
OpenSoundEffect(const AudioDevicePtr & device,const SampleSourcePtr & source,SoundEffectType type)1465   inline SoundEffect* OpenSoundEffect(
1466     const AudioDevicePtr& device,
1467     const SampleSourcePtr& source,
1468     SoundEffectType type)
1469   {
1470     return hidden::AdrOpenSoundEffect(device.get(), source.get(), type);
1471   }
1472 
1473   /**
1474    * Calls OpenSoundEffect(AudioDevice*, SampleSource*,
1475    * SoundEffectType) with a sample source created from the filename.
1476    */
1477   inline SoundEffect* OpenSoundEffect(
1478     const AudioDevicePtr& device,
1479     const char* filename,
1480     SoundEffectType type,
1481     FileFormat file_format = FF_AUTODETECT)
1482   {
1483     SampleSource* source = OpenSampleSource(filename, file_format);
1484     return OpenSoundEffect(device, source, type);
1485   }
1486 
1487   /**
1488    * Calls OpenSoundEffect(AudioDevice*, SampleSource*,
1489    * SoundEffectType) with a sample source created from the file.
1490    */
1491   inline SoundEffect* OpenSoundEffect(
1492     const AudioDevicePtr& device,
1493     const FilePtr& file,
1494     SoundEffectType type,
1495     FileFormat file_format = FF_AUTODETECT)
1496   {
1497     SampleSource* source = OpenSampleSource(file, file_format);
1498     return OpenSoundEffect(device, source, type);
1499   }
1500 
1501   /**
1502    * Opens a default file implementation from the local filesystem.
1503    *
1504    * @param filename   The name of the file on the local filesystem.
1505    * @param writeable  Whether the writing to the file is allowed.
1506    */
OpenFile(const char * filename,bool writeable)1507   inline File* OpenFile(const char* filename, bool writeable) {
1508     return hidden::AdrOpenFile(filename, writeable);
1509   }
1510 
1511   /**
1512    * Creates a File implementation that reads from a buffer in memory.
1513    * It stores a copy of the buffer that is passed in.
1514    *
1515    * The File object does <i>not</i> take ownership of the memory buffer.
1516    * When the file is destroyed, it will not free the memory.
1517    *
1518    * @param buffer  Pointer to the beginning of the data.
1519    * @param size    Size of the buffer in bytes.
1520    *
1521    * @return  0 if size is non-zero and buffer is null. Otherwise,
1522    *          returns a valid File object.
1523    */
CreateMemoryFile(const void * buffer,int size)1524   inline File* CreateMemoryFile(const void* buffer, int size) {
1525     return hidden::AdrCreateMemoryFile(buffer, size);
1526   }
1527 
1528   /**
1529    * Generates a list of available CD device names.
1530    *
1531    * @param devices A vector of strings to be filled.
1532    */
EnumerateCDDevices(std::vector<std::string> & devices)1533   inline void EnumerateCDDevices(std::vector<std::string>& devices) {
1534     const char* d = hidden::AdrEnumerateCDDevices();
1535     while (d && *d) {
1536       devices.push_back(d);
1537       d += strlen(d) + 1;
1538     }
1539   }
1540 
1541   /**
1542    * Opens the specified CD playback device.
1543    *
1544    * @param device  The filesystem device to be played.
1545    *                e.g. Linux: "/dev/cdrom", Windows: "D:"
1546    *
1547    * @return  0 if opening device failed, valid CDDrive object otherwise.
1548    */
OpenCDDevice(const char * device)1549   inline CDDevice* OpenCDDevice(const char* device) {
1550     return hidden::AdrOpenCDDevice(device);
1551   }
1552 
1553   /**
1554    * Opens the specified MIDI synthesizer device.
1555    *
1556    * @param device  The name of the device.  Unused for now.
1557    *
1558    * @return  0 if opening device failed, valid MIDIDevice object otherwise.
1559    */
OpenMIDIDevice(const char * device)1560   inline MIDIDevice* OpenMIDIDevice(const char* device) {
1561     return hidden::AdrOpenMIDIDevice(device);
1562   }
1563 
1564 }
1565 
1566 
1567 #endif
1568