4

I have an Ubuntu Touch application in the works. The application needs to playback sound. I've used QtMultimedia from C++ for sound playback. The sound plays fine on PC but not on the phone.

The odd thing is that when running the application on the phone using QtCreator and Build → Ubuntu → Run Application on Device, the sound plays back just fine. When installing the application on the phone and using Build → Ubuntu → Install Application on Device, and then running it from the phone's Dash the sound is not heard. My development environment is Ubuntu 14.04 and the phone runs Ubuntu Touch (trusty) v250.

For reference here is the code snippet that I used for the actual playback:

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)
{
    // ...
}

The full source code for 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();
}

The Playlist.cpp file:

#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

The application log:

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." 

The manifest.json file:

{
    "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"
}

The AppArmor profile:

{
    "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

Did you add 'audio' to your security policy? Go to the "Publish" section in QtCreator, then under the "Security Policy Groups" list click the "+" button and add "audio". Then try installing the package on the device again and see if it works.

The reason I suspect this is because when simply running the code on the device, QtCreator copies the files into a temporary location and launches them from the commandline, so they run unconfined. But when installing it from the click package, it will be confined to the security policy defined in that package.

See http://developer.ubuntu.com/publish/apps/security-policy-for-click-packages/ for more info on confinement and security policies.

1
  • I've set the 'audio' permission and still not sound. – kicsyromy Apr 3 '14 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.