summaryrefslogtreecommitdiff
path: root/pulseplayer.h
blob: de8087862bd21021197dfbaa3c0b645e0bde6db5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* SPDXLicenseID: MPL-2.0
*
* Copyright (C) 2014, GENIVI Alliance
*
* This file is part of AudioManager Monitor
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License (MPL), v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* For further information see http://www.genivi.org/.
*
* List of changes:
*/

#ifndef PULSEPLAYER_H
#define PULSEPLAYER_H

#include <QFile>
#include <QByteArray>
#include <QDataStream>
#include <QIODevice>
#include <QObject>
#include <QThread>
#include <QString>
#include <QDebug>
#include <pulse/simple.h>
#include <pulse/error.h>
#include <pulse/thread-mainloop.h>
#include <pulse/context.h>
#include <pulse/pulseaudio.h>
#include <pulse/proplist.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <pulseaudiocontroller.h>

#define PA_BUF_SIZE 2048
class InternalPlayer : public QObject
{
    Q_OBJECT
public:
    InternalPlayer(QString fileName, QString sinkName, QString sourceName, QMap<QString, QString> proplist, QObject *parent = 0);
    QString mFilePath;
    QString mSourceName;
    QString mSinkName;
    bool mIsAlive;

    pa_threaded_mainloop* getMainloop() {    return mMainloop;    }
    pa_context* getContext() {    return mContext;    }
    bool isPlaying() {    return mIsPlaying;    }
    char* getDevice() {    return mDevice;    }
    pa_buffer_attr* gerAttrBuff() {    return mAttrBuff;    }
    void setupStream();
    void disconnectStream();

public slots:
    void play(QString sourceName);
    void stop(QString sourceName);

signals:
    void playStateChanged();

private:
    QMap<QString,QString> mPropMap;
    QString mFileName;
    QFile *mFile;
    int mLastError;
    bool mIsInitSuccess;
    bool mIsPlaying;
    //void *mBuffer;
    QByteArray mBuffer;
    size_t mBufferIndex;
    size_t mBufferLength;
    pa_buffer_attr *mAttrBuff;


    // Member variables to control pulseaudio...
    pa_threaded_mainloop *mMainloop;
    pa_mainloop_api *mApi;
    pa_context *mContext;
    pa_stream *mStream;
    pa_proplist *mPropList;

    pa_sample_spec mPASampleSpec;
    char *mDevice;


    // PulseAudio Callback functions...
    static void contextStateCallback(pa_context *context, void *userdata);
    static void streamStateCallback(pa_stream *stream, void *userdata);
    static void streamWriteCallback(pa_stream *stream, size_t length, void *userdata);
    static void streamDrainCallback(pa_stream *stream, int success, void *userdata);
    static void contextDrainCallback(pa_context *context, void *userdata);

    bool setupPulseAudio();
    bool openFile();


    // PulseAudio Processing functions...
    void waitForOperation(pa_operation *operation);
    void playInternal(pa_stream *stream, size_t length, void *userdata);
};

class PulsePlayer : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool playing READ isPlaying NOTIFY playStateChanged)
    Q_PROPERTY(QString source READ sourceName WRITE setSourceName)
    Q_PROPERTY(QString sink READ sinkName WRITE setSinkName)
    Q_PROPERTY(QString role READ roleName WRITE setRoleName)
    Q_PROPERTY(QString file READ fileName WRITE setFileName)
public:
    explicit PulsePlayer(QObject *parent = 0);

    Q_INVOKABLE bool isPlaying() { return mPlayer ? mPlayer->isPlaying() : false; }
    Q_INVOKABLE void play();
    Q_INVOKABLE void stop();
    const QString sourceName() { return mSourceName; }
    void setSourceName(const QString &name) { mSourceName = name; }
    const QString sinkName() { return mSinkName; }
    void setSinkName(const QString &name) { mSinkName = name; }
    const QString roleName() { return mRoleName; }
    void setRoleName(const QString &name) { mRoleName = name; }
    const QString fileName() { return mFileName; }
    void setFileName(const QString &name) { mFileName = name; }


signals:
    void doPlay(QString sourceName);
    void doStop(QString sourceName);
    void playStateChanged();

private:
    InternalPlayer *mPlayer;
    QThread *mWorker;
    QString mSourceName;
    QString mSinkName;
    QString mRoleName;
    QString mFileName;

};

#endif // PULSEPLAYER_H