KCompactDisc

audio_phonon.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2006 Alexander Kern <alex.kern@gmx.de>
3
4 based on example for Phonon Architecture, Matthias Kretz <kretz@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License version 2 as published by the Free Software Foundation.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "audio_phonon.h"
22#include "audio.h"
23
24#include <QDataStream>
25
26#include <phonon/audiooutput.h>
27#include <phonon/audiopath.h>
28#include <phonon/mediaobject.h>
29
30LibWMPcmPlayer::LibWMPcmPlayer() : AbstractMediaStream(NULL),
31 m_media(NULL),
32 m_cmd(WM_CDM_UNKNOWN),
33 m_blk(NULL)
34{
35 Phonon::AudioOutput* m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
36 Phonon::AudioPath* m_path = new Phonon::AudioPath(this);
37 m_path->addOutput(m_output);
38 m_media = new Phonon::MediaObject(this);
39 m_media->addAudioPath(m_path);
40 m_media->setCurrentSource(this);
41 setStreamSeekable(false);
42 setStreamSize(0xffffffff);
43
44 connect(this, SIGNAL(cmdChanged(int)), this, SLOT(executeCmd(int)));
45 connect(this, SIGNAL(nextBuffer(cdda_block*)), this, SLOT(playBuffer(cdda_block*)));
46 connect(m_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
47 this, SLOT(stateChanged(Phonon::State,Phonon::State)));
48
49 DEBUGLOG("writeHeader\n");
50 writeData( wavHeader() );
51 DEBUGLOG("writeHeader end\n");
52}
53
54LibWMPcmPlayer::~LibWMPcmPlayer()
55{
56 stop();
57}
58
59QByteArray LibWMPcmPlayer::wavHeader() const
60{
61 QByteArray data;
62 QDataStream stream( &data, QIODevice::WriteOnly );
63 stream.setByteOrder( QDataStream::LittleEndian );
64 stream
65 << 0x46464952 //"RIFF"
66 << static_cast<quint32>( 0x7FFFFFFF )
67 << 0x45564157 //"WAVE"
68 << 0x20746D66 //"fmt " //Subchunk1ID
69 << static_cast<quint32>( 16 ) //Subchunk1Size
70 << static_cast<quint16>( 1 ) //AudioFormat
71 << static_cast<quint16>( 2 ) //NumChannels
72 << static_cast<quint32>( 44100 ) //SampleRate
73 << static_cast<quint32>( 2*2*44100 )//ByteRate
74 << static_cast<quint16>( 2*2 ) //BlockAlign
75 << static_cast<quint16>( 16 ) //BitsPerSample
76 << 0x61746164 //"data" //Subchunk2ID
77 << static_cast<quint32>( 0x7FFFFFFF-36 )//Subchunk2Size
78 ;
79
80 return data;
81}
82
83void LibWMPcmPlayer::reset()
84{
85 setStreamSeekable(false);
86 setStreamSize(0xffffffff);
87 DEBUGLOG("writeHeader\n");
88 writeData( wavHeader() );
89 DEBUGLOG("writeHeader end\n");
90}
91
92void LibWMPcmPlayer::needData()
93{
94 DEBUGLOG("needData\n");
95 m_mutex.lock();
96 m_readyToPlay.wakeAll();
97 m_mutex.unlock();
98
99}
100
101void LibWMPcmPlayer::setNextBuffer(struct cdda_block *blk)
102{
103 Q_EMIT nextBuffer(blk);
104 m_mutex.lock();
105 m_readyToPlay.wait(&m_mutex);
106 m_mutex.unlock();
107}
108
109void LibWMPcmPlayer::playBuffer(struct cdda_block *blk)
110{
111 if(m_cmd != WM_CDM_PLAYING) {
112 Q_EMIT cmdChanged(WM_CDM_PLAYING);
113 m_cmd = WM_CDM_PLAYING;
114 }
115 writeData(QByteArray(blk->buf, blk->buflen));
116
117}
118
119void LibWMPcmPlayer::pause(void)
120{
121 if(m_cmd != WM_CDM_PAUSED) {
122 Q_EMIT cmdChanged(WM_CDM_PAUSED);
123 m_cmd = WM_CDM_PAUSED;
124
125 m_readyToPlay.wakeAll();
126 }
127}
128
129void LibWMPcmPlayer::stop(void)
130{
131 if(m_cmd != WM_CDM_STOPPED) {
132 Q_EMIT cmdChanged(WM_CDM_STOPPED);
133 m_cmd = WM_CDM_STOPPED;
134
135 m_readyToPlay.wakeAll();
136 }
137}
138
139void LibWMPcmPlayer::executeCmd(int cmd)
140{
141 switch(cmd) {
142 case WM_CDM_PLAYING:
143DEBUGLOG("set play\n");
144 m_media->play();
145 break;
146 case WM_CDM_PAUSED:
147DEBUGLOG("set pause\n");
148 m_media->pause();
149 break;
150 case WM_CDM_STOPPED:
151DEBUGLOG("set stop\n");
152 m_media->stop();
153 break;
154 default:
155 cmd = WM_CDM_STOPPED;
156 break;
157 }
158}
159
160void LibWMPcmPlayer::stateChanged( Phonon::State newstate, Phonon::State oldstate )
161{
162 DEBUGLOG("stateChanged from %i to %i\n", oldstate, newstate);
163}
164
165static LibWMPcmPlayer *PhononObject = NULL;
166
167int phonon_open(void)
168{
169 DEBUGLOG("phonon_open\n");
170
171 if(PhononObject) {
172 ERRORLOG("Already initialized!\n");
173 return -1;
174 }
175
176 PhononObject = new LibWMPcmPlayer();
177
178 return 0;
179}
180
181int phonon_close(void)
182{
183 DEBUGLOG("phonon_close\n");
184
185 if(!PhononObject) {
186 ERRORLOG("Unable to close\n");
187 return -1;
188 }
189
190 delete PhononObject;
191
192 PhononObject = NULL;
193
194 return 0;
195}
196
197/*
198 * Play some audio and pass a status message upstream, if applicable.
199 * Returns 0 on success.
200 */
201int
202phonon_play(struct cdda_block *blk)
203{
204 DEBUGLOG("phonon_play %ld samples, frame %i\n",
205 blk->buflen / (2 * 2), blk->frame);
206
207 if(!PhononObject) {
208 ERRORLOG("Unable to play\n");
209 blk->status = WM_CDM_CDDAERROR;
210 return -1;
211 }
212
213 PhononObject->setNextBuffer(blk);
214
215 return 0;
216}
217
218/*
219 * Pause the audio immediately.
220 */
221int
222phonon_pause(void)
223{
224 DEBUGLOG("phonon_pause\n");
225
226 if(!PhononObject) {
227 ERRORLOG("Unable to pause\n");
228 return -1;
229 }
230
231 PhononObject->pause();
232
233 return 0;
234}
235
236/*
237 * Stop the audio immediately.
238 */
239int
240phonon_stop(void)
241{
242 DEBUGLOG("phonon_stop\n");
243
244 if(!PhononObject) {
245 ERRORLOG("Unable to stop\n");
246 return -1;
247 }
248
249 PhononObject->stop();
250
251 return 0;
252}
253
254/*
255 * Get the current audio state.
256 */
257int
258phonon_state(struct cdda_block *blk)
259{
260 DEBUGLOG("phonon_state\n");
261
262 return -1; /* not implemented yet for PHONON */
263}
264
265static struct audio_oops phonon_oops = {
266 phonon_open,
267 phonon_close,
268 phonon_play,
269 phonon_pause,
270 phonon_stop,
271 phonon_state,
272 NULL,
273 NULL
274};
275
276extern "C" struct audio_oops*
277setup_phonon(const char *dev, const char *ctl)
278{
279 DEBUGLOG("setup_phonon\n");
280
281 phonon_open();
282
283 return &phonon_oops;
284}
285
286#include "audio_phonon.moc"
287#include "moc_audio_phonon.cpp"
void writeData(const QByteArray &data)
void lock()
void unlock()
Q_EMITQ_EMIT
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool wait(QMutex *lockedMutex, QDeadlineTimer deadline)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:26 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.