39 ** |
39 ** |
40 ****************************************************************************/ |
40 ****************************************************************************/ |
41 |
41 |
42 #include "qmediarecorder.h" |
42 #include "qmediarecorder.h" |
43 |
43 |
44 #include "qmediarecordercontrol.h" |
44 #include <qmediarecordercontrol.h> |
45 #include "qmediaobject_p.h" |
45 #include <qmediaobject_p.h> |
46 #include "qmediaservice.h" |
46 #include <qmediaservice.h> |
47 #include "qmediaserviceprovider.h" |
47 #include <qmediaserviceprovider.h> |
48 #include "qaudioencodercontrol.h" |
48 #include <qmetadatawritercontrol.h> |
49 #include "qvideoencodercontrol.h" |
49 #include <qaudioencodercontrol.h> |
50 #include "qmediacontainercontrol.h" |
50 #include <qvideoencodercontrol.h> |
|
51 #include <qmediacontainercontrol.h> |
51 |
52 |
52 #include <QtCore/qdebug.h> |
53 #include <QtCore/qdebug.h> |
53 #include <QtCore/qurl.h> |
54 #include <QtCore/qurl.h> |
54 #include <QtCore/qstringlist.h> |
55 #include <QtCore/qstringlist.h> |
55 #include <QtCore/qmetaobject.h> |
56 #include <QtCore/qmetaobject.h> |
56 |
57 |
57 #include <QtMultimedia/qaudioformat.h> |
58 #include <qaudioformat.h> |
58 |
59 |
59 QT_BEGIN_NAMESPACE |
60 QT_BEGIN_NAMESPACE |
60 |
61 |
61 /*! |
62 /*! |
62 \class QMediaRecorder |
63 \class QMediaRecorder |
63 \ingroup multimedia |
64 \ingroup multimedia |
64 |
65 |
65 \preliminary |
66 \preliminary |
66 \brief The QMediaRecorder class is used for the recording of media content. |
67 \brief The QMediaRecorder class is used for the recording of media content. |
67 |
68 |
68 The QMediaRecorder class is a high level media recording class. |
69 The QMediaRecorder class is a high level media recording class. It's not |
69 It's not intended to be used alone but for accessing the media |
70 intended to be used alone but for accessing the media recording functions |
70 recording functions of other media objects, like QRadioTuner, |
71 of other media objects, like QRadioTuner, or QAudioCaptureSource. |
71 or QAudioCaptureSource. |
|
72 |
|
73 If the radio is used as a source, recording |
|
74 is only possible when the source is in appropriate state |
|
75 |
72 |
76 \code |
73 \code |
77 // Audio only recording |
74 // Audio only recording |
78 audioSource = new QAudioCaptureSource; |
75 audioSource = new QAudioCaptureSource; |
79 recorder = new QMediaRecorder(audioSource); |
76 recorder = new QMediaRecorder(audioSource); |
80 |
77 |
81 QAudioEncoderSettings audioSettings; |
78 QAudioEncoderSettings audioSettings; |
82 audioSettings.setCodec("audio/vorbis"); |
79 audioSettings.setCodec("audio/vorbis"); |
83 audioSettings.setQuality(QtMediaServices::HighQuality); |
80 audioSettings.setQuality(QtMultimedia::HighQuality); |
84 |
81 |
85 recorder->setEncodingSettings(audioSettings); |
82 recorder->setEncodingSettings(audioSettings); |
86 |
83 |
87 recorder->setOutputLocation(QUrl::fromLocalFile(fileName)); |
84 recorder->setOutputLocation(QUrl::fromLocalFile(fileName)); |
88 recorder->record(); |
85 recorder->record(); |
104 } |
101 } |
105 } _registerRecorderMetaTypes; |
102 } _registerRecorderMetaTypes; |
106 } |
103 } |
107 |
104 |
108 |
105 |
109 class QMediaRecorderPrivate : public QMediaObjectPrivate |
106 class QMediaRecorderPrivate |
110 { |
107 { |
111 Q_DECLARE_NON_CONST_PUBLIC(QMediaRecorder) |
108 Q_DECLARE_NON_CONST_PUBLIC(QMediaRecorder) |
112 |
109 |
113 public: |
110 public: |
114 QMediaRecorderPrivate(); |
111 QMediaRecorderPrivate(); |
115 void initControls(); |
112 |
|
113 QMediaObject *mediaObject; |
116 |
114 |
117 QMediaRecorderControl *control; |
115 QMediaRecorderControl *control; |
118 QMediaContainerControl *formatControl; |
116 QMediaContainerControl *formatControl; |
119 QAudioEncoderControl *audioControl; |
117 QAudioEncoderControl *audioControl; |
120 QVideoEncoderControl *videoControl; |
118 QVideoEncoderControl *videoControl; |
|
119 QMetaDataWriterControl *metaDataControl; |
121 |
120 |
122 QMediaRecorder::State state; |
121 QMediaRecorder::State state; |
123 QMediaRecorder::Error error; |
122 QMediaRecorder::Error error; |
124 QString errorString; |
123 QString errorString; |
125 |
124 |
126 void _q_stateChanged(QMediaRecorder::State state); |
125 void _q_stateChanged(QMediaRecorder::State state); |
127 void _q_error(int error, const QString &errorString); |
126 void _q_error(int error, const QString &errorString); |
|
127 void _q_serviceDestroyed(); |
|
128 |
|
129 QMediaRecorder *q_ptr; |
128 }; |
130 }; |
129 |
131 |
130 QMediaRecorderPrivate::QMediaRecorderPrivate(): |
132 QMediaRecorderPrivate::QMediaRecorderPrivate(): |
|
133 mediaObject(0), |
131 control(0), |
134 control(0), |
132 formatControl(0), |
135 formatControl(0), |
133 audioControl(0), |
136 audioControl(0), |
134 videoControl(0), |
137 videoControl(0), |
|
138 metaDataControl(0), |
135 state(QMediaRecorder::StoppedState), |
139 state(QMediaRecorder::StoppedState), |
136 error(QMediaRecorder::NoError) |
140 error(QMediaRecorder::NoError) |
137 { |
141 { |
138 } |
142 } |
139 |
143 |
140 void QMediaRecorderPrivate::initControls() |
144 #define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v))) |
|
145 |
|
146 void QMediaRecorderPrivate::_q_stateChanged(QMediaRecorder::State ps) |
141 { |
147 { |
142 Q_Q(QMediaRecorder); |
148 Q_Q(QMediaRecorder); |
143 |
149 |
144 if (!service) |
150 /* |
145 return; |
|
146 |
|
147 control = qobject_cast<QMediaRecorderControl*>(service->control(QMediaRecorderControl_iid)); |
|
148 formatControl = qobject_cast<QMediaContainerControl *>(service->control(QMediaContainerControl_iid)); |
|
149 audioControl = qobject_cast<QAudioEncoderControl *>(service->control(QAudioEncoderControl_iid)); |
|
150 videoControl = qobject_cast<QVideoEncoderControl *>(service->control(QVideoEncoderControl_iid)); |
|
151 |
|
152 if (control) { |
|
153 q->connect(control, SIGNAL(stateChanged(QMediaRecorder::State)), |
|
154 q, SLOT(_q_stateChanged(QMediaRecorder::State))); |
|
155 |
|
156 q->connect(control, SIGNAL(error(int,QString)), |
|
157 q, SLOT(_q_error(int,QString))); |
|
158 } |
|
159 } |
|
160 |
|
161 #define ENUM_NAME(c,e,v) (c::staticMetaObject.enumerator(c::staticMetaObject.indexOfEnumerator(e)).valueToKey((v))) |
|
162 |
|
163 |
|
164 void QMediaRecorderPrivate::_q_stateChanged(QMediaRecorder::State ps) |
|
165 { |
|
166 Q_Q(QMediaRecorder); |
|
167 |
|
168 if (ps == QMediaRecorder::RecordingState) |
151 if (ps == QMediaRecorder::RecordingState) |
169 q->addPropertyWatch("duration"); |
152 q->addPropertyWatch("duration"); |
170 else |
153 else |
171 q->removePropertyWatch("duration"); |
154 q->removePropertyWatch("duration"); |
|
155 */ |
172 |
156 |
173 // qDebug() << "Recorder state changed:" << ENUM_NAME(QMediaRecorder,"State",ps); |
157 // qDebug() << "Recorder state changed:" << ENUM_NAME(QMediaRecorder,"State",ps); |
174 if (state != ps) { |
158 if (state != ps) { |
175 emit q->stateChanged(ps); |
159 emit q->stateChanged(ps); |
176 } |
160 } |
187 this->errorString = errorString; |
171 this->errorString = errorString; |
188 |
172 |
189 emit q->error(this->error); |
173 emit q->error(this->error); |
190 } |
174 } |
191 |
175 |
|
176 void QMediaRecorderPrivate::_q_serviceDestroyed() |
|
177 { |
|
178 q_func()->setMediaObject(0); |
|
179 } |
|
180 |
192 |
181 |
193 /*! |
182 /*! |
194 Constructs a media recorder which records the media produced by \a mediaObject. |
183 Constructs a media recorder which records the media produced by \a mediaObject. |
195 |
184 |
196 The \a parent is passed to QMediaObject. |
185 The \a parent is passed to QMediaObject. |
197 */ |
186 */ |
198 |
187 |
199 QMediaRecorder::QMediaRecorder(QMediaObject *mediaObject, QObject *parent): |
188 QMediaRecorder::QMediaRecorder(QMediaObject *mediaObject, QObject *parent): |
200 QMediaObject(*new QMediaRecorderPrivate, parent, mediaObject->service()) |
189 QObject(parent), |
201 { |
190 d_ptr(new QMediaRecorderPrivate) |
202 Q_D(QMediaRecorder); |
191 { |
203 |
192 Q_D(QMediaRecorder); |
204 d->initControls(); |
193 d->q_ptr = this; |
|
194 setMediaObject(mediaObject); |
205 } |
195 } |
206 |
196 |
207 /*! |
197 /*! |
208 Destroys a media recorder object. |
198 Destroys a media recorder object. |
209 */ |
199 */ |
210 |
200 |
211 QMediaRecorder::~QMediaRecorder() |
201 QMediaRecorder::~QMediaRecorder() |
212 { |
202 { |
|
203 } |
|
204 |
|
205 QMediaObject *QMediaRecorder::mediaObject() const |
|
206 { |
|
207 return d_func()->mediaObject; |
|
208 } |
|
209 |
|
210 bool QMediaRecorder::setMediaObject(QMediaObject *object) |
|
211 { |
|
212 Q_D(QMediaRecorder); |
|
213 |
|
214 if (object == d->mediaObject) |
|
215 return true; |
|
216 |
|
217 if (d->mediaObject) { |
|
218 if (d->control) { |
|
219 disconnect(d->control, SIGNAL(stateChanged(QMediaRecorder::State)), |
|
220 this, SLOT(_q_stateChanged(QMediaRecorder::State))); |
|
221 |
|
222 disconnect(d->control, SIGNAL(mutedChanged(bool)), |
|
223 this, SIGNAL(mutedChanged(bool))); |
|
224 |
|
225 disconnect(d->control, SIGNAL(durationChanged(qint64)), |
|
226 this, SIGNAL(durationChanged(qint64))); |
|
227 |
|
228 disconnect(d->control, SIGNAL(error(int,QString)), |
|
229 this, SLOT(_q_error(int,QString))); |
|
230 } |
|
231 |
|
232 QMediaService *service = d->mediaObject->service(); |
|
233 |
|
234 if (service) { |
|
235 disconnect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); |
|
236 |
|
237 if (d->control) |
|
238 service->releaseControl(d->control); |
|
239 if (d->formatControl) |
|
240 service->releaseControl(d->formatControl); |
|
241 if (d->audioControl) |
|
242 service->releaseControl(d->audioControl); |
|
243 if (d->videoControl) |
|
244 service->releaseControl(d->videoControl); |
|
245 if (d->metaDataControl) { |
|
246 disconnect(d->metaDataControl, SIGNAL(metaDataChanged()), |
|
247 this, SIGNAL(metaDataChanged())); |
|
248 disconnect(d->metaDataControl, SIGNAL(metaDataAvailableChanged(bool)), |
|
249 this, SIGNAL(metaDataAvailableChanged(bool))); |
|
250 disconnect(d->metaDataControl, SIGNAL(writableChanged(bool)), |
|
251 this, SIGNAL(metaDataWritableChanged(bool))); |
|
252 |
|
253 service->releaseControl(d->metaDataControl); |
|
254 } |
|
255 } |
|
256 } |
|
257 |
|
258 d->control = 0; |
|
259 d->formatControl = 0; |
|
260 d->audioControl = 0; |
|
261 d->videoControl = 0; |
|
262 d->metaDataControl = 0; |
|
263 |
|
264 d->mediaObject = object; |
|
265 |
|
266 if (d->mediaObject) { |
|
267 QMediaService *service = d->mediaObject->service(); |
|
268 |
|
269 if (service) { |
|
270 d->control = qobject_cast<QMediaRecorderControl*>(service->requestControl(QMediaRecorderControl_iid)); |
|
271 |
|
272 if (d->control) { |
|
273 d->formatControl = qobject_cast<QMediaContainerControl *>(service->requestControl(QMediaContainerControl_iid)); |
|
274 d->audioControl = qobject_cast<QAudioEncoderControl *>(service->requestControl(QAudioEncoderControl_iid)); |
|
275 d->videoControl = qobject_cast<QVideoEncoderControl *>(service->requestControl(QVideoEncoderControl_iid)); |
|
276 |
|
277 QMediaControl *control = service->requestControl(QMetaDataWriterControl_iid); |
|
278 if (control) { |
|
279 d->metaDataControl = qobject_cast<QMetaDataWriterControl *>(control); |
|
280 if (!d->metaDataControl) { |
|
281 service->releaseControl(control); |
|
282 } else { |
|
283 connect(d->metaDataControl, |
|
284 SIGNAL(metaDataChanged()), |
|
285 SIGNAL(metaDataChanged())); |
|
286 connect(d->metaDataControl, |
|
287 SIGNAL(metaDataAvailableChanged(bool)), |
|
288 SIGNAL(metaDataAvailableChanged(bool))); |
|
289 connect(d->metaDataControl, |
|
290 SIGNAL(writableChanged(bool)), |
|
291 SIGNAL(metaDataWritableChanged(bool))); |
|
292 } |
|
293 } |
|
294 |
|
295 connect(d->control, SIGNAL(stateChanged(QMediaRecorder::State)), |
|
296 this, SLOT(_q_stateChanged(QMediaRecorder::State))); |
|
297 |
|
298 connect(d->control, SIGNAL(mutedChanged(bool)), |
|
299 this, SIGNAL(mutedChanged(bool))); |
|
300 |
|
301 connect(d->control, SIGNAL(durationChanged(qint64)), |
|
302 this, SIGNAL(durationChanged(qint64))); |
|
303 |
|
304 connect(d->control, SIGNAL(error(int,QString)), |
|
305 this, SLOT(_q_error(int,QString))); |
|
306 |
|
307 connect(service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); |
|
308 |
|
309 |
|
310 return true; |
|
311 } |
|
312 } |
|
313 |
|
314 d->mediaObject = 0; |
|
315 return false; |
|
316 } |
|
317 |
|
318 return true; |
213 } |
319 } |
214 |
320 |
215 /*! |
321 /*! |
216 \property QMediaRecorder::outputLocation |
322 \property QMediaRecorder::outputLocation |
217 \brief the destination location of media content. |
323 \brief the destination location of media content. |
218 |
324 |
219 Setting the location can fail for example when the service supports |
325 Setting the location can fail, for example when the service supports only |
220 only local file system locations while the network url was passed, |
326 local file system locations but a network URL was passed. If the service |
221 or the service doesn't support media recording. |
327 does not support media recording this setting the output location will |
|
328 always fail. |
222 */ |
329 */ |
223 |
330 |
224 /*! |
331 /*! |
225 Returns true if media recorder service ready to use. |
332 Returns true if media recorder service ready to use. |
226 */ |
333 */ |
451 } |
580 } |
452 |
581 |
453 /*! |
582 /*! |
454 Sets the \a audio and \a video encoder settings and \a container format MIME type. |
583 Sets the \a audio and \a video encoder settings and \a container format MIME type. |
455 |
584 |
456 It's only possible to change setttings when the encoder |
585 If some parameters are not specified, or null settings are passed, the |
457 is in the QMediaEncoder::StoppedState state. |
586 encoder will choose default encoding parameters, depending on media |
458 |
587 source properties. |
459 If some parameters are not specified, or null settings are passed, |
588 While setEncodingSettings is optional, the backend can preload |
460 the encoder choose the default encoding parameters, depending on |
|
461 media source properties. |
|
462 But while setEncodingSettings is optional, the backend can preload |
|
463 encoding pipeline to improve recording startup time. |
589 encoding pipeline to improve recording startup time. |
|
590 |
|
591 It's only possible to change settings when the encoder is in the |
|
592 QMediaEncoder::StoppedState state. |
464 |
593 |
465 \sa audioSettings(), videoSettings(), containerMimeType() |
594 \sa audioSettings(), videoSettings(), containerMimeType() |
466 */ |
595 */ |
467 |
596 |
468 void QMediaRecorder::setEncodingSettings(const QAudioEncoderSettings &audio, |
597 void QMediaRecorder::setEncodingSettings(const QAudioEncoderSettings &audio, |
560 |
689 |
561 Signals that an \a error has occurred. |
690 Signals that an \a error has occurred. |
562 */ |
691 */ |
563 |
692 |
564 |
693 |
|
694 /*! |
|
695 \property QMediaRecorder::metaDataAvailable |
|
696 \brief whether access to a media object's meta-data is available. |
|
697 |
|
698 If this is true there is meta-data available, otherwise there is no meta-data available. |
|
699 */ |
|
700 |
|
701 bool QMediaRecorder::isMetaDataAvailable() const |
|
702 { |
|
703 Q_D(const QMediaRecorder); |
|
704 |
|
705 return d->metaDataControl |
|
706 ? d->metaDataControl->isMetaDataAvailable() |
|
707 : false; |
|
708 } |
|
709 |
|
710 /*! |
|
711 \fn QMediaRecorder::metaDataAvailableChanged(bool available) |
|
712 |
|
713 Signals that the \a available state of a media object's meta-data has changed. |
|
714 */ |
|
715 |
|
716 /*! |
|
717 \property QMediaRecorder::metaDataWritable |
|
718 \brief whether a media object's meta-data is writable. |
|
719 |
|
720 If this is true the meta-data is writable, otherwise the meta-data is read-only. |
|
721 */ |
|
722 |
|
723 bool QMediaRecorder::isMetaDataWritable() const |
|
724 { |
|
725 Q_D(const QMediaRecorder); |
|
726 |
|
727 return d->metaDataControl |
|
728 ? d->metaDataControl->isWritable() |
|
729 : false; |
|
730 } |
|
731 |
|
732 /*! |
|
733 \fn QMediaRecorder::metaDataWritableChanged(bool writable) |
|
734 |
|
735 Signals that the \a writable state of a media object's meta-data has changed. |
|
736 */ |
|
737 |
|
738 /*! |
|
739 Returns the value associated with a meta-data \a key. |
|
740 */ |
|
741 QVariant QMediaRecorder::metaData(QtMultimedia::MetaData key) const |
|
742 { |
|
743 Q_D(const QMediaRecorder); |
|
744 |
|
745 return d->metaDataControl |
|
746 ? d->metaDataControl->metaData(key) |
|
747 : QVariant(); |
|
748 } |
|
749 |
|
750 /*! |
|
751 Sets a \a value for a meta-data \a key. |
|
752 */ |
|
753 void QMediaRecorder::setMetaData(QtMultimedia::MetaData key, const QVariant &value) |
|
754 { |
|
755 Q_D(QMediaRecorder); |
|
756 |
|
757 if (d->metaDataControl) |
|
758 d->metaDataControl->setMetaData(key, value); |
|
759 } |
|
760 |
|
761 /*! |
|
762 Returns a list of keys there is meta-data available for. |
|
763 */ |
|
764 QList<QtMultimedia::MetaData> QMediaRecorder::availableMetaData() const |
|
765 { |
|
766 Q_D(const QMediaRecorder); |
|
767 |
|
768 return d->metaDataControl |
|
769 ? d->metaDataControl->availableMetaData() |
|
770 : QList<QtMultimedia::MetaData>(); |
|
771 } |
|
772 |
|
773 /*! |
|
774 \fn QMediaRecorder::metaDataChanged() |
|
775 |
|
776 Signals that a media object's meta-data has changed. |
|
777 */ |
|
778 |
|
779 /*! |
|
780 Returns the value associated with a meta-data \a key. |
|
781 |
|
782 The naming and type of extended meta-data is not standardized, so the values and meaning |
|
783 of keys may vary between backends. |
|
784 */ |
|
785 QVariant QMediaRecorder::extendedMetaData(const QString &key) const |
|
786 { |
|
787 Q_D(const QMediaRecorder); |
|
788 |
|
789 return d->metaDataControl |
|
790 ? d->metaDataControl->extendedMetaData(key) |
|
791 : QVariant(); |
|
792 } |
|
793 |
|
794 /*! |
|
795 Sets a \a value for a meta-data \a key. |
|
796 |
|
797 The naming and type of extended meta-data is not standardized, so the values and meaning |
|
798 of keys may vary between backends. |
|
799 */ |
|
800 void QMediaRecorder::setExtendedMetaData(const QString &key, const QVariant &value) |
|
801 { |
|
802 Q_D(QMediaRecorder); |
|
803 |
|
804 if (d->metaDataControl) |
|
805 d->metaDataControl->setExtendedMetaData(key, value); |
|
806 } |
|
807 |
|
808 /*! |
|
809 Returns a list of keys there is extended meta-data available for. |
|
810 */ |
|
811 QStringList QMediaRecorder::availableExtendedMetaData() const |
|
812 { |
|
813 Q_D(const QMediaRecorder); |
|
814 |
|
815 return d->metaDataControl |
|
816 ? d->metaDataControl->availableExtendedMetaData() |
|
817 : QStringList(); |
|
818 } |
|
819 |
565 #include "moc_qmediarecorder.cpp" |
820 #include "moc_qmediarecorder.cpp" |
566 QT_END_NAMESPACE |
821 QT_END_NAMESPACE |
567 |
822 |