Added license information
[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
26 Player::Player(QObject *parent) :
27     QObject(parent)
28 {
29         _player = new Phonon::MediaObject(this);
30         _output = new Phonon::AudioOutput(Phonon::MusicCategory, this);
31         _player->setTickInterval(1000);
32         connect(_player, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(_stateChanged(Phonon::State,Phonon::State)));
33         connect(_player, SIGNAL(tick(qint64)), this, SLOT(_tick(qint64)));
34         Phonon::createPath(_player, _output);
35         int seed = reinterpret_cast<int> (_player);
36         qsrand(seed);
37         _random = false;
38         _repeat = false;
39         _current = -1;
40 }
41
42 void Player::setTrackId(int id) {
43         _current = id;
44         if (!_history.isEmpty() && _history.top() != _current || _history.isEmpty()) {
45                 _history.push(_current);
46         }
47         _track = _playlist.tracks().at(_current);
48         _set_source();
49         _state = PLAYER_LOADING;
50         emit stateChanged(_state);
51 }
52
53 void Player::toggle() {
54         if (_state == PLAYER_PLAYING) { // pause
55                 _player->pause();
56                 _state = PLAYER_PAUSED;
57                 emit stateChanged(_state);
58         } else { //play
59                 play();
60         }
61 }
62
63 void Player::stop() {
64         _player->stop();
65         _state = PLAYER_STOPPED;
66         emit stateChanged(_state);
67 }
68
69 void Player::next() {
70         int count = _playlist.tracks().count();
71         if (count == 0) {
72                 stop(); // empty playlist
73                 return;
74         }
75         _history.push(_current % count);
76         if (!_queue.isEmpty()) {
77                 _current = _queue.dequeue();
78         } else if (!_prev_history.isEmpty()) {
79                 _current = _prev_history.pop();
80         } else {
81                 if (_random) {
82                         _current = (count + (qrand()  + qrand() + qrand()) % count) % count;
83                 } else {
84                         _current = _current + 1;
85                 }
86         }
87         if (_random && _history.count() >= count && !_repeat ||
88                 !_repeat && _current >= count) {
89                 _history.clear();
90                 stop();
91         } else {
92                 _current %= count;
93                 _track = _playlist.tracks().at(_current);
94                 _set_source();
95                 play();
96         }
97 }
98
99 void Player::_set_source() {
100         _player->setCurrentSource(Phonon::MediaSource(_track.source()));
101         emit trackChanged(_track);
102 }
103
104 void Player::prev() {
105         if (_history.count() > 0) {
106                 _prev_history.push(_current);
107                 _current = _history.pop();
108                 _track = _playlist.tracks().at(_current);
109         }
110         _set_source();
111         play();
112 }
113
114 void Player::_stateChanged(Phonon::State newState, Phonon::State oldState) {
115         switch (newState) {
116         case Phonon::PlayingState:
117                 if (_state == PLAYER_LOADING) {
118                         _state = PLAYER_PLAYING;
119                         emit stateChanged(_state);
120                 }
121                 break;
122         case Phonon::StoppedState:
123                 break;
124         case Phonon::LoadingState:
125                 break;
126         case Phonon::PausedState:
127                 if (_state == PLAYER_PLAYING) {
128                         next();
129                 } else if (_state == PLAYER_ERROR) {
130                         play();
131                 }
132                 break;
133         case Phonon::BufferingState:
134                 break;
135         case Phonon::ErrorState:
136                 _state = PLAYER_ERROR;
137                 qDebug() << _player->errorString();
138                 break;
139         }
140 }
141
142 void Player::_tick(qint64 ticks) {
143         int done = ticks/1000;
144         int all = _track.metadata().length();
145         emit tick(done, all);
146         if (done+2 == all) {
147                 _track.setCount(_track.count()+1);
148                 emit trackDone(_track);
149         }
150 }
151
152 void Player::setPlaylist(Playlist playlist) {
153         _playlist = playlist;
154         _history.clear();
155         _prev_history.clear();
156         _queue.clear();
157 }
158
159 void Player::seek(int s) {
160         _player->seek(s*1000);
161 }
162
163 void Player::play() {
164         _state = PLAYER_PLAYING;
165         emit stateChanged(_state);
166         if (_current == -1) {
167                 _current = 0;
168                 _track = _playlist.tracks().at(0);
169                 _set_source();
170         }
171         _player->play();
172 }
173
174 void Player::enqueue(int id) {
175         _queue.enqueue(id);
176 }