1 /*
2   This file is part of Deadbeef Player source code
3   http://deadbeef.sourceforge.net
4 
5   playback queue management
6 
7   Copyright (C) 2009-2015 Alexey Yakovenko
8 
9   This software is provided 'as-is', without any express or implied
10   warranty.  In no event will the authors be held liable for any damages
11   arising from the use of this software.
12 
13   Permission is granted to anyone to use this software for any purpose,
14   including commercial applications, and to alter it and redistribute it
15   freely, subject to the following restrictions:
16 
17   1. The origin of this software must not be misrepresented; you must not
18   claim that you wrote the original software. If you use this software
19   in a product, an acknowledgment in the product documentation would be
20   appreciated but is not required.
21   2. Altered source versions must be plainly marked as such, and must not be
22   misrepresented as being the original software.
23   3. This notice may not be removed or altered from any source distribution.
24 
25   Alexey Yakovenko waker@users.sourceforge.net
26 */
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include "playqueue.h"
31 #include "messagepump.h"
32 
33 #define PLAYQUEUE_SIZE 100
34 static playItem_t *playqueue[100];
35 static int playqueue_count = 0;
36 
37 #define trace(...) { fprintf(stderr, __VA_ARGS__); }
38 //#define trace(fmt,...)
39 
40 int
playqueue_push(playItem_t * it)41 playqueue_push (playItem_t *it) {
42     if (playqueue_count == PLAYQUEUE_SIZE) {
43         trace ("playqueue is full\n");
44         return -1;
45     }
46     pl_lock ();
47     pl_item_ref (it);
48     playqueue[playqueue_count++] = it;
49     pl_unlock ();
50     send_trackinfochanged (it);
51     messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
52     return 0;
53 }
54 
55 void
playqueue_clear(void)56 playqueue_clear (void) {
57     pl_lock ();
58     for (int i = 0; i < playqueue_count; i++) {
59         pl_item_unref (playqueue[i]);
60         playqueue[i] = NULL;
61     }
62     playqueue_count = 0;
63     pl_unlock ();
64     messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
65 }
66 
67 void
playqueue_pop(void)68 playqueue_pop (void) {
69     if (!playqueue_count) {
70         return;
71     }
72     pl_lock ();
73     if (playqueue_count == 1) {
74         playqueue_count = 0;
75         send_trackinfochanged (playqueue[0]);
76         messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
77         pl_item_unref (playqueue[0]);
78         pl_unlock ();
79         return;
80     }
81     playItem_t *it = playqueue[0];
82     memmove (&playqueue[0], &playqueue[1], (playqueue_count-1) * sizeof (playItem_t*));
83     playqueue_count--;
84     pl_item_unref (it);
85     pl_unlock ();
86     messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
87 }
88 
89 void
playqueue_remove(playItem_t * it)90 playqueue_remove (playItem_t *it) {
91     pl_lock ();
92     for (;;) {
93         int i;
94         for (i = 0; i < playqueue_count; i++) {
95             if (playqueue[i] == it) {
96                 if (i < playqueue_count-1) {
97                     memmove (&playqueue[i], &playqueue[i+1], (playqueue_count-i) * sizeof (playItem_t*));
98                 }
99                 pl_item_unref (it);
100                 playqueue_count--;
101                 break;
102             }
103         }
104         if (i == playqueue_count) {
105             break;
106         }
107     }
108     pl_unlock ();
109     messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
110 }
111 
112 int
playqueue_test(playItem_t * it)113 playqueue_test (playItem_t *it) {
114     pl_lock ();
115     for (int i = 0; i < playqueue_count; i++) {
116         if (playqueue[i] == it) {
117             pl_unlock ();
118             return i;
119         }
120     }
121     pl_unlock ();
122     return -1;
123 }
124 
125 playItem_t *
playqueue_getnext(void)126 playqueue_getnext (void) {
127     pl_lock ();
128     if (playqueue_count > 0) {
129         playItem_t *val = playqueue[0];
130         pl_item_ref (val);
131         pl_unlock ();
132         return val;
133     }
134     pl_unlock ();
135     return NULL;
136 }
137 
138 int
playqueue_getcount(void)139 playqueue_getcount (void) {
140     return playqueue_count;
141 }
142 
143 playItem_t *
playqueue_get_item(int i)144 playqueue_get_item (int i) {
145     pl_lock ();
146     playItem_t *it = playqueue[i];
147     pl_item_ref (it);
148     pl_unlock ();
149     return it;
150 }
151 
152 void
playqueue_remove_nth(int n)153 playqueue_remove_nth (int n) {
154     pl_lock ();
155     playItem_t *it = playqueue[n];
156     if (n < playqueue_count-1) {
157         memmove (playqueue + n, playqueue + n + 1, (playqueue_count-n) * sizeof (playItem_t*));
158     }
159     playqueue_count--;
160 
161     pl_item_unref (it);
162     pl_unlock ();
163     messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
164 }
165 
166 void
playqueue_insert_at(int n,playItem_t * it)167 playqueue_insert_at (int n, playItem_t *it) {
168     if (playqueue_count == PLAYQUEUE_SIZE) {
169         trace ("playqueue is full\n");
170         return;
171     }
172     pl_lock ();
173     if (n == playqueue_count) {
174         playqueue_push(it);
175         pl_unlock ();
176         return;
177     }
178     memmove (playqueue+n+1, playqueue+n, (playqueue_count - n) * sizeof (playItem_t *));
179     playqueue[n] = it;
180     pl_item_ref (it);
181     playqueue_count++;
182     pl_unlock ();
183     messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0);
184 }
185