我正在开发一个 Ubuntu Touch 应用程序。该应用程序需要播放声音。我使用 C++ 中的 QtMultimedia 进行声音播放。声音在 PC 上播放正常,但在手机上播放不正常。
奇怪的是,当使用 QtCreator 和 Build → Ubuntu → Run Application on Device 在手机上运行应用程序时,声音播放正常。当在手机上安装应用程序并使用 Build → Ubuntu → Install Application on Device,然后从手机的 Dash 运行它时,听不到声音。我的开发环境是 Ubuntu 14.04,手机运行 Ubuntu Touch (trusty) v250。
作为参考,这里是我用于实际播放的代码片段:
Playlist::Playlist(QObject *parent) :
QObject(parent),
m_trackListHandler(new TrackListHandler()),
m_playlist(new QMediaPlaylist()),
m_player(new QMediaPlayer()),
m_currentIndex(0)
{
m_player->setPlaylist(m_playlist);
}
void Playlist::playTrack(int index)
{
if (index < m_trackList.count())
{
m_playlist->setCurrentIndex(index);
m_currentIndex = index;
m_player->play();
emit playbackStarted(m_trackList.at(index));
}
}
void Playlist::resumePlayback()
{
// ...
}
void Playlist::pause()
{
// ...
}
void Playlist::nextTrack()
{
// ...
}
void Playlist::previousTrack()
{
// ...
}
void Playlist::appendTrack(PTrack track)
{
// ...
}
void Playlist::appendAndPlay(PTrack track)
{
// ...
}
playlist.h 的完整源代码:
#include "playlist.h"
#include "album.h"
#include "track.h"
#include "tracklisthandler.h"
#include <QMediaPlaylist>
#include <QMediaPlayer>
#include "logger.h"
Playlist & Playlist::instance()
{
static Playlist instance;
return instance;
}
Playlist::Playlist(QObject *parent) :
QObject(parent),
m_trackListHandler(new TrackListHandler()),
m_playlist(new QMediaPlaylist()),
m_player(new QMediaPlayer()),
m_currentIndex(0)
{
LOG_INFO << "called";
m_player->setPlaylist(m_playlist);
}
Playlist::~Playlist()
{
delete m_trackListHandler;
delete m_playlist;
delete m_player;
}
void Playlist::playTrack(int index)
{
LOG_INFO << "called";
if (index < m_trackList.count())
{
m_playlist->setCurrentIndex(index);
m_currentIndex = index;
m_player->play();
emit playbackStarted(m_trackList.at(index));
}
}
void Playlist::resumePlayback()
{
LOG_INFO << "called";
m_player->play();
emit playbackStarted(m_trackList.at(m_currentIndex));
}
void Playlist::pause()
{
LOG_INFO << "called";
m_player->pause();
}
void Playlist::nextTrack()
{
LOG_INFO << "called";
int nextIndex = m_currentIndex + 1;
if (nextIndex >= m_trackList.count())
{
nextIndex = 0;
}
m_currentIndex = nextIndex;
m_playlist->setCurrentIndex(m_currentIndex);
m_player->play();
emit playbackStarted(m_trackList.at(m_currentIndex));
}
void Playlist::previousTrack()
{
LOG_INFO << "called";
int previousIndex = m_currentIndex - 1;
if (previousIndex <= 0)
{
previousIndex = m_trackList.count() - 1;
}
m_currentIndex = previousIndex;
m_playlist->setCurrentIndex(m_currentIndex);
m_player->play();
emit playbackStarted(m_trackList.at(m_currentIndex));
}
void Playlist::appendTrack(PTrack track)
{
LOG_INFO << "called";
m_trackList.append(track);
m_playlist->addMedia(m_trackListHandler->streamUrl(track));
emit playlistChanged();
}
void Playlist::appendAndPlay(PTrack track)
{
LOG_INFO << "called";
m_trackList.append(track);
m_playlist->addMedia(m_trackListHandler->streamUrl(track));
m_currentIndex = m_trackList.indexOf(track);
m_playlist->setCurrentIndex(m_currentIndex);
m_player->play();
emit playlistChanged();
emit playbackStarted(track);
}
TrackList Playlist::tracks() const
{
return m_trackList;
}
void Playlist::clear()
{
m_trackList.clear();
m_playlist->clear();
}
int Playlist::count() const
{
return m_trackList.count();
}
Playlist.cpp 文件:
#ifndef PLAYLIST_H
#define PLAYLIST_H
#include <QObject>
#include "common.h"
class TrackListHandler;
class QMediaPlaylist;
class QMediaPlayer;
class Playlist : public QObject
{
Q_OBJECT
public:
static Playlist &instance();
public:
void playTrack(int index);
void resumePlayback();
void pause();
void nextTrack();
void previousTrack();
void appendAndPlay(PTrack track);
void appendTrack(PTrack track);
TrackList tracks() const;
void clear();
int count() const;
signals:
void playlistChanged();
void playbackStarted(PTrack track);
private:
TrackList m_trackList;
TrackListHandler *m_trackListHandler;
QMediaPlaylist *m_playlist;
QMediaPlayer *m_player;
int m_currentIndex;
private:
Playlist(QObject *parent = 0);
virtual ~Playlist();
Playlist(Playlist const &): QObject(0) { }
Playlist &operator =(Playlist const &) { return *this; }
};
#endif // PLAYLIST_H
应用日志:
playlist.cpp 111 void Playlist::appendAndPlay(PTrack) INFO: called
shm_open() failed: Permission denied
Failed to create secure directory (/run/user/32011/pulse): Permission denied
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
GStreamer; Unable to pause - "http://192.168.0.110:4040/rest/stream.view?&v=1.10.2&c=ro.kicsyromy.playsonic&id=396"
shm_open() failed: Permission denied
Failed to create secure directory (/run/user/32011/pulse): Permission denied
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
GStreamer; Unable to play - "http://192.168.0.110:4040/rest/stream.view?&v=1.10.2&c=ro.kicsyromy.playsonic&id=396"
playlistmodel.cpp 33 virtual QVariant PlaylistModel::data(const QModelIndex&, int) const INFO: called for index 0
playlistmodel.cpp 33 virtual QVariant PlaylistModel::data(const QModelIndex&, int) const INFO: called for index 0
playlistmodel.cpp 33 virtual QVariant PlaylistModel::data(const QModelIndex&, int) const INFO: called for index 0
Error: "Could not initialize supporting library."
manifest.json 文件:
{
"architecture": "all",
"description": "Player client for Subsonic and Subsonic API compatible servers",
"framework": "ubuntu-sdk-13.10",
"hooks": {
"Playsonic": {
"apparmor": "Playsonic.json",
"desktop": "Playsonic.desktop"
}
},
"maintainer": "Romeo Calota",
"name": "ro.kicsyromy.playsonic",
"title": "Playsonic",
"version": "0.1"
}
AppArmor 配置文件:
{
"policy_groups": [
"networking",
"audio",
"accounts",
"audio",
"calendar",
"camera",
"connectivity",
"contacts",
"content_exchange",
"content_exchange_source",
"friends",
"history",
"location",
"microphone",
"music_files",
"music_files_read",
"networking",
"picture_files",
"picture_files_read",
"sensors",
"usermetrics",
"video",
"video_files",
"video_files_read"
],
"policy_version": 1
}
答案1
您是否已将“音频”添加到安全策略中?转到 QtCreator 中的“发布”部分,然后在“安全策略组”列表下单击“+”按钮并添加“音频”。然后尝试再次在设备上安装该包,看看它是否有效。
我怀疑这是因为当在设备上运行代码时,QtCreator 会将文件复制到临时位置并从命令行启动它们,因此它们不受限制地运行。但是当从 click 包安装它时,它将受到该包中定义的安全策略的限制。
看http://developer.ubuntu.com/publish/apps/security-policy-for-click-packages/了解有关监禁和安全政策的更多信息。