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