-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPlayer.cpp
More file actions
125 lines (104 loc) · 3.45 KB
/
Copy pathPlayer.cpp
File metadata and controls
125 lines (104 loc) · 3.45 KB
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
// Author: Niklas Meinzer <meinzer.niklas@gmail.com>
// This code is open-source under the terms of the GPLv3 (see LICENSE file)
#include <thread>
#include <string>
#include <ao/ao.h>
#include <mpg123.h>
#include <iostream>
#include "./LibraryBrowserScreen.h"
#include "./Player.h"
// _____________________________________________________________________________
Player::Player() :
_stopFlag(false), _playing(false), _currentSong(""), _playerThread(nullptr) {
}
// _____________________________________________________________________________
void Player::play(const string& file) {
if (_playerThread != nullptr) stop();
_playing = true;
// create thread
std::cout << "playing: " << file << std::endl;
_currentSong = LibraryBrowserScreen::getFileNameFromPath(file);
_playerThread.reset(new std::thread(&Player::playInAThread, this, file));
}
// _____________________________________________________________________________
void Player::stop() {
if (_playerThread != nullptr) {
// set the stop flag which asks the player thread to stop playback and
// terminate
_stopFlag = true;
// wait for the thread to actually terminate
_playerThread->join();
// destroy the thread and set the thread pointer to NULL
_playerThread.reset(nullptr);
// reset the stop Flag
_stopFlag = false;
}
}
// _____________________________________________________________________________
void Player::enqueue(const string& file) {
_playlist.push(file);
}
// _____________________________________________________________________________
void Player::update() {
// check if a song is being played
if (! _playing.load()) {
// check if songs are left in the playlist
if(_playlist.size() != 0) {
string nextSong = _playlist.front();
play(nextSong);
_playlist.pop();
}
}
}
// _____________________________________________________________________________
void Player::playInAThread(const string& file) {
mpg123_handle *mh;
unsigned char *buffer;
size_t buffer_size;
size_t done;
int err;
int driver;
ao_device *dev;
ao_sample_format format;
int channels, encoding;
long rate;
/* initializations */
ao_initialize();
driver = ao_default_driver_id();
mpg123_init();
mh = mpg123_new(NULL, &err);
buffer_size = mpg123_outblock(mh);
buffer = (unsigned char*) malloc(buffer_size * sizeof(unsigned char));
/* open the file and get the decoding format */
mpg123_open(mh, file.c_str());
mpg123_getformat(mh, &rate, &channels, &encoding);
/* set the output format and open the output device */
format.bits = mpg123_encsize(encoding) * 8;
format.rate = rate;
format.channels = channels;
format.byte_format = AO_FMT_NATIVE;
format.matrix = 0;
dev = ao_open_live(driver, &format, NULL);
/* decode and play */
while (!_stopFlag.load() && mpg123_read(mh, buffer, buffer_size, &done) == MPG123_OK)
ao_play(dev, reinterpret_cast<char*>(buffer), done);
/* clean up */
free(buffer);
ao_close(dev);
mpg123_close(mh);
mpg123_delete(mh);
mpg123_exit();
ao_shutdown();
_playing = false;
}
// _____________________________________________________________________________
const queue<string>& Player::getPlayQueue() const {
return _playlist;
}
// _____________________________________________________________________________
bool Player::getCurrentSong(string& name) const {
// return false if nothing is being played
if (!_playing.load()) return false;
name = _currentSong;
return true;
}