1 /*************************************************************************
2    RecordController.cpp  -  controller/state matching for the audio recorder
3                              -------------------
4     begin                : Sat Oct 04 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 "RecordController.h"
21 #include "RecordState.h"
22 
23 //***************************************************************************
RecordController()24 Kwave::RecordController::RecordController()
25     :QObject(),
26      m_state(Kwave::REC_UNINITIALIZED),
27      m_next_state(Kwave::REC_EMPTY),
28      m_trigger_set(false),
29      m_enable_prerecording(false),
30      m_empty(true)
31 {
32 }
33 
34 //***************************************************************************
~RecordController()35 Kwave::RecordController::~RecordController()
36 {
37 }
38 
39 //***************************************************************************
setInitialized(bool initialized)40 void Kwave::RecordController::setInitialized(bool initialized)
41 {
42     if (initialized) {
43 	m_next_state = (m_empty) ? Kwave::REC_EMPTY : Kwave::REC_DONE;
44 	emit stateChanged(m_state = Kwave::REC_EMPTY);
45     } else {
46 	m_next_state = Kwave::REC_UNINITIALIZED;
47 	emit stateChanged(Kwave::REC_UNINITIALIZED);
48     }
49 }
50 
51 //***************************************************************************
setEmpty(bool empty)52 void Kwave::RecordController::setEmpty(bool empty)
53 {
54     m_empty = empty;
55 }
56 
57 //***************************************************************************
enablePrerecording(bool enable)58 void Kwave::RecordController::enablePrerecording(bool enable)
59 {
60     m_enable_prerecording = enable;
61 }
62 
63 //***************************************************************************
actionReset()64 void Kwave::RecordController::actionReset()
65 {
66     switch (m_state) {
67 	case Kwave::REC_UNINITIALIZED:
68 	    // already empty, nothing to do
69 	    break;
70 	case Kwave::REC_RECORDING:
71 #if 0
72 	    // fall back to REC_WAITING_FOR_TRIGGER
73 	    m_next_state = Kwave::REC_EMPTY;
74 	    emit stateChanged(m_state = Kwave::REC_WAITING_FOR_TRIGGER);
75 	    break;
76 #endif
77 	case Kwave::REC_EMPTY:
78 	case Kwave::REC_BUFFERING:
79 	case Kwave::REC_WAITING_FOR_TRIGGER:
80 	case Kwave::REC_PRERECORDING:
81 	case Kwave::REC_PAUSED:
82 	case Kwave::REC_DONE:
83 	    bool accepted = true;
84 	    emit sigReset(accepted);
85 	    if (accepted) emit stateChanged(m_state = Kwave::REC_EMPTY);
86 	    break;
87     }
88 }
89 
90 //***************************************************************************
actionStop()91 void Kwave::RecordController::actionStop()
92 {
93     switch (m_state) {
94 	case Kwave::REC_UNINITIALIZED:
95 	case Kwave::REC_EMPTY:
96 	case Kwave::REC_DONE:
97 	    // already stopped, nothing to do
98 	    break;
99 	case Kwave::REC_BUFFERING:
100 	case Kwave::REC_WAITING_FOR_TRIGGER:
101 	case Kwave::REC_PRERECORDING:
102 	    // abort, change to REC_EMPTY
103 	    emit sigStopRecord(0);
104 	    break;
105 	case Kwave::REC_RECORDING:
106 	case Kwave::REC_PAUSED:
107 	    // abort, change to REC_DONE
108 	    m_next_state = Kwave::REC_DONE;
109 	    emit sigStopRecord(0);
110 	    break;
111     }
112 }
113 
114 //***************************************************************************
actionPause()115 void Kwave::RecordController::actionPause()
116 {
117     switch (m_state) {
118 	case Kwave::REC_UNINITIALIZED:
119 	case Kwave::REC_EMPTY:
120 	case Kwave::REC_DONE:
121 	    // what do you want ?
122 	    break;
123 	case Kwave::REC_BUFFERING:
124 	case Kwave::REC_WAITING_FOR_TRIGGER:
125 	case Kwave::REC_PRERECORDING:
126 	    // this should never happen
127 	    qWarning("RecordController::actionPause(): "
128 	             "state = %s ???", stateName(m_state));
129 	    break;
130 	case Kwave::REC_RECORDING:
131 	    // pause recording
132 	    emit stateChanged(m_state = Kwave::REC_PAUSED);
133 	    break;
134 	case Kwave::REC_PAUSED:
135 	    // continue recording
136 	    emit stateChanged(m_state = Kwave::REC_RECORDING);
137 	    break;
138     }
139 }
140 
141 //***************************************************************************
actionStart()142 void Kwave::RecordController::actionStart()
143 {
144     switch (m_state) {
145 	case Kwave::REC_UNINITIALIZED:
146 	    break; // impossible
147 	case Kwave::REC_EMPTY:
148 	case Kwave::REC_DONE:
149 	    // interpret this as manual trigger
150 	    emit sigStartRecord();
151 	    break;
152 	case Kwave::REC_BUFFERING:
153 	case Kwave::REC_PRERECORDING:
154 	case Kwave::REC_WAITING_FOR_TRIGGER:
155 	    // interpret as "trigger now"
156 	    m_next_state = Kwave::REC_EMPTY;
157 	    emit stateChanged(m_state = Kwave::REC_RECORDING);
158 	    break;
159 	case Kwave::REC_PAUSED:
160 	    // interpret this as "continue"
161 	    m_next_state = Kwave::REC_RECORDING;
162 	    emit stateChanged(m_state = Kwave::REC_RECORDING);
163 	    break;
164 	case Kwave::REC_RECORDING:
165 	    // already recording...
166 	    m_next_state = Kwave::REC_DONE;
167 	    break;
168     }
169 }
170 
171 //***************************************************************************
deviceRecordStarted()172 void Kwave::RecordController::deviceRecordStarted()
173 {
174     switch (m_state) {
175 	case Kwave::REC_UNINITIALIZED:
176 	    break; // impossible
177 	case Kwave::REC_EMPTY:
178 	case Kwave::REC_PAUSED:
179 	case Kwave::REC_DONE:
180 	    // continue, pre-recording or trigger
181 	    m_next_state = (m_empty) ? Kwave::REC_EMPTY : Kwave::REC_DONE;
182 	    emit stateChanged(m_state = Kwave::REC_BUFFERING);
183 	    break;
184 	case Kwave::REC_BUFFERING:
185 	case Kwave::REC_WAITING_FOR_TRIGGER:
186 	case Kwave::REC_PRERECORDING:
187 	case Kwave::REC_RECORDING:
188 	    // this should never happen
189 	    qWarning("RecordController::deviceRecordStarted(): "
190 	             "state = %s ???", stateName(m_state));
191 	    break;
192     }
193 }
194 
195 //***************************************************************************
deviceBufferFull()196 void Kwave::RecordController::deviceBufferFull()
197 {
198     switch (m_state) {
199 	case Kwave::REC_UNINITIALIZED:
200 	    break; // impossible
201 	case Kwave::REC_EMPTY:
202 	    // we are only "recording" for updating the level
203 	    // meters and other effects -> no state change
204 	    break;
205 	case Kwave::REC_WAITING_FOR_TRIGGER:
206 	case Kwave::REC_PRERECORDING:
207 	case Kwave::REC_RECORDING:
208 	    // this should never happen
209 	    qWarning("RecordController::deviceBufferFull(): "
210 	             "state = %s ???", stateName(m_state));
211 	    break;
212 	case Kwave::REC_PAUSED: /* == buffering again after pause */
213 	    // -> will change to "REC_BUFFERING" soon...
214 	    break;
215 	case Kwave::REC_BUFFERING:
216 	    if (m_enable_prerecording) {
217 		// prerecording was set
218 		m_state = Kwave::REC_PRERECORDING;
219 	    } else if (m_trigger_set) {
220 		// trigger was set
221 		m_state = Kwave::REC_WAITING_FOR_TRIGGER;
222 	    } else {
223 		// default: just start recording
224 		m_next_state = Kwave::REC_DONE;
225 		m_state = Kwave::REC_RECORDING;
226 	    }
227 	    emit stateChanged(m_state);
228 	    break;
229 	case Kwave::REC_DONE:
230 	    // might occur when the buffer content is flushed
231 	    // after a stop
232 	    break;
233     }
234 }
235 
236 //***************************************************************************
enableTrigger(bool enable)237 void Kwave::RecordController::enableTrigger(bool enable)
238 {
239     m_trigger_set = enable;
240 }
241 
242 //***************************************************************************
deviceTriggerReached()243 void Kwave::RecordController::deviceTriggerReached()
244 {
245     switch (m_state) {
246 	case Kwave::REC_UNINITIALIZED:
247 	case Kwave::REC_EMPTY:
248 	case Kwave::REC_BUFFERING:
249 	case Kwave::REC_RECORDING:
250 	case Kwave::REC_PAUSED:
251 	case Kwave::REC_DONE:
252 	    // this should never happen
253 	    qWarning("RecordController::deviceTriggerReached(): "
254 	             "state = %s ???", stateName(m_state));
255 	    break;
256 	case Kwave::REC_PRERECORDING:
257 	case Kwave::REC_WAITING_FOR_TRIGGER:
258 	    Q_ASSERT(m_trigger_set);
259 	    if ((m_enable_prerecording) &&
260 	        (m_state == Kwave::REC_WAITING_FOR_TRIGGER))
261 	    {
262 		// prerecording was set
263 		m_state = Kwave::REC_PRERECORDING;
264 	    } else {
265 		// default: just start recording
266 		m_state = Kwave::REC_RECORDING;
267 		m_next_state = Kwave::REC_DONE;
268 	    }
269 	    emit stateChanged(m_state);
270 	    break;
271     }
272 }
273 
274 //***************************************************************************
deviceRecordStopped(int)275 void Kwave::RecordController::deviceRecordStopped(int)
276 {
277     switch (m_state) {
278 	case Kwave::REC_UNINITIALIZED:
279 	case Kwave::REC_EMPTY:
280 	case Kwave::REC_DONE:
281 	    // this could happen when an abort occurs during buffering
282 	    emit stateChanged(m_state);
283 	    break;
284 	case Kwave::REC_BUFFERING:
285 	case Kwave::REC_PRERECORDING:
286 	case Kwave::REC_WAITING_FOR_TRIGGER:
287 	    // abort, no real data produced
288 	    if (m_empty) {
289 		emit stateChanged(m_state = Kwave::REC_EMPTY);
290 	    } else {
291 		emit stateChanged(m_state = Kwave::REC_DONE);
292 	    }
293 	    break;
294 	case Kwave::REC_RECORDING:
295 	    // recording -> pause or done
296 	    switch (m_next_state) {
297 		case Kwave::REC_EMPTY:
298 		    // something went wrong when starting the recorder
299 		    if (m_empty) {
300 			emit stateChanged(m_state = Kwave::REC_EMPTY);
301 		    } else {
302 			emit stateChanged(m_state = Kwave::REC_DONE);
303 		    }
304 		    break;
305 		case Kwave::REC_PAUSED:
306 		    emit stateChanged(m_state = Kwave::REC_PAUSED);
307 		    break;
308 		case Kwave::REC_DONE:
309 		    emit stateChanged(m_state = Kwave::REC_DONE);
310 		    break;
311 		default:
312 		    qWarning("RecordController::deviceRecordStopped(): "
313 		             "next state = %s ???", stateName(m_next_state));
314 	    }
315 	    break;
316 	case Kwave::REC_PAUSED:
317 	    // pause -> done
318 	    emit stateChanged(m_state = Kwave::REC_DONE);
319 	    break;
320     }
321 }
322 
323 //***************************************************************************
stateName(const Kwave::RecordState state)324 const char *Kwave::RecordController::stateName(const Kwave::RecordState state)
325 {
326     switch (state) {
327 	case Kwave::REC_UNINITIALIZED:       return "REC_UNINITIALIZED";
328 	case Kwave::REC_EMPTY:               return "REC_EMPTY";
329 	case Kwave::REC_BUFFERING:           return "REC_BUFFERING";
330 	case Kwave::REC_WAITING_FOR_TRIGGER: return "REC_WAITING_FOR_TRIGGER";
331 	case Kwave::REC_PRERECORDING:        return "REC_PRERECORDING";
332 	case Kwave::REC_RECORDING:           return "REC_RECORDING";
333 	case Kwave::REC_PAUSED:              return "REC_PAUSED";
334 	case Kwave::REC_DONE:                return "REC_DONE";
335     }
336     return "-INVALID-";
337 }
338 
339 //***************************************************************************
340 //***************************************************************************
341