controller.cpp 5.62 KB
Newer Older
1
2
3
4
5
#include "controller.h"
#include <mutex>

namespace Modules {

Leander Schulten's avatar
Leander Schulten committed
6
Controller::Controller():run_(false)
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
void Controller::setSpotify(Spotify::Spotify *spotify){
    if(spotify==this->spotify)
        return;
    for(const auto & c : spotifyConnections){
        QObject::disconnect(c);
    }
    spotifyConnections.clear();
    this->spotify = spotify;
    spotifyState.enabled = spotify != nullptr;
    if(spotify&&spotify->getCurrentPlayingObject()){
        spotifyState.enabled = true;
        spotifyConnections.push_back(QObject::connect(spotify,&Spotify::Spotify::currentTrackChanged,[&,spotify](){
            if(spotify->getCurrentAudioFeatures()&&spotify->getCurrentPlayingObject()&&spotify->getCurrentPlayingObject()->item){
                spotifyState.currentTrack.~TrackObject();
                new (&spotifyState.currentTrack) TrackObject(*spotify->getCurrentAudioFeatures(),*spotify->getCurrentPlayingObject()->item);
                spotifyState.newTrack = true;
            }else{
                spotifyState.currentTrack.~TrackObject();
                new (&spotifyState.currentTrack) TrackObject();
            }
        }));
        spotifyConnections.push_back(QObject::connect(spotify,&QObject::destroyed,[this](){
            this->setSpotify(nullptr);
        }));
        spotifyConnections.push_back(QObject::connect(spotify,&Spotify::Spotify::audioFeaturesChanged,[&,spotify](){
            if(spotify->getCurrentAudioFeatures()&&spotify->getCurrentPlayingObject()&&spotify->getCurrentPlayingObject()->item){
                spotifyState.currentTrack.~TrackObject();
                new (&spotifyState.currentTrack) TrackObject(*spotify->getCurrentAudioFeatures(),*spotify->getCurrentPlayingObject()->item);
                spotifyState.newTrack = true;
            }else{
                spotifyState.currentTrack.~TrackObject();
                new (&spotifyState.currentTrack) TrackObject();
            }
        }));
    }
}

bool Controller::haveAnalysis()const{
    return spotify&&spotify->getCurrentAudioAnalysis()&&spotify->getCurrentPlayingObject()&&spotify->getCurrentPlayingObject()->item;
}

void Controller::updateSpotifyState(){
    if(haveAnalysis()){
        spotifyState.enabled = true;
        spotifyState.currentTrack.progress_ms = spotify->getCurrentPlayingObject()->getProgressInMs();
        spotifyState.isPlaying = spotify->getCurrentPlayingObject()->is_playing;        
#define UPDATE_OBJECT(type,Type,Object) \
    if(int newIndex = spotify->getCurrentAudioAnalysis()->getIndexIn ## Type ## sForTime(spotifyState.currentTrack.progress_ms);newIndex != lastIndexOfCurrent ## Type){ \
        lastIndexOfCurrent ## Type = newIndex; \
        spotifyState.current ## Type .~ Object(); \
        if(newIndex>=0){ \
            new (&spotifyState.current ## Type) Object(spotify->getCurrentAudioAnalysis()->type ## s[5]); \
            spotifyState.new ## Type = true; \
        } else {\
            new (&spotifyState.current ## Type) Object(); \
            spotifyState.new ## Type = true; \
        } \
    }else{ \
        spotifyState.new##Type = false;\
    }
        if(spotifyState.isPlaying){
            UPDATE_OBJECT(bar,Bar,TimeIntervalObject)
            UPDATE_OBJECT(tatum,Tatum,TimeIntervalObject)
            UPDATE_OBJECT(beat,Beat,TimeIntervalObject)
            UPDATE_OBJECT(section,Section,SectionObject)
            UPDATE_OBJECT(segment,Segment,SegmentObject)
#undef UPDATE_OBJECT
        }
    }else{
#define UPDATE_OBJECT(Type,Object) \
        spotifyState.current ## Type .~ Object(); \
        new (&spotifyState.current ## Type) Object(); \
        spotifyState.new ## Type = false;

        UPDATE_OBJECT(Bar, TimeIntervalObject)
        UPDATE_OBJECT(Beat, TimeIntervalObject)
        UPDATE_OBJECT(Tatum, TimeIntervalObject)
        UPDATE_OBJECT(Section, SectionObject)
        UPDATE_OBJECT(Segment, SegmentObject)
        UPDATE_OBJECT(Track, TrackObject)
#undef UPDATE_OBJECT
        spotifyState.haveCurrentTrack = false;
        spotifyState.isPlaying = false;
        spotifyState.enabled = false;
    }

}

99
100
101
void Controller::run() noexcept{
    while (run_) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
Leander Schulten's avatar
Leander Schulten committed
102
        std::unique_lock<std::mutex> l(vectorLock);
103
        updateSpotifyState();
Leander Schulten's avatar
Leander Schulten committed
104
105
        for(auto pb = runningProgramms.begin() ; pb != runningProgramms.end();){
            if((*pb)->doStep(1)){
106
                deletingProgramBlock = (*pb).get();
107
                (**pb).stop();
108
                deletingProgramBlock = nullptr;
Leander Schulten's avatar
Leander Schulten committed
109
110
111
112
113
                pb = runningProgramms.erase(pb);
            }else{
                ++pb;
            }
        }
114
        spotifyState.newTrack = false;
115
116
117
    }
}

Leander Schulten's avatar
Leander Schulten committed
118
119
void Controller::runProgramm(std::shared_ptr<ProgramBlock> pb){
    std::unique_lock<std::mutex> l(vectorLock);
120
    runningProgramms.push_back(pb);  
Leander Schulten's avatar
Leander Schulten committed
121
122
123
}

void Controller::stopProgramm(std::shared_ptr<ProgramBlock> pb){
124
125
126
    // preventing deadlocks, this method is called when call stop on a ProgramBlock, wich is called in function run
    if(deletingProgramBlock == pb.get())
        return;
Leander Schulten's avatar
Leander Schulten committed
127
    std::unique_lock<std::mutex> l(vectorLock);
128
    runningProgramms.erase(std::remove(runningProgramms.begin(),runningProgramms.end(),pb),runningProgramms.end());    
129
}
Leander Schulten's avatar
Leander Schulten committed
130
131
void Controller::stopProgramm(ProgramBlock* pb){
    std::unique_lock<std::mutex> l(vectorLock);
132
    runningProgramms.erase(std::remove_if(runningProgramms.begin(),runningProgramms.end(),[&](const auto &v){return v.get()==pb;}),runningProgramms.end());    
Leander Schulten's avatar
Leander Schulten committed
133
}
134
135
136
137

bool Controller::isProgramRunning(ProgramBlock * pb){
    std::unique_lock<std::mutex> l(vectorLock);
    return std::any_of(runningProgramms.cbegin(),runningProgramms.cend(),[=](const auto & p){return p.get()==pb;});
Leander Schulten's avatar
Leander Schulten committed
138
139
}

140
}