summaryrefslogtreecommitdiff
path: root/plugins/org.apache.cordova.media/src/ubuntu
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.apache.cordova.media/src/ubuntu')
-rw-r--r--plugins/org.apache.cordova.media/src/ubuntu/media.cpp128
-rw-r--r--plugins/org.apache.cordova.media/src/ubuntu/media.h267
2 files changed, 395 insertions, 0 deletions
diff --git a/plugins/org.apache.cordova.media/src/ubuntu/media.cpp b/plugins/org.apache.cordova.media/src/ubuntu/media.cpp
new file mode 100644
index 00000000..2814b5b3
--- /dev/null
+++ b/plugins/org.apache.cordova.media/src/ubuntu/media.cpp
@@ -0,0 +1,128 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#include "media.h"
+
+void Media::create(int scId, int ecId, const QString &id, const QString &src) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) != _id2Player.end()) {
+ _id2Player[id]->stop();
+ _id2Player.remove(id);
+ }
+
+ _id2Player[id] = QSharedPointer<Player>(new Player(id, src, this));
+}
+
+void Media::relase(int scId, int ecId, const QString &id) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ _id2Player.remove(id);
+}
+
+void Media::startPlayingAudio(int scId, int ecId, const QString &id, const QString &src, QVariantMap options) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+ Q_UNUSED(src);
+ Q_UNUSED(options);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ QSharedPointer<Player> player = _id2Player[id];
+ player->play();
+}
+
+void Media::pausePlayingAudio(int scId, int ecId, const QString &id) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ QSharedPointer<Player> player = _id2Player[id];
+ player->pause();
+}
+
+void Media::stopPlayingAudio(int scId, int ecId, const QString &id) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ QSharedPointer<Player> player = _id2Player[id];
+ player->stop();
+}
+
+void Media::startRecordingAudio(int scId, int ecId, const QString &id, const QString &src) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+ Q_UNUSED(src);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ QSharedPointer<Player> player = _id2Player[id];
+ player->startRecording();
+}
+
+void Media::stopRecordingAudio(int scId, int ecId, const QString &id) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ QSharedPointer<Player> player = _id2Player[id];
+ player->stopRecording();
+}
+
+void Media::getCurrentPositionAudio(int scId, int ecId, const QString &id) {
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+
+ QSharedPointer<Player> player = _id2Player[id];
+ double position = player->getPosition();
+ this->cb(scId, position);
+}
+
+void Media::seekToAudio(int scId, int ecId, const QString &id, qint64 position) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+
+ QSharedPointer<Player> player = _id2Player[id];
+ player->seekTo(position);
+}
+
+void Media::setVolume(int scId, int ecId, const QString &id, int volume) {
+ Q_UNUSED(scId);
+ Q_UNUSED(ecId);
+
+ if (_id2Player.find(id) == _id2Player.end())
+ return;
+ QSharedPointer<Player> player = _id2Player[id];
+ player->setVolume(volume);
+}
diff --git a/plugins/org.apache.cordova.media/src/ubuntu/media.h b/plugins/org.apache.cordova.media/src/ubuntu/media.h
new file mode 100644
index 00000000..c1f37122
--- /dev/null
+++ b/plugins/org.apache.cordova.media/src/ubuntu/media.h
@@ -0,0 +1,267 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+#ifndef MEDIA_H_789768978
+#define MEDIA_H_789768978
+
+#include <QtMultimedia/QMediaPlayer>
+#include <QtCore>
+#include <QAudioRecorder>
+#include <QtMultimedia/QAudioEncoderSettings>
+
+#include <cplugin.h>
+#include <cordova.h>
+
+class Player;
+
+class Media: public CPlugin {
+ Q_OBJECT
+public:
+ explicit Media(Cordova *cordova): CPlugin(cordova) {
+ }
+
+ virtual const QString fullName() override {
+ return Media::fullID();
+ }
+
+ virtual const QString shortName() override {
+ return "Media";
+ }
+
+ static const QString fullID() {
+ return "Media";
+ }
+
+ enum State {
+ MEDIA_NONE = 0,
+ MEDIA_STARTING = 1,
+ MEDIA_RUNNING = 2,
+ MEDIA_PAUSED = 3,
+ MEDIA_STOPPED = 4
+ };
+ enum ErrorCode {
+ MEDIA_ERR_NONE_ACTIVE = 0,
+ MEDIA_ERR_ABORTED = 1,
+ MEDIA_ERR_NETWORK = 2,
+ MEDIA_ERR_DECODE = 3,
+ MEDIA_ERR_NONE_SUPPORTED = 4
+ };
+
+ void execJS(const QString &js) {
+ m_cordova->execJS(js);
+ }
+public slots:
+ void create(int scId, int ecId, const QString &id, const QString &src);
+ void relase(int scId, int ecId, const QString &id);
+
+ void startRecordingAudio(int scId, int ecId, const QString &id, const QString &src);
+ void stopRecordingAudio(int scId, int ecId, const QString &id);
+
+ void startPlayingAudio(int scId, int ecId, const QString &id, const QString &src, QVariantMap options);
+ void pausePlayingAudio(int scId, int ecId, const QString &id);
+ void stopPlayingAudio(int scId, int ecId, const QString &id);
+ void getCurrentPositionAudio(int scId, int ecId, const QString &id);
+ void seekToAudio(int scId, int ecId, const QString &id, qint64 position);
+ void setVolume(int scId, int ecId, const QString &id, int volume);
+
+private:
+ QMap<QString, QSharedPointer<Player> > _id2Player;
+};
+
+class Player: public QObject {
+ Q_OBJECT
+public:
+ Player(const QString &id, QString src, Media *plugin):
+ _state(Media::MEDIA_NONE),
+ _src(src),
+ _mode(MODE_NONE),
+ _plugin(plugin),
+ _id(id),
+ _stateChanged(false) {
+ QUrl url(src, QUrl::TolerantMode);
+
+ if (url.scheme().isEmpty()) {
+ QAudioEncoderSettings audioSettings;
+
+ _recorder.setEncodingSettings(audioSettings);
+ _recorder.setOutputLocation(QFileInfo(src).absoluteFilePath());
+
+ _player.setMedia(QUrl::fromLocalFile(QFileInfo(src).absoluteFilePath()));
+ } else {
+ _player.setMedia(url);
+ }
+ QObject::connect(&_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(onMediaStatusChanged(QMediaPlayer::MediaStatus)));
+ QObject::connect(&_recorder, SIGNAL(error(QMediaRecorder::Error)), this, SLOT(onError(QMediaRecorder::Error)));
+
+ connect(&_timer, SIGNAL(timeout()), this, SLOT(reportPosition()));
+ }
+
+ void startRecording() {
+ if (recordMode() && _state != Media::MEDIA_RUNNING) {
+ _recorder.record();
+ setState(Media::MEDIA_RUNNING);
+ }
+ }
+ void stopRecording() {
+ if (recordMode() && _state == Media::MEDIA_RUNNING) {
+ _recorder.stop();
+ setState(Media::MEDIA_STOPPED);
+ }
+ }
+
+ void setVolume(int volume) {
+ _player.setVolume(volume);
+ }
+
+ void play() {
+ if (playMode() && _state != Media::MEDIA_RUNNING) {
+ _player.play();
+ setState(Media::MEDIA_RUNNING);
+ }
+ }
+ void pause() {
+ if (playMode() && _state == Media::MEDIA_RUNNING) {
+ _player.pause();
+ setState(Media::MEDIA_PAUSED);
+ }
+ }
+ void stop() {
+ if (playMode() && (_state == Media::MEDIA_RUNNING || _state == Media::MEDIA_PAUSED)) {
+ _player.stop();
+ setState(Media::MEDIA_STOPPED);
+ }
+ }
+ double getDuration() {
+ if (_mode == MODE_NONE || _player.duration() == -1)
+ return -1;
+ if (_mode != MODE_PLAY)
+ return -2;
+ return static_cast<double>(_player.duration()) / 1000.0;
+ }
+ double getPosition() {
+ if (_mode != MODE_PLAY)
+ return -1;
+ return static_cast<double>(_player.position()) / 1000.0;
+ }
+ bool seekTo(qint64 position) {
+ if (!_player.isSeekable())
+ return false;
+ _player.setPosition(position * 1000);
+ return true;
+ }
+private slots:
+ void reportPosition() {
+ double position = getPosition();
+ _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_POSITION, %2)")
+ .arg(_id).arg(position));
+ double duration = getDuration();
+ _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_DURATION, %2)")
+ .arg(_id).arg(duration));
+
+ if (_stateChanged && !(_state == Media::MEDIA_RUNNING && (duration == -1 || position == 0))) {
+ qCritical() << _id << "POSITION" << position << ":" << duration;
+ _stateChanged = false;
+ _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_STATE, %2)").arg(_id).arg(_state));
+ }
+ }
+
+ void onMediaStatusChanged(QMediaPlayer::MediaStatus status) {
+ if (status == QMediaPlayer::InvalidMedia) {
+ reportError(Media::MEDIA_ERR_ABORTED, "AudioPlayer Error: The current media cannot be played.");
+ setState(Media::MEDIA_STOPPED);
+ }
+ if (status == QMediaPlayer::EndOfMedia) {
+ setState(Media::MEDIA_STOPPED);
+ seekTo(0);
+ }
+ }
+ void onError(QMediaRecorder::Error) {
+ reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: Device is not ready or not available.");
+ setState(Media::MEDIA_STOPPED);
+ }
+
+private:
+ void reportError(int code, const QString &descr) {
+ Q_UNUSED(descr);
+ _plugin->execJS(QString("Media.onStatus('%1', Media.MEDIA_ERROR, {code: %2})")
+ .arg(_id).arg(code));
+ }
+
+ bool playMode() {
+ switch (_mode) {
+ case Player::MODE_NONE:
+ _mode = MODE_PLAY;
+ break;
+ case Player::MODE_PLAY:
+ break;
+ case Player::MODE_RECORD:
+ reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: Can't play in record mode.");
+ return false;
+ break;
+ }
+ return true;
+ }
+
+ bool recordMode() {
+ switch (_mode) {
+ case Player::MODE_NONE:
+ if (_recorder.outputLocation().isEmpty()) {
+ reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: unsupported output location.");
+ return false;
+ }
+ _mode = MODE_RECORD;
+ break;
+ case Player::MODE_PLAY:
+ reportError(Media::MEDIA_ERR_NONE_SUPPORTED, "AudioPlayer Error: Can't play in play mode.");
+ return false;
+ break;
+ case Player::MODE_RECORD:
+ break;
+ }
+ return true;
+ }
+
+ void setState(Media::State state) {
+ _state = state;
+ _stateChanged = true;
+ _timer.start(250);
+ }
+
+ QMediaPlayer _player;
+
+ QAudioRecorder _recorder;
+ QTimer _timer;
+
+ Media::State _state;
+ QString _src;
+ enum Mode {
+ MODE_NONE,
+ MODE_PLAY,
+ MODE_RECORD
+ };
+ Mode _mode;
+ Media *_plugin;
+ QString _id;
+
+ bool _stateChanged;
+};
+
+#endif