summaryrefslogtreecommitdiffstats
path: root/src/soundio/sounddevicenetwork.h
blob: 7c5b8686e795ca76f044dd45b4af7ab6a568b0c7 (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
#pragma once

#include <QString>
#include <QSharedPointer>
#include <QThread>

#ifdef __LINUX__
#include <pthread.h>
#endif

#include "util/performancetimer.h"
#include "util/memory.h"
#include "soundio/sounddevice.h"
#include "engine/sidechain/networkoutputstreamworker.h"

#define CPU_USAGE_UPDATE_RATE 30 // in 1/s, fits to display frame rate
#define CPU_OVERLOAD_DURATION 500 // in ms

class SoundManager;
class ControlProxy;
class EngineNetworkStream;
class SoundDeviceNetworkThread;


class SoundDeviceNetwork : public SoundDevice {
  public:
    SoundDeviceNetwork(UserSettingsPointer config,
                       SoundManager* sm,
                       QSharedPointer<EngineNetworkStream> pNetworkStream);
    ~SoundDeviceNetwork() override;

    SoundDeviceError open(bool isClkRefDevice, int syncBuffers) override;
    bool isOpen() const override;
    SoundDeviceError close() override;
    void readProcess() override;
    void writeProcess() override;
    QString getError() const override;

    unsigned int getDefaultSampleRate() const override {
        return 44100;
    }

    void callbackProcessClkRef();

  private:
    void updateCallbackEntryToDacTime();
    void updateAudioLatencyUsage();

    void workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker,
            int outChunkSize, int readAvailable,
            CSAMPLE* dataPtr1, ring_buffer_size_t size1,
            CSAMPLE* dataPtr2, ring_buffer_size_t size2);
    void workerWrite(NetworkOutputStreamWorkerPtr pWorker,
            const CSAMPLE* buffer, int frames);
    void workerWriteSilence(NetworkOutputStreamWorkerPtr pWorker, int frames);

    QSharedPointer<EngineNetworkStream> m_pNetworkStream;
    std::unique_ptr<FIFO<CSAMPLE> > m_outputFifo;
    std::unique_ptr<FIFO<CSAMPLE> > m_inputFifo;
    bool m_inputDrift;

    std::unique_ptr<ControlProxy> m_pMasterAudioLatencyUsage;
    mixxx::Duration m_timeInAudioCallback;
    mixxx::Duration m_audioBufferTime;
    int m_framesSinceAudioLatencyUsageUpdate;
    std::unique_ptr<SoundDeviceNetworkThread> m_pThread;
    bool m_denormals;
    qint64 m_targetTime;
    PerformanceTimer m_clkRefTimer;
};

class SoundDeviceNetworkThread : public QThread {
    Q_OBJECT
  public:
    SoundDeviceNetworkThread(SoundDeviceNetwork* pParent)
        : m_pParent(pParent),
          m_stop(false) {
    }

    void stop() {
        m_stop = true;
    }

    void usleep_(unsigned long t) {
        usleep(t);
    }

  private:
    void run() override {
#ifdef __LINUX__
        struct sched_param spm = { 0 };
        spm.sched_priority = 1;
        if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &spm)) {
            qWarning() << "SoundDeviceNetworkThread: Failed bumping priority";
        }
#endif

        while(!m_stop) {
            m_pParent->callbackProcessClkRef();
        }
    }
    SoundDeviceNetwork* m_pParent;
    bool m_stop;
};