kwave  18.07.70
RecordThread.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  RecordThread.cpp - thread for lowlevel audio recording
3  -------------------
4  begin : Mon Oct 20 2003
5  copyright : (C) 2003 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <errno.h>
21 
22 #include <QVariant>
23 
24 #include "RecordDevice.h"
25 #include "RecordThread.h"
26 
27 //***************************************************************************
29  :Kwave::WorkerThread(Q_NULLPTR, QVariant()), m_device(Q_NULLPTR),
30  m_empty_queue(), m_buffer_count(0), m_buffer_size(0)
31 {
32 }
33 
34 //***************************************************************************
36 {
37  stop();
38  m_full_queue.clear();
39  m_empty_queue.clear();
40 }
41 
42 //***************************************************************************
44 {
45  Q_ASSERT(!isRunning());
46  if (isRunning()) return;
47 
48  m_device = device;
49 }
50 
51 //***************************************************************************
52 int Kwave::RecordThread::setBuffers(unsigned int count, unsigned int size)
53 {
54  Q_ASSERT(!isRunning());
55  if (isRunning()) return -EBUSY;
56 
57  // flush all queues
58  m_full_queue.clear();
59  m_empty_queue.clear();
60 
61  // fill the "empty" queue again
62  QByteArray buf(size, 0x00);
63  for (unsigned int i = 0; i < count; i++)
64  m_empty_queue.enqueue(buf);
65 
66  // take the new settings
67  m_buffer_size = size;
68  m_buffer_count = count;
69 
70  // return number of buffers or -ENOMEM if not even two allocated
71  return (m_empty_queue.count() >= 2) ? m_empty_queue.count() : -ENOMEM;
72 }
73 
74 //***************************************************************************
76 {
77  return (m_empty_queue.count());
78 }
79 
80 //***************************************************************************
82 {
83  return (m_full_queue.count());
84 }
85 
86 //***************************************************************************
88 {
89  if (m_full_queue.count()) {
90  // de-queue the buffer from the full list
91  QByteArray buf = m_full_queue.dequeue();
92 
93  // put the buffer back to the empty list
94  m_empty_queue.enqueue(buf);
95 
96  // return the buffer
97  return buf;
98  } else {
99  // return an empty buffer
100  return QByteArray();
101  }
102 }
103 
104 //***************************************************************************
106 {
107  int result = 0;
108  bool interrupted = false;
109 
110  // read data until we receive a close signal
111  while (!shouldStop() && !interrupted) {
112  // dequeue a buffer from the "empty" queue
113 
114  if (m_empty_queue.isEmpty()) {
115  // we had a "buffer overflow"
116  qWarning("RecordThread::run() -> NO EMPTY BUFFER FOUND !!!");
117  result = -ENOBUFS;
118  break;
119  }
120 
121  QByteArray buffer = m_empty_queue.dequeue();
122  int len = buffer.size();
123  Q_ASSERT(buffer.size());
124  if (!len) {
125  result = -ENOBUFS;
126  break;
127  }
128 
129  // read into the current buffer
130  unsigned int offset = 0;
131  while (len && !interrupted && !shouldStop()) {
132  // read raw data from the record device
133  result = (m_device) ?
134  m_device->read(buffer, offset) : -EBADF;
135 
136  if ((result < 0) && (result != -EAGAIN))
137  qWarning("RecordThread: read result = %d (%s)",
138  result, strerror(-result));
139 
140  if (result == -EAGAIN) {
141  continue;
142  } else if (result == -EBADF) {
143  // file open has failed
144  interrupted = true;
145  break;
146  } else if (result == -EINTR) {
147  // thread was interrupted, received signal?
148  interrupted = true;
149  break;
150  } else if (result < 1) {
151  // something went wrong !?
152  interrupted = true;
153  qWarning("RecordThread::run(): read returned %d", result);
154  break;
155  } else {
156  offset += result;
157  len = buffer.size() - offset;
158  Q_ASSERT(len >= 0);
159  if (len < 0) len = 0;
160  }
161  }
162 
163  // return buffer into the empty queue and abort on errors
164  // do not use it
165  if (interrupted && (result < 0)) {
166  m_empty_queue.enqueue(buffer);
167  break;
168  }
169 
170  // inform the application that there is something to dequeue
171  m_full_queue.enqueue(buffer);
172  emit bufferFull();
173  }
174 
175  // do not evaluate the result of the last operation if there
176  // was the external request to stop
177  if (shouldStop() || (interrupted && (result > 0)))
178  result = 0;
179 
180  if (result) emit stopped(result);
181 }
182 
183 //***************************************************************************
184 //***************************************************************************
unsigned int m_buffer_size
Definition: RecordThread.h:102
Definition: App.h:33
virtual int read(QByteArray &buffer, unsigned int offset)=0
QQueue< QByteArray > m_full_queue
Definition: RecordThread.h:96
Kwave::RecordDevice * m_device
Definition: RecordThread.h:90
int setBuffers(unsigned int count, unsigned int size)
virtual ~RecordThread() Q_DECL_OVERRIDE
unsigned int m_buffer_count
Definition: RecordThread.h:99
QByteArray dequeue()
unsigned int queuedBuffers()
virtual int stop(unsigned int timeout=10000)
QQueue< QByteArray > m_empty_queue
Definition: RecordThread.h:93
void setRecordDevice(Kwave::RecordDevice *device)
void stopped(int errorcode)
virtual void run() Q_DECL_OVERRIDE
unsigned int remainingBuffers()