1 /*
2  * Copyright (C) 2006 iptelorg GmbH
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 /** @file AmPlaylist.h */
28 #ifndef AmPlaylist_h
29 #define AmPlaylist_h
30 
31 #include "AmAudio.h"
32 #include "AmThread.h"
33 #include "AmEventQueue.h"
34 
35 #include <deque>
36 using std::deque;
37 /** \brief entry in an \ref AmPlaylist */
38 struct AmPlaylistItem
39 {
40 
41   AmAudio* play;
42   AmAudio* record;
43 
AmPlaylistItemAmPlaylistItem44   AmPlaylistItem(AmAudio* play,
45 		 AmAudio* record)
46     : play(play), record(record) {}
47 
~AmPlaylistItemAmPlaylistItem48   virtual ~AmPlaylistItem() { }
49 };
50 
51 /**
52  * \brief AmAudio component that plays entries serially
53  *
54  * This class can be plugged to the Input or Output of a
55  * session. Entries can be added or removed from the playlist,
56  * and the current entry is played until it is finished,
57  * then the next entry is played.
58  */
59 class AmPlaylist: public AmAudio
60 {
61 
62   AmMutex                items_mut;
63   deque<AmPlaylistItem*> items;
64 
65   AmMutex                cur_mut;
66   AmPlaylistItem*        cur_item;
67 
68   AmEventQueue*          ev_q;
69 
70   void updateCurrentItem();
71   void gotoNextItem(bool notify);
72 
73  protected:
74   /** Fake implement AmAudio's pure virtual methods */
read(unsigned int user_ts,unsigned int size)75   int read(unsigned int user_ts, unsigned int size){ return -1; }
write(unsigned int user_ts,unsigned int size)76   int write(unsigned int user_ts, unsigned int size){ return -1; }
77 
78   /** override AmAudio */
79   int get(unsigned long long system_ts, unsigned char* buffer,
80 	  int output_sample_rate, unsigned int nb_samples);
81 
82   int put(unsigned long long system_ts, unsigned char* buffer,
83 	  int input_sample_rate, unsigned int size);
84 
85   /** from AmAudio */
86   void close();
87 
88  public:
89   AmPlaylist(AmEventQueue* q = NULL);
90   ~AmPlaylist();
91 
92   bool isEmpty();
93 
94   void addToPlaylist(AmPlaylistItem* item);
95   void addToPlayListFront(AmPlaylistItem* item);
96 
97   void flush();
98 };
99 
100 /**
101  * \brief event fired by the AmPlaylistSeparator
102  */
103 class AmPlaylistSeparatorEvent :
104   public AmEvent {
105 public:
AmPlaylistSeparatorEvent(int id)106   AmPlaylistSeparatorEvent(int id)
107     : AmEvent(id) { }
108 };
109 
110 /**
111  * \brief playlistelement to notify session about the playlist progress
112  *
113  * null-playlist element which notifies session that this position in
114  * playlist is reached. It fies a AmPlaylistSeparatorEvent if it is
115  * read or written.
116  */
117 class AmPlaylistSeparator
118   : public AmAudio {
119   bool notified;
120   AmEventQueue* ev_q;
121   int id;
122 public:
AmPlaylistSeparator(AmEventQueue * q,int id)123   AmPlaylistSeparator(AmEventQueue* q, int id)
124     : notified(false), ev_q(q), id(id) { }
~AmPlaylistSeparator()125   ~AmPlaylistSeparator() { }
126 
read(unsigned int user_ts,unsigned int size)127   int read(unsigned int user_ts, unsigned int size){
128     if (!notified)
129       ev_q->postEvent(new AmPlaylistSeparatorEvent(id));
130     notified = true;
131     return 0;
132   }
write(unsigned int user_ts,unsigned int size)133   int write(unsigned int user_ts, unsigned int size){
134     return read(user_ts, size);
135   }
136 };
137 
138 
139 
140 
141 #endif
142