1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
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.
25 #include "dependencyobject.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
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.
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.
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).
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
{
68 AudioFrame (MediaFrame
*frame
);
75 AudioFrame
*current_frame
;
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
;
96 EVENTHANDLER (AudioSource
, FirstFrameEnqueued
, EventObject
, EventArgs
);
103 AudioSource (AudioPlayer
*player
, MediaPlayer
*mplayer
, AudioStream
*stream
);
104 virtual ~AudioSource ();
106 // Writes frames to the specified destination
107 // Returns the number of frames actually written
108 // frame: consists of 1 audio sample of input_bytes_per_sample bytes * number of channels
109 guint32
Write (void *dest
, guint32 samples
);
110 guint32
WriteFull (AudioData
**channel_data
/* Array of info about channels, NULL ended. */, guint32 samples
);
112 virtual void Played () { }
113 virtual void Paused () { }
114 virtual void Stopped () { }
116 // The deriving class must call this method when it has finished playing
117 // all the written samples.
120 // Called whenever the state changes
121 virtual void StateChanged (AudioState old_state
) {}
123 // Must return the time difference between the last written sample
124 // and what the audio hw is playing now (in pts).
125 // This method will only be called if GetState () == AudioPlaying
126 // Must return G_MAXUINT64 in case of any errors.
127 virtual guint64
GetDelayInternal () = 0;
129 virtual bool InitializeInternal () { return true; }
131 // There's no guarantee CloseInternal won't be called more than once.
132 virtual void CloseInternal () {};
135 virtual void Dispose ();
142 // Initialize(Internal) is called before adding the source to the list of sources
143 // If Initialize fails (returns false), the source is not added to the list of sources.
146 // Close(Internal) is called after removing the source from the list of sources
149 // This method may return G_MAXUINT64 if it has no idea which is the current pts.
150 // This may happen if nothing has been done yet (the derived audio source hasn't
151 // requested any writes).
152 guint64
GetCurrentPts ();
153 guint32
GetInputBytesPerFrame ();
154 guint32
GetOutputBytesPerFrame ();
155 guint32
GetInputBytesPerSample ();
156 guint32
GetOutputBytesPerSample ();
158 /* This method must only be called during initilization so that output_bytes_per_sample is thread-safe without locking */
159 void SetOutputBytesPerSample (guint32 value
);
161 AudioStream
*GetStreamReffed ();
162 bool IsQueueEmpty ();
164 AudioState
GetState ();
165 void SetState (AudioState value
);
166 static const char *GetStateName (AudioState state
);
168 void SetFlag (AudioFlags
, bool value
);
169 bool GetFlag (AudioFlags flag
);
172 static char *GetFlagNames (AudioFlags flags
);
175 guint32
GetChannels ();
176 guint32
GetSampleRate ();
178 double GetBalance ();
179 void SetBalance (double value
);
182 void SetVolume (double value
);
185 void SetMuted (bool value
);
187 void SetAudioStream (AudioStream
*value
);
188 AudioStream
*GetAudioStream ();
190 bool IsPlaying () { return GetState () == AudioPlaying
&& !GetFlag (AudioWaiting
); }
192 virtual const char *GetTypeName () { return "AudioSource"; }
195 class AudioListNode
: public List::Node
{
200 AudioListNode (AudioSource
*source
);
201 virtual ~AudioListNode ();
205 pthread_mutex_t mutex
;
207 gint32 current_generation
;
208 AudioListNode
*last_node
; // The last node returned by GetNext.
217 void Add (AudioSource
*node
);
218 // Returns true if the node existed in the list
219 bool Remove (AudioSource
*node
);
221 // Enumerating all sources:
222 // First call StartEnumeration, then call GetNext until NULL is returned.
223 // Only one enumeration can be going at the same time, otherwise they'll
224 // interfere with eachother.
225 // GetNext returns the AudioSource reffed, the caller must unref.
226 void StartEnumeration ();
227 AudioSource
*GetNext (bool only_playing
);
229 // Returns the first AudioSource in the list (reffed, the caller must unref)
230 // Returns NULL if the list is empty.
231 AudioSource
*GetHead ();
238 // our AudioPlayer instance
239 static AudioPlayer
*instance
;
240 static pthread_mutex_t instance_mutex
;
242 static AudioPlayer
*CreatePlayer ();
245 AudioSource
*AddImpl (MediaPlayer
*mplayer
, AudioStream
*stream
);
246 void RemoveImpl (AudioSource
*node
);
247 void ShutdownImpl ();
250 // The list of all the audio sources.
251 // This is protected so that derived classes can enumerate the sources,
252 // derived classes must not add/remove sources.
253 AudioSources sources
;
256 virtual ~AudioPlayer () {}
258 // called after the node has been created and added to the list of sources
259 virtual void AddInternal (AudioSource
*node
) = 0;
260 // called after the node has been removed from the list of sources, but before the node is deleted.
261 // not called if the node isn't in the list of sources.
262 virtual void RemoveInternal (AudioSource
*node
) = 0;
263 // called just after ctor.
264 virtual bool Initialize () = 0;
265 // before all the nodes will be removedthis method is called
266 // to ensure that we have stopped the play loop
267 virtual void PrepareShutdownInternal () = 0;
268 // all the nodes will have been removed when this method is called
269 // after this call has returned, the player will be deleted immediately.
270 virtual void FinishShutdownInternal () = 0;
271 // Must return a new AudioSource specific for each backend.
272 virtual AudioSource
*CreateNode (MediaPlayer
*mplayer
, AudioStream
*stream
) = 0;
275 // Creates a audio source from the MediaPlayer and AudioStream.
276 // Returns NULL if there were any errors.
277 // Note: Actually returning an object doesn't mean audio will be played.
278 // some backends are async and will only cause an error to be raised
279 // later (in which case the AudioSource's state would be AudioError)
280 static AudioSource
*Add (MediaPlayer
*mplayer
, AudioStream
*stream
);
281 // Removes an audio source.
282 static void Remove (AudioSource
*source
);
283 // Shuts down the audio engine
284 static void Shutdown ();
287 #endif /* __AUDIO_H__ */