KCompactDisc

audio_phonon.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2006 Alexander Kern <[email protected]>
3 
4  based on example for Phonon Architecture, Matthias Kretz <[email protected]>
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 <QByteArray>
25 #include <QDataStream>
26 #include <QTimer>
27 #include <QWaitCondition>
28 #include <QMutex>
29 
30 #include <phonon/audiooutput.h>
31 #include <phonon/audiopath.h>
32 #include <phonon/mediaobject.h>
33 
34 LibWMPcmPlayer::LibWMPcmPlayer() : AbstractMediaStream(NULL),
35  m_media(NULL),
36  m_cmd(WM_CDM_UNKNOWN),
37  m_blk(NULL)
38 {
39  Phonon::AudioOutput* m_output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
40  Phonon::AudioPath* m_path = new Phonon::AudioPath(this);
41  m_path->addOutput(m_output);
42  m_media = new Phonon::MediaObject(this);
43  m_media->addAudioPath(m_path);
44  m_media->setCurrentSource(this);
45  setStreamSeekable(false);
46  setStreamSize(0xffffffff);
47 
48  connect(this, SIGNAL(cmdChanged(int)), this, SLOT(executeCmd(int)));
49  connect(this, SIGNAL(nextBuffer(cdda_block*)), this, SLOT(playBuffer(cdda_block*)));
50  connect(m_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
51  this, SLOT(stateChanged(Phonon::State,Phonon::State)));
52 
53  DEBUGLOG("writeHeader\n");
54  writeData( wavHeader() );
55  DEBUGLOG("writeHeader end\n");
56 }
57 
58 LibWMPcmPlayer::~LibWMPcmPlayer()
59 {
60  stop();
61 }
62 
63 QByteArray LibWMPcmPlayer::wavHeader() const
64 {
65  QByteArray data;
66  QDataStream stream( &data, QIODevice::WriteOnly );
67  stream.setByteOrder( QDataStream::LittleEndian );
68  stream
69  << 0x46464952 //"RIFF"
70  << static_cast<quint32>( 0x7FFFFFFF )
71  << 0x45564157 //"WAVE"
72  << 0x20746D66 //"fmt " //Subchunk1ID
73  << static_cast<quint32>( 16 ) //Subchunk1Size
74  << static_cast<quint16>( 1 ) //AudioFormat
75  << static_cast<quint16>( 2 ) //NumChannels
76  << static_cast<quint32>( 44100 ) //SampleRate
77  << static_cast<quint32>( 2*2*44100 )//ByteRate
78  << static_cast<quint16>( 2*2 ) //BlockAlign
79  << static_cast<quint16>( 16 ) //BitsPerSample
80  << 0x61746164 //"data" //Subchunk2ID
81  << static_cast<quint32>( 0x7FFFFFFF-36 )//Subchunk2Size
82  ;
83 
84  return data;
85 }
86 
87 void LibWMPcmPlayer::reset()
88 {
89  setStreamSeekable(false);
90  setStreamSize(0xffffffff);
91  DEBUGLOG("writeHeader\n");
92  writeData( wavHeader() );
93  DEBUGLOG("writeHeader end\n");
94 }
95 
96 void LibWMPcmPlayer::needData()
97 {
98  DEBUGLOG("needData\n");
99  m_mutex.lock();
100  m_readyToPlay.wakeAll();
101  m_mutex.unlock();
102 
103 }
104 
105 void LibWMPcmPlayer::setNextBuffer(struct cdda_block *blk)
106 {
107  Q_EMIT nextBuffer(blk);
108  m_mutex.lock();
109  m_readyToPlay.wait(&m_mutex);
110  m_mutex.unlock();
111 }
112 
113 void LibWMPcmPlayer::playBuffer(struct cdda_block *blk)
114 {
115  if(m_cmd != WM_CDM_PLAYING) {
116  Q_EMIT cmdChanged(WM_CDM_PLAYING);
117  m_cmd = WM_CDM_PLAYING;
118  }
119  writeData(QByteArray(blk->buf, blk->buflen));
120 
121 }
122 
123 void LibWMPcmPlayer::pause(void)
124 {
125  if(m_cmd != WM_CDM_PAUSED) {
126  Q_EMIT cmdChanged(WM_CDM_PAUSED);
127  m_cmd = WM_CDM_PAUSED;
128 
129  m_readyToPlay.wakeAll();
130  }
131 }
132 
133 void LibWMPcmPlayer::stop(void)
134 {
135  if(m_cmd != WM_CDM_STOPPED) {
136  Q_EMIT cmdChanged(WM_CDM_STOPPED);
137  m_cmd = WM_CDM_STOPPED;
138 
139  m_readyToPlay.wakeAll();
140  }
141 }
142 
143 void LibWMPcmPlayer::executeCmd(int cmd)
144 {
145  switch(cmd) {
146  case WM_CDM_PLAYING:
147 DEBUGLOG("set play\n");
148  m_media->play();
149  break;
150  case WM_CDM_PAUSED:
151 DEBUGLOG("set pause\n");
152  m_media->pause();
153  break;
154  case WM_CDM_STOPPED:
155 DEBUGLOG("set stop\n");
156  m_media->stop();
157  break;
158  default:
159  cmd = WM_CDM_STOPPED;
160  break;
161  }
162 }
163 
164 void LibWMPcmPlayer::stateChanged( Phonon::State newstate, Phonon::State oldstate )
165 {
166  DEBUGLOG("stateChanged from %i to %i\n", oldstate, newstate);
167 }
168 
169 static LibWMPcmPlayer *PhononObject = NULL;
170 
171 int phonon_open(void)
172 {
173  DEBUGLOG("phonon_open\n");
174 
175  if(PhononObject) {
176  ERRORLOG("Already initialized!\n");
177  return -1;
178  }
179 
180  PhononObject = new LibWMPcmPlayer();
181 
182  return 0;
183 }
184 
185 int phonon_close(void)
186 {
187  DEBUGLOG("phonon_close\n");
188 
189  if(!PhononObject) {
190  ERRORLOG("Unable to close\n");
191  return -1;
192  }
193 
194  delete PhononObject;
195 
196  PhononObject = NULL;
197 
198  return 0;
199 }
200 
201 /*
202  * Play some audio and pass a status message upstream, if applicable.
203  * Returns 0 on success.
204  */
205 int
206 phonon_play(struct cdda_block *blk)
207 {
208  DEBUGLOG("phonon_play %ld samples, frame %i\n",
209  blk->buflen / (2 * 2), blk->frame);
210 
211  if(!PhononObject) {
212  ERRORLOG("Unable to play\n");
213  blk->status = WM_CDM_CDDAERROR;
214  return -1;
215  }
216 
217  PhononObject->setNextBuffer(blk);
218 
219  return 0;
220 }
221 
222 /*
223  * Pause the audio immediately.
224  */
225 int
226 phonon_pause(void)
227 {
228  DEBUGLOG("phonon_pause\n");
229 
230  if(!PhononObject) {
231  ERRORLOG("Unable to pause\n");
232  return -1;
233  }
234 
235  PhononObject->pause();
236 
237  return 0;
238 }
239 
240 /*
241  * Stop the audio immediately.
242  */
243 int
244 phonon_stop(void)
245 {
246  DEBUGLOG("phonon_stop\n");
247 
248  if(!PhononObject) {
249  ERRORLOG("Unable to stop\n");
250  return -1;
251  }
252 
253  PhononObject->stop();
254 
255  return 0;
256 }
257 
258 /*
259  * Get the current audio state.
260  */
261 int
262 phonon_state(struct cdda_block *blk)
263 {
264  DEBUGLOG("phonon_state\n");
265 
266  return -1; /* not implemented yet for PHONON */
267 }
268 
269 static struct audio_oops phonon_oops = {
270  phonon_open,
271  phonon_close,
272  phonon_play,
273  phonon_pause,
274  phonon_stop,
275  phonon_state,
276  NULL,
277  NULL
278 };
279 
280 extern "C" struct audio_oops*
281 setup_phonon(const char *dev, const char *ctl)
282 {
283  DEBUGLOG("setup_phonon\n");
284 
285  phonon_open();
286 
287  return &phonon_oops;
288 }
289 
290 #include "audio_phonon.moc"
KGuiItem stop()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 18 2021 23:23:11 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.