revert previous commit
[moon.git] / src / audio.h
blob02acf8a3cf382e68c010ebbe5f2ea1587a0eaf03
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"
27 #include "mutex.h"
29 // uncomment to dump raw audio data to /tmp.
30 // the exact command to play the raw audio file will be printed to stdout
31 // #define DUMP_AUDIO
33 enum AudioFlags {
34 // The AudioSource has been initialized correctly.
35 // This flag is removed if SetState (AudioError) is called.
36 AudioInitialized = 1 << 0,
37 // The audio source has run out of data to write (the last frame had FrameEventEOF set).
38 // There still may be samples in the pipeline somewhere causing audio to be played.
39 // This flag is removed when AppendFrame is called.
40 AudioEOF = 1 << 1,
41 // The audio source has run out of data to write, and is waiting for more.
42 // There still may be samples in the pipeline somewhere causing audio to be played.
43 // This flag is removed when AppendFrame is called.
44 AudioWaiting = 1 << 2,
45 // The audio source has run out of data to write and has played all available samples.
46 // This flag is removed when Play/Pause/Stop/AppendFrame is called.
47 AudioEnded = 1 << 3,
50 enum AudioState {
51 AudioNone, // Initial state.
52 AudioError, // An error has occured.
53 AudioPlaying, // Play has been called
54 AudioPaused, // Pause has been called
55 AudioStopped, // Stop has been called (or we've played all the available data).
58 struct AudioData {
59 void *dest; // Audio samples
60 gint32 distance; // The distance between samples (in bytes)
63 // All AudioSource's public methods must be safe to call from any thread.
64 class AudioSource : public EventObject {
65 private:
66 struct AudioFrame {
67 MediaFrame *frame;
68 guint32 bytes_used;
69 AudioFrame (MediaFrame *frame);
70 ~AudioFrame ();
73 MediaPlayer *mplayer;
74 AudioStream *stream;
75 AudioPlayer *player;
76 AudioFrame *current_frame;
77 AudioState state;
78 AudioFlags flags;
80 double balance;
81 double volume;
82 bool muted;
84 guint64 last_write_pts; // The last pts written
85 guint64 last_current_pts; // The last value returned from GetCurrentPts
87 guint32 channels; // The number of channels
88 guint32 sample_rate; // The sample rate in the audio source
89 guint32 input_bytes_per_sample; // The number of bytes per sample
90 guint32 output_bytes_per_sample; // The number of bytes per sample in the output. Defaults to same as input_bytes_per_sample.
92 Mutex mutex;
94 void Lock ();
95 void Unlock ();
97 MediaPlayer *GetMediaPlayerReffed ();
99 EVENTHANDLER (AudioSource, FirstFrameEnqueued, EventObject, EventArgs);
101 #ifdef DUMP_AUDIO
102 FILE *dump_fd;
103 #endif
105 protected:
106 AudioSource (Type::Kind type, AudioPlayer *player, MediaPlayer *mplayer, AudioStream *stream);
107 virtual ~AudioSource ();
109 // Writes frames to the specified destination
110 // Returns the number of frames actually written
111 // frame: consists of 1 audio sample of input_bytes_per_sample bytes * number of channels
112 guint32 Write (void *dest, guint32 samples);
113 guint32 WriteFull (AudioData **channel_data /* Array of info about channels, NULL ended. */, guint32 samples);
115 virtual void Played () { }
116 virtual void Paused () { }
117 virtual void Stopped () { }
119 // The deriving class must call this method when it has finished playing
120 // all the written samples.
121 void Underflowed ();
123 // Called whenever the state changes
124 virtual void StateChanged (AudioState old_state) {}
126 // Must return the time difference between the last written sample
127 // and what the audio hw is playing now (in pts).
128 // This method will only be called if GetState () == AudioPlaying
129 // Must return G_MAXUINT64 in case of any errors.
130 virtual guint64 GetDelayInternal () = 0;
132 virtual bool InitializeInternal () { return true; }
134 // There's no guarantee CloseInternal won't be called more than once.
135 virtual void CloseInternal () {};
137 public:
138 virtual void Dispose ();
140 void Play ();
141 void Pause ();
142 void Stop ();
143 guint64 GetDelay ();
145 // Initialize(Internal) is called before adding the source to the list of sources
146 // If Initialize fails (returns false), the source is not added to the list of sources.
147 bool Initialize ();
149 // Close(Internal) is called after removing the source from the list of sources
150 void Close ();
152 // This method may return G_MAXUINT64 if it has no idea which is the current pts.
153 // This may happen if nothing has been done yet (the derived audio source hasn't
154 // requested any writes).
155 guint64 GetCurrentPts ();
156 guint32 GetInputBytesPerFrame ();
157 guint32 GetOutputBytesPerFrame ();
158 guint32 GetInputBytesPerSample ();
159 guint32 GetOutputBytesPerSample ();
161 /* This method must only be called during initilization so that output_bytes_per_sample is thread-safe without locking */
162 void SetOutputBytesPerSample (guint32 value);
164 AudioStream *GetStreamReffed ();
165 bool IsQueueEmpty ();
167 AudioState GetState ();
168 void SetState (AudioState value);
169 static const char *GetStateName (AudioState state);
171 void SetFlag (AudioFlags, bool value);
172 bool GetFlag (AudioFlags flag);
174 #if LOGGING
175 static char *GetFlagNames (AudioFlags flags);
176 #endif
178 guint32 GetChannels ();
179 guint32 GetSampleRate ();
181 double GetBalance ();
182 void SetBalance (double value);
184 double GetVolume ();
185 void SetVolume (double value);
187 bool GetMuted ();
188 void SetMuted (bool value);
190 void SetAudioStream (AudioStream *value);
191 AudioStream *GetAudioStream ();
193 bool IsPlaying () { return GetState () == AudioPlaying && !GetFlag (AudioWaiting); }
195 virtual const char *GetTypeName () { return "AudioSource"; }
198 class AudioListNode : public List::Node {
199 public:
200 AudioSource *source;
201 gint32 generation;
203 AudioListNode (AudioSource *source);
204 virtual ~AudioListNode ();
207 class AudioSources {
208 pthread_mutex_t mutex;
209 List list;
210 gint32 current_generation;
211 AudioListNode *last_node; // The last node returned by GetNext.
213 void Lock ();
214 void Unlock ();
216 public:
217 AudioSources ();
218 ~AudioSources ();
220 void Add (AudioSource *node);
221 // Returns true if the node existed in the list
222 bool Remove (AudioSource *node);
224 // Enumerating all sources:
225 // First call StartEnumeration, then call GetNext until NULL is returned.
226 // Only one enumeration can be going at the same time, otherwise they'll
227 // interfere with eachother.
228 // GetNext returns the AudioSource reffed, the caller must unref.
229 void StartEnumeration ();
230 AudioSource *GetNext (bool only_playing);
232 // Returns the first AudioSource in the list (reffed, the caller must unref)
233 // Returns NULL if the list is empty.
234 AudioSource *GetHead ();
235 #if DEBUG
236 int Length ();
237 #endif
240 class AudioPlayer {
241 // our AudioPlayer instance
242 static AudioPlayer *instance;
243 static pthread_mutex_t instance_mutex;
245 static AudioPlayer *CreatePlayer ();
248 AudioSource *AddImpl (MediaPlayer *mplayer, AudioStream *stream);
249 void RemoveImpl (AudioSource *node);
250 void ShutdownImpl ();
252 static AudioPlayer *GetInstance ();
255 * We use our own refcounting here, since we can't derive from EventObject
256 * (which is always a per deployment object, while AudioPlayer is per-process).
257 * As with EventObject, the AudioPlayer will be deleted once refcount reaches 0.
259 gint32 refcount;
260 void ref ();
261 void unref ();
263 protected:
264 // The list of all the audio sources.
265 // This is protected so that derived classes can enumerate the sources,
266 // derived classes must not add/remove sources.
267 AudioSources sources;
269 AudioPlayer ();
270 virtual ~AudioPlayer () {}
271 virtual void Dispose ();
273 // called after the node has been created and added to the list of sources
274 virtual void AddInternal (AudioSource *node) = 0;
275 // called after the node has been removed from the list of sources, but before the node is deleted.
276 // not called if the node isn't in the list of sources.
277 virtual void RemoveInternal (AudioSource *node) = 0;
278 // called just after ctor.
279 virtual bool Initialize () = 0;
280 // before all the nodes will be removedthis method is called
281 // to ensure that we have stopped the play loop
282 virtual void PrepareShutdownInternal () = 0;
283 // all the nodes will have been removed when this method is called
284 // after this call has returned, the player will be deleted immediately.
285 virtual void FinishShutdownInternal () = 0;
286 // Must return a new AudioSource specific for each backend.
287 virtual AudioSource *CreateNode (MediaPlayer *mplayer, AudioStream *stream) = 0;
289 public:
290 // Creates a audio source from the MediaPlayer and AudioStream.
291 // Returns NULL if there were any errors.
292 // Note: Actually returning an object doesn't mean audio will be played.
293 // some backends are async and will only cause an error to be raised
294 // later (in which case the AudioSource's state would be AudioError)
295 static AudioSource *Add (MediaPlayer *mplayer, AudioStream *stream);
296 // Removes an audio source.
297 static void Remove (AudioSource *source);
298 // Shuts down the audio engine
299 static void Shutdown ();
302 #endif /* __AUDIO_H__ */