1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include <QtCore/qdebug.h> |
41 | #include <QtCore/qmap.h> |
42 | |
43 | #include "qmediaservice.h" |
44 | #include "qmediaserviceprovider_p.h" |
45 | #include "qmediaserviceproviderplugin.h" |
46 | #include "qmediapluginloader_p.h" |
47 | #include "qmediaplayer.h" |
48 | |
49 | QT_BEGIN_NAMESPACE |
50 | |
51 | QMediaServiceProviderFactoryInterface::~QMediaServiceProviderFactoryInterface() |
52 | { |
53 | } |
54 | |
55 | class QMediaServiceProviderHintPrivate : public QSharedData |
56 | { |
57 | public: |
58 | QMediaServiceProviderHintPrivate(QMediaServiceProviderHint::Type type) |
59 | : type(type) |
60 | { |
61 | } |
62 | |
63 | QMediaServiceProviderHintPrivate(const QMediaServiceProviderHintPrivate &other) |
64 | :QSharedData(other), |
65 | type(other.type), |
66 | device(other.device), |
67 | cameraPosition(other.cameraPosition), |
68 | mimeType(other.mimeType), |
69 | codecs(other.codecs), |
70 | features(other.features) |
71 | { |
72 | } |
73 | |
74 | ~QMediaServiceProviderHintPrivate() |
75 | { |
76 | } |
77 | |
78 | QMediaServiceProviderHint::Type type; |
79 | QByteArray device; |
80 | QCamera::Position cameraPosition = QCamera::UnspecifiedPosition; |
81 | QString mimeType; |
82 | QStringList codecs; |
83 | QMediaServiceProviderHint::Features features; |
84 | }; |
85 | |
86 | /*! |
87 | \class QMediaServiceProviderHint |
88 | \obsolete |
89 | |
90 | \brief The QMediaServiceProviderHint class describes what is required of a QMediaService. |
91 | |
92 | \inmodule QtMultimedia |
93 | |
94 | \ingroup multimedia |
95 | \ingroup multimedia_control |
96 | \ingroup multimedia_core |
97 | |
98 | \internal |
99 | |
100 | The QMediaServiceProvider class uses hints to select an appropriate media service. |
101 | */ |
102 | |
103 | /*! |
104 | \enum QMediaServiceProviderHint::Feature |
105 | |
106 | Enumerates features a media service may provide. |
107 | |
108 | \value LowLatencyPlayback |
109 | The service is expected to play simple audio formats, |
110 | but playback should start without significant delay. |
111 | Such playback service can be used for beeps, ringtones, etc. |
112 | |
113 | \value RecordingSupport |
114 | The service provides audio or video recording functions. |
115 | |
116 | \value StreamPlayback |
117 | The service is capable of playing QIODevice based streams. |
118 | |
119 | \value VideoSurface |
120 | The service is capable of renderering to a QAbstractVideoSurface |
121 | output. |
122 | */ |
123 | |
124 | /*! |
125 | \enum QMediaServiceProviderHint::Type |
126 | |
127 | Enumerates the possible types of media service provider hint. |
128 | |
129 | \value Null En empty hint, use the default service. |
130 | \value ContentType Select media service most suitable for certain content type. |
131 | \value Device Select media service which supports certain device. |
132 | \value SupportedFeatures Select media service supporting the set of optional features. |
133 | \value CameraPosition Select media service having a camera at a specified position. |
134 | */ |
135 | |
136 | |
137 | /*! |
138 | Constructs an empty media service provider hint. |
139 | */ |
140 | QMediaServiceProviderHint::QMediaServiceProviderHint() |
141 | :d(new QMediaServiceProviderHintPrivate(Null)) |
142 | { |
143 | } |
144 | |
145 | /*! |
146 | Constructs a ContentType media service provider hint. |
147 | |
148 | This type of hint describes a service that is able to play content of a specific MIME \a type |
149 | encoded with one or more of the listed \a codecs. |
150 | */ |
151 | QMediaServiceProviderHint::QMediaServiceProviderHint(const QString &type, const QStringList& codecs) |
152 | :d(new QMediaServiceProviderHintPrivate(ContentType)) |
153 | { |
154 | d->mimeType = type; |
155 | d->codecs = codecs; |
156 | } |
157 | |
158 | /*! |
159 | Constructs a Device media service provider hint. |
160 | |
161 | This type of hint describes a media service that utilizes a specific \a device. |
162 | */ |
163 | QMediaServiceProviderHint::QMediaServiceProviderHint(const QByteArray &device) |
164 | :d(new QMediaServiceProviderHintPrivate(Device)) |
165 | { |
166 | d->device = device; |
167 | } |
168 | |
169 | /*! |
170 | \since 5.3 |
171 | |
172 | Constructs a CameraPosition media service provider hint. |
173 | |
174 | This type of hint describes a media service that has a camera in the specific \a position. |
175 | */ |
176 | QMediaServiceProviderHint::QMediaServiceProviderHint(QCamera::Position position) |
177 | :d(new QMediaServiceProviderHintPrivate(CameraPosition)) |
178 | { |
179 | d->cameraPosition = position; |
180 | } |
181 | |
182 | /*! |
183 | Constructs a SupportedFeatures media service provider hint. |
184 | |
185 | This type of hint describes a service which supports a specific set of \a features. |
186 | */ |
187 | QMediaServiceProviderHint::QMediaServiceProviderHint(QMediaServiceProviderHint::Features features) |
188 | :d(new QMediaServiceProviderHintPrivate(SupportedFeatures)) |
189 | { |
190 | d->features = features; |
191 | } |
192 | |
193 | /*! |
194 | Constructs a copy of the media service provider hint \a other. |
195 | */ |
196 | QMediaServiceProviderHint::QMediaServiceProviderHint(const QMediaServiceProviderHint &other) |
197 | :d(other.d) |
198 | { |
199 | } |
200 | |
201 | /*! |
202 | Destroys a media service provider hint. |
203 | */ |
204 | QMediaServiceProviderHint::~QMediaServiceProviderHint() |
205 | { |
206 | } |
207 | |
208 | /*! |
209 | Assigns the value \a other to a media service provider hint. |
210 | */ |
211 | QMediaServiceProviderHint& QMediaServiceProviderHint::operator=(const QMediaServiceProviderHint &other) |
212 | { |
213 | d = other.d; |
214 | return *this; |
215 | } |
216 | |
217 | /*! |
218 | Identifies if \a other is of equal value to a media service provider hint. |
219 | |
220 | Returns true if the hints are equal, and false if they are not. |
221 | */ |
222 | bool QMediaServiceProviderHint::operator == (const QMediaServiceProviderHint &other) const |
223 | { |
224 | return (d == other.d) || |
225 | (d->type == other.d->type && |
226 | d->device == other.d->device && |
227 | d->cameraPosition == other.d->cameraPosition && |
228 | d->mimeType == other.d->mimeType && |
229 | d->codecs == other.d->codecs && |
230 | d->features == other.d->features); |
231 | } |
232 | |
233 | /*! |
234 | Identifies if \a other is not of equal value to a media service provider hint. |
235 | |
236 | Returns true if the hints are not equal, and false if they are. |
237 | */ |
238 | bool QMediaServiceProviderHint::operator != (const QMediaServiceProviderHint &other) const |
239 | { |
240 | return !(*this == other); |
241 | } |
242 | |
243 | /*! |
244 | Returns true if a media service provider is null. |
245 | */ |
246 | bool QMediaServiceProviderHint::isNull() const |
247 | { |
248 | return d->type == Null; |
249 | } |
250 | |
251 | /*! |
252 | Returns the type of a media service provider hint. |
253 | */ |
254 | QMediaServiceProviderHint::Type QMediaServiceProviderHint::type() const |
255 | { |
256 | return d->type; |
257 | } |
258 | |
259 | /*! |
260 | Returns the mime type of the media a service is expected to be able play. |
261 | */ |
262 | QString QMediaServiceProviderHint::mimeType() const |
263 | { |
264 | return d->mimeType; |
265 | } |
266 | |
267 | /*! |
268 | Returns a list of codes a media service is expected to be able to decode. |
269 | */ |
270 | QStringList QMediaServiceProviderHint::codecs() const |
271 | { |
272 | return d->codecs; |
273 | } |
274 | |
275 | /*! |
276 | Returns the name of a device a media service is expected to utilize. |
277 | */ |
278 | QByteArray QMediaServiceProviderHint::device() const |
279 | { |
280 | return d->device; |
281 | } |
282 | |
283 | /*! |
284 | \since 5.3 |
285 | |
286 | Returns the camera's position a media service is expected to utilize. |
287 | */ |
288 | QCamera::Position QMediaServiceProviderHint::cameraPosition() const |
289 | { |
290 | return d->cameraPosition; |
291 | } |
292 | |
293 | |
294 | /*! |
295 | Returns a set of features a media service is expected to provide. |
296 | */ |
297 | QMediaServiceProviderHint::Features QMediaServiceProviderHint::features() const |
298 | { |
299 | return d->features; |
300 | } |
301 | |
302 | |
303 | Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, loader, |
304 | (QMediaServiceProviderFactoryInterface_iid, QLatin1String("mediaservice" ), Qt::CaseInsensitive)) |
305 | |
306 | |
307 | class QPluginServiceProvider : public QMediaServiceProvider |
308 | { |
309 | struct MediaServiceData { |
310 | QByteArray type; |
311 | QMediaServiceProviderPlugin *plugin; |
312 | |
313 | MediaServiceData() : plugin(nullptr) { } |
314 | }; |
315 | |
316 | QMap<const QMediaService*, MediaServiceData> mediaServiceData; |
317 | |
318 | public: |
319 | QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) override |
320 | { |
321 | QString key(QLatin1String(type.constData())); |
322 | |
323 | QList<QMediaServiceProviderPlugin *>plugins; |
324 | const auto instances = loader()->instances(key); |
325 | for (QObject *obj : instances) { |
326 | QMediaServiceProviderPlugin *plugin = |
327 | qobject_cast<QMediaServiceProviderPlugin*>(object: obj); |
328 | if (plugin) |
329 | plugins << plugin; |
330 | } |
331 | |
332 | if (!plugins.isEmpty()) { |
333 | QMediaServiceProviderPlugin *plugin = nullptr; |
334 | |
335 | switch (hint.type()) { |
336 | case QMediaServiceProviderHint::Null: |
337 | plugin = plugins[0]; |
338 | //special case for media player, if low latency was not asked, |
339 | //prefer services not offering it, since they are likely to support |
340 | //more formats |
341 | if (type == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) { |
342 | for (QMediaServiceProviderPlugin *currentPlugin : qAsConst(t&: plugins)) { |
343 | QMediaServiceFeaturesInterface *iface = |
344 | qobject_cast<QMediaServiceFeaturesInterface*>(object: currentPlugin); |
345 | |
346 | if (!iface || !(iface->supportedFeatures(service: type) & |
347 | QMediaServiceProviderHint::LowLatencyPlayback)) { |
348 | plugin = currentPlugin; |
349 | break; |
350 | } |
351 | |
352 | } |
353 | } |
354 | break; |
355 | case QMediaServiceProviderHint::SupportedFeatures: |
356 | plugin = plugins[0]; |
357 | for (QMediaServiceProviderPlugin *currentPlugin : qAsConst(t&: plugins)) { |
358 | QMediaServiceFeaturesInterface *iface = |
359 | qobject_cast<QMediaServiceFeaturesInterface*>(object: currentPlugin); |
360 | |
361 | if (iface) { |
362 | if ((iface->supportedFeatures(service: type) & hint.features()) == hint.features()) { |
363 | plugin = currentPlugin; |
364 | break; |
365 | } |
366 | } |
367 | } |
368 | break; |
369 | case QMediaServiceProviderHint::Device: { |
370 | plugin = plugins[0]; |
371 | for (QMediaServiceProviderPlugin *currentPlugin : qAsConst(t&: plugins)) { |
372 | QMediaServiceSupportedDevicesInterface *iface = |
373 | qobject_cast<QMediaServiceSupportedDevicesInterface*>(object: currentPlugin); |
374 | |
375 | if (iface && iface->devices(service: type).contains(t: hint.device())) { |
376 | plugin = currentPlugin; |
377 | break; |
378 | } |
379 | } |
380 | } |
381 | break; |
382 | case QMediaServiceProviderHint::CameraPosition: { |
383 | plugin = plugins[0]; |
384 | if (type == QByteArray(Q_MEDIASERVICE_CAMERA) |
385 | && hint.cameraPosition() != QCamera::UnspecifiedPosition) { |
386 | for (QMediaServiceProviderPlugin *currentPlugin : qAsConst(t&: plugins)) { |
387 | const QMediaServiceSupportedDevicesInterface *deviceIface = |
388 | qobject_cast<QMediaServiceSupportedDevicesInterface*>(object: currentPlugin); |
389 | const QMediaServiceCameraInfoInterface *cameraIface = |
390 | qobject_cast<QMediaServiceCameraInfoInterface*>(object: currentPlugin); |
391 | |
392 | if (deviceIface && cameraIface) { |
393 | const QList<QByteArray> cameras = deviceIface->devices(service: type); |
394 | for (const QByteArray &camera : cameras) { |
395 | if (cameraIface->cameraPosition(device: camera) == hint.cameraPosition()) { |
396 | plugin = currentPlugin; |
397 | break; |
398 | } |
399 | } |
400 | } |
401 | } |
402 | } |
403 | } |
404 | break; |
405 | case QMediaServiceProviderHint::ContentType: { |
406 | QMultimedia::SupportEstimate estimate = QMultimedia::NotSupported; |
407 | for (QMediaServiceProviderPlugin *currentPlugin : qAsConst(t&: plugins)) { |
408 | QMultimedia::SupportEstimate currentEstimate = QMultimedia::MaybeSupported; |
409 | QMediaServiceSupportedFormatsInterface *iface = |
410 | qobject_cast<QMediaServiceSupportedFormatsInterface*>(object: currentPlugin); |
411 | |
412 | if (iface) |
413 | currentEstimate = iface->hasSupport(mimeType: hint.mimeType(), codecs: hint.codecs()); |
414 | |
415 | if (currentEstimate > estimate) { |
416 | estimate = currentEstimate; |
417 | plugin = currentPlugin; |
418 | |
419 | if (currentEstimate == QMultimedia::PreferredService) |
420 | break; |
421 | } |
422 | } |
423 | } |
424 | break; |
425 | } |
426 | |
427 | if (plugin != nullptr) { |
428 | QMediaService *service = plugin->create(key); |
429 | if (service != nullptr) { |
430 | MediaServiceData d; |
431 | d.type = type; |
432 | d.plugin = plugin; |
433 | mediaServiceData.insert(akey: service, avalue: d); |
434 | } |
435 | |
436 | return service; |
437 | } |
438 | } |
439 | |
440 | qWarning() << "defaultServiceProvider::requestService(): no service found for -" << key; |
441 | return nullptr; |
442 | } |
443 | |
444 | void releaseService(QMediaService *service) override |
445 | { |
446 | if (service != nullptr) { |
447 | MediaServiceData d = mediaServiceData.take(akey: service); |
448 | |
449 | if (d.plugin != nullptr) |
450 | d.plugin->release(service); |
451 | } |
452 | } |
453 | |
454 | QMediaServiceProviderHint::Features supportedFeatures(const QMediaService *service) const override |
455 | { |
456 | if (service) { |
457 | MediaServiceData d = mediaServiceData.value(akey: service); |
458 | |
459 | if (d.plugin) { |
460 | QMediaServiceFeaturesInterface *iface = |
461 | qobject_cast<QMediaServiceFeaturesInterface*>(object: d.plugin); |
462 | |
463 | if (iface) |
464 | return iface->supportedFeatures(service: d.type); |
465 | } |
466 | } |
467 | |
468 | return QMediaServiceProviderHint::Features(); |
469 | } |
470 | |
471 | QMultimedia::SupportEstimate hasSupport(const QByteArray &serviceType, |
472 | const QString &mimeType, |
473 | const QStringList& codecs, |
474 | int flags) const override |
475 | { |
476 | const QList<QObject*> instances = loader()->instances(key: QLatin1String(serviceType)); |
477 | |
478 | if (instances.isEmpty()) |
479 | return QMultimedia::NotSupported; |
480 | |
481 | bool allServicesProvideInterface = true; |
482 | QMultimedia::SupportEstimate supportEstimate = QMultimedia::NotSupported; |
483 | |
484 | for (QObject *obj : instances) { |
485 | QMediaServiceSupportedFormatsInterface *iface = |
486 | qobject_cast<QMediaServiceSupportedFormatsInterface*>(object: obj); |
487 | |
488 | |
489 | if (flags) { |
490 | QMediaServiceFeaturesInterface *iface = |
491 | qobject_cast<QMediaServiceFeaturesInterface*>(object: obj); |
492 | |
493 | if (iface) { |
494 | QMediaServiceProviderHint::Features features = iface->supportedFeatures(service: serviceType); |
495 | |
496 | //if low latency playback was asked, skip services known |
497 | //not to provide low latency playback |
498 | if ((flags & QMediaPlayer::LowLatency) && |
499 | !(features & QMediaServiceProviderHint::LowLatencyPlayback)) |
500 | continue; |
501 | |
502 | //the same for QIODevice based streams support |
503 | if ((flags & QMediaPlayer::StreamPlayback) && |
504 | !(features & QMediaServiceProviderHint::StreamPlayback)) |
505 | continue; |
506 | } |
507 | } |
508 | |
509 | if (iface) |
510 | supportEstimate = qMax(a: supportEstimate, b: iface->hasSupport(mimeType, codecs)); |
511 | else |
512 | allServicesProvideInterface = false; |
513 | } |
514 | |
515 | //don't return PreferredService |
516 | supportEstimate = qMin(a: supportEstimate, b: QMultimedia::ProbablySupported); |
517 | |
518 | //Return NotSupported only if no services are available of serviceType |
519 | //or all the services returned NotSupported, otherwise return at least MaybeSupported |
520 | if (!allServicesProvideInterface) |
521 | supportEstimate = qMax(a: QMultimedia::MaybeSupported, b: supportEstimate); |
522 | |
523 | return supportEstimate; |
524 | } |
525 | |
526 | QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const override |
527 | { |
528 | const QList<QObject*> instances = loader()->instances(key: QLatin1String(serviceType)); |
529 | |
530 | QStringList supportedTypes; |
531 | |
532 | for (QObject *obj : instances) { |
533 | QMediaServiceSupportedFormatsInterface *iface = |
534 | qobject_cast<QMediaServiceSupportedFormatsInterface*>(object: obj); |
535 | |
536 | |
537 | if (flags) { |
538 | QMediaServiceFeaturesInterface *iface = |
539 | qobject_cast<QMediaServiceFeaturesInterface*>(object: obj); |
540 | |
541 | if (iface) { |
542 | QMediaServiceProviderHint::Features features = iface->supportedFeatures(service: serviceType); |
543 | |
544 | // If low latency playback was asked for, skip MIME types from services known |
545 | // not to provide low latency playback |
546 | if ((flags & QMediaPlayer::LowLatency) && |
547 | !(features & QMediaServiceProviderHint::LowLatencyPlayback)) |
548 | continue; |
549 | |
550 | //the same for QIODevice based streams support |
551 | if ((flags & QMediaPlayer::StreamPlayback) && |
552 | !(features & QMediaServiceProviderHint::StreamPlayback)) |
553 | continue; |
554 | |
555 | //the same for QAbstractVideoSurface support |
556 | if ((flags & QMediaPlayer::VideoSurface) && |
557 | !(features & QMediaServiceProviderHint::VideoSurface)) |
558 | continue; |
559 | } |
560 | } |
561 | |
562 | if (iface) { |
563 | supportedTypes << iface->supportedMimeTypes(); |
564 | } |
565 | } |
566 | |
567 | // Multiple services may support the same MIME type |
568 | supportedTypes.removeDuplicates(); |
569 | |
570 | return supportedTypes; |
571 | } |
572 | |
573 | QByteArray defaultDevice(const QByteArray &serviceType) const override |
574 | { |
575 | const auto instances = loader()->instances(key: QLatin1String(serviceType)); |
576 | for (QObject *obj : instances) { |
577 | const QMediaServiceDefaultDeviceInterface *iface = |
578 | qobject_cast<QMediaServiceDefaultDeviceInterface*>(object: obj); |
579 | |
580 | if (iface) { |
581 | QByteArray name = iface->defaultDevice(service: serviceType); |
582 | if (!name.isEmpty()) |
583 | return name; |
584 | } |
585 | } |
586 | |
587 | // if QMediaServiceDefaultDeviceInterface is not implemented, return the |
588 | // first available device. |
589 | QList<QByteArray> devs = devices(serviceType); |
590 | if (!devs.isEmpty()) |
591 | return devs.first(); |
592 | |
593 | return QByteArray(); |
594 | } |
595 | |
596 | QList<QByteArray> devices(const QByteArray &serviceType) const override |
597 | { |
598 | QList<QByteArray> res; |
599 | |
600 | const auto instances = loader()->instances(key: QLatin1String(serviceType)); |
601 | for (QObject *obj : instances) { |
602 | QMediaServiceSupportedDevicesInterface *iface = |
603 | qobject_cast<QMediaServiceSupportedDevicesInterface*>(object: obj); |
604 | |
605 | if (iface) { |
606 | res.append(t: iface->devices(service: serviceType)); |
607 | } |
608 | } |
609 | |
610 | return res; |
611 | } |
612 | |
613 | QString deviceDescription(const QByteArray &serviceType, const QByteArray &device) override |
614 | { |
615 | const auto instances = loader()->instances(key: QLatin1String(serviceType)); |
616 | for (QObject *obj : instances) { |
617 | QMediaServiceSupportedDevicesInterface *iface = |
618 | qobject_cast<QMediaServiceSupportedDevicesInterface*>(object: obj); |
619 | |
620 | if (iface) { |
621 | if (iface->devices(service: serviceType).contains(t: device)) |
622 | return iface->deviceDescription(service: serviceType, device); |
623 | } |
624 | } |
625 | |
626 | return QString(); |
627 | } |
628 | |
629 | QCamera::Position cameraPosition(const QByteArray &device) const override |
630 | { |
631 | const QByteArray serviceType(Q_MEDIASERVICE_CAMERA); |
632 | const auto instances = loader()->instances(key: QString::fromLatin1(str: serviceType)); |
633 | for (QObject *obj : instances) { |
634 | const QMediaServiceSupportedDevicesInterface *deviceIface = |
635 | qobject_cast<QMediaServiceSupportedDevicesInterface*>(object: obj); |
636 | const QMediaServiceCameraInfoInterface *cameraIface = |
637 | qobject_cast<QMediaServiceCameraInfoInterface*>(object: obj); |
638 | |
639 | if (cameraIface) { |
640 | if (deviceIface && !deviceIface->devices(service: serviceType).contains(t: device)) |
641 | continue; |
642 | return cameraIface->cameraPosition(device); |
643 | } |
644 | } |
645 | |
646 | return QCamera::UnspecifiedPosition; |
647 | } |
648 | |
649 | int cameraOrientation(const QByteArray &device) const override |
650 | { |
651 | const QByteArray serviceType(Q_MEDIASERVICE_CAMERA); |
652 | const auto instances = loader()->instances(key: QString::fromLatin1(str: serviceType)); |
653 | for (QObject *obj : instances) { |
654 | const QMediaServiceSupportedDevicesInterface *deviceIface = |
655 | qobject_cast<QMediaServiceSupportedDevicesInterface*>(object: obj); |
656 | const QMediaServiceCameraInfoInterface *cameraIface = |
657 | qobject_cast<QMediaServiceCameraInfoInterface*>(object: obj); |
658 | |
659 | if (cameraIface) { |
660 | if (deviceIface && !deviceIface->devices(service: serviceType).contains(t: device)) |
661 | continue; |
662 | return cameraIface->cameraOrientation(device); |
663 | } |
664 | } |
665 | |
666 | return 0; |
667 | } |
668 | }; |
669 | |
670 | Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider); |
671 | |
672 | /*! |
673 | \class QMediaServiceProvider |
674 | \obsolete |
675 | \ingroup multimedia |
676 | \ingroup multimedia_control |
677 | \ingroup multimedia_core |
678 | |
679 | \internal |
680 | |
681 | \brief The QMediaServiceProvider class provides an abstract allocator for media services. |
682 | */ |
683 | |
684 | /*! |
685 | \internal |
686 | \fn QMediaServiceProvider::requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) |
687 | |
688 | Requests an instance of a \a type service which best matches the given \a |
689 | hint. |
690 | |
691 | Returns a pointer to the requested service, or a null pointer if there is |
692 | no suitable service. |
693 | |
694 | The returned service must be released with releaseService when it is |
695 | finished with. |
696 | */ |
697 | |
698 | /*! |
699 | \internal |
700 | \fn QMediaServiceProvider::releaseService(QMediaService *service) |
701 | |
702 | Releases a media \a service requested with requestService(). |
703 | */ |
704 | |
705 | /*! |
706 | \internal |
707 | \fn QMediaServiceProvider::supportedFeatures(const QMediaService *service) const |
708 | |
709 | Returns the features supported by a given \a service. |
710 | */ |
711 | QMediaServiceProviderHint::Features QMediaServiceProvider::supportedFeatures(const QMediaService *service) const |
712 | { |
713 | Q_UNUSED(service); |
714 | |
715 | return {}; |
716 | } |
717 | |
718 | /*! |
719 | \internal |
720 | Returns how confident a media service provider is that is can provide a \a |
721 | serviceType service that is able to play media of a specific \a mimeType |
722 | that is encoded using the listed \a codecs while adhering to constraints |
723 | identified in \a flags. |
724 | */ |
725 | QMultimedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, |
726 | const QString &mimeType, |
727 | const QStringList& codecs, |
728 | int flags) const |
729 | { |
730 | Q_UNUSED(serviceType); |
731 | Q_UNUSED(mimeType); |
732 | Q_UNUSED(codecs); |
733 | Q_UNUSED(flags); |
734 | |
735 | return QMultimedia::MaybeSupported; |
736 | } |
737 | |
738 | /*! |
739 | \internal |
740 | \fn QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const |
741 | |
742 | Returns a list of MIME types supported by the service provider for the |
743 | specified \a serviceType. |
744 | |
745 | The resultant list is restricted to MIME types which can be supported given |
746 | the constraints in \a flags. |
747 | */ |
748 | QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const |
749 | { |
750 | Q_UNUSED(serviceType); |
751 | Q_UNUSED(flags); |
752 | |
753 | return QStringList(); |
754 | } |
755 | |
756 | /*! |
757 | \internal |
758 | \since 5.3 |
759 | |
760 | Returns the default device for a \a service type. |
761 | */ |
762 | QByteArray QMediaServiceProvider::defaultDevice(const QByteArray &serviceType) const |
763 | { |
764 | Q_UNUSED(serviceType); |
765 | return QByteArray(); |
766 | } |
767 | |
768 | /*! |
769 | \internal |
770 | Returns the list of devices related to \a service type. |
771 | */ |
772 | QList<QByteArray> QMediaServiceProvider::devices(const QByteArray &service) const |
773 | { |
774 | Q_UNUSED(service); |
775 | return QList<QByteArray>(); |
776 | } |
777 | |
778 | /*! |
779 | \internal |
780 | Returns the description of \a device related to \a serviceType, suitable for use by |
781 | an application for display. |
782 | */ |
783 | QString QMediaServiceProvider::deviceDescription(const QByteArray &serviceType, const QByteArray &device) |
784 | { |
785 | Q_UNUSED(serviceType); |
786 | Q_UNUSED(device); |
787 | return QString(); |
788 | } |
789 | |
790 | /*! |
791 | \internal |
792 | \since 5.3 |
793 | |
794 | Returns the physical position of a camera \a device on the system hardware. |
795 | */ |
796 | QCamera::Position QMediaServiceProvider::cameraPosition(const QByteArray &device) const |
797 | { |
798 | Q_UNUSED(device); |
799 | return QCamera::UnspecifiedPosition; |
800 | } |
801 | |
802 | /*! |
803 | \internal |
804 | \since 5.3 |
805 | |
806 | Returns the physical orientation of the camera \a device. The value is the angle by which the |
807 | camera image should be rotated anti-clockwise (in steps of 90 degrees) so it shows correctly on |
808 | the display in its natural orientation. |
809 | */ |
810 | int QMediaServiceProvider::cameraOrientation(const QByteArray &device) const |
811 | { |
812 | Q_UNUSED(device); |
813 | return 0; |
814 | } |
815 | |
816 | static QMediaServiceProvider *qt_defaultMediaServiceProvider = nullptr; |
817 | |
818 | /*! |
819 | Sets a media service \a provider as the default. |
820 | It's useful for unit tests to provide mock service. |
821 | |
822 | \internal |
823 | */ |
824 | void QMediaServiceProvider::setDefaultServiceProvider(QMediaServiceProvider *provider) |
825 | { |
826 | qt_defaultMediaServiceProvider = provider; |
827 | } |
828 | |
829 | |
830 | /*! |
831 | \internal |
832 | Returns a default provider of media services. |
833 | */ |
834 | QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider() |
835 | { |
836 | return qt_defaultMediaServiceProvider != nullptr |
837 | ? qt_defaultMediaServiceProvider |
838 | : static_cast<QMediaServiceProvider *>(pluginProvider()); |
839 | } |
840 | |
841 | /*! |
842 | \class QMediaServiceProviderPlugin |
843 | \obsolete |
844 | \inmodule QtMultimedia |
845 | \brief The QMediaServiceProviderPlugin class interface provides an interface for QMediaService |
846 | plug-ins. |
847 | |
848 | A media service provider plug-in may implement one or more of |
849 | QMediaServiceSupportedFormatsInterface, |
850 | QMediaServiceSupportedDevicesInterface, and QMediaServiceFeaturesInterface |
851 | to identify the features it supports. |
852 | */ |
853 | |
854 | /*! |
855 | \fn QMediaServiceProviderPlugin::create(const QString &key) |
856 | |
857 | Constructs a new instance of the QMediaService identified by \a key. |
858 | |
859 | The QMediaService returned must be destroyed with release(). |
860 | */ |
861 | |
862 | /*! |
863 | \fn QMediaServiceProviderPlugin::release(QMediaService *service) |
864 | |
865 | Destroys a media \a service constructed with create(). |
866 | */ |
867 | |
868 | |
869 | /*! |
870 | \class QMediaServiceSupportedFormatsInterface |
871 | \obsolete |
872 | \inmodule QtMultimedia |
873 | \brief The QMediaServiceSupportedFormatsInterface class interface |
874 | identifies if a media service plug-in supports a media format. |
875 | |
876 | A QMediaServiceProviderPlugin may implement this interface. |
877 | */ |
878 | |
879 | /*! |
880 | \fn QMediaServiceSupportedFormatsInterface::~QMediaServiceSupportedFormatsInterface() |
881 | |
882 | Destroys a media service supported formats interface. |
883 | */ |
884 | |
885 | /*! |
886 | \fn QMediaServiceSupportedFormatsInterface::hasSupport(const QString &mimeType, const QStringList& codecs) const |
887 | |
888 | Returns the level of support a media service plug-in has for a \a mimeType |
889 | and set of \a codecs. |
890 | */ |
891 | |
892 | /*! |
893 | \fn QMediaServiceSupportedFormatsInterface::supportedMimeTypes() const |
894 | |
895 | Returns a list of MIME types supported by the media service plug-in. |
896 | */ |
897 | |
898 | /*! |
899 | \class QMediaServiceSupportedDevicesInterface |
900 | \obsolete |
901 | \inmodule QtMultimedia |
902 | \brief The QMediaServiceSupportedDevicesInterface class interface |
903 | identifies the devices supported by a media service plug-in. |
904 | |
905 | A QMediaServiceProviderPlugin may implement this interface. |
906 | */ |
907 | |
908 | /*! |
909 | \fn QMediaServiceSupportedDevicesInterface::~QMediaServiceSupportedDevicesInterface() |
910 | |
911 | Destroys a media service supported devices interface. |
912 | */ |
913 | |
914 | /*! |
915 | \fn QList<QByteArray> QMediaServiceSupportedDevicesInterface::devices(const QByteArray &service) const |
916 | |
917 | Returns a list of devices available for a \a service type. |
918 | */ |
919 | |
920 | /*! |
921 | \fn QString QMediaServiceSupportedDevicesInterface::deviceDescription(const QByteArray &service, const QByteArray &device) |
922 | |
923 | Returns the description of a \a device available for a \a service type. |
924 | */ |
925 | |
926 | /*! |
927 | \class QMediaServiceDefaultDeviceInterface |
928 | \obsolete |
929 | \inmodule QtMultimedia |
930 | \brief The QMediaServiceDefaultDeviceInterface class interface |
931 | identifies the default device used by a media service plug-in. |
932 | |
933 | A QMediaServiceProviderPlugin may implement this interface. |
934 | |
935 | \since 5.3 |
936 | */ |
937 | |
938 | /*! |
939 | \fn QMediaServiceDefaultDeviceInterface::~QMediaServiceDefaultDeviceInterface() |
940 | |
941 | Destroys a media service default device interface. |
942 | */ |
943 | |
944 | /*! |
945 | \fn QByteArray QMediaServiceDefaultDeviceInterface::defaultDevice(const QByteArray &service) const |
946 | |
947 | Returns the default device for a \a service type. |
948 | */ |
949 | |
950 | /*! |
951 | \class QMediaServiceCameraInfoInterface |
952 | \obsolete |
953 | \inmodule QtMultimedia |
954 | \since 5.3 |
955 | \brief The QMediaServiceCameraInfoInterface class interface |
956 | provides camera-specific information about devices supported by a camera service plug-in. |
957 | |
958 | A QMediaServiceProviderPlugin may implement this interface, in that case it also needs to |
959 | implement the QMediaServiceSupportedDevicesInterface. |
960 | */ |
961 | |
962 | /*! |
963 | \fn QMediaServiceCameraInfoInterface::~QMediaServiceCameraInfoInterface() |
964 | |
965 | Destroys a media service camera info interface. |
966 | */ |
967 | |
968 | /*! |
969 | \fn QMediaServiceCameraInfoInterface::cameraPosition(const QByteArray &device) const |
970 | |
971 | Returns the physical position of a camera \a device supported by a camera service plug-in. |
972 | */ |
973 | |
974 | /*! |
975 | \fn QMediaServiceCameraInfoInterface::cameraOrientation(const QByteArray &device) const |
976 | |
977 | Returns the physical orientation of a camera \a device supported by a camera service plug-in. |
978 | */ |
979 | |
980 | /*! |
981 | \class QMediaServiceFeaturesInterface |
982 | \obsolete |
983 | \inmodule QtMultimedia |
984 | \brief The QMediaServiceFeaturesInterface class interface identifies |
985 | features supported by a media service plug-in. |
986 | |
987 | A QMediaServiceProviderPlugin may implement this interface. |
988 | */ |
989 | |
990 | /*! |
991 | \fn QMediaServiceFeaturesInterface::~QMediaServiceFeaturesInterface() |
992 | |
993 | Destroys a media service features interface. |
994 | */ |
995 | /*! |
996 | \fn QMediaServiceFeaturesInterface::supportedFeatures(const QByteArray &service) const |
997 | |
998 | Returns a set of features supported by a plug-in \a service. |
999 | */ |
1000 | |
1001 | QT_END_NAMESPACE |
1002 | |
1003 | #include "moc_qmediaserviceprovider_p.cpp" |
1004 | #include "moc_qmediaserviceproviderplugin.cpp" |
1005 | |