2009-11-13 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / src / audio.h
blob753b3995f4a5325653cc88825a110586cadffa6c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * audio.h:
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
14 #ifndef __AUDIO_H__
15 #define __AUDIO_H__
17 class AudioStream;
18 class MediaPlayer;
19 class MediaFrame;
21 class AudioSource;
22 class AudioSources;
23 class AudioPlayer;
25 #include "dependencyobject.h"
26 #include "pipeline.h"
28 // uncomment to dump raw audio data to /tmp.
29 // the exact command to play the raw audio file will be printed to stdout
30 // #define DUMP_AUDIO
32 enum AudioFlags {
33 // The AudioSource has been initialized correctly.
34 // This flag is removed if SetState (AudioError) is called.
35 AudioInitialized = 1 << 0,
36 // The audio source has run out of data to write (the last frame had FrameEventEOF set).
37 // There still may be samples in the pipeline somewhere causing audio to be played.
38 // This flag is removed when AppendFrame is called.
39 AudioEOF = 1 << 1,
40 // The audio source has run out of data to write, and is waiting for more.
41 // There still may be samples in the pipeline somewhere causing audio to be played.
42 // This flag is removed when AppendFrame is called.
43 AudioWaiting = 1 << 2,
44 // The audio source has run out of data to write and has played all available samples.
45 // This flag is removed when Play/Pause/Stop/AppendFrame is called.
46 AudioEnded = 1 << 3,
49 enum AudioState {
50 AudioNone, // Initial state.
51 AudioError, // An error has occured.
52 AudioPlaying, // Play has been called
53 AudioPaused, // Pause has been called
54 AudioStopped, // Stop has been called (or we've played all the available data).
57 struct AudioData {
58 void *dest; // Audio samples
59 gint32 distance; // The distance between samples (in bytes)
62 // All AudioSource's public methods must be safe to call from any thread.
63 class AudioSource : public EventObject {
64 private:
65 struct AudioFrame {
66 MediaFrame *frame;
67 guint32 bytes_used;
68 AudioFrame (MediaFrame *frame);
69 ~AudioFrame ();
72 MediaPlayer *mplayer;
73 AudioStream *stream;
74 AudioPlayer *player;
75 AudioFrame *current_frame;
76 AudioState state;
77 AudioFlags flags;
79 double balance;
80 double volume;
81 bool muted;
83 guint64 last_write_pts; // The last pts written
84 guint64 last_current_pts; // The last value returned from GetCurrentPts
86 guint32 channels; // The number of channels
87 guint32 sample_rate; // The sample rate in the audio source
88 guint32 input_bytes_per_sample; // The number of bytes per sample
89 guint32 output_bytes_per_sample; // The number of bytes per sample in the output. Defaults to same as input_bytes_per_sample.
91 pthread_mutex_t mutex;
93 void Lock ();
94 void Unlock ();
96 MediaPlayer *GetMediaPlayerReffed ();
98 EVENTHANDLER (AudioSource, FirstFrameEnqueued, EventObject, EventArgs);
100 #ifdef DUMP_AUDIO
101 FILE *dump_fd;
102 #endif
104 protected:
105 AudioSource (AudioPlayer *player, MediaPlayer *mplayer, AudioStream *stream);
106 virtual ~AudioSource ();
108 // Writes frames to the specified destination
109 // Returns the number of frames actually written
110 // frame: consists of 1 audio sample of input_bytes_per_sample bytes * number of channels
111 guint32 Write (void *dest, guint32 samples);
112 guint32 WriteFull (AudioData **channel_data /* Array of info about channels, NULL ended. */, guint32 samples);
114 virtual void Played () { }
115 virtual void Paused () { }
116 virtual void Stopped () { }
118 // The deriving class must call this method when it has finished playing
119 // all the written samples.
120 void Underflowed ();
122 // Called whenever the state changes
123 virtual void StateChanged (AudioState old_state) {}
125 // Must return the time difference between the last written sample
126 // and what the audio hw is playing now (in pts).
127 // This method will only be called if GetState () == AudioPlaying
128 // Must return G_MAXUINT64 in case of any errors.
129 virtual guint64 GetDelayInternal () = 0;
131 virtual bool InitializeInternal () { return true; }
133 // There's no guarantee CloseInternal won't be called more than once.
134 virtual void CloseInternal () {};
136 public:
137 virtual void Dispose ();
139 void Play ();
140 void Pause ();
141 void Stop ();
142 guint64 GetDelay ();
144 // Initialize(Internal) is called before adding the source to the list of sources
145 // If Initialize fails (returns false), the source is not added to the list of sources.
146 bool Initialize ();
148 // Close(Internal) is called after removing the source from the list of sources
149 void Close ();
151 // This method may return G_MAXUINT64 if it has no idea which is the current pts.
152 // This may happen if nothing has been done yet (the derived audio source hasn't
153 // requested any writes).
154 guint64 GetCurrentPts ();
155 guint32 GetInputBytesPerFrame ();
156 guint32 GetOutputBytesPerFrame ();
157 guint32 GetInputBytesPerSample ();
158 guint32 GetOutputBytesPerSample ();
160 /* This method must only be called during initilization so that output_bytes_per_sample is thread-safe without locking */
161 void SetOutputBytesPerSample (guint32 value);
163 AudioStream *GetStreamReffed ();
164 bool IsQueueEmpty ();
166 AudioState GetState ();
167 void SetState (AudioState value);
168 static const char *GetStateName (AudioState state);
170 void SetFlag (AudioFlags, bool value);
171 bool GetFlag (AudioFlags flag);
173 #if DEBUG
174 static char *GetFlagNames (AudioFlags flags);
175 #endif
177 guint32 GetChannels ();
178 guint32 GetSampleRate ();
180 double GetBalance ();
181 void SetBalance (double value);
183 double GetVolume ();
184 void SetVolume (double value);
186 bool GetMuted ();
187 void SetMuted (bool value);
189 void SetAudioStream (AudioStream *value);
190 AudioStream *GetAudioStream ();
192 bool IsPlaying () { return GetState () == AudioPlaying && !GetFlag (AudioWaiting); }
194 virtual const char *GetTypeName () { return "AudioSource"; }
197 class AudioListNode : public List::Node {
198 public:
199 AudioSource *source;
200 gint32 generation;
202 AudioListNode (AudioSource *source);
203 virtual ~AudioListNode ();
206 class AudioSources {
207 pthread_mutex_t mutex;
208 List list;
209 gint32 current_generation;
210 AudioListNode *last_node; // The last node returned by GetNext.
212 void Lock ();
213 void Unlock ();
215 public:
216 AudioSources ();
217 ~AudioSources ();
219 void Add (AudioSource *node);
220 // Returns true if the node existed in the list
221 bool Remove (AudioSource *node);
223 // Enumerating all sources:
224 // First call StartEnumeration, then call GetNext until NULL is returned.
225 // Only one enumeration can be going at the same time, otherwise they'll
226 // interfere with eachother.
227 // GetNext returns the AudioSource reffed, the caller must unref.
228 void StartEnumeration ();
229 AudioSource *GetNext (bool only_playing);
231 // Returns the first AudioSource in the list (reffed, the caller must unref)
232 // Returns NULL if the list is empty.
233 AudioSource *GetHead ();
234 #if DEBUG
235 int Length ();
236 #endif
239 class AudioPlayer {
240 // our AudioPlayer instance
241 static AudioPlayer *instance;
242 static pthread_mutex_t instance_mutex;
244 static AudioPlayer *CreatePlayer ();
247 AudioSource *AddImpl (MediaPlayer *mplayer, AudioStream *stream);
248 void RemoveImpl (AudioSource *node);
249 void ShutdownImpl ();
251 static AudioPlayer *GetInstance ();
254 * We use our own refcounting here, since we can't derive from EventObject
255 * (which is always a per deployment object, while AudioPlayer is per-process).
256 * As with EventObject, the AudioPlayer will be deleted once refcount reaches 0.
258 gint32 refcount;
259 void ref ();
260 void unref ();
262 protected:
263 // The list of all the audio sources.
264 // This is protected so that derived classes can enumerate the sources,
265 // derived classes must not add/remove sources.
266 AudioSources sources;
268 AudioPlayer ();
269 virtual ~AudioPlayer () {}
270 virtual void Dispose ();
272 // called after the node has been created and added to the list of sources
273 virtual void AddInternal (AudioSource *node) = 0;
274 // called after the node has been removed from the list of sources, but before the node is deleted.
275 // not called if the node isn't in the list of sources.
276 virtual void RemoveInternal (AudioSource *node) = 0;
277 // called just after ctor.
278 virtual bool Initialize () = 0;
279 // before all the nodes will be removedthis method is called
280 // to ensure that we have stopped the play loop
281 virtual void PrepareShutdownInternal () = 0;
282 // all the nodes will have been removed when this method is called
283 // after this call has returned, the player will be deleted immediately.
284 virtual void FinishShutdownInternal () = 0;
285 // Must return a new AudioSource specific for each backend.
286 virtual AudioSource *CreateNode (MediaPlayer *mplayer, AudioStream *stream) = 0;
288 public:
289 // Creates a audio source from the MediaPlayer and AudioStream.
290 // Returns NULL if there were any errors.
291 // Note: Actually returning an object doesn't mean audio will be played.
292 // some backends are async and will only cause an error to be raised
293 // later (in which case the AudioSource's state would be AudioError)
294 static AudioSource *Add (MediaPlayer *mplayer, AudioStream *stream);
295 // Removes an audio source.
296 static void Remove (AudioSource *source);
297 // Shuts down the audio engine
298 static void Shutdown ();
301 #endif /* __AUDIO_H__ */