Advertisement
Guest User

Untitled

a guest
Mar 21st, 2012
319
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. qandroidmediaplayer.h
  2.  
  3. #ifndef QANDROIDMEDIAPLAYER_H
  4. #define QANDROIDMEDIAPLAYER_H
  5.  
  6. #include <QtCore>
  7. #include <SLES/OpenSLES.h>
  8. #include <SLES/OpenSLES_Android.h>
  9.  
  10. class QAndroidMediaPlayer : public QObject
  11. {
  12.     Q_OBJECT
  13.     Q_ENUMS(State)
  14.     Q_ENUMS(MediaStatus)
  15.     Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
  16.     Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged)
  17.     Q_PROPERTY(qint64 position READ position WRITE setPosition NOTIFY positionChanged)
  18.     Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
  19.     Q_PROPERTY(int notifyInterval READ notifyInterval WRITE setNotifyInterval NOTIFY notifyIntervalChanged)
  20.     Q_PROPERTY(State state READ state NOTIFY stateChanged)
  21.  
  22.     friend void GlobalCallbackPositionChanged(SLPlayItf caller, void *pContext, SLuint32 playevent);
  23. public:
  24.     explicit QAndroidMediaPlayer(QObject *parent = 0);
  25.     ~QAndroidMediaPlayer();
  26.  
  27.     enum State {
  28.         StoppedState = 0,
  29.         PlayingState = 1,
  30.         PausedState = 2
  31.     };
  32.  
  33.     enum MediaStatus {
  34.         EndOfMedia = 7
  35.     };
  36.  
  37.     bool isMuted() const;
  38.     void setMuted(bool);
  39.  
  40.     int volume() const;
  41.     void setVolume(int);
  42.  
  43.     qint64 position() const;
  44.     void setPosition(qint64);
  45.  
  46.     qint64 duration() const;
  47.  
  48.     int notifyInterval() const;
  49.     void setNotifyInterval(int);
  50.  
  51.     State state() const;
  52.  
  53. signals:
  54.     void mutedChanged(bool);
  55.     void volumeChanged(int);
  56.     void positionChanged(qint64);
  57.     void durationChanged(qint64);
  58.     void notifyIntervalChanged(int);
  59.     void mediaStatusChanged(int);
  60.     void stateChanged(int);
  61.  
  62. public slots:
  63.     void setMedia(const QUrl& media);
  64.     void play();
  65.     void pause();
  66.     void stop();
  67.  
  68. private:
  69.     static void checkResult(const SLresult&);
  70.     static void openMusicProfile();
  71.     //void closeMusicProfile();
  72.     void openAudioPlayer(const QUrl& url);
  73.     void closeAudioPlayer();
  74.     void callbackPositionChanged(SLuint32 playevent);
  75.  
  76.     static SLObjectItf m_engineObj;
  77.     static SLEngineItf m_engineItf;
  78.  
  79.     static SLObjectItf m_outputObj;
  80.  
  81.     SLObjectItf m_playerObject;
  82.     SLPlayItf m_playItf;
  83.     SLSeekItf m_SeekItf;
  84.  
  85.     int m_notifyInterval;
  86.     QAndroidMediaPlayer::State m_state;
  87.  
  88. };
  89.  
  90. #endif // QANDROIDMEDIAPLAYER_H
  91.  
  92. qandroidmediaplayer.cpp
  93.  
  94. #include "qandroidmediaplayer.h"
  95.  
  96. void GlobalCallbackPositionChanged(SLPlayItf, void *pContext, SLuint32 playevent)
  97. {
  98.     qDebug() << "GlobalCallbackPositionChanged";
  99.     QAndroidMediaPlayer* player = qobject_cast<QAndroidMediaPlayer*>(pContext);
  100.     if (player) {
  101.         player->callbackPositionChanged(playevent);
  102.     }
  103. }
  104.  
  105. SLObjectItf QAndroidMediaPlayer::m_engineObj = NULL;
  106. SLEngineItf QAndroidMediaPlayer::m_engineItf = NULL;
  107. SLObjectItf QAndroidMediaPlayer::m_outputObj = NULL;
  108.  
  109. QAndroidMediaPlayer::QAndroidMediaPlayer(QObject *parent) :
  110.     QObject(parent),
  111.     m_playerObject(NULL),
  112.     m_playItf(NULL),
  113.     m_SeekItf(NULL),
  114.     m_notifyInterval(1000)
  115. {
  116.     qDebug() << "Load started";
  117.     if (m_engineObj == NULL) {
  118.         openMusicProfile();
  119.     }
  120.     qDebug() << "Load finished";
  121.     qDebug() << "Append finished";
  122. }
  123.  
  124.  
  125. QAndroidMediaPlayer::~QAndroidMediaPlayer()
  126. {
  127.     this->closeAudioPlayer();
  128.     //this->closeMusicProfile();
  129. }
  130.  
  131. void QAndroidMediaPlayer::setMedia(const QUrl& url)
  132. {
  133.     qDebug() << "setMedia AndoidPlayer";
  134.     this->openAudioPlayer(url);
  135. }
  136.  
  137. // stub
  138. bool QAndroidMediaPlayer::isMuted() const
  139. {
  140.     return false;
  141. }
  142.  
  143. // stub
  144. void QAndroidMediaPlayer::setMuted(bool)
  145. {
  146. }
  147.  
  148. // stub
  149. int QAndroidMediaPlayer::volume() const
  150. {
  151.     return 0;
  152. }
  153.  
  154. // stub
  155. void QAndroidMediaPlayer::setVolume(int)
  156. {
  157. }
  158.  
  159. int QAndroidMediaPlayer::notifyInterval() const
  160. {
  161.     if (m_playItf == NULL) return m_notifyInterval;
  162.     SLresult res;
  163.     SLmillisecond interval;
  164.     res = (*m_playItf)->GetPositionUpdatePeriod(m_playItf, &interval);
  165.     checkResult(res);
  166.     return (int)interval;
  167. }
  168.  
  169. void QAndroidMediaPlayer::setNotifyInterval(int val)
  170. {
  171.     m_notifyInterval = val;
  172.     if (m_playItf == NULL) return;
  173.     SLresult res;
  174.     SLmillisecond interval;
  175.     res = (*m_playItf)->GetPositionUpdatePeriod(m_playItf, &interval);
  176.     checkResult(res);
  177.     if (val != (int)interval) {
  178.         res = (*m_playItf)->SetPositionUpdatePeriod(m_playItf, (SLmillisecond)val);
  179.         checkResult(res);
  180.         emit notifyIntervalChanged(val);
  181.     }
  182. }
  183.  
  184. qint64 QAndroidMediaPlayer::position() const
  185. {
  186.     if (m_playItf == NULL) return 0;
  187.     SLresult res;
  188.     SLmillisecond position;
  189.     res = (*m_playItf)->GetPosition(m_playItf, &position);
  190.     checkResult(res);
  191.     return (qint64)position;
  192. }
  193.  
  194. void QAndroidMediaPlayer::setPosition(qint64 pos)
  195. {
  196.     if (m_SeekItf == NULL) return;
  197.     // [TODO]: REVIEW SET POSITION
  198.     SLuint32 seekMode = SL_SEEKMODE_ACCURATE; //SL_SEEKMODE_FAST
  199.     SLresult res;
  200.     res = (*m_SeekItf)->SetPosition(m_SeekItf, (SLuint32)pos, seekMode);
  201.     if (res != SL_RESULT_FEATURE_UNSUPPORTED) {
  202.         checkResult(res);
  203.     }
  204.     // [TODO] CHECK IS THIS REQUIRED!!!
  205.     positionChanged(pos);
  206. }
  207.  
  208. qint64 QAndroidMediaPlayer::duration() const
  209. {
  210.     if (m_playItf == NULL) return 0;
  211.     SLresult res;
  212.     SLmillisecond duration;
  213.     res = (*m_playItf)->GetDuration(m_playItf, &duration);
  214.     checkResult(res);
  215.     return (qint64)duration;
  216. }
  217.  
  218. QAndroidMediaPlayer::State QAndroidMediaPlayer::state() const
  219. {
  220.     return m_state;
  221. }
  222.  
  223. void QAndroidMediaPlayer::checkResult(const SLresult & res)
  224. {
  225.     if (res != SL_RESULT_SUCCESS) {
  226.         qDebug() << "Error result!!! Exiting...";
  227.         exit(1);
  228.     }
  229. }
  230.  
  231. void QAndroidMediaPlayer::openMusicProfile()
  232. {
  233.     SLresult res;
  234.  
  235.     // API will be thread-safe
  236.     SLEngineOption engineOption[2] = {{ (SLuint32) SL_ENGINEOPTION_THREADSAFE,
  237.                                         (SLuint32) SL_BOOLEAN_TRUE }};
  238.     // Create SLObjectItf
  239.     res = slCreateEngine(&m_engineObj, 1, engineOption, 0, NULL, NULL);
  240.     checkResult(res);
  241.  
  242.     // Realizing OpenSL Engine in synchronous mode
  243.     res = (*m_engineObj)->Realize(m_engineObj, SL_BOOLEAN_FALSE);
  244.     checkResult(res);
  245.  
  246.     // Get SL Engine interface
  247.     res = (*m_engineObj)->GetInterface(m_engineObj, SL_IID_ENGINE, &m_engineItf);
  248.     checkResult(res);
  249.  
  250.     // Create Output Mix object to be used by player. SLVolumeItf on OutputMix is absent on Android :(
  251.     res = (*m_engineItf)->CreateOutputMix(m_engineItf, &m_outputObj, 0, NULL, NULL);
  252.     checkResult(res);
  253.  
  254.     // Realizing Output Mix
  255.     res = (*m_outputObj)->Realize(m_outputObj, SL_BOOLEAN_FALSE);
  256.     checkResult(res);
  257. }
  258.  
  259. //void QAndroidMediaPlayer::closeMusicProfile()
  260. //{
  261. //    // Shutdown Output Mix object
  262. //    if (m_outputObj != NULL) {
  263. //        (*m_outputObj)->Destroy(m_outputObj);
  264. //        m_outputObj = NULL;
  265. //    }
  266.  
  267. //    // Shutdown OpenSL Engine
  268. //    if (m_engineObj != NULL) {
  269. //        (*m_engineObj)->Destroy(m_engineObj);
  270. //        m_engineObj = NULL;
  271. //        m_engineItf = NULL;
  272. //    }
  273. //}
  274.  
  275. void QAndroidMediaPlayer::openAudioPlayer(const QUrl& url)
  276. {
  277.     qDebug() << "openAudioPlayer";
  278.     SLresult res;
  279.  
  280.     // Close old AudioPlayer
  281.     this->closeAudioPlayer();
  282.  
  283.     // configure audio source
  284.     // (requires the INTERNET permission depending on the uri parameter)
  285.     SLDataLocator_URI loc_uri = { SL_DATALOCATOR_URI, (SLchar *) url.toString().toUtf8().constData() };
  286.     SLDataFormat_MIME format_mime = { SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED };
  287.     SLDataSource audioSrc = { &loc_uri, &format_mime };
  288.  
  289.     // configure audio sink
  290.     SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, m_outputObj};
  291.     SLDataSink audioSnk = {&loc_outmix, NULL};
  292.  
  293.     // create audio player
  294.     const SLInterfaceID ids[1] = {SL_IID_SEEK};
  295.     const SLboolean req[1] = {SL_BOOLEAN_TRUE};
  296.     res = (*m_engineItf)->CreateAudioPlayer(m_engineItf, &m_playerObject, &audioSrc,
  297.             &audioSnk, 1, ids, req);
  298.     // note that an invalid URI is not detected here, but during prepare/prefetch on Android,
  299.     // or possibly during Realize on other platforms
  300.     checkResult(res);
  301.  
  302.     // realize the player
  303.     res = (*m_playerObject)->Realize(m_playerObject, SL_BOOLEAN_FALSE);
  304.     checkResult(res);
  305.  
  306.     // get the play interface
  307.     res = (*m_playerObject)->GetInterface(m_playerObject, SL_IID_PLAY, &m_playItf);
  308.     checkResult(res);
  309.  
  310.     // set notify interval
  311.     res = (*m_playItf)->SetPositionUpdatePeriod(m_playItf, (SLmillisecond)m_notifyInterval);
  312.     checkResult(res);
  313.  
  314.     // get the seek interface
  315.     res = (*m_playerObject)->GetInterface(m_playerObject, SL_IID_SEEK, &m_SeekItf);
  316.     checkResult(res);
  317.  
  318. //    //[TODO] ADD REGISTER TICK CALLBACK
  319. //    res = (*m_playItf)->RegisterCallback(m_playItf, &GlobalCallbackPositionChanged, this);
  320. //    checkResult(res);
  321.  
  322. }
  323.  
  324. void QAndroidMediaPlayer::closeAudioPlayer()
  325. {
  326.     // destroy player
  327.     if (m_playerObject != NULL) {
  328.         (*m_playerObject)->Destroy(m_playerObject);
  329.         m_playerObject = NULL;
  330.         m_playItf = NULL;
  331.         m_SeekItf = NULL;
  332.     }
  333. }
  334.  
  335. void QAndroidMediaPlayer::play()
  336. {
  337.     SLresult res;
  338.     // make sure the URI audio player was created
  339.     if (NULL != m_playItf) {
  340.         // check current state
  341.         SLuint32 playState;
  342.         res = (*m_playItf)->GetPlayState(m_playItf, &playState);
  343.         checkResult(res);
  344.         if (playState != SL_PLAYSTATE_PLAYING) {
  345.             // set the player's state
  346.             res = (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_PLAYING);
  347.             checkResult(res);
  348.             m_state = QAndroidMediaPlayer::PausedState;
  349.             emit stateChanged(m_state);
  350.         }
  351.     }
  352. }
  353.  
  354. void QAndroidMediaPlayer::pause()
  355. {
  356.     SLresult res;
  357.     // make sure the URI audio player was created
  358.     if (NULL != m_playItf) {
  359.         // check current state
  360.         SLuint32 playState;
  361.         res = (*m_playItf)->GetPlayState(m_playItf, &playState);
  362.         checkResult(res);
  363.         if (playState == SL_PLAYSTATE_PLAYING) {
  364.             // set the player's state
  365.             res = (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_PAUSED);
  366.             checkResult(res);
  367.             m_state = QAndroidMediaPlayer::PlayingState;
  368.             emit stateChanged(m_state);
  369.         }
  370.     }
  371. }
  372.  
  373. void QAndroidMediaPlayer::stop()
  374. {
  375.     SLresult res;
  376.     // make sure the URI audio player was created
  377.     if (NULL != m_playItf) {
  378.         // check current state
  379.         SLuint32 playState;
  380.         res = (*m_playItf)->GetPlayState(m_playItf, &playState);
  381.         checkResult(res);
  382.         if (playState != SL_PLAYSTATE_STOPPED) {
  383.             // set the player's state
  384.             res = (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_STOPPED);
  385.             checkResult(res);
  386.             m_state = QAndroidMediaPlayer::StoppedState;
  387.             emit stateChanged(m_state);
  388.         }
  389.     }
  390. }
  391.  
  392. void QAndroidMediaPlayer::callbackPositionChanged(SLuint32 playevent)
  393. {
  394.     qDebug() << "callbackPositionChanged" + QString::number(playevent);
  395.     switch (playevent) {
  396.     // At the end of file
  397.     case SL_PLAYEVENT_HEADATEND:
  398.         this->stop();
  399.         m_state = QAndroidMediaPlayer::StoppedState;
  400.         emit stateChanged(m_state);
  401.         emit mediaStatusChanged(QAndroidMediaPlayer::EndOfMedia);
  402.         break;
  403.     case SL_PLAYEVENT_HEADATMARKER:
  404.         break;
  405.     // At the new pos
  406.     case SL_PLAYEVENT_HEADATNEWPOS:
  407.         emit positionChanged(position());
  408.         break;
  409.     case SL_PLAYEVENT_HEADMOVING:
  410.         break;
  411.     case SL_PLAYEVENT_HEADSTALLED:
  412.         break;
  413.     default:
  414.         break;
  415.     }
  416. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement