~ubuntu-branches/ubuntu/trusty/mpd/trusty

« back to all changes in this revision

Viewing changes to src/playlist.c

  • Committer: Bazaar Package Importer
  • Author(s): Angel Abad
  • Date: 2011-02-02 12:26:30 UTC
  • mfrom: (1.5.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110202122630-bdyx8w4k94doz4fs
Tags: 0.16.1-1ubuntu1
* Merge from debian unstable. Remaining changes:
  - debian/control:
    + Don't build-depend on libmikmod2-dev (Debian bug #510675).
    + Move avahi-daemon from Suggests field to Recommends field.
  - debian/mpd.init.d:
    + Read mpd user from mpd.conf.
  - debian/control, debian/rules:
    + Add libmp3lame-dev to the build dependencies and enable lame.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 
2
 * Copyright (C) 2003-2010 The Music Player Daemon Project
3
3
 * http://www.musicpd.org
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
17
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
 */
19
19
 
 
20
#include "config.h"
20
21
#include "playlist_internal.h"
21
22
#include "playlist_save.h"
22
23
#include "player_control.h"
34
35
#undef G_LOG_DOMAIN
35
36
#define G_LOG_DOMAIN "playlist"
36
37
 
37
 
void playlistVersionChange(struct playlist *playlist)
 
38
void
 
39
playlist_increment_version_all(struct playlist *playlist)
38
40
{
39
41
        queue_modify_all(&playlist->queue);
40
42
        idle_add(IDLE_PLAYLIST);
61
63
 
62
64
        playlist->queued = -1;
63
65
        playlist->current = -1;
64
 
 
65
 
        playlist->prev_elapsed = g_timer_new();
66
66
}
67
67
 
68
68
void
69
69
playlist_finish(struct playlist *playlist)
70
70
{
71
71
        queue_finish(&playlist->queue);
72
 
 
73
 
        g_timer_destroy(playlist->prev_elapsed);
74
72
}
75
73
 
76
74
/**
91
89
        g_debug("queue song %i:\"%s\"", playlist->queued, uri);
92
90
        g_free(uri);
93
91
 
94
 
        queueSong(song);
 
92
        pc_enqueue_song(song);
95
93
}
96
94
 
97
95
/**
98
 
 * Check if the player thread has already started playing the "queued"
99
 
 * song.
 
96
 * Called if the player thread has started playing the "queued" song.
100
97
 */
101
 
static void syncPlaylistWithQueue(struct playlist *playlist)
 
98
static void
 
99
playlist_song_started(struct playlist *playlist)
102
100
{
103
 
        if (pc.next_song == NULL && playlist->queued != -1) {
104
 
                /* queued song has started: copy queued to current,
105
 
                   and notify the clients */
106
 
 
107
 
                int current = playlist->current;
108
 
                playlist->current = playlist->queued;
109
 
                playlist->queued = -1;
110
 
 
111
 
                if(playlist->queue.consume)
112
 
                        deleteFromPlaylist(playlist, queue_order_to_position(&playlist->queue, current));
113
 
 
114
 
                idle_add(IDLE_PLAYER);
 
101
        assert(pc.next_song == NULL);
 
102
        assert(playlist->queued >= -1);
 
103
 
 
104
        /* queued song has started: copy queued to current,
 
105
           and notify the clients */
 
106
 
 
107
        int current = playlist->current;
 
108
        playlist->current = playlist->queued;
 
109
        playlist->queued = -1;
 
110
 
 
111
        /* Pause if we are in single mode. */
 
112
        if(playlist->queue.single && !playlist->queue.repeat) {
 
113
                pc_set_pause(true);
115
114
        }
 
115
 
 
116
        if(playlist->queue.consume)
 
117
                playlist_delete(playlist, queue_order_to_position(&playlist->queue, current));
 
118
 
 
119
        idle_add(IDLE_PLAYER);
116
120
}
117
121
 
118
122
const struct song *
179
183
}
180
184
 
181
185
void
182
 
playPlaylistOrderNumber(struct playlist *playlist, int orderNum)
 
186
playlist_play_order(struct playlist *playlist, int orderNum)
183
187
{
184
188
        struct song *song;
185
189
        char *uri;
193
197
        g_debug("play %i:\"%s\"", orderNum, uri);
194
198
        g_free(uri);
195
199
 
196
 
        playerPlay(song);
 
200
        pc_play(song);
197
201
        playlist->current = orderNum;
198
202
}
199
203
 
200
204
static void
201
 
playPlaylistIfPlayerStopped(struct playlist *playlist);
 
205
playlist_resume_playback(struct playlist *playlist);
202
206
 
203
207
/**
204
208
 * This is the "PLAYLIST" event handler.  It is invoked by the player
205
209
 * thread whenever it requests a new queued song, or when it exits.
206
210
 */
207
 
void syncPlayerAndPlaylist(struct playlist *playlist)
 
211
void
 
212
playlist_sync(struct playlist *playlist)
208
213
{
209
214
        if (!playlist->playing)
210
215
                /* this event has reached us out of sync: we aren't
211
216
                   playing anymore; ignore the event */
212
217
                return;
213
218
 
214
 
        if (getPlayerState() == PLAYER_STATE_STOP)
 
219
        player_lock();
 
220
        enum player_state pc_state = pc_get_state();
 
221
        const struct song *pc_next_song = pc.next_song;
 
222
        player_unlock();
 
223
 
 
224
        if (pc_state == PLAYER_STATE_STOP)
215
225
                /* the player thread has stopped: check if playback
216
226
                   should be restarted with the next song.  That can
217
227
                   happen if the playlist isn't filling the queue fast
218
228
                   enough */
219
 
                playPlaylistIfPlayerStopped(playlist);
 
229
                playlist_resume_playback(playlist);
220
230
        else {
221
231
                /* check if the player thread has already started
222
232
                   playing the queued song */
223
 
                syncPlaylistWithQueue(playlist);
 
233
                if (pc_next_song == NULL && playlist->queued != -1)
 
234
                        playlist_song_started(playlist);
224
235
 
225
236
                /* make sure the queued song is always set (if
226
237
                   possible) */
227
 
                if (pc.next_song == NULL)
 
238
                if (pc.next_song == NULL && playlist->queued < 0)
228
239
                        playlist_update_queued_song(playlist, NULL);
229
240
        }
230
241
}
234
245
 * decide whether to re-start playback
235
246
 */
236
247
static void
237
 
playPlaylistIfPlayerStopped(struct playlist *playlist)
 
248
playlist_resume_playback(struct playlist *playlist)
238
249
{
239
250
        enum player_error error;
240
251
 
241
252
        assert(playlist->playing);
242
 
        assert(getPlayerState() == PLAYER_STATE_STOP);
 
253
        assert(pc_get_state() == PLAYER_STATE_STOP);
243
254
 
244
 
        error = getPlayerError();
 
255
        error = pc_get_error();
245
256
        if (error == PLAYER_ERROR_NOERROR)
246
257
                playlist->error_count = 0;
247
258
        else
252
263
            playlist->error_count >= queue_length(&playlist->queue))
253
264
                /* too many errors, or critical error: stop
254
265
                   playback */
255
 
                stopPlaylist(playlist);
 
266
                playlist_stop(playlist);
256
267
        else
257
268
                /* continue playback at the next song */
258
 
                nextSongInPlaylist(playlist);
 
269
                playlist_next(playlist);
259
270
}
260
271
 
261
272
bool
262
 
getPlaylistRepeatStatus(const struct playlist *playlist)
 
273
playlist_get_repeat(const struct playlist *playlist)
263
274
{
264
275
        return playlist->queue.repeat;
265
276
}
266
277
 
267
278
bool
268
 
getPlaylistRandomStatus(const struct playlist *playlist)
 
279
playlist_get_random(const struct playlist *playlist)
269
280
{
270
281
        return playlist->queue.random;
271
282
}
272
283
 
273
284
bool
274
 
getPlaylistSingleStatus(const struct playlist *playlist)
 
285
playlist_get_single(const struct playlist *playlist)
275
286
{
276
287
        return playlist->queue.single;
277
288
}
278
289
 
279
290
bool
280
 
getPlaylistConsumeStatus(const struct playlist *playlist)
 
291
playlist_get_consume(const struct playlist *playlist)
281
292
{
282
293
        return playlist->queue.consume;
283
294
}
284
295
 
285
 
void setPlaylistRepeatStatus(struct playlist *playlist, bool status)
 
296
void
 
297
playlist_set_repeat(struct playlist *playlist, bool status)
286
298
{
287
299
        if (status == playlist->queue.repeat)
288
300
                return;
297
309
        idle_add(IDLE_OPTIONS);
298
310
}
299
311
 
300
 
static void orderPlaylist(struct playlist *playlist)
 
312
static void
 
313
playlist_order(struct playlist *playlist)
301
314
{
302
315
        if (playlist->current >= 0)
303
316
                /* update playlist.current, order==position now */
307
320
        queue_restore_order(&playlist->queue);
308
321
}
309
322
 
310
 
void setPlaylistSingleStatus(struct playlist *playlist, bool status)
 
323
void
 
324
playlist_set_single(struct playlist *playlist, bool status)
311
325
{
312
326
        if (status == playlist->queue.single)
313
327
                return;
322
336
        idle_add(IDLE_OPTIONS);
323
337
}
324
338
 
325
 
void setPlaylistConsumeStatus(struct playlist *playlist, bool status)
 
339
void
 
340
playlist_set_consume(struct playlist *playlist, bool status)
326
341
{
327
342
        if (status == playlist->queue.consume)
328
343
                return;
331
346
        idle_add(IDLE_OPTIONS);
332
347
}
333
348
 
334
 
void setPlaylistRandomStatus(struct playlist *playlist, bool status)
 
349
void
 
350
playlist_set_random(struct playlist *playlist, bool status)
335
351
{
336
352
        const struct song *queued;
337
353
 
366
382
                } else
367
383
                        playlist->current = -1;
368
384
        } else
369
 
                orderPlaylist(playlist);
 
385
                playlist_order(playlist);
370
386
 
371
387
        playlist_update_queued_song(playlist, queued);
372
388
 
373
389
        idle_add(IDLE_OPTIONS);
374
390
}
375
391
 
376
 
int getPlaylistCurrentSong(const struct playlist *playlist)
 
392
int
 
393
playlist_get_current_song(const struct playlist *playlist)
377
394
{
378
395
        if (playlist->current >= 0)
379
396
                return queue_order_to_position(&playlist->queue,
382
399
        return -1;
383
400
}
384
401
 
385
 
int getPlaylistNextSong(const struct playlist *playlist)
 
402
int
 
403
playlist_get_next_song(const struct playlist *playlist)
386
404
{
387
405
        if (playlist->current >= 0)
388
406
        {
389
 
                if (playlist->queue.single == 1)
390
 
                {
391
 
                        if (playlist->queue.repeat == 1)
392
 
                                return queue_order_to_position(&playlist->queue,
393
 
                                                      playlist->current);
394
 
                        else
395
 
                                return -1;
396
 
                }
397
 
                if (playlist->current + 1 < (int)queue_length(&playlist->queue))
 
407
                if (playlist->queue.single == 1 && playlist->queue.repeat == 1)
 
408
                        return queue_order_to_position(&playlist->queue,
 
409
                                                       playlist->current);
 
410
                else if (playlist->current + 1 < (int)queue_length(&playlist->queue))
398
411
                        return queue_order_to_position(&playlist->queue,
399
412
                                               playlist->current + 1);
400
413
                else if (playlist->queue.repeat == 1)
405
418
}
406
419
 
407
420
unsigned long
408
 
getPlaylistVersion(const struct playlist *playlist)
 
421
playlist_get_version(const struct playlist *playlist)
409
422
{
410
423
        return playlist->queue.version;
411
424
}
412
425
 
413
426
int
414
 
getPlaylistLength(const struct playlist *playlist)
 
427
playlist_get_length(const struct playlist *playlist)
415
428
{
416
429
        return queue_length(&playlist->queue);
417
430
}
418
431
 
419
432
unsigned
420
 
getPlaylistSongId(const struct playlist *playlist, unsigned song)
 
433
playlist_get_song_id(const struct playlist *playlist, unsigned song)
421
434
{
422
435
        return queue_position_to_id(&playlist->queue, song);
423
436
}