tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / media / MediaRecorder.cpp
blobd2d6be449e1d7fd4cc5076723acd1dce55dade47
1 /*
2 * Copyright 2015, Hamish Morrison <hamishm53@gmail.com>
3 * Copyright 2014, Dario Casalinuovo
4 * Copyright 1999, Be Incorporated
5 * All Rights Reserved.
6 * This file may be used under the terms of the Be Sample Code License.
7 */
10 #include <MediaRecorder.h>
12 #include <MediaAddOn.h>
13 #include <MediaRoster.h>
14 #include <TimeSource.h>
16 #include <MediaDebug.h>
17 #include <MediaRecorderNode.h>
20 BMediaRecorder::BMediaRecorder(const char* name, media_type type)
22 fInitErr(B_OK),
23 fConnected(false),
24 fRunning(false),
25 fReleaseOutputNode(false),
26 fRecordHook(NULL),
27 fNotifyHook(NULL),
28 fNode(NULL),
29 fBufferCookie(NULL)
31 CALLED();
33 BMediaRoster::Roster(&fInitErr);
35 if (fInitErr == B_OK) {
36 fNode = new(std::nothrow) BMediaRecorderNode(name, this, type);
37 if (fNode == NULL)
38 fInitErr = B_NO_MEMORY;
40 fInitErr = BMediaRoster::CurrentRoster()->RegisterNode(fNode);
45 BMediaRecorder::~BMediaRecorder()
47 CALLED();
49 if (fNode != NULL) {
50 Stop();
51 Disconnect();
52 fNode->Release();
57 status_t
58 BMediaRecorder::InitCheck() const
60 CALLED();
62 return fInitErr;
66 void
67 BMediaRecorder::SetAcceptedFormat(const media_format& format)
69 CALLED();
71 fNode->SetAcceptedFormat(format);
75 status_t
76 BMediaRecorder::SetHooks(ProcessFunc recordFunc, NotifyFunc notifyFunc,
77 void* cookie)
79 CALLED();
81 fRecordHook = recordFunc;
82 fNotifyHook = notifyFunc;
83 fBufferCookie = cookie;
85 return B_OK;
89 void
90 BMediaRecorder::BufferReceived(void* buffer, size_t size,
91 const media_header& header)
93 CALLED();
95 if (fRecordHook) {
96 (*fRecordHook)(fBufferCookie, header.start_time,
97 buffer, size, Format());
102 status_t
103 BMediaRecorder::Connect(const media_format& format)
105 CALLED();
107 if (fInitErr != B_OK)
108 return fInitErr;
110 if (fConnected)
111 return B_MEDIA_ALREADY_CONNECTED;
113 status_t err = B_OK;
114 media_node node;
116 switch (format.type) {
117 // switch on format for default
118 case B_MEDIA_RAW_AUDIO:
119 err = BMediaRoster::Roster()->GetAudioMixer(&node);
120 break;
121 case B_MEDIA_RAW_VIDEO:
122 case B_MEDIA_ENCODED_VIDEO:
123 err = BMediaRoster::Roster()->GetVideoInput(&node);
124 break;
125 // give up?
126 default:
127 return B_MEDIA_BAD_FORMAT;
130 if (err != B_OK)
131 return err;
133 fReleaseOutputNode = true;
135 err = _Connect(node, NULL, format);
137 if (err != B_OK) {
138 BMediaRoster::Roster()->ReleaseNode(node);
139 fReleaseOutputNode = false;
142 return err;
146 status_t
147 BMediaRecorder::Connect(const dormant_node_info& dormantNode,
148 const media_format& format)
150 CALLED();
152 if (fInitErr != B_OK)
153 return fInitErr;
155 if (fConnected)
156 return B_MEDIA_ALREADY_CONNECTED;
158 media_node node;
159 status_t err = BMediaRoster::Roster()->InstantiateDormantNode(dormantNode,
160 &node, B_FLAVOR_IS_GLOBAL);
162 if (err != B_OK)
163 return err;
165 fReleaseOutputNode = true;
167 err = _Connect(node, NULL, format);
169 if (err != B_OK) {
170 BMediaRoster::Roster()->ReleaseNode(node);
171 fReleaseOutputNode = false;
174 return err;
178 status_t
179 BMediaRecorder::Connect(const media_node& node,
180 const media_output* output, const media_format* format)
182 CALLED();
184 if (fInitErr != B_OK)
185 return fInitErr;
187 if (fConnected)
188 return B_MEDIA_ALREADY_CONNECTED;
190 if (format == NULL && output != NULL)
191 format = &output->format;
193 return _Connect(node, output, *format);
197 status_t
198 BMediaRecorder::Disconnect()
200 CALLED();
202 status_t err = B_OK;
204 if (fInitErr != B_OK)
205 return fInitErr;
207 if (!fConnected)
208 return B_MEDIA_NOT_CONNECTED;
210 if (!fNode)
211 return B_ERROR;
213 if (fRunning)
214 err = Stop();
216 if (err != B_OK)
217 return err;
219 // do the disconnect
220 err = BMediaRoster::CurrentRoster()->Disconnect(
221 fOutputNode.node, fOutput.source,
222 fNode->Node().node, fInput.destination);
224 if (fReleaseOutputNode) {
225 BMediaRoster::Roster()->ReleaseNode(fOutputNode);
226 fReleaseOutputNode = false;
229 fConnected = false;
230 fRunning = false;
232 return err;
236 status_t
237 BMediaRecorder::Start(bool force)
239 CALLED();
241 if (fInitErr != B_OK)
242 return fInitErr;
244 if (!fConnected)
245 return B_MEDIA_NOT_CONNECTED;
247 if (fRunning && !force)
248 return EALREADY;
250 if (!fNode)
251 return B_ERROR;
253 // start node here
254 status_t err = B_OK;
256 if ((fOutputNode.kind & B_TIME_SOURCE) != 0)
257 err = BMediaRoster::CurrentRoster()->StartTimeSource(
258 fOutputNode, BTimeSource::RealTime());
259 else
260 err = BMediaRoster::CurrentRoster()->StartNode(
261 fOutputNode, fNode->TimeSource()->Now());
263 // then un-mute it
264 if (err == B_OK) {
265 fNode->SetDataEnabled(true);
266 fRunning = true;
267 } else
268 fRunning = false;
270 return err;
274 status_t
275 BMediaRecorder::Stop(bool force)
277 CALLED();
279 if (fInitErr != B_OK)
280 return fInitErr;
282 if (!fRunning && !force)
283 return EALREADY;
285 if (!fNode)
286 return B_ERROR;
288 // should have the Node mute the output here
289 fNode->SetDataEnabled(false);
291 fRunning = false;
293 return BMediaRoster::CurrentRoster()->StopNode(fNode->Node(), 0);
297 bool
298 BMediaRecorder::IsRunning() const
300 CALLED();
302 return fRunning;
306 bool
307 BMediaRecorder::IsConnected() const
309 CALLED();
311 return fConnected;
315 const media_output&
316 BMediaRecorder::MediaOutput() const
318 CALLED();
320 return fOutput;
324 const media_input&
325 BMediaRecorder::MediaInput() const
327 CALLED();
329 return fInput;
333 const media_format&
334 BMediaRecorder::Format() const
336 CALLED();
338 return fOutput.format;
342 status_t
343 BMediaRecorder::_Connect(const media_node& node,
344 const media_output* output, const media_format& format)
346 CALLED();
348 status_t err = B_OK;
349 media_format ourFormat = format;
350 media_output ourOutput;
352 if (fNode == NULL)
353 return B_ERROR;
355 fNode->SetAcceptedFormat(ourFormat);
357 fOutputNode = node;
359 // figure out the output provided
360 if (output != NULL) {
361 ourOutput = *output;
362 } else if (err == B_OK) {
363 media_output outputs[10];
364 int32 count = 10;
366 err = BMediaRoster::Roster()->GetFreeOutputsFor(fOutputNode,
367 outputs, count, &count, ourFormat.type);
369 if (err != B_OK)
370 return err;
372 for (int i = 0; i < count; i++) {
373 if (format_is_compatible(outputs[i].format, ourFormat)) {
374 ourOutput = outputs[i];
375 ourFormat = outputs[i].format;
376 break;
381 if (ourOutput.source == media_source::null)
382 return B_MEDIA_BAD_SOURCE;
384 // find our Node's free input
385 media_input ourInput;
386 err = fNode->GetInput(&ourInput);
387 if (err != B_OK)
388 return err;
390 media_node timeSource;
391 if ((node.kind & B_TIME_SOURCE) != 0)
392 timeSource = node;
393 else
394 BMediaRoster::Roster()->GetTimeSource(&timeSource);
396 // set time source
397 err = BMediaRoster::Roster()->SetTimeSourceFor(fNode->Node().node,
398 timeSource.node);
400 if (err != B_OK)
401 return err;
403 // start the recorder node (it's always running)
404 err = BMediaRoster::CurrentRoster()->StartNode(fOutputNode,
405 fNode->TimeSource()->Now());
407 if (err != B_OK)
408 return err;
410 // perform the connection
411 fOutput = ourOutput;
412 fInput = ourInput;
414 err = BMediaRoster::CurrentRoster()->Connect(fOutput.source,
415 fInput.destination, &ourFormat, &fOutput, &fInput,
416 BMediaRoster::B_CONNECT_MUTED);
418 if (err != B_OK)
419 return err;
421 fConnected = true;
422 return B_OK;
426 void BMediaRecorder::_ReservedMediaRecorder0() { }
427 void BMediaRecorder::_ReservedMediaRecorder1() { }
428 void BMediaRecorder::_ReservedMediaRecorder2() { }
429 void BMediaRecorder::_ReservedMediaRecorder3() { }
430 void BMediaRecorder::_ReservedMediaRecorder4() { }
431 void BMediaRecorder::_ReservedMediaRecorder5() { }
432 void BMediaRecorder::_ReservedMediaRecorder6() { }
433 void BMediaRecorder::_ReservedMediaRecorder7() { }