Browse code

b/f: avoid to hide AmAudio::close() with AmPlaylist::close(…)

- AmPlaylist::close(…) is now replaced by AmPlaylist::flush().
- AmAudio::noAudio event is only sent if the play-cursor reaches the end (not through flush() or close()).

Raphael Coeffic authored on 22/02/2012 12:18:03
Showing 27 changed files
... ...
@@ -292,7 +292,7 @@ void AnnRecorderDialog::onDtmf(int event, int duration_msec) {
292 292
   switch (state) {
293 293
   case S_WAIT_START: { 
294 294
     DBG("received key %d in state S_WAIT_START: start recording\n", event); 
295
-    playlist.close(false);
295
+    playlist.flush();
296 296
 
297 297
     wav_file.close();
298 298
     msg_filename = "/tmp/" + getLocalTag() + ".wav";
... ...
@@ -312,14 +312,14 @@ void AnnRecorderDialog::onDtmf(int event, int duration_msec) {
312 312
   case S_RECORDING: {
313 313
     DBG("received key %d in state S_RECORDING: replay recording\n", event); 
314 314
     prompts.addToPlaylist(BEEP,  (long)this, playlist);
315
-    playlist.close(false);
315
+    playlist.flush();
316 316
     replayRecording();
317 317
     
318 318
   } break;
319 319
 
320 320
   case S_CONFIRM: { 
321 321
     DBG("received key %d in state S_CONFIRM save or redo\n", event); 
322
-    playlist.close(false);
322
+    playlist.flush();
323 323
 
324 324
     wav_file.close();
325 325
     if (event == 1) {
... ...
@@ -235,7 +235,6 @@ CallBackDialog::CallBackDialog(AmPromptCollection& prompts,
235 235
 CallBackDialog::~CallBackDialog()
236 236
 {
237 237
   prompts.cleanup((long)this);
238
-  play_list.close(false);
239 238
 }
240 239
 
241 240
 
... ...
@@ -280,7 +279,7 @@ void CallBackDialog::onDtmf(int event, int duration)
280 279
 	prompts.addToPlaylist(WELCOME_PROMPT,  (long)this, play_list);
281 280
       } else {
282 281
 	state = CBTellingNumber;
283
-	play_list.close();
282
+	play_list.flush();
284 283
 	for (size_t i=0;i<call_number.length();i++) {
285 284
 	  string num = "";
286 285
 	  num[0] = call_number[i]; // this works? 
... ...
@@ -390,7 +390,7 @@ ConferenceDialog::~ConferenceDialog()
390 390
   DBG("ConferenceDialog::~ConferenceDialog()\n");
391 391
 
392 392
   // clean playlist items
393
-  play_list.close(false);
393
+  play_list.flush();
394 394
 
395 395
 #ifdef WITH_SAS_TTS
396 396
   // garbage collect tts files - TODO: delete files
... ...
@@ -529,7 +529,7 @@ void ConferenceDialog::setupAudio()
529 529
   }
530 530
 
531 531
 
532
-  play_list.close();// !!!
532
+  play_list.flush();
533 533
 
534 534
   if(dialout_channel.get()){
535 535
 
... ...
@@ -660,7 +660,7 @@ void ConferenceDialog::process(AmEvent* ev)
660 660
 
661 661
 	state = CS_dialout_connected;
662 662
 
663
-	play_list.close(); // !!!
663
+	play_list.flush();
664 664
 	play_list.addToPlaylist(new AmPlaylistItem(dialout_channel.get(),
665 665
 						   dialout_channel.get()));
666 666
 	break;
... ...
@@ -671,7 +671,7 @@ void ConferenceDialog::process(AmEvent* ev)
671 671
 	  RingTone.reset(new AmRingTone(0,2000,4000,440,480)); // US
672 672
 
673 673
 	DBG("adding ring tone to the playlist (dialedout = %i)\n",dialedout);
674
-	play_list.close();
674
+	play_list.flush();
675 675
 	play_list.addToPlaylist(new AmPlaylistItem(RingTone.get(),NULL));
676 676
 	break;
677 677
 
... ...
@@ -682,7 +682,6 @@ void ConferenceDialog::process(AmEvent* ev)
682 682
 	  ErrorTone.reset(new AmRingTone(2000,250,250,440,480));
683 683
 
684 684
 	DBG("adding error tone to the playlist (dialedout = %i)\n",dialedout);
685
-	//play_list.close();
686 685
 	play_list.addToPlayListFront(new AmPlaylistItem(ErrorTone.get(),NULL));
687 686
 	break;
688 687
 		
... ...
@@ -860,7 +859,7 @@ void ConferenceDialog::connectMainChannel()
860 859
   dialedout = false;
861 860
   dialout_channel.reset(NULL);
862 861
     
863
-  play_list.close();
862
+  play_list.flush();
864 863
 
865 864
   if(!channel.get())
866 865
     channel.reset(AmConferenceStatus
... ...
@@ -873,7 +872,7 @@ void ConferenceDialog::connectMainChannel()
873 872
 
874 873
 void ConferenceDialog::closeChannels()
875 874
 {
876
-  play_list.close();
875
+  play_list.flush();
877 876
   setInOut(NULL,NULL);
878 877
   channel.reset(NULL);
879 878
   dialout_channel.reset(NULL);
... ...
@@ -521,9 +521,9 @@ void DSMCall::playPrompt(const string& name, bool loop) {
521 521
   }
522 522
 }
523 523
 
524
-void DSMCall::closePlaylist(bool notify) {
525
-  DBG("close playlist\n");
526
-  playlist.close(notify);  
524
+void DSMCall::flushPlaylist() {
525
+  DBG("flush playlist\n");
526
+  playlist.flush();  
527 527
 }
528 528
 
529 529
 void DSMCall::addToPlaylist(AmPlaylistItem* item) {
... ...
@@ -101,7 +101,7 @@ public:
101 101
 
102 102
   // DSMSession interface
103 103
   void playPrompt(const string& name, bool loop = false);
104
-  void closePlaylist(bool notify);
104
+  void flushPlaylist();
105 105
   void addToPlaylist(AmPlaylistItem* item);
106 106
   void playFile(const string& name, bool loop, bool front=false);
107 107
   void recordFile(const string& name);
... ...
@@ -62,7 +62,7 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) {
62 62
   DEF_CMD("stopRecord", SCStopRecordAction);
63 63
   DEF_CMD("getRecordLength", SCGetRecordLengthAction);
64 64
   DEF_CMD("getRecordDataSize", SCGetRecordDataSizeAction);
65
-  DEF_CMD("closePlaylist", SCClosePlaylistAction);
65
+  DEF_CMD("flushPlaylist", SCFlushPlaylistAction);
66 66
   DEF_CMD("setInOutPlaylist", SCSetInOutPlaylistAction);
67 67
   DEF_CMD("addSeparator", SCAddSeparatorAction);
68 68
   DEF_CMD("connectMedia", SCConnectMediaAction);
... ...
@@ -318,10 +318,8 @@ EXEC_ACTION_START(SCGetRecordDataSizeAction) {
318 318
   sc_sess->var[varname]=int2str(sc_sess->getRecordDataSize());
319 319
 } EXEC_ACTION_END;
320 320
 
321
-EXEC_ACTION_START(SCClosePlaylistAction) {
322
-  bool notify = 
323
-    resolveVars(arg, sess, sc_sess, event_params) == "true";
324
-  sc_sess->closePlaylist(notify);
321
+EXEC_ACTION_START(SCFlushPlaylistAction) {
322
+  sc_sess->flushPlaylist();
325 323
 } EXEC_ACTION_END;
326 324
 
327 325
 
... ...
@@ -53,7 +53,7 @@ DEF_ACTION_1P(SCRecordFileAction);
53 53
 DEF_ACTION_1P(SCStopRecordAction);
54 54
 DEF_ACTION_1P(SCGetRecordDataSizeAction);
55 55
 DEF_ACTION_1P(SCGetRecordLengthAction);
56
-DEF_ACTION_1P(SCClosePlaylistAction);
56
+DEF_ACTION_1P(SCFlushPlaylistAction);
57 57
 DEF_ACTION_1P(SCSetInOutPlaylistAction);
58 58
 DEF_ACTION_1P(SCStopAction);
59 59
 DEF_ACTION_1P(SCConnectMediaAction);
... ...
@@ -111,7 +111,7 @@ class DSMSession {
111 111
   virtual void setOutputPlaylist() = 0;
112 112
 
113 113
   virtual void addToPlaylist(AmPlaylistItem* item) = 0;
114
-  virtual void closePlaylist(bool notify) = 0;
114
+  virtual void flushPlaylist() = 0;
115 115
   virtual void setPromptSet(const string& name) = 0;
116 116
   virtual void addSeparator(const string& name, bool front = false) = 0;
117 117
   virtual void connectMedia() = 0;
... ...
@@ -175,7 +175,7 @@ NOT_IMPLEMENTED(setInputPlaylist());
175 175
 NOT_IMPLEMENTED(setOutputPlaylist());
176 176
 
177 177
 NOT_IMPLEMENTED(addToPlaylist(AmPlaylistItem* item));
178
-NOT_IMPLEMENTED(closePlaylist(bool notify));
178
+NOT_IMPLEMENTED(flushPlaylist());
179 179
 NOT_IMPLEMENTED(setPromptSet(const string& name));
180 180
 NOT_IMPLEMENTED(addSeparator(const string& name, bool front));
181 181
 NOT_IMPLEMENTED(connectMedia());
... ...
@@ -66,7 +66,7 @@ class SystemDSM
66 66
    void setOutputPlaylist();
67 67
 
68 68
    void addToPlaylist(AmPlaylistItem* item);
69
-   void closePlaylist(bool notify);
69
+   void flushPlaylist();
70 70
    void setPromptSet(const string& name);
71 71
    void addSeparator(const string& name, bool front = false);
72 72
    void connectMedia();
... ...
@@ -218,17 +218,12 @@ extern "C" {
218 218
     return Py_None;
219 219
   }
220 220
 
221
-  static PyObject* closePlaylist(PyObject*, PyObject* args)
221
+  static PyObject* flushPlaylist(PyObject*, PyObject* args)
222 222
   {
223
-    int notify = 0;
224
-
225
-    if(!PyArg_ParseTuple(args,"i",&notify))
226
-      return NULL;
227
-
228 223
     GET_SESS_PTR;
229 224
     
230
-    DBG("playFile(notify=%s)\n", notify?"true":"false");
231
-    sess->closePlaylist(notify);
225
+    DBG("flushPlaylist()\n");
226
+    sess->flushPlaylist();
232 227
     Py_INCREF(Py_None);
233 228
     return Py_None;
234 229
   }
... ...
@@ -347,7 +342,7 @@ extern "C" {
347 342
     {"getRecordLength",  (PyCFunction)getRecordLength, METH_NOARGS,"get the length of the current recording"},
348 343
     {"getRecordDataSize",(PyCFunction)getRecordDataSize, METH_NOARGS,"get the data size of the current recording"},
349 344
     {"stopRecord",      (PyCFunction)stopRecord, METH_NOARGS,"stop the running recording"},
350
-    {"closePlaylist",   (PyCFunction)closePlaylist, METH_VARARGS,"close the playlist"},
345
+    {"flushPlaylist",   (PyCFunction)flushPlaylist, METH_NOARGS,"flush the playlist"},
351 346
     {"setPromptSet",    (PyCFunction)setPromptSet, METH_VARARGS,"set prompt set"},
352 347
     {"addSeparator",    (PyCFunction)addSeparator, METH_VARARGS,"add a named separator to playlist"},
353 348
     {"connectMedia",    (PyCFunction)connectMedia, METH_NOARGS,"connect media (RTP processing)"},
... ...
@@ -379,7 +379,7 @@ CallGenDialog::CallGenDialog(AmPromptCollection& prompts,
379 379
 CallGenDialog::~CallGenDialog()
380 380
 {
381 381
   prompts.cleanup((long)this);
382
-  play_list.close(false);
382
+  play_list.flush();
383 383
   report(CGDestroy);
384 384
 }
385 385
 
... ...
@@ -452,7 +452,7 @@ void CallGenDialog::process(AmEvent* event)
452 452
     time(&disconnect_ts);
453 453
     report(CGDisconnect);
454 454
 
455
-    play_list.close();
455
+    play_list.flush();
456 456
     setInOut(NULL,NULL);
457 457
     setStopped();
458 458
     dlg.bye();
... ...
@@ -466,7 +466,7 @@ void CallGenDialog::onBye(const AmSipRequest& req) {
466 466
   time(&disconnect_ts);
467 467
   report(CGDisconnect);
468 468
 
469
-  play_list.close();
469
+  play_list.flush();
470 470
   setInOut(NULL,NULL);
471 471
   setStopped();
472 472
 }
... ...
@@ -106,7 +106,7 @@ PinAuthConferenceDialog::PinAuthConferenceDialog(AmPromptCollection& prompts)
106 106
 
107 107
 PinAuthConferenceDialog::~PinAuthConferenceDialog()
108 108
 {
109
-  play_list.close(false);
109
+  play_list.flush();
110 110
   prompts.cleanup((long)this);
111 111
 }
112 112
 
... ...
@@ -126,7 +126,7 @@ void PinAuthConferenceDialog::connectConference(const string& room) {
126 126
   channel.reset(AmConferenceStatus::getChannel(conf_id,getLocalTag()));
127 127
 
128 128
   // clear the playlist
129
-  play_list.close(false);
129
+  play_list.flush();
130 130
 
131 131
   // add the channel to our playlist
132 132
   play_list.addToPlaylist(new AmPlaylistItem(channel.get(),
... ...
@@ -150,7 +150,7 @@ void PinAuthConferenceDialog::onSessionStart()
150 150
  
151 151
 void PinAuthConferenceDialog::onBye(const AmSipRequest& req)
152 152
 {
153
-  play_list.close();
153
+  play_list.flush();
154 154
   setInOut(NULL,NULL);
155 155
   channel.reset(NULL);
156 156
   setStopped();
... ...
@@ -224,7 +224,7 @@ void PinAuthConferenceDialog::onDtmf(int event, int duration)
224 224
       } else {
225 225
 	state = EnteringConference;
226 226
 	setInOut(NULL, NULL);
227
-	play_list.close();
227
+	play_list.flush();
228 228
 	for (size_t i=0;i<pin_str.length();i++) {
229 229
 	  string num = "";
230 230
 	  num[0] = pin_str[i];
... ...
@@ -108,7 +108,7 @@ int CCAcc::subtractCredit(string pin, int amount) {
108 108
     credits_mut.unlock();
109 109
     return -1;
110 110
   }
111
-  if (it->second - amount < 0) {
111
+  if ((int)it->second - amount < 0) {
112 112
     credits[pin] = 0;
113 113
   } else {
114 114
     credits[pin] = it->second - amount;
... ...
@@ -115,7 +115,7 @@ void MyCCDialog::onDtmf(int event, int duration) {
115 115
   case CC_Collecting_PIN: {
116 116
     // flush the playlist (stop playing) 
117 117
     // if a key is entered
118
-    playlist.close(); 
118
+    playlist.flush(); 
119 119
     
120 120
     if(event <10) {
121 121
       pin +=int2str(event);
... ...
@@ -141,7 +141,7 @@ void MyCCDialog::onDtmf(int event, int duration) {
141 141
   case CC_Collecting_Number: {
142 142
     // flush the playlist (stop playing) 
143 143
     // if a key is entered
144
-    playlist.close(); 
144
+    playlist.flush(); 
145 145
     if(event <10) {
146 146
       number +=int2str(event);
147 147
       DBG("number is now '%s'\n", number.c_str());
... ...
@@ -45,7 +45,7 @@ MyJukeboxDialog::MyJukeboxDialog()
45 45
 MyJukeboxDialog::~MyJukeboxDialog()
46 46
 {
47 47
   // clean playlist items
48
-  playlist.close(false);
48
+  playlist.flush();
49 49
   // clean used AmAudioFile objects
50 50
   for (vector<AmAudioFile*>::iterator it=
51 51
 	 used_audio_files.begin(); it != used_audio_files.end();it++)
... ...
@@ -554,7 +554,7 @@ IvrDialog::~IvrDialog()
554 554
 {
555 555
   DBG("----------- IvrDialog::~IvrDialog() ------------- \n");
556 556
 
557
-  playlist.close(false);
557
+  playlist.flush();
558 558
   
559 559
   PYLOCK;
560 560
   Py_XDECREF(py_mod);
... ...
@@ -181,7 +181,7 @@ static PyObject* IvrDialogBase_flush(IvrDialogBase* self, PyObject* args)
181 181
 {
182 182
   assert(self->p_dlg);
183 183
 
184
-  self->p_dlg->playlist.close();
184
+  self->p_dlg->playlist.flush();
185 185
     
186 186
   Py_INCREF(Py_None);
187 187
   return Py_None;
... ...
@@ -45,7 +45,7 @@ using std::string;
45 45
 // request the client to connect the streams
46 46
 #define RTMP_CALL_CONNECT_STREAMS 4
47 47
 
48
-class SIPRegistrationEvent;
48
+struct SIPRegistrationEvent;
49 49
 class RtmpSession;
50 50
 class RtmpSender;
51 51
 class RtmpAudio;
... ...
@@ -1235,7 +1235,8 @@ RTMP_ClientPacket(RTMP *r, RTMPPacket *packet)
1235 1235
       RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,
1236 1236
 	  packet->m_packetType);
1237 1237
 #ifdef _DEBUG
1238
-      RTMP_LogHex(RTMP_LOGDEBUG, packet->m_body, packet->m_nBodySize);
1238
+      RTMP_LogHex(RTMP_LOGDEBUG, (const uint8_t*)packet->m_body, 
1239
+		  packet->m_nBodySize);
1239 1240
 #endif
1240 1241
     }
1241 1242
 
... ...
@@ -74,7 +74,7 @@ VoiceboxDialog::VoiceboxDialog(const string& user,
74 74
 VoiceboxDialog::~VoiceboxDialog()
75 75
 {
76 76
   // empty playlist items
77
-  play_list.close(false);
77
+  play_list.flush();
78 78
   prompts->cleanup((long)this);
79 79
 }
80 80
 
... ...
@@ -144,7 +144,7 @@ void VoiceboxDialog::onDtmf(int event, int duration)
144 144
       event, duration);
145 145
   
146 146
   if (EnteringPin == state) {
147
-    play_list.close(false);
147
+    play_list.flush();
148 148
     // check pin
149 149
     if (event<10) {
150 150
       entered_pin += int2str(event);
... ...
@@ -154,7 +154,7 @@ void VoiceboxDialog::onDtmf(int event, int duration)
154 154
     if (event==10 || event==11) { // # and * keys
155 155
       if (entered_pin.compare(pin)) { // wrong pin
156 156
 	entered_pin.clear();
157
-	play_list.close(false);       
157
+	play_list.flush();
158 158
 	prompts->addToPlaylist("pin_prompt", (long)this, play_list, true);
159 159
       }
160 160
     }
... ...
@@ -166,11 +166,11 @@ void VoiceboxDialog::onDtmf(int event, int duration)
166 166
 
167 167
   if (MsgAction == state) {      
168 168
     if ((unsigned int)event == VoiceboxFactory::repeat_key) {
169
-      play_list.close(false);
169
+      play_list.flush();
170 170
       repeatCurMessage();
171 171
     } else if ((unsigned int)event == VoiceboxFactory::save_key) {
172 172
       state = Prompting;
173
-      play_list.close(false);
173
+      play_list.flush();
174 174
       enqueueBack("msg_saved");
175 175
       saveCurMessage();
176 176
       edited_msgs.push_back(*cur_msg);
... ...
@@ -181,7 +181,7 @@ void VoiceboxDialog::onDtmf(int event, int duration)
181 181
       }
182 182
     } else if ((unsigned int)event == VoiceboxFactory::delete_key) { 
183 183
       state = Prompting;
184
-      play_list.close(false);
184
+      play_list.flush();
185 185
       enqueueBack("msg_deleted");
186 186
       deleteCurMessage(); 
187 187
       advanceMessage();
... ...
@@ -448,7 +448,7 @@ bool VoiceboxDialog::enqueueCurMessage() {
448 448
 }
449 449
 
450 450
 void VoiceboxDialog::repeatCurMessage() {
451
-  play_list.close(false);
451
+  play_list.flush();
452 452
   message.rewind();
453 453
   play_list.addToPlaylist(new AmPlaylistItem(&message, NULL));
454 454
   enqueueBack("msg_menu");
... ...
@@ -752,7 +752,7 @@ AnswerMachineDialog::AnswerMachineDialog(const string& user,
752 752
 
753 753
 AnswerMachineDialog::~AnswerMachineDialog()
754 754
 {
755
-  playlist.close(false);
755
+  playlist.flush();
756 756
 }
757 757
 
758 758
 void AnswerMachineDialog::process(AmEvent* event)
... ...
@@ -763,37 +763,7 @@ void AnswerMachineDialog::process(AmEvent* event)
763 763
     switch(ae->event_id){
764 764
 
765 765
     case AmAudioEvent::noAudio:
766
-
767
-      switch(status){
768
-
769
-      case 0: {
770
-	// announcement mode - no recording
771
-	if (MODE_ANN == vm_mode) {
772
-	  dlg.bye();
773
-	  setStopped();
774
-	  return;
775
-	}
776
-
777
-	playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));
778
-		
779
-	setTimer(RECORD_TIMER, AnswerMachineFactory::MaxRecordTime);
780
-
781
-	status = 1;
782
-      } break;
783
-
784
-      case 1:
785
-	a_beep.rewind();
786
-	playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
787
-	status = 2;
788
-	break;
789
-
790
-      case 2:
791
-	dlg.bye();
792
-	saveMessage();
793
-	setStopped();
794
-	break;
795
-
796
-      }
766
+      onNoAudio();
797 767
       break;
798 768
 
799 769
     case AmAudioEvent::cleared:
... ...
@@ -812,13 +782,47 @@ void AnswerMachineDialog::process(AmEvent* event)
812 782
   if(plugin_event && plugin_event->name == "timer_timeout" &&
813 783
      plugin_event->data.get(0).asInt() == RECORD_TIMER) {
814 784
 
815
-    // clear list
816
-    playlist.close();
785
+    playlist.flush();
786
+    onNoAudio();
817 787
   }
818 788
   else
819 789
     AmSession::process(event);
820 790
 }
821 791
 
792
+void AnswerMachineDialog::onNoAudio()
793
+{
794
+  switch(status){
795
+    
796
+  case 0: {
797
+    // announcement mode - no recording
798
+    if (MODE_ANN == vm_mode) {
799
+      dlg.bye();
800
+      setStopped();
801
+      return;
802
+    }
803
+    
804
+    playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));
805
+    
806
+    setTimer(RECORD_TIMER, AnswerMachineFactory::MaxRecordTime);
807
+    
808
+    status = 1;
809
+  } break;
810
+
811
+  case 1:
812
+    a_beep.rewind();
813
+    playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
814
+    status = 2;
815
+    break;
816
+    
817
+  case 2:
818
+    dlg.bye();
819
+    saveMessage();
820
+    setStopped();
821
+    break;
822
+    
823
+  }
824
+}
825
+
822 826
 void AnswerMachineDialog::onSessionStart()
823 827
 {
824 828
   // disable DTMF detection - don't use DTMF here
... ...
@@ -127,6 +127,8 @@ class AnswerMachineDialog : public AmSession
127 127
     void saveMessage();
128 128
     void saveBox(FILE* fp);
129 129
 
130
+    void onNoAudio();
131
+
130 132
  public:
131 133
   AnswerMachineDialog(const string& user, 
132 134
 		      const string& sender, 
... ...
@@ -68,7 +68,7 @@ WebConferenceDialog::~WebConferenceDialog()
68 68
   }
69 69
 
70 70
   prompts.cleanup((long)this);
71
-  play_list.close(false);
71
+  play_list.flush();
72 72
   if (is_dialout || (InConference == state)) {
73 73
     factory->updateStatus(is_dialout?dlg.user:conf_id, 
74 74
 			  getLocalTag(), 
... ...
@@ -97,7 +97,7 @@ void WebConferenceDialog::connectConference(const string& room) {
97 97
 					    ConfNewParticipant,getLocalTag());
98 98
 
99 99
   // clear the playlist
100
-  play_list.close();
100
+  play_list.flush();
101 101
 
102 102
   // add the channel to our playlist
103 103
   play_list.addToPlaylist(new AmPlaylistItem(channel.get(), channel.get()));
... ...
@@ -273,7 +273,7 @@ void WebConferenceDialog::onBye(const AmSipRequest& req)
273 273
 }
274 274
 
275 275
 void WebConferenceDialog::disconnectConference() {
276
-  play_list.close();
276
+  play_list.flush();
277 277
   setInOut(NULL,NULL);
278 278
   channel.reset(NULL);
279 279
   setStopped();
... ...
@@ -369,7 +369,7 @@ void WebConferenceDialog::onDtmf(int event, int duration) {
369 369
       pin_str += int2str(event);
370 370
       DBG("added '%s': PIN is now '%s'.\n", 
371 371
 	  int2str(event).c_str(), pin_str.c_str());
372
-      play_list.close(false);
372
+      play_list.flush();
373 373
     } else if (event==10 || event==11) {
374 374
       // pound and star key
375 375
       if (!pin_str.length() || !factory->isValidConference(pin_str)) {
... ...
@@ -378,7 +378,7 @@ void WebConferenceDialog::onDtmf(int event, int duration) {
378 378
       } else {
379 379
 	state = EnteringConference;
380 380
 	setInOut(NULL, NULL);
381
-	play_list.close();
381
+	play_list.flush();
382 382
 	for (size_t i=0;i<pin_str.length();i++) {
383 383
 	  string num = "";
384 384
 	  num[0] = pin_str[i];
... ...
@@ -293,6 +293,7 @@ AmAudio::~AmAudio()
293 293
   if (NULL != resample_state) 
294 294
     src_delete(resample_state);
295 295
 #endif
296
+  close();
296 297
 }
297 298
 
298 299
 void AmAudio::setFormat(AmAudioFormat* new_fmt) {
... ...
@@ -46,19 +46,13 @@ void AmPlaylist::gotoNextItem(bool notify)
46 46
   bool had_item = false;
47 47
   if(cur_item){
48 48
 
49
-    // 	if(cur_item->play)
50
-    // 	    cur_item->play->close();
51
-
52
-    // 	if(cur_item->record)
53
-    // 	    cur_item->record->close();
54
-
55 49
     delete cur_item;
56 50
     cur_item = 0;
57 51
     had_item = true;
58 52
   }
59 53
 
60 54
   updateCurrentItem();
61
-  if(notify && had_item && !cur_item){
55
+  if(notify && had_item && !cur_item && ev_q){
62 56
     DBG("posting AmAudioEvent::noAudio event!\n");
63 57
     ev_q->postEvent(new AmAudioEvent(AmAudioEvent::noAudio));
64 58
   }
... ...
@@ -76,7 +70,7 @@ int AmPlaylist::get(unsigned int user_ts, unsigned char* buffer, unsigned int nb
76 70
 	(ret = cur_item->play->get(user_ts,buffer,nb_samples)) <= 0){
77 71
 
78 72
     DBG("get: gotoNextItem\n");
79
-    gotoNextItem();
73
+    gotoNextItem(true);
80 74
   }
81 75
 
82 76
   if(!cur_item || !cur_item->play) {
... ...
@@ -99,7 +93,7 @@ int AmPlaylist::put(unsigned int user_ts, unsigned char* buffer, unsigned int si
99 93
 	(ret = cur_item->record->put(user_ts,buffer,size)) < 0){
100 94
 
101 95
     DBG("put: gotoNextItem\n");
102
-    gotoNextItem();
96
+    gotoNextItem(true);
103 97
   }
104 98
 
105 99
   if(!cur_item || !cur_item->record)
... ...
@@ -116,11 +110,6 @@ AmPlaylist::AmPlaylist(AmEventQueue* q)
116 110
   
117 111
 }
118 112
 
119
-AmPlaylist::~AmPlaylist()
120
-{
121
-  close(false);
122
-}
123
-
124 113
 void AmPlaylist::addToPlaylist(AmPlaylistItem* item)
125 114
 {
126 115
   items_mut.lock();
... ...
@@ -143,7 +132,14 @@ void AmPlaylist::addToPlayListFront(AmPlaylistItem* item)
143 132
   cur_mut.unlock();
144 133
 }
145 134
 
146
-void AmPlaylist::close(bool notify)
135
+void AmPlaylist::close()
136
+{
137
+  DBG("flushing playlist before closing\n");
138
+  flush();
139
+  AmAudio::close();
140
+}
141
+
142
+void AmPlaylist::flush()
147 143
 {
148 144
   cur_mut.lock();
149 145
   if(!cur_item && !items.empty()){
... ...
@@ -152,7 +148,7 @@ void AmPlaylist::close(bool notify)
152 148
   }
153 149
 
154 150
   while(cur_item)
155
-    gotoNextItem(notify);
151
+    gotoNextItem(false);
156 152
   cur_mut.unlock();
157 153
 }
158 154
 
... ...
@@ -68,26 +68,29 @@ class AmPlaylist: public AmAudio
68 68
   AmEventQueue*          ev_q;
69 69
 
70 70
   void updateCurrentItem();
71
-  void gotoNextItem(bool notify = true);
71
+  void gotoNextItem(bool notify);
72 72
     
73 73
  protected:
74
-  // Fake implement AmAudio's pure virtual methods
74
+  /** Fake implement AmAudio's pure virtual methods */
75 75
   int read(unsigned int user_ts, unsigned int size){ return -1; }
76 76
   int write(unsigned int user_ts, unsigned int size){ return -1; }
77 77
     
78
-  // override AmAudio
78
+  /** override AmAudio */
79 79
   int get(unsigned int user_ts, unsigned char* buffer, unsigned int nb_samples);
80 80
   int put(unsigned int user_ts, unsigned char* buffer, unsigned int size);
81 81
 	
82
- public:
83
-  AmPlaylist(AmEventQueue* q);
84
-  ~AmPlaylist();
82
+  /** from AmAudio */
83
+  void close();
85 84
     
85
+ public:
86
+  AmPlaylist(AmEventQueue* q = NULL);
87
+
86 88
   bool isEmpty();
87 89
 
88 90
   void addToPlaylist(AmPlaylistItem* item);
89 91
   void addToPlayListFront(AmPlaylistItem* item);
90
-  void close(bool notify = true);
92
+
93
+  void flush();
91 94
 };
92 95
 
93 96
 /**