1 /*
2 * Copyright (C) 2002-2003 Fhg Fokus
3 *
4 * This file is part of SEMS, a free SIP media server.
5 *
6 * SEMS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. This program is released under
10 * the GPL with the additional exemption that compiling, linking,
11 * and/or using OpenSSL is allowed.
12 *
13 * For a license to use the SEMS software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
16 * info@iptel.org
17 *
18 * SEMS is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 */
27
28 #include "AmPlaylist.h"
29 #include "amci/codecs.h"
30 #include "log.h"
31
updateCurrentItem()32 void AmPlaylist::updateCurrentItem()
33 {
34 if(!cur_item){
35 items_mut.lock();
36 if(!items.empty()){
37 cur_item = items.front();
38 items.pop_front();
39 }
40 items_mut.unlock();
41 }
42 }
43
gotoNextItem(bool notify)44 void AmPlaylist::gotoNextItem(bool notify)
45 {
46 bool had_item = false;
47 if(cur_item){
48
49 delete cur_item;
50 cur_item = 0;
51 had_item = true;
52 }
53
54 updateCurrentItem();
55 if(notify && had_item && !cur_item && ev_q){
56 DBG("posting AmAudioEvent::noAudio event!\n");
57 ev_q->postEvent(new AmAudioEvent(AmAudioEvent::noAudio));
58 }
59 }
60
get(unsigned long long system_ts,unsigned char * buffer,int output_sample_rate,unsigned int nb_samples)61 int AmPlaylist::get(unsigned long long system_ts, unsigned char* buffer,
62 int output_sample_rate, unsigned int nb_samples)
63 {
64 int ret = -1;
65
66 cur_mut.lock();
67 updateCurrentItem();
68
69 while(cur_item &&
70 cur_item->play &&
71 (ret = cur_item->play->get(system_ts,buffer,
72 output_sample_rate,
73 nb_samples)) <= 0) {
74
75 DBG("get: gotoNextItem\n");
76 gotoNextItem(true);
77 }
78
79 if(!cur_item || !cur_item->play) {
80 ret = calcBytesToRead(nb_samples);
81 memset(buffer,0,ret);
82 }
83
84 cur_mut.unlock();
85 return ret;
86 }
87
put(unsigned long long system_ts,unsigned char * buffer,int input_sample_rate,unsigned int size)88 int AmPlaylist::put(unsigned long long system_ts, unsigned char* buffer,
89 int input_sample_rate, unsigned int size)
90 {
91 int ret = -1;
92
93 cur_mut.lock();
94 updateCurrentItem();
95 while(cur_item &&
96 cur_item->record &&
97 (ret = cur_item->record->put(system_ts,buffer,
98 input_sample_rate,
99 size)) < 0) {
100
101 DBG("put: gotoNextItem\n");
102 gotoNextItem(true);
103 }
104
105 if(!cur_item || !cur_item->record)
106 ret = size;
107
108 cur_mut.unlock();
109 return ret;
110 }
111
AmPlaylist(AmEventQueue * q)112 AmPlaylist::AmPlaylist(AmEventQueue* q)
113 : AmAudio(new AmAudioFormat(CODEC_PCM16)),
114 cur_item(0), ev_q(q)
115 {
116
117 }
118
~AmPlaylist()119 AmPlaylist::~AmPlaylist() {
120 flush();
121 }
122
addToPlaylist(AmPlaylistItem * item)123 void AmPlaylist::addToPlaylist(AmPlaylistItem* item)
124 {
125 items_mut.lock();
126 items.push_back(item);
127 items_mut.unlock();
128 }
129
addToPlayListFront(AmPlaylistItem * item)130 void AmPlaylist::addToPlayListFront(AmPlaylistItem* item)
131 {
132 cur_mut.lock();
133 items_mut.lock();
134 if(cur_item){
135 items.push_front(cur_item);
136 cur_item = item;
137 }
138 else {
139 items.push_front(item);
140 }
141 items_mut.unlock();
142 cur_mut.unlock();
143 }
144
close()145 void AmPlaylist::close()
146 {
147 DBG("flushing playlist before closing\n");
148 flush();
149 AmAudio::close();
150 }
151
flush()152 void AmPlaylist::flush()
153 {
154 cur_mut.lock();
155 if(!cur_item && !items.empty()){
156 cur_item = items.front();
157 items.pop_front();
158 }
159
160 while(cur_item)
161 gotoNextItem(false);
162 cur_mut.unlock();
163 }
164
isEmpty()165 bool AmPlaylist::isEmpty()
166 {
167 bool res(true);
168
169 cur_mut.lock();
170 items_mut.lock();
171
172 res = (!cur_item) && items.empty();
173
174 items_mut.unlock();
175 cur_mut.unlock();
176
177 return res;
178 }
179