-
Notifications
You must be signed in to change notification settings - Fork 0
/
powermatempd.cpp
163 lines (130 loc) · 3.36 KB
/
powermatempd.cpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include "powermatempd.h"
#include "powermate.h"
#include "mpd.h"
#include "log.h"
#include <iostream>
#include <cstdlib>
#include <poll.h>
using namespace std;
PowermateMpd::PowermateMpd( Powermate& powermate, Mpd& mpd )
: powermate_( powermate ),
mpd_( mpd ),
playing_( false ),
position_( 0 ),
pressed_( false ),
pressedAndRotated_( false )
{
ledOnOff( mpd.getIsOn() );
}
void PowermateMpd::processStateChange( const Powermate::State& newPmState ) {
/*
* press - do nothing
* release - toggle play, set LED playing state
* press and rotate - change volume
* rotate - switch song
* release after rotate - set LED to playing state
*/
bool rotated = abs( newPmState.position_ - position_ ) > minRotation_;
if ( newPmState.pressed_ && ! pressed_ ) {
/*
* Newly pressed.
*/
pressed_ = true;
pressedAndRotated_ = false;
} else if ( ! newPmState.pressed_ && pressed_ ) {
/*
* Released
*/
if ( ! pressedAndRotated_ ) {
bool isOn;
mpd_.toggleOnOff( isOn );
ledOnOff( isOn );
} else {
/*
* Release after volume change. Just reset LED state.
*/
bool isOn = mpd_.getIsOn();
ledOnOff( isOn );
}
pressed_ = false;
pressedAndRotated_ = false;
} else if ( rotated ) {
if ( newPmState.pressed_ ) {
/*
* Press and rotate.
*/
pressedAndRotated_ = true;
unsigned volumePercent;
if ( newPmState.position_ > position_ ) {
mpd_.volumeUp( volumePercent );
} else {
mpd_.volumeDown( volumePercent );
}
ledPercent( volumePercent );
} else {
/*
* Rotate
*/
if ( newPmState.position_ > position_ ) {
mpd_.nextTrack();
} else {
mpd_.previousTrack();
}
}
position_ = newPmState.position_;
}
}
void PowermateMpd::run() {
bool result = true;
Powermate::State state;
const unsigned mpdPollFdIndex = 0;
const unsigned pmPollFdIndex = 1;
struct pollfd pollFds[2];
pollFds[mpdPollFdIndex].fd = mpd_.getFd();
pollFds[mpdPollFdIndex].events = POLLIN;
pollFds[mpdPollFdIndex].revents = 0;
pollFds[pmPollFdIndex].fd = powermate_.getReadFd();
pollFds[pmPollFdIndex].events = POLLIN;
pollFds[pmPollFdIndex].revents = 0;
while ( result ) {
if ( powermate_.hasBufferedEvents() ) {
result = powermate_.waitForInput( state );
processStateChange( state );
continue;
}
mpd_.idleBegin();
poll( pollFds, sizeof(pollFds) / sizeof(pollFds[0]), -1 );
/*
* We need to end the idle on the MPD connection so we can send
* it a command below. Unfortunately due to the way that the
* MPD protocol implements idle there is always a chance that
* state change events will be lost between idle waits.
*/
bool stateChanged;
mpd_.idleEnd( stateChanged );
if ( stateChanged ) {
bool isOn = mpd_.getIsOn();
LOG( logDEBUG) << "State changed" << " " << isOn << endl;
ledOnOff( isOn );
}
if ( pollFds[pmPollFdIndex].revents & POLLIN ) {
/*
* Powermate has event data to read.
*/
result = powermate_.waitForInput( state );
processStateChange( state );
} else if ( pollFds[pmPollFdIndex].revents ) {
/*
* Quit if poll reports an error. POLLERR, POLLHUP, or
* POLLNVAL could be set in revents.
*/
result = false;
}
}
}
void PowermateMpd::ledOnOff( bool onOff ) {
ledPercent( onOff ? 100 : 0 );
}
void PowermateMpd::ledPercent( unsigned percent ) {
powermate_.setLedBrightnessPercent( percent );
}