22
25
music = gst_element_factory_make ("playbin", "play");
23
26
/*If you don't want play video with gstreamer*/
24
27
fakesink = gst_element_factory_make ("fakesink", "fakesink");
25
g_object_set (G_OBJECT (music), "video-sink", fakesink, NULL);
27
sink = gst_element_factory_make ("gconfaudiosink", "audiosink");
28
/* if we could create the gconf sink use that, otherwise let playbin decide */
30
/* set the profile property on the gconfaudiosink to "music and movies" */
31
if (g_object_class_find_property (G_OBJECT_GET_CLASS (sink), "profile"))
32
g_object_set (G_OBJECT (sink), "profile", 1, NULL);
34
g_object_set (G_OBJECT (music), "audio-sink", sink, NULL);
28
g_object_set (G_OBJECT (music), "video-sink", fakesink, NULL);
30
sink = gst_element_factory_make ("gconfaudiosink", "audiosink");
31
/* if we could create the gconf sink use that, otherwise let playbin decide */
33
/* set the profile property on the gconfaudiosink to "music and movies" */
34
if (g_object_class_find_property (G_OBJECT_GET_CLASS (sink), "profile"))
35
g_object_set (G_OBJECT (sink), "profile", 1, NULL);
36
g_object_set (G_OBJECT (music), "audio-sink", sink, NULL);
40
m_thread.reset(new boost::thread(boost::ref(*this)));
45
boost::mutex::scoped_lock l(m_mutex);
42
50
#ifdef USE_LIBXINE_AUDIO
44
xine_event_dispose_queue(event_queue);
47
xine_close_audio_driver(xine, ao_port);
48
xine_close_video_driver(xine, vo_port);
52
xine_event_dispose_queue(event_queue);
55
xine_close_audio_driver(xine, ao_port);
56
xine_close_video_driver(xine, vo_port);
51
59
#ifdef USE_GSTREAMER_AUDIO
52
60
gst_object_unref (GST_OBJECT (music));
56
void CAudio::playMusic( char * filename )
61
#ifdef USE_LIBXINE_AUDIO
65
// Boost WTF time format, directly from C...
66
boost::xtime& operator+=(boost::xtime& time, double seconds) {
67
double nsec = 1e9 * (time.sec + seconds) + time.nsec;
68
time.sec = boost::xtime::xtime_sec_t(nsec / 1e9);
69
time.nsec = boost::xtime::xtime_nsec_t(std::fmod(nsec, 1e9));
72
boost::xtime operator+(boost::xtime const& left, double seconds) {
73
boost::xtime time = left;
74
return time += seconds;
78
boost::xtime_get(&time, boost::TIME_UTC);
83
void CAudio::operator()() {
88
boost::mutex::scoped_lock l(m_mutex);
90
m_condready.notify_all();
91
while (m_type == NONE) m_cond.wait(l);
95
filename = m_filename;
98
case NONE: // Should not get here...
100
case STOP: stopMusic_internal(); break;
102
// Wait a little while before actually starting
103
boost::thread::sleep(now() + 0.35);
105
boost::mutex::scoped_lock l(m_mutex);
106
// Did we receive another event already?
107
if (m_type != NONE) continue;
109
playPreview_internal(filename);
111
case PLAY: playMusic_internal(filename); break;
116
unsigned int CAudio::getVolume_internal() {
117
#ifdef USE_LIBXINE_AUDIO
118
return xine_get_param(stream, XINE_PARAM_AUDIO_VOLUME);
120
#ifdef USE_GSTREAMER_AUDIO
122
g_object_get (music, "volume", &vol, NULL);
123
return (unsigned int)(vol*100);
127
void CAudio::setVolume_internal(unsigned int _volume) {
128
#ifdef USE_LIBXINE_AUDIO
129
xine_set_param(stream, XINE_PARAM_AUDIO_VOLUME, _volume);
131
#ifdef USE_GSTREAMER_AUDIO
132
gdouble vol = _volume/100.;
133
g_object_set (music, "volume", vol, NULL);
137
void CAudio::playMusic_internal(std::string const& filename) {
138
stopMusic_internal();
139
#ifdef USE_LIBXINE_AUDIO
65
if (!xine_open(stream, filename) || !xine_play(stream, 0, 0)) {
66
printf("could not open %s\n", filename);
69
if( !xine_get_pos_length(stream, &pos_stream, &pos_time, &length) )
70
length = LENGTH_ERROR;
142
if (!xine_open(stream, filename.c_str()) || !xine_play(stream, 0, 0)) {
143
std::cout << "Could not open " << filename << std::endl;
145
if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length)) length = LENGTH_ERROR;
74
148
#ifdef USE_GSTREAMER_AUDIO
75
if( filename[0] == '/' )
76
g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",filename,NULL), NULL);
78
g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",get_current_dir_name(),"/",filename,NULL), NULL);
149
if (filename[0] == '/') g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",filename.c_str(),NULL), NULL);
150
else g_object_set(G_OBJECT (music), "uri", g_strconcat("file://",get_current_dir_name(),"/",filename.c_str(),NULL), NULL);
79
151
gst_element_set_state (music, GST_STATE_PLAYING);
80
152
GstFormat fmt = GST_FORMAT_TIME;
82
if (!gst_element_query_duration (music, &fmt, &len))
83
length = LENGTH_ERROR;
85
length = (int) (len/GST_MSECOND);
154
length = gst_element_query_duration(music, &fmt, &len) ? int(len/GST_MSECOND) : LENGTH_ERROR;
91
void CAudio::playPreview( char * filename )
158
void CAudio::playPreview_internal(std::string const& filename) {
159
unsigned int volume = getVolume_internal();
160
setVolume_internal(0);
161
stopMusic_internal();
96
162
#ifdef USE_LIBXINE_AUDIO
100
if (!xine_open(stream, filename) || !xine_play(stream, 0, 30000)) {
101
printf("could not open %s\n", filename);
104
if( !xine_get_pos_length(stream, &pos_stream, &pos_time, &length) )
105
length = LENGTH_ERROR;
166
if (!xine_open(stream, filename.c_str()) || !xine_play(stream, 0, 0) || !xine_play(stream, 0, 30000)) {
167
std::cout << "Could not open " << filename << std::endl;
170
if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length)) length = LENGTH_ERROR;
109
173
#ifdef USE_GSTREAMER_AUDIO
110
if( filename[0] == '/' )
111
g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",filename,NULL), NULL);
113
g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",get_current_dir_name(),"/",filename,NULL), NULL);
174
if (filename[0] == '/') g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",filename.c_str(),NULL), NULL);
175
else g_object_set (G_OBJECT (music), "uri", g_strconcat("file://",get_current_dir_name(),"/",filename.c_str(),NULL), NULL);
114
176
gst_element_set_state (music, GST_STATE_PAUSED);
115
177
GstState state_paused = GST_STATE_PAUSED;
116
178
gst_element_get_state (music, NULL, &state_paused, GST_CLOCK_TIME_NONE);
117
if( !gst_element_seek(music, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
118
GST_SEEK_TYPE_SET, 30*GST_SECOND,
119
GST_SEEK_TYPE_SET, 60*GST_SECOND))
120
g_print("playPreview() seek failed\n");
179
if (!gst_element_seek(music, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
180
GST_SEEK_TYPE_SET, 30*GST_SECOND, GST_SEEK_TYPE_NONE, 0))
181
g_print("playPreview() seek failed\n");
121
182
gst_element_set_state (music, GST_STATE_PLAYING);
122
183
GstFormat fmt = GST_FORMAT_TIME;
124
if (!gst_element_query_duration (music, &fmt, &len))
125
length = LENGTH_ERROR;
127
length = (int) (len/GST_MSECOND);
185
if (!gst_element_query_duration (music, &fmt, &len)) length = LENGTH_ERROR;
186
else length = int(len/GST_MSECOND);
188
// Wait a little while before restoring volume to prevent clicks
189
boost::thread::sleep(now() + 0.05);
190
setVolume_internal(volume);
131
int CAudio::getLength( void )
133
if( length == LENGTH_ERROR ) {
193
double CAudio::getLength_internal() {
194
if (length != LENGTH_ERROR) return 1e-3 * length;
134
195
#ifdef USE_LIBXINE_AUDIO
137
if( !xine_get_pos_length(stream, &pos_stream, &pos_time, &length) )
138
length = LENGTH_ERROR;
198
if (!xine_get_pos_length(stream, &pos_stream, &pos_time, &length)) length = LENGTH_ERROR;
140
200
#ifdef USE_GSTREAMER_AUDIO
141
GstFormat fmt = GST_FORMAT_TIME;
143
if (!gst_element_query_duration (music, &fmt, &len))
144
length = LENGTH_ERROR;
146
length = (int) (len/GST_MSECOND);
201
GstFormat fmt = GST_FORMAT_TIME;
203
length = gst_element_query_duration (music, &fmt, &len) ? int(len/GST_MSECOND) : LENGTH_ERROR;
150
if( length == LENGTH_ERROR )
205
return length == LENGTH_ERROR ? 0.0 : 1e-3 * length;
156
bool CAudio::isPlaying( void )
208
bool CAudio::isPlaying_internal() {
158
209
#ifdef USE_LIBXINE_AUDIO
160
while((event = xine_event_get(event_queue))) {
161
switch(event->type) {
162
case XINE_EVENT_UI_PLAYBACK_FINISHED:
166
xine_event_free(event);
211
while((event = xine_event_get(event_queue))) {
212
if (event->type == XINE_EVENT_UI_PLAYBACK_FINISHED) xine_playing = 0;
213
xine_event_free(event);
174
217
#ifdef USE_GSTREAMER_AUDIO
175
218
// If the length cannot be computed, we assume that the song is playing
176
219
// (happening in the first fex seconds)
220
if (getLength_internal() == 0) return true;
180
221
// If we are not in the last second, then we are not at the end of the song
181
if( getLength() - getPosition() > 1000 )
222
return getLength_internal() - getPosition_internal() > 1.0;
189
void CAudio::stopMusic( void )
227
void CAudio::stopMusic_internal() {
228
// if (!isPlaying_internal()) return;
191
229
#ifdef USE_LIBXINE_AUDIO
194
232
#ifdef USE_GSTREAMER_AUDIO
195
233
gst_element_set_state (music, GST_STATE_NULL);
199
int CAudio::getPosition( void )
237
double CAudio::getPosition_internal() {
238
double position = 0.0;
203
239
#ifdef USE_LIBXINE_AUDIO
208
if (xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time)) {
243
position = xine_get_pos_length(stream, &pos_stream, &pos_time, &length_time) ? 1e-3 * pos_time : 0.0;
214
245
#ifdef USE_GSTREAMER_AUDIO
215
246
GstFormat fmt = GST_FORMAT_TIME;
217
if (!gst_element_query_position (music, &fmt, &pos))
220
position = (int) (pos/GST_MSECOND);
248
position = gst_element_query_position(music, &fmt, &pos) ? double(pos) / GST_SECOND : 0.0;
226
bool CAudio::isPaused( void ) {
227
#ifdef USE_LIBXINE_AUDIO
229
int speed = xine_get_param(stream,XINE_PARAM_SPEED);
230
if (speed == XINE_SPEED_PAUSE)
237
#ifdef USE_GSTREAMER_AUDIO
238
return GST_STATE(music) == GST_STATE_PAUSED;
242
void CAudio::togglePause( void ){
244
#ifdef USE_LIBXINE_AUDIO
246
xine_set_param(stream,XINE_PARAM_SPEED,XINE_SPEED_NORMAL);
248
xine_set_param(stream,XINE_PARAM_SPEED,XINE_SPEED_PAUSE);
250
#ifdef USE_GSTREAMER_AUDIO
252
gst_element_set_state(music, GST_STATE_PLAYING);
254
gst_element_set_state(music, GST_STATE_PAUSED);
258
void CAudio::seek( int seek_dist ){
260
int position = getPosition()+seek_dist;
261
if ( position < 0) position = 0;
262
if ( position > getLength() - 1000){
263
fprintf(stdout,"seeking too far ahead\n");
266
fprintf(stdout,"seeking from %d to %d\n",getPosition(),position);
267
#ifdef USE_LIBXINE_AUDIO
268
xine_play(stream,0,position);
270
#ifdef USE_GSTREAMER_AUDIO
271
gst_element_set_state (music, GST_STATE_PAUSED);
272
GstState state_paused = GST_STATE_PAUSED;
273
gst_element_get_state (music, NULL, &state_paused, GST_CLOCK_TIME_NONE);
274
if( !gst_element_seek_simple(music, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position*GST_MSECOND))
275
g_print("playPreview() seek failed\n");
276
gst_element_set_state (music, GST_STATE_PLAYING);
253
bool CAudio::isPaused_internal() {
254
#ifdef USE_LIBXINE_AUDIO
255
return isPlaying_internal() && xine_get_param(stream,XINE_PARAM_SPEED) == XINE_SPEED_PAUSE;
257
#ifdef USE_GSTREAMER_AUDIO
258
return GST_STATE(music) == GST_STATE_PAUSED;
262
void CAudio::togglePause_internal() {
263
if (!isPlaying_internal()) return;
264
#ifdef USE_LIBXINE_AUDIO
265
xine_set_param(stream, XINE_PARAM_SPEED, isPaused_internal() ? XINE_SPEED_NORMAL : XINE_SPEED_PAUSE);
267
#ifdef USE_GSTREAMER_AUDIO
268
gst_element_set_state(music, isPaused_internal() ? GST_STATE_PLAYING : GST_STATE_PAUSED);
272
void CAudio::seek_internal(double seek_dist) {
273
if (!isPlaying_internal()) return;
274
int position = std::max(0.0, std::min(getLength_internal() - 1.0, getPosition_internal() + seek_dist));
275
#ifdef USE_LIBXINE_AUDIO
276
xine_play(stream, 0, 1e3 * position);
278
#ifdef USE_GSTREAMER_AUDIO
279
gst_element_set_state(music, GST_STATE_PAUSED);
280
GstState state_paused = GST_STATE_PAUSED;
281
gst_element_get_state(music, NULL, &state_paused, GST_CLOCK_TIME_NONE);
282
if (!gst_element_seek_simple(music, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position*GST_SECOND))
283
throw std::runtime_error("CAudio::seek_internal() failed");
284
gst_element_set_state(music, GST_STATE_PLAYING);