05d37cd65d86cb542974eb9d43938082cc4440f2
[someplayer] / src / player / player.cpp
1 /*
2  * SomePlayer - An alternate music player for Maemo 5
3  * Copyright (C) 2010 Nikolay (somebody) Tischenko <niktischenko@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20 #include "player.h"
21 #include <phonon/MediaSource>
22
23 using namespace SomePlayer::Playback;
24 using namespace SomePlayer::DataObjects;
25 using namespace SomePlayer::Storage;
26
27 Player::Player(QObject *parent) :
28     QObject(parent)
29 {
30         _player = new Phonon::MediaObject(this);
31         _output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
32         _player->setTickInterval(1000);
33         connect(_player, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(_stateChanged(Phonon::State,Phonon::State)));
34         connect(_player, SIGNAL(tick(qint64)), this, SLOT(_tick(qint64)));
35         Phonon::createPath(_player, _output);
36         int seed = reinterpret_cast<int> (_player);
37         qsrand(seed);
38         _random = _config.getValue("playback/random").toBool();
39         _repeat = _config.getValue("playback/repeat").toBool();
40         _current = -1;
41 }
42
43 void Player::setTrackId(int id) {
44         _current = id;
45         if (!_history.isEmpty() && _history.top() != _current || _history.isEmpty()) {
46                 _history.push(_current);
47         }
48         _track = _playlist.tracks().at(_current);
49         _set_source();
50         _state = PLAYER_LOADING;
51         emit stateChanged(_state);
52 }
53
54 void Player::toggle() {
55         if (_state == PLAYER_PLAYING) { // pause
56                 _player->pause();
57                 _state = PLAYER_PAUSED;
58                 emit stateChanged(_state);
59         } else { //play
60                 play();
61         }
62 }
63
64 void Player::stop() {
65         _player->stop();
66         _state = PLAYER_STOPPED;
67         emit stateChanged(_state);
68 }
69
70 void Player::next() {
71         int count = _playlist.tracks().count();
72         if (count == 0) {
73                 stop(); // empty playlist
74                 return;
75         }
76         _history.push(_current % count);
77         if (!_queue.isEmpty()) {
78                 _current = _queue.dequeue();
79         } else if (!_prev_history.isEmpty()) {
80                 _current = _prev_history.pop();
81         } else {
82                 if (_random) {
83                         _current = (count + (qrand()  + qrand() + qrand()) % count) % count;
84                 } else {
85                         _current = _current + 1;
86                 }
87         }
88         if (_random && _history.count() >= count && !_repeat ||
89                 !_repeat && _current >= count) {
90                 _history.clear();
91                 stop();
92         } else {
93                 _current %= count;
94                 _track = _playlist.tracks().at(_current);
95                 _set_source();
96                 play();
97         }
98 }
99
100 void Player::_set_source() {
101         _player->setCurrentSource(Phonon::MediaSource(_track.source()));
102         emit trackChanged(_track);
103 }
104
105 void Player::prev() {
106         if (_history.count() > 0) {
107                 _prev_history.push(_current);
108                 _current = _history.pop();
109                 _track = _playlist.tracks().at(_current);
110         }
111         _set_source();
112         play();
113 }
114
115 void Player::_stateChanged(Phonon::State newState, Phonon::State /*oldState*/) {
116         switch (newState) {
117         case Phonon::PlayingState:
118                 if (_state == PLAYER_LOADING) {
119                         _state = PLAYER_PLAYING;
120                         emit stateChanged(_state);
121                 }
122                 break;
123         case Phonon::StoppedState:
124                 break;
125         case Phonon::LoadingState:
126                 break;
127         case Phonon::PausedState:
128                 if (_state == PLAYER_PLAYING) {
129                         next();
130                 } else if (_state == PLAYER_ERROR) {
131                         play();
132                 }
133                 break;
134         case Phonon::BufferingState:
135                 break;
136         case Phonon::ErrorState:
137                 _state = PLAYER_ERROR;
138                 qDebug() << _player->errorString();
139                 break;
140         }
141 }
142
143 void Player::_tick(qint64 ticks) {
144         int done = ticks/1000;
145         int all = _track.metadata().length();
146         emit tick(done, all);
147         if (done+2 == all) {
148                 _track.setCount(_track.count()+1);
149                 emit trackDone(_track);
150         }
151 }
152
153 void Player::setPlaylist(Playlist playlist) {
154         _playlist = playlist;
155         _history.clear();
156         _prev_history.clear();
157         _queue.clear();
158 }
159
160 void Player::seek(int s) {
161         _player->seek(s*1000);
162 }
163
164 void Player::play() {
165         if (_playlist.tracks().isEmpty())
166                 return;
167         _state = PLAYER_PLAYING;
168         emit stateChanged(_state);
169         if (_current == -1) {
170                 _current = 0;
171                 _track = _playlist.tracks().at(0);
172                 _set_source();
173         }
174         _player->play();
175 }
176
177 void Player::enqueue(int id) {
178         _queue.enqueue(id);
179 }
180
181 void Player::toggleRandom() {
182         _random = !_random;
183         _config.setValue("playback/random", _random);
184 }
185
186 void Player::toggleRepeat() {
187         _repeat = !_repeat;
188         _config.setValue("playback/repeat", _repeat);
189 }
190
191 void Player::setVolume(int v) {
192         _output->setVolume(v*0.01);
193 }