~ubuntu-branches/ubuntu/vivid/ekiga/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/engine/audiooutput/audiooutput-scheduler.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kilian Krause
  • Date: 2011-07-17 00:24:50 UTC
  • mfrom: (5.1.5 upstream) (7.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20110717002450-ytg3wsrc1ptd3153
Tags: 3.3.1-1
* New upstream release.
 - Required libpt-dev 2.10 and libopal-dev 3.10
* Fix debian/watch to catch new version
* Remove libnotify0.7.patch - included upstream
* Add libboost-dev and libboost-signals-dev to Build-Depends
* debian/rules: Don't install *.la files for new internal shared libs
* Fix Vcs URIs to point to correct desktop/experimental/ekiga tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * Ekiga -- A VoIP and Video-Conferencing application
 
4
 * Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
 
5
 
 
6
 * This program 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 (at
 
9
 * your option) any later version. This program is distributed in the hope
 
10
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
 
11
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
12
 * See the GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along
 
15
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 *
 
18
 * Ekiga is licensed under the GPL license and as a special exception, you
 
19
 * have permission to link or otherwise combine this program with the
 
20
 * programs OPAL, OpenH323 and PWLIB, and distribute the combination, without
 
21
 * applying the requirements of the GNU GPL to the OPAL, OpenH323 and PWLIB
 
22
 * programs, as long as you do follow the requirements of the GNU GPL for all
 
23
 * the rest of the software thus combined.
 
24
 */
 
25
 
 
26
 
 
27
/*
 
28
 *                         audiooutput-scheduler.h  -  description
 
29
 *                         ------------------------------------------
 
30
 *   begin                : written in 2008 by Matthias Schneider
 
31
 *   copyright            : (c) 2008 by Matthias Schneider
 
32
 *   description          : Declaration of a scheduler for sound events that is run in 
 
33
 *                          a separate thread.
 
34
 *
 
35
 */
 
36
 
 
37
#include "audiooutput-scheduler.h"
 
38
#include "audiooutput-core.h"
 
39
#include "config.h"
 
40
#ifdef WIN32
 
41
#include "platform/winpaths.h"
 
42
#endif
 
43
 
 
44
using namespace Ekiga;
 
45
 
 
46
AudioEventScheduler::AudioEventScheduler (AudioOutputCore& _audio_output_core)
 
47
: PThread (1000, NoAutoDeleteThread, HighestPriority, "AudioEventScheduler"),
 
48
  audio_output_core (_audio_output_core)
 
49
{
 
50
  end_thread = false;
 
51
  // Since windows does not like to restart a thread that 
 
52
  // was never started, we do so here
 
53
  this->Resume ();
 
54
  thread_created.Wait ();
 
55
}
 
56
 
 
57
AudioEventScheduler::~AudioEventScheduler ()
 
58
{
 
59
  end_thread = true;
 
60
  run_thread.Signal ();
 
61
 
 
62
  /* Wait for the Main () method to be terminated */
 
63
  PWaitAndSignal m(thread_ended);
 
64
 
 
65
}
 
66
 
 
67
void AudioEventScheduler::Main ()
 
68
{
 
69
  PWaitAndSignal m(thread_ended);
 
70
 
 
71
  std::vector <AudioEvent> pending_event_list;
 
72
  unsigned idle_time = 65535;
 
73
  AudioEvent event;
 
74
  char* buffer = NULL;
 
75
  unsigned long buffer_len = 0;
 
76
  unsigned channels, sample_rate, bps;
 
77
  AudioOutputPS ps;
 
78
 
 
79
  thread_created.Signal ();
 
80
 
 
81
  while (!end_thread) {
 
82
 
 
83
    if (idle_time == 65535)
 
84
      run_thread.Wait ();
 
85
    else
 
86
      run_thread.Wait (idle_time);
 
87
 
 
88
    if (end_thread)
 
89
      break;
 
90
      
 
91
    get_pending_event_list(pending_event_list);
 
92
    PTRACE(4, "AEScheduler\tChecking pending list with " << pending_event_list.size() << " elements");
 
93
 
 
94
    while (pending_event_list.size() > 0) {
 
95
      event = *(pending_event_list.begin()); pending_event_list.erase(pending_event_list.begin());
 
96
      load_wav(event.name, event.is_file_name, buffer, buffer_len, channels, sample_rate, bps, ps);
 
97
      if (buffer) {
 
98
         audio_output_core.play_buffer (ps, buffer, buffer_len, channels, sample_rate, bps);
 
99
        free (buffer);
 
100
        buffer = NULL;
 
101
      }
 
102
      Current()->Sleep (10);
 
103
    }
 
104
    idle_time = get_time_to_next_event();
 
105
  }
 
106
}
 
107
 
 
108
void AudioEventScheduler::get_pending_event_list (std::vector<AudioEvent> & pending_event_list)
 
109
{
 
110
  PWaitAndSignal m(event_list_mutex);
 
111
 
 
112
  AudioEvent event;
 
113
  std::vector <AudioEvent> new_event_list;
 
114
  unsigned long time = get_time_ms();
 
115
 
 
116
  pending_event_list.clear();
 
117
 
 
118
  while (event_list.size() > 0) {
 
119
 
 
120
    event = *(event_list.begin()); event_list.erase(event_list.begin());
 
121
 
 
122
    if (event.interval == 0) {
 
123
      pending_event_list.push_back(event);
 
124
    }
 
125
    else {
 
126
      if (event.time <= time) {
 
127
        pending_event_list.push_back(event);
 
128
        event.repetitions--; 
 
129
        if (event.repetitions > 0) {
 
130
          event.time = time + event.interval;
 
131
          new_event_list.push_back(event);
 
132
        }
 
133
      }
 
134
      else {
 
135
        new_event_list.push_back(event);
 
136
      }
 
137
    }
 
138
  }
 
139
 
 
140
  event_list = new_event_list;
 
141
}
 
142
 
 
143
unsigned long AudioEventScheduler::get_time_ms()
 
144
{
 
145
  GTimeVal time_val;
 
146
  g_get_current_time(&time_val);
 
147
  return (time_val.tv_sec * 1000 + (unsigned long) (time_val.tv_usec / 1000) );
 
148
}
 
149
 
 
150
unsigned AudioEventScheduler::get_time_to_next_event()
 
151
{
 
152
  PWaitAndSignal m(event_list_mutex);
 
153
  unsigned long time = get_time_ms();
 
154
  unsigned min_time = 65535;
 
155
 
 
156
  for (std::vector<AudioEvent>::iterator iter = event_list.begin ();
 
157
       iter !=event_list.end ();
 
158
       iter++) {
 
159
 
 
160
    if ( (iter->interval > 0) && ((iter->time - time) < min_time) )
 
161
      min_time = iter->time - time;
 
162
  }
 
163
  return min_time;
 
164
}
 
165
 
 
166
void AudioEventScheduler::add_event_to_queue(const std::string & name, bool is_file_name, unsigned interval, unsigned repetitions)
 
167
{
 
168
  PTRACE(4, "AEScheduler\tAdding Event " << name << " " << interval << "/" << repetitions << " to queue");
 
169
  PWaitAndSignal m(event_list_mutex);
 
170
  AudioEvent event;
 
171
  event.name = name;
 
172
  event.is_file_name = is_file_name;
 
173
  event.interval = interval;
 
174
  event.repetitions = repetitions;
 
175
  event.time = get_time_ms();
 
176
  event_list.push_back(event);
 
177
  run_thread.Signal();
 
178
}
 
179
 
 
180
void AudioEventScheduler::remove_event_from_queue(const std::string & name)
 
181
{
 
182
  PTRACE(4, "AEScheduler\tRemoving Event " << name << " from queue");
 
183
  PWaitAndSignal m(event_list_mutex);
 
184
 
 
185
  bool found = false;
 
186
  std::vector<AudioEvent>::iterator iter;
 
187
 
 
188
  for (iter = event_list.begin ();
 
189
       iter != event_list.end () ;
 
190
       iter++) {
 
191
 
 
192
      if ( (iter->name == name) ) { 
 
193
        found = true;
 
194
        break;
 
195
      }
 
196
  }
 
197
 
 
198
  if (found) {
 
199
    event_list.erase(iter);
 
200
  }
 
201
}
 
202
 
 
203
void AudioEventScheduler::load_wav(const std::string & event_name, bool is_file_name, char* & buffer, unsigned long & len, unsigned & channels, unsigned & sample_rate, unsigned & bps, AudioOutputPS & ps)
 
204
{
 
205
  PWAVFile* wav = NULL;
 
206
  std::string file_name;
 
207
 
 
208
  len = 0;
 
209
  buffer = NULL;
 
210
 
 
211
  // Shall we also try event name as file name?
 
212
  if (is_file_name) {
 
213
    file_name = event_name;
 
214
    ps = primary;
 
215
  }
 
216
  else 
 
217
    if (!get_file_name(event_name, file_name, ps)) // if this event is disabled
 
218
      return;
 
219
 
 
220
  PTRACE(4, "AEScheduler\tTrying to load " << file_name << " for event " << event_name);
 
221
  wav = new PWAVFile (file_name.c_str(), PFile::ReadOnly);
 
222
 
 
223
  if (!wav->IsValid ()) {
 
224
     /* it isn't a full path to a file : add our default path */
 
225
 
 
226
    delete wav;
 
227
    wav = NULL;
 
228
 
 
229
    gchar* filename = g_build_filename (DATA_DIR, "sounds", PACKAGE_NAME, file_name.c_str(), NULL);
 
230
    PTRACE(4, "AEScheduler\tTrying to load " << filename << " for event " << event_name);
 
231
 
 
232
    wav = new PWAVFile (filename, PFile::ReadOnly);
 
233
    g_free (filename);
 
234
  }
 
235
  
 
236
  if (wav->IsValid ()) {
 
237
    len = wav->GetDataLength();
 
238
    channels = wav->GetChannels ();
 
239
    sample_rate = wav->GetSampleRate ();
 
240
    bps = wav->GetSampleSize ();
 
241
 
 
242
    buffer = (char*) malloc (len);
 
243
    memset(buffer, 127, len);
 
244
    wav->Read(buffer, len);
 
245
  }
 
246
 
 
247
  delete wav;
 
248
}
 
249
 
 
250
 
 
251
bool AudioEventScheduler::get_file_name(const std::string & event_name, std::string & file_name, AudioOutputPS & ps)
 
252
{
 
253
  PWaitAndSignal m(event_file_list_mutex);
 
254
 
 
255
  file_name = "";
 
256
 
 
257
  for (std::vector<EventFileName>::iterator iter = event_file_list.begin ();
 
258
       iter != event_file_list.end ();
 
259
       iter++) {
 
260
 
 
261
    if (iter->event_name == event_name) {
 
262
      file_name = iter->file_name;
 
263
      ps = iter->ps;
 
264
      return (iter->enabled);
 
265
    }
 
266
  }
 
267
 
 
268
  return false;
 
269
}
 
270
 
 
271
void AudioEventScheduler::set_file_name(const std::string & event_name, const std::string & file_name,  AudioOutputPS ps, bool enabled)
 
272
{
 
273
  PWaitAndSignal m(event_file_list_mutex);
 
274
 
 
275
  bool found = false;
 
276
 
 
277
  for (std::vector<EventFileName>::iterator iter = event_file_list.begin ();
 
278
       iter != event_file_list.end ();
 
279
       iter++) {
 
280
 
 
281
    if (iter->event_name == event_name) {
 
282
      iter->file_name = file_name;
 
283
      iter->enabled = enabled;
 
284
      iter->ps = ps;
 
285
      found = true;
 
286
      break;
 
287
    }
 
288
  }
 
289
 
 
290
  if (!found) {
 
291
    EventFileName event_file_name;
 
292
    event_file_name.event_name = event_name;
 
293
    event_file_name.file_name = file_name;
 
294
    event_file_name.enabled = enabled;
 
295
    event_file_name.ps = secondary;
 
296
    event_file_list.push_back(event_file_name);
 
297
  }
 
298
}