vfs: check userland buffers before reading them.
[haiku.git] / src / kits / media / experimental / MediaClient.cpp
blobb5c937e4fcf883854166b426e8f87f315e4b0fbf
1 /*
2 * Copyright 2015, Dario Casalinuovo. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "MediaClient.h"
8 #include <MediaConnection.h>
10 #include <MediaRoster.h>
11 #include <TimeSource.h>
13 #include "MediaClientNode.h"
15 #include "debug.h"
18 namespace BPrivate { namespace media {
21 class ConnReleaser {
22 public:
23 ConnReleaser(BMediaConnection* conn)
25 fConn(conn) {}
27 virtual ~ConnReleaser()
29 fConn->Release();
32 bool operator== (const ConnReleaser &c1)
34 return c1.fConn == this->fConn;
37 protected:
38 BMediaConnection* Obj() const
40 return fConn;
43 private:
44 BMediaConnection* fConn;
48 class InputReleaser : public ConnReleaser {
49 public:
50 InputReleaser(BMediaInput* input)
52 ConnReleaser(input) {}
54 BMediaInput* Obj() const
56 return dynamic_cast<BMediaInput*>(ConnReleaser::Obj());
61 class OutputReleaser : public ConnReleaser {
62 public:
63 OutputReleaser(BMediaOutput* output)
65 ConnReleaser(output) {}
67 BMediaOutput* Obj() const
69 return dynamic_cast<BMediaOutput*>(ConnReleaser::Obj());
78 BMediaClient::BMediaClient(const char* name,
79 media_type type, media_client_kinds kinds)
81 fLastID(-1)
83 CALLED();
85 fNode = new BMediaClientNode(name, this, type);
86 _Init();
88 fClient.node = fNode->Node();
89 fClient.kinds = kinds;
93 BMediaClient::~BMediaClient()
95 CALLED();
97 _Deinit();
101 const media_client&
102 BMediaClient::Client() const
104 return fClient;
108 status_t
109 BMediaClient::InitCheck() const
111 CALLED();
113 return fInitErr;
117 media_client_kinds
118 BMediaClient::Kinds() const
120 CALLED();
122 return fClient.Kinds();
126 media_type
127 BMediaClient::MediaType() const
129 CALLED();
131 // Right now ConsumerType() and ProducerType() are the same.
132 return fNode->ConsumerType();
136 status_t
137 BMediaClient::RegisterInput(BMediaInput* input)
139 input->_ConnectionRegistered(this, ++fLastID);
140 _AddInput(input);
141 return B_OK;
145 status_t
146 BMediaClient::RegisterOutput(BMediaOutput* output)
148 output->_ConnectionRegistered(this, ++fLastID);
149 _AddOutput(output);
150 return B_OK;
154 status_t
155 BMediaClient::Bind(BMediaInput* input, BMediaOutput* output)
157 CALLED();
159 if (input == NULL
160 || output == NULL)
161 return B_ERROR;
163 if (input->fOwner != this || output->fOwner != this)
164 return B_ERROR;
166 // TODO: Implement binding one input to more outputs.
167 if (input->fBind != NULL
168 || output->fBind != NULL)
169 return B_ERROR;
171 input->fBind = output;
172 output->fBind = input;
173 return B_OK;
177 status_t
178 BMediaClient::Unbind(BMediaInput* input, BMediaOutput* output)
180 CALLED();
182 if (input == NULL
183 || input == NULL)
184 return B_ERROR;
186 if (input->fOwner != this || output->fOwner != this)
187 return B_ERROR;
189 input->fBind = NULL;
190 output->fBind = NULL;
191 return B_OK;
195 status_t
196 BMediaClient::Connect(BMediaConnection* ourConnection,
197 BMediaConnection* theirConnection)
199 CALLED();
201 return Connect(ourConnection, theirConnection->Connection());
205 status_t
206 BMediaClient::Connect(BMediaConnection* ourConnection,
207 const media_connection& theirConnection)
209 CALLED();
211 BMediaOutput* output = dynamic_cast<BMediaOutput*>(ourConnection);
212 if (output != NULL && theirConnection.IsInput())
213 return _ConnectInput(output, theirConnection);
215 BMediaInput* input = dynamic_cast<BMediaInput*>(ourConnection);
216 if (input != NULL && theirConnection.IsOutput())
217 return _ConnectOutput(input, theirConnection);
219 return B_ERROR;
223 status_t
224 BMediaClient::Connect(BMediaConnection* connection,
225 const media_client& client)
227 UNIMPLEMENTED();
229 return B_ERROR;
233 status_t
234 BMediaClient::Disconnect()
236 CALLED();
238 for (int32 i = 0; i < CountInputs(); i++)
239 InputAt(i)->Disconnect();
241 for (int32 i = 0; i < CountOutputs(); i++)
242 OutputAt(i)->Disconnect();
244 return B_OK;
248 int32
249 BMediaClient::CountInputs() const
251 CALLED();
253 return fInputs.CountItems();
257 int32
258 BMediaClient::CountOutputs() const
260 CALLED();
262 return fOutputs.CountItems();
266 BMediaInput*
267 BMediaClient::InputAt(int32 index) const
269 CALLED();
271 return fInputs.ItemAt(index)->Obj();
275 BMediaOutput*
276 BMediaClient::OutputAt(int32 index) const
278 CALLED();
280 return fOutputs.ItemAt(index)->Obj();
284 BMediaInput*
285 BMediaClient::FindInput(const media_connection& input) const
287 CALLED();
289 if (!input.IsInput())
290 return NULL;
292 return _FindInput(input._Destination());
296 BMediaOutput*
297 BMediaClient::FindOutput(const media_connection& output) const
299 CALLED();
301 if (!output.IsOutput())
302 return NULL;
304 return _FindOutput(output._Source());
308 bool
309 BMediaClient::IsRunning() const
311 CALLED();
313 return fRunning;
317 status_t
318 BMediaClient::Start()
320 CALLED();
322 status_t err = B_OK;
323 for (int32 i = 0; i < CountOutputs(); i++) {
324 media_node remoteNode = OutputAt(i)->Connection()._RemoteNode();
325 if (remoteNode.kind & B_TIME_SOURCE)
326 err = BMediaRoster::CurrentRoster()->StartTimeSource(
327 remoteNode, BTimeSource::RealTime());
328 else
329 err = BMediaRoster::CurrentRoster()->StartNode(
330 remoteNode, fNode->TimeSource()->Now());
333 return BMediaRoster::CurrentRoster()->StartNode(
334 fNode->Node(), fNode->TimeSource()->Now());
338 status_t
339 BMediaClient::Stop()
341 CALLED();
343 return BMediaRoster::CurrentRoster()->StopNode(
344 fNode->Node(), fNode->TimeSource()->Now());
348 status_t
349 BMediaClient::Seek(bigtime_t mediaTime,
350 bigtime_t performanceTime)
352 CALLED();
354 return BMediaRoster::CurrentRoster()->SeekNode(fNode->Node(),
355 mediaTime, performanceTime);
359 status_t
360 BMediaClient::Roll(bigtime_t start, bigtime_t stop, bigtime_t seek)
362 CALLED();
364 return BMediaRoster::CurrentRoster()->RollNode(fNode->Node(),
365 start, stop, seek);
369 status_t
370 BMediaClient::Preroll()
372 CALLED();
374 return BMediaRoster::CurrentRoster()->PrerollNode(fNode->Node());
378 status_t
379 BMediaClient::SyncTo(bigtime_t performanceTime, bigtime_t timeout)
381 CALLED();
383 return BMediaRoster::CurrentRoster()->SyncToNode(fNode->Node(),
384 performanceTime, timeout);
388 BMediaNode::run_mode
389 BMediaClient::RunMode() const
391 CALLED();
393 return fNode->RunMode();
397 status_t
398 BMediaClient::SetRunMode(BMediaNode::run_mode mode)
400 CALLED();
402 return BMediaRoster::CurrentRoster()->SetRunModeNode(fNode->Node(), mode);
406 bigtime_t
407 BMediaClient::CurrentTime() const
409 CALLED();
411 return fCurrentTime;
415 BMediaAddOn*
416 BMediaClient::AddOn(int32* id) const
418 CALLED();
420 return NULL;
424 void
425 BMediaClient::HandleStart(bigtime_t performanceTime)
427 fRunning = true;
431 void
432 BMediaClient::HandleStop(bigtime_t performanceTime)
434 fRunning = false;
438 void
439 BMediaClient::HandleSeek(bigtime_t mediaTime, bigtime_t performanceTime)
444 status_t
445 BMediaClient::FormatSuggestion(media_type type, int32 quality,
446 media_format* format)
448 return B_ERROR;
452 void
453 BMediaClient::_Init()
455 CALLED();
457 BMediaRoster* roster = BMediaRoster::Roster(&fInitErr);
458 if (fInitErr == B_OK && roster != NULL)
459 fInitErr = roster->RegisterNode(fNode);
463 void
464 BMediaClient::_Deinit()
466 CALLED();
468 if (IsRunning())
469 Stop();
471 Disconnect();
473 // This will release the connections too.
474 fInputs.MakeEmpty(true);
475 fOutputs.MakeEmpty(true);
477 fNode->Release();
481 void
482 BMediaClient::_AddInput(BMediaInput* input)
484 CALLED();
486 fInputs.AddItem(new InputReleaser(input));
490 void
491 BMediaClient::_AddOutput(BMediaOutput* output)
493 CALLED();
495 fOutputs.AddItem(new OutputReleaser(output));
499 BMediaInput*
500 BMediaClient::_FindInput(const media_destination& dest) const
502 CALLED();
504 for (int32 i = 0; i < CountInputs(); i++) {
505 if (dest.id == InputAt(i)->_Destination().id)
506 return InputAt(i);
508 return NULL;
512 BMediaOutput*
513 BMediaClient::_FindOutput(const media_source& source) const
515 CALLED();
517 for (int32 i = 0; i < CountOutputs(); i++) {
518 if (source.id == OutputAt(i)->_Source().id)
519 return OutputAt(i);
521 return NULL;
525 status_t
526 BMediaClient::_ConnectInput(BMediaOutput* output,
527 const media_connection& input)
529 CALLED();
531 if (input._Destination() == media_destination::null)
532 return B_MEDIA_BAD_DESTINATION;
534 media_output ourOutput = output->Connection()._MediaOutput();
535 media_input theirInput = input._MediaInput();
536 media_format format = output->AcceptedFormat();
538 return BMediaRoster::CurrentRoster()->Connect(ourOutput.source,
539 theirInput.destination, &format, &ourOutput, &theirInput,
540 BMediaRoster::B_CONNECT_MUTED);
544 status_t
545 BMediaClient::_ConnectOutput(BMediaInput* input,
546 const media_connection& output)
548 CALLED();
550 if (output._Source() == media_source::null)
551 return B_MEDIA_BAD_SOURCE;
553 media_input ourInput = input->Connection()._MediaInput();
554 media_output theirOutput = output._MediaOutput();
555 media_format format = input->AcceptedFormat();
557 return BMediaRoster::CurrentRoster()->Connect(theirOutput.source,
558 ourInput.destination, &format, &theirOutput, &ourInput,
559 BMediaRoster::B_CONNECT_MUTED);
563 status_t
564 BMediaClient::_DisconnectConnection(BMediaConnection* conn)
566 if (conn->Client() != this)
567 return B_ERROR;
569 const media_connection& handle = conn->Connection();
570 if (handle.IsInput()) {
571 return BMediaRoster::CurrentRoster()->Disconnect(
572 handle._RemoteNode().node, handle._Source(),
573 handle._Node().node, handle._Destination());
574 } else {
575 return BMediaRoster::CurrentRoster()->Disconnect(
576 handle._Node().node, handle._Source(),
577 handle._RemoteNode().node, handle._Destination());
580 return B_ERROR;
584 status_t
585 BMediaClient::_ReleaseConnection(BMediaConnection* conn)
587 if (conn->Client() != this)
588 return B_ERROR;
590 if (conn->Connection().IsInput()) {
591 InputReleaser obj = InputReleaser(dynamic_cast<BMediaInput*>(conn));
592 fInputs.RemoveItem(&obj);
593 return B_OK;
594 } else {
595 OutputReleaser obj = OutputReleaser(dynamic_cast<BMediaOutput*>(conn));
596 fOutputs.RemoveItem(&obj);
597 return B_OK;
600 return B_ERROR;
604 void BMediaClient::_ReservedMediaClient0() {}
605 void BMediaClient::_ReservedMediaClient1() {}
606 void BMediaClient::_ReservedMediaClient2() {}
607 void BMediaClient::_ReservedMediaClient3() {}
608 void BMediaClient::_ReservedMediaClient4() {}
609 void BMediaClient::_ReservedMediaClient5() {}
610 void BMediaClient::_ReservedMediaClient6() {}
611 void BMediaClient::_ReservedMediaClient7() {}
612 void BMediaClient::_ReservedMediaClient8() {}
613 void BMediaClient::_ReservedMediaClient9() {}
614 void BMediaClient::_ReservedMediaClient10() {}