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