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