drumstick
0.5.0
Main Page
Related Pages
Modules
Classes
Files
Examples
File List
File Members
playthread.cpp
Go to the documentation of this file.
1
/*
2
MIDI Sequencer C++ library
3
Copyright (C) 2006-2010, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4
5
This library is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
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
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License along
16
with this program; if not, write to the Free Software Foundation, Inc.,
17
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
*/
19
20
#include "
playthread.h
"
21
#include "
alsaclient.h
"
22
#include "
alsaqueue.h
"
23
#include <QReadLocker>
24
#include <QWriteLocker>
25
31
namespace
drumstick {
32
56
const
int
TIMEOUT = 100;
57
63
SequencerOutputThread::SequencerOutputThread
(
MidiClient
*seq,
int
portId)
64
:
QThread
(),
65
m_MidiClient(seq),
66
m_Queue(0),
67
m_PortId(portId),
68
m_Stopped(false),
69
m_QueueId(0),
70
m_npfds(0),
71
m_pfds(0)
72
{
73
if
(
m_MidiClient
!= NULL) {
74
m_Queue
=
m_MidiClient
->
getQueue
();
75
m_QueueId
=
m_Queue
->getId();
76
}
77
}
78
84
bool
85
SequencerOutputThread::stopRequested
()
86
{
87
QReadLocker locker(&
m_mutex
);
88
return
m_Stopped
;
89
}
90
94
void
95
SequencerOutputThread::stop
()
96
{
97
QWriteLocker locker(&
m_mutex
);
98
m_Stopped
=
true
;
99
locker.unlock();
100
while
(isRunning())
101
wait(TIMEOUT);
102
}
103
108
void
109
SequencerOutputThread::sendEchoEvent
(
int
tick)
110
{
111
if
(!
stopRequested
() &&
m_MidiClient
!= NULL) {
112
SystemEvent
ev(SND_SEQ_EVENT_ECHO);
113
ev.
setSource
(
m_PortId
);
114
ev.
setDestination
(
m_MidiClient
->
getClientId
(),
m_PortId
);
115
ev.
scheduleTick
(
m_QueueId
, tick,
false
);
116
sendSongEvent
(&ev);
117
}
118
}
119
124
void
125
SequencerOutputThread::sendSongEvent
(
SequencerEvent
* ev)
126
{
127
if
(
m_MidiClient
!= NULL) {
128
while
(!
stopRequested
() &&
129
(snd_seq_event_output_direct(
m_MidiClient
->
getHandle
(), ev->
getHandle
()) < 0))
130
poll(
m_pfds
,
m_npfds
, TIMEOUT);
131
}
132
}
133
137
void
138
SequencerOutputThread::drainOutput
()
139
{
140
if
(
m_MidiClient
!= NULL) {
141
while
(!
stopRequested
() &&
142
(snd_seq_drain_output(
m_MidiClient
->
getHandle
()) < 0))
143
poll(
m_pfds
,
m_npfds
, TIMEOUT);
144
}
145
}
146
150
void
151
SequencerOutputThread::syncOutput
()
152
{
153
if
(!
stopRequested
() &&
m_MidiClient
!= NULL) {
154
QueueStatus
status =
m_Queue
->
getStatus
();
155
while
(!
stopRequested
() && (status.
getEvents
() > 0)) {
156
usleep(TIMEOUT);
157
status =
m_Queue
->
getStatus
();
158
}
159
}
160
}
161
165
void
SequencerOutputThread::run
()
166
{
167
unsigned
int
last_tick;
168
if
(
m_MidiClient
!= NULL) {
169
try
{
170
m_npfds
= snd_seq_poll_descriptors_count(
m_MidiClient
->
getHandle
(), POLLOUT);
171
m_pfds
= (pollfd*) alloca(
m_npfds
*
sizeof
(pollfd));
172
snd_seq_poll_descriptors(
m_MidiClient
->
getHandle
(),
m_pfds
,
m_npfds
, POLLOUT);
173
last_tick =
getInitialPosition
();
174
if
(last_tick == 0) {
175
m_Queue
->
start
();
176
}
else
{
177
m_Queue
->
setTickPosition
(last_tick);
178
m_Queue
->
continueRunning
();
179
}
180
while
(!
stopRequested
() &&
hasNext
()) {
181
SequencerEvent
* ev =
nextEvent
();
182
if
(
getEchoResolution
() > 0) {
183
while
(!
stopRequested
() && (last_tick < ev->getTick())) {
184
last_tick +=
getEchoResolution
();
185
sendEchoEvent
(last_tick);
186
}
187
}
188
if
(!
stopRequested
() && !
SequencerEvent::isConnectionChange
(ev))
189
sendSongEvent
(ev);
190
}
191
if
(
stopRequested
()) {
192
m_Queue
->
clear
();
193
emit
stopped
();
194
}
else
{
195
drainOutput
();
196
syncOutput
();
197
if
(
stopRequested
())
198
emit
stopped
();
199
else
200
emit
finished
();
201
}
202
m_Queue
->
stop
();
203
}
catch
(...) {
204
qWarning(
"exception in output thread"
);
205
}
206
m_npfds
= 0;
207
m_pfds
= 0;
208
}
209
}
210
215
void
SequencerOutputThread::start
( Priority priority )
216
{
217
QWriteLocker locker(&
m_mutex
);
218
m_Stopped
=
false
;
219
QThread::start
( priority );
220
}
221
222
}
/* namespace drumstick */
223
library
src
playthread.cpp
Generated by
1.8.1.2