drumstick 1.1.3
playthread.cpp
Go to the documentation of this file.
1/*
2 MIDI Sequencer C++ library
3 Copyright (C) 2006-2019, 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
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <QReadLocker>
20#include <QWriteLocker>
23#include <drumstick/alsaqueue.h>
24
30namespace drumstick {
31
55const int TIMEOUT = 100;
56
63 : QThread(),
64 m_MidiClient(seq),
65 m_Queue(0),
66 m_PortId(portId),
67 m_Stopped(false),
68 m_QueueId(0),
69 m_npfds(0),
70 m_pfds(0)
71{
72 if (m_MidiClient != NULL) {
74 m_QueueId = m_Queue->getId();
75 }
76}
77
83bool
85{
86 QReadLocker locker(&m_mutex);
87 return m_Stopped;
88}
89
93void
95{
96 QWriteLocker locker(&m_mutex);
97 m_Stopped = true;
98 locker.unlock();
99 while (isRunning())
100 wait(TIMEOUT);
101}
102
107void
109{
110 if (!stopRequested() && m_MidiClient != NULL) {
111 SystemEvent ev(SND_SEQ_EVENT_ECHO);
114 ev.scheduleTick(m_QueueId, tick, false);
115 sendSongEvent(&ev);
116 }
117}
118
123void
125{
126 if (m_MidiClient != NULL) {
127 while (!stopRequested() &&
128 (snd_seq_event_output_direct(m_MidiClient->getHandle(), ev->getHandle()) < 0))
129 poll(m_pfds, m_npfds, TIMEOUT);
130 }
131}
132
136void
138{
139 if (m_MidiClient != NULL) {
140 while (!stopRequested() &&
141 (snd_seq_drain_output(m_MidiClient->getHandle()) < 0))
142 poll(m_pfds, m_npfds, TIMEOUT);
143 }
144}
145
149void
151{
152 if (!stopRequested() && m_MidiClient != NULL) {
153 QueueStatus status = m_Queue->getStatus();
154 while (!stopRequested() && (status.getEvents() > 0)) {
155 usleep(TIMEOUT);
156 status = m_Queue->getStatus();
157 }
158 }
159}
160
165{
166 unsigned int last_tick;
167 if (m_MidiClient != NULL) {
168 try {
169 m_npfds = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLOUT);
170 m_pfds = (pollfd*) alloca(m_npfds * sizeof(pollfd));
171 snd_seq_poll_descriptors(m_MidiClient->getHandle(), m_pfds, m_npfds, POLLOUT);
172 last_tick = getInitialPosition();
173 if (last_tick == 0) {
174 m_Queue->start();
175 } else {
176 m_Queue->setTickPosition(last_tick);
178 }
179 while (!stopRequested() && hasNext()) {
181 if (getEchoResolution() > 0) {
182 while (!stopRequested() && (last_tick < ev->getTick())) {
183 last_tick += getEchoResolution();
184 sendEchoEvent(last_tick);
185 }
186 }
188 sendSongEvent(ev);
189 }
190 if (stopRequested()) {
191 m_Queue->clear();
192 emit stopped();
193 } else {
194 drainOutput();
195 syncOutput();
196 if (stopRequested())
197 emit stopped();
198 else
199 emit finished();
200 }
201 m_Queue->stop();
202 } catch (...) {
203 qWarning("exception in output thread");
204 }
205 m_npfds = 0;
206 m_pfds = 0;
207 }
208}
209
214void SequencerOutputThread::start( Priority priority )
215{
216 QWriteLocker locker(&m_mutex);
217 m_Stopped = false;
218 QThread::start( priority );
219}
220
221} /* namespace drumstick */
222
Classes managing ALSA Sequencer clients.
Classes managing ALSA Sequencer queues.
The QThread class provides platform-independent threads.
Client management.
Definition alsaclient.h:198
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
int getClientId()
Gets the client ID.
void setTickPosition(snd_seq_tick_time_t pos)
Sets the queue position in musical time (ticks).
void continueRunning()
Start the queue without resetting the last position.
QueueStatus & getStatus()
Gets a QueueStatus object reference.
void start()
Start the queue.
void stop()
Stop the queue.
void clear()
Clear the queue, dropping any scheduled events.
Queue status container.
Definition alsaqueue.h:80
int getEvents()
Gets the number of queued events.
Base class for the event's hierarchy.
Definition alsaevent.h:53
static bool isConnectionChange(const SequencerEvent *event)
Checks if the event's type is of type connection change.
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition alsaevent.h:122
void scheduleTick(const int queue, const int tick, const bool relative)
Sets the event to be scheduled in musical time (ticks) units.
void setDestination(const unsigned char client, const unsigned char port)
Sets the client:port destination of the event.
void setSource(const unsigned char port)
Sets the event's source port ID.
virtual SequencerEvent * nextEvent()=0
Gets the next event in the sequence.
virtual void run()
Thread process loop.
virtual unsigned int getInitialPosition()
Gets the initial position in ticks of the sequence.
Definition playthread.h:57
virtual void sendEchoEvent(int tick)
Sends an echo event, with the same PortId as sender and destination.
SequencerOutputThread(MidiClient *seq, int portId)
Constructor.
virtual void syncOutput()
Waits until the ALSA output queue is empty (all the events have been played.)
int m_QueueId
MidiQueue numeric identifier.
Definition playthread.h:111
MidiClient * m_MidiClient
MidiClient instance pointer.
Definition playthread.h:107
bool m_Stopped
Stopped status.
Definition playthread.h:110
virtual void stop()
Stops playing the current sequence.
virtual void sendSongEvent(SequencerEvent *ev)
Sends a SequencerEvent.
virtual void drainOutput()
Flush the ALSA output buffer.
pollfd * m_pfds
Array of pollfd pointers.
Definition playthread.h:113
QReadWriteLock m_mutex
Mutex object used for synchronization.
Definition playthread.h:114
MidiQueue * m_Queue
MidiQueue instance pointer.
Definition playthread.h:108
virtual bool hasNext()=0
Check if there is one more event in the sequence.
virtual unsigned int getEchoResolution()
Gets the echo event resolution in ticks.
Definition playthread.h:64
void stopped()
Signal emitted when the play-back has stopped.
int m_npfds
Number of pollfd pointers.
Definition playthread.h:112
int m_PortId
MidiPort numeric identifier.
Definition playthread.h:109
void start(Priority priority=InheritPriority)
Starts the playback thread.
virtual bool stopRequested()
Checks if stop has been requested.
void finished()
Signal emitted when the sequence play-back has finished.
Generic event.
Definition alsaevent.h:438
Sequencer output thread.