• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004--2008, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "talk/session/phone/channelmanager.h"
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <algorithm>
35 
36 #include "talk/base/common.h"
37 #include "talk/base/logging.h"
38 #include "talk/base/sigslotrepeater.h"
39 #include "talk/base/stringencode.h"
40 #include "talk/session/phone/mediaengine.h"
41 #include "talk/session/phone/soundclip.h"
42 
43 namespace cricket {
44 
45 enum {
46   MSG_CREATEVOICECHANNEL = 1,
47   MSG_DESTROYVOICECHANNEL = 2,
48   MSG_SETAUDIOOPTIONS = 3,
49   MSG_SETOUTPUTVOLUME = 4,
50   MSG_SETLOCALMONITOR = 5,
51   MSG_SETVOICELOGGING = 6,
52   MSG_CREATEVIDEOCHANNEL = 11,
53   MSG_DESTROYVIDEOCHANNEL = 12,
54   MSG_SETVIDEOOPTIONS = 13,
55   MSG_SETLOCALRENDERER = 14,
56   MSG_SETDEFAULTVIDEOENCODERCONFIG = 15,
57   MSG_SETVIDEOLOGGING = 16,
58   MSG_CREATESOUNDCLIP = 17,
59   MSG_DESTROYSOUNDCLIP = 18,
60   MSG_CAMERASTARTED = 19,
61   MSG_SETVIDEOCAPTURE = 20,
62 };
63 
64 struct CreationParams : public talk_base::MessageData {
CreationParamscricket::CreationParams65   CreationParams(BaseSession* session, const std::string& content_name,
66                  bool rtcp, VoiceChannel* voice_channel)
67       : session(session),
68         content_name(content_name),
69         rtcp(rtcp),
70         voice_channel(voice_channel),
71         video_channel(NULL) {}
72   BaseSession* session;
73   std::string content_name;
74   bool rtcp;
75   VoiceChannel* voice_channel;
76   VideoChannel* video_channel;
77 };
78 
79 struct AudioOptions : public talk_base::MessageData {
AudioOptionscricket::AudioOptions80   AudioOptions(int o, const Device* in, const Device* out)
81       : options(o), in_device(in), out_device(out) {}
82   int options;
83   const Device* in_device;
84   const Device* out_device;
85   bool result;
86 };
87 
88 struct VolumeLevel : public talk_base::MessageData {
VolumeLevelcricket::VolumeLevel89   explicit VolumeLevel(int l) : level(l), result(false) {}
90   int level;
91   bool result;
92 };
93 
94 struct VideoOptions : public talk_base::MessageData {
VideoOptionscricket::VideoOptions95   explicit VideoOptions(const Device* d) : cam_device(d), result(false) {}
96   const Device* cam_device;
97   bool result;
98 };
99 
100 struct DefaultVideoEncoderConfig : public talk_base::MessageData {
DefaultVideoEncoderConfigcricket::DefaultVideoEncoderConfig101   explicit DefaultVideoEncoderConfig(const VideoEncoderConfig& c)
102       : config(c), result(false) {}
103   VideoEncoderConfig config;
104   bool result;
105 };
106 
107 struct LocalMonitor : public talk_base::MessageData {
LocalMonitorcricket::LocalMonitor108   explicit LocalMonitor(bool e) : enable(e), result(false) {}
109   bool enable;
110   bool result;
111 };
112 
113 struct LocalRenderer : public talk_base::MessageData {
LocalRenderercricket::LocalRenderer114   explicit LocalRenderer(VideoRenderer* r) : renderer(r), result(false) {}
115   VideoRenderer* renderer;
116   bool result;
117 };
118 
119 struct LoggingOptions : public talk_base::MessageData {
LoggingOptionscricket::LoggingOptions120   explicit LoggingOptions(int lev, const char* f) : level(lev), filter(f) {}
121   int level;
122   std::string filter;
123 };
124 
125 struct CaptureParams : public talk_base::MessageData {
CaptureParamscricket::CaptureParams126   explicit CaptureParams(bool c) : capture(c), result(CR_FAILURE) {}
127 
128   bool capture;
129   CaptureResult result;
130 };
131 
ChannelManager(talk_base::Thread * worker_thread)132 ChannelManager::ChannelManager(talk_base::Thread* worker_thread)
133     : media_engine_(MediaEngine::Create()),
134       device_manager_(new DeviceManager()),
135       initialized_(false),
136       main_thread_(talk_base::Thread::Current()),
137       worker_thread_(worker_thread),
138       audio_in_device_(DeviceManager::kDefaultDeviceName),
139       audio_out_device_(DeviceManager::kDefaultDeviceName),
140       audio_options_(MediaEngine::DEFAULT_AUDIO_OPTIONS),
141       local_renderer_(NULL),
142       capturing_(false),
143       monitoring_(false) {
144   Construct();
145 }
146 
ChannelManager(MediaEngine * me,DeviceManager * dm,talk_base::Thread * worker_thread)147 ChannelManager::ChannelManager(MediaEngine* me, DeviceManager* dm,
148                                talk_base::Thread* worker_thread)
149     : media_engine_(me),
150       device_manager_(dm),
151       initialized_(false),
152       main_thread_(talk_base::Thread::Current()),
153       worker_thread_(worker_thread),
154       audio_in_device_(DeviceManager::kDefaultDeviceName),
155       audio_out_device_(DeviceManager::kDefaultDeviceName),
156       audio_options_(MediaEngine::DEFAULT_AUDIO_OPTIONS),
157       local_renderer_(NULL),
158       capturing_(false),
159       monitoring_(false) {
160   Construct();
161 }
162 
Construct()163 void ChannelManager::Construct() {
164   // Init the device manager immediately, and set up our default video device.
165   SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
166   device_manager_->Init();
167   // Set camera_device_ to the name of the default video capturer.
168   SetVideoOptions(DeviceManager::kDefaultDeviceName);
169 
170   // Camera is started asynchronously, request callbacks when startup
171   // completes to be able to forward them to the rendering manager.
172   media_engine_->SignalVideoCaptureResult.connect(
173       this, &ChannelManager::OnVideoCaptureResult);
174 }
175 
~ChannelManager()176 ChannelManager::~ChannelManager() {
177   if (initialized_)
178     Terminate();
179 }
180 
GetCapabilities()181 int ChannelManager::GetCapabilities() {
182   return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
183 }
184 
GetSupportedAudioCodecs(std::vector<AudioCodec> * codecs) const185 void ChannelManager::GetSupportedAudioCodecs(
186     std::vector<AudioCodec>* codecs) const {
187   codecs->clear();
188 
189   for (std::vector<AudioCodec>::const_iterator it =
190            media_engine_->audio_codecs().begin();
191       it != media_engine_->audio_codecs().end(); ++it) {
192     codecs->push_back(*it);
193   }
194 }
195 
GetSupportedVideoCodecs(std::vector<VideoCodec> * codecs) const196 void ChannelManager::GetSupportedVideoCodecs(
197     std::vector<VideoCodec>* codecs) const {
198   codecs->clear();
199 
200   std::vector<VideoCodec>::const_iterator it;
201   for (it = media_engine_->video_codecs().begin();
202       it != media_engine_->video_codecs().end(); ++it) {
203     codecs->push_back(*it);
204   }
205 }
206 
Init()207 bool ChannelManager::Init() {
208   ASSERT(!initialized_);
209   if (initialized_) {
210     return false;
211   }
212 
213   ASSERT(worker_thread_ != NULL);
214   if (worker_thread_ && worker_thread_->started()) {
215     if (media_engine_->Init()) {
216       initialized_ = true;
217 
218       // Now that we're initialized, apply any stored preferences. A preferred
219       // device might have been unplugged. In this case, we fallback to the
220       // default device but keep the user preferences. The preferences are
221       // changed only when the Javascript FE changes them.
222       const std::string preferred_audio_in_device = audio_in_device_;
223       const std::string preferred_audio_out_device = audio_out_device_;
224       const std::string preferred_camera_device = camera_device_;
225       Device device;
226       if (!device_manager_->GetAudioInputDevice(audio_in_device_, &device)) {
227         LOG(LS_WARNING) << "The preferred microphone '" << audio_in_device_
228                         << "' is unavailable. Fall back to the default.";
229         audio_in_device_ = DeviceManager::kDefaultDeviceName;
230       }
231       if (!device_manager_->GetAudioOutputDevice(audio_out_device_, &device)) {
232         LOG(LS_WARNING) << "The preferred speaker '" << audio_out_device_
233                         << "' is unavailable. Fall back to the default.";
234         audio_out_device_ = DeviceManager::kDefaultDeviceName;
235       }
236       if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
237         LOG(LS_WARNING) << "The preferred camera '" << camera_device_
238                         << "' is unavailable. Fall back to the default.";
239         camera_device_ = DeviceManager::kDefaultDeviceName;
240       }
241 
242       if (!SetAudioOptions(audio_in_device_, audio_out_device_,
243                            audio_options_)) {
244         LOG(LS_WARNING) << "Failed to SetAudioOptions with"
245                         << " microphone: " << audio_in_device_
246                         << " speaker: " << audio_out_device_
247                         << " options: " << audio_options_;
248       }
249       if (!SetVideoOptions(camera_device_)) {
250         LOG(LS_WARNING) << "Failed to SetVideoOptions with camera: "
251                         << camera_device_;
252       }
253 
254       // Restore the user preferences.
255       audio_in_device_ = preferred_audio_in_device;
256       audio_out_device_ = preferred_audio_out_device;
257       camera_device_ = preferred_camera_device;
258 
259       // Now apply the default video codec that has been set earlier.
260       if (default_video_encoder_config_.max_codec.id != 0) {
261         SetDefaultVideoEncoderConfig(default_video_encoder_config_);
262       }
263       // And the local renderer.
264       if (local_renderer_) {
265         SetLocalRenderer(local_renderer_);
266       }
267     }
268   }
269   return initialized_;
270 }
271 
Terminate()272 void ChannelManager::Terminate() {
273   ASSERT(initialized_);
274   if (!initialized_) {
275     return;
276   }
277 
278   // Need to destroy the voice/video channels
279   while (!video_channels_.empty()) {
280     DestroyVideoChannel_w(video_channels_.back());
281   }
282   while (!voice_channels_.empty()) {
283     DestroyVoiceChannel_w(voice_channels_.back());
284   }
285   while (!soundclips_.empty()) {
286     DestroySoundclip_w(soundclips_.back());
287   }
288 
289   media_engine_->Terminate();
290   initialized_ = false;
291 }
292 
CreateVoiceChannel(BaseSession * session,const std::string & content_name,bool rtcp)293 VoiceChannel* ChannelManager::CreateVoiceChannel(
294     BaseSession* session, const std::string& content_name, bool rtcp) {
295   CreationParams params(session, content_name, rtcp, NULL);
296   return (Send(MSG_CREATEVOICECHANNEL, &params)) ? params.voice_channel : NULL;
297 }
298 
CreateVoiceChannel_w(BaseSession * session,const std::string & content_name,bool rtcp)299 VoiceChannel* ChannelManager::CreateVoiceChannel_w(
300     BaseSession* session, const std::string& content_name, bool rtcp) {
301   talk_base::CritScope cs(&crit_);
302 
303   // This is ok to alloc from a thread other than the worker thread
304   ASSERT(initialized_);
305   VoiceMediaChannel* media_channel = media_engine_->CreateChannel();
306   if (media_channel == NULL)
307     return NULL;
308 
309   VoiceChannel* voice_channel = new VoiceChannel(
310       worker_thread_, media_engine_.get(), media_channel,
311       session, content_name, rtcp);
312   voice_channels_.push_back(voice_channel);
313   return voice_channel;
314 }
315 
DestroyVoiceChannel(VoiceChannel * voice_channel)316 void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
317   if (voice_channel) {
318     talk_base::TypedMessageData<VoiceChannel *> data(voice_channel);
319     Send(MSG_DESTROYVOICECHANNEL, &data);
320   }
321 }
322 
DestroyVoiceChannel_w(VoiceChannel * voice_channel)323 void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
324   talk_base::CritScope cs(&crit_);
325   // Destroy voice channel.
326   ASSERT(initialized_);
327   VoiceChannels::iterator it = std::find(voice_channels_.begin(),
328       voice_channels_.end(), voice_channel);
329   ASSERT(it != voice_channels_.end());
330   if (it == voice_channels_.end())
331     return;
332 
333   voice_channels_.erase(it);
334   delete voice_channel;
335 }
336 
CreateVideoChannel(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)337 VideoChannel* ChannelManager::CreateVideoChannel(
338     BaseSession* session, const std::string& content_name, bool rtcp,
339     VoiceChannel* voice_channel) {
340   CreationParams params(session, content_name, rtcp, voice_channel);
341   return (Send(MSG_CREATEVIDEOCHANNEL, &params)) ? params.video_channel : NULL;
342 }
343 
CreateVideoChannel_w(BaseSession * session,const std::string & content_name,bool rtcp,VoiceChannel * voice_channel)344 VideoChannel* ChannelManager::CreateVideoChannel_w(
345     BaseSession* session, const std::string& content_name, bool rtcp,
346     VoiceChannel* voice_channel) {
347   talk_base::CritScope cs(&crit_);
348 
349   // This is ok to alloc from a thread other than the worker thread
350   ASSERT(initialized_);
351   VideoMediaChannel* media_channel =
352       // voice_channel can be NULL in case of NullVoiceEngine.
353       media_engine_->CreateVideoChannel(voice_channel ?
354           voice_channel->media_channel() : NULL);
355   if (media_channel == NULL)
356     return NULL;
357 
358   VideoChannel* video_channel = new VideoChannel(
359       worker_thread_, media_engine_.get(), media_channel,
360       session, content_name, rtcp, voice_channel);
361   video_channels_.push_back(video_channel);
362   return video_channel;
363 }
364 
DestroyVideoChannel(VideoChannel * video_channel)365 void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
366   if (video_channel) {
367     talk_base::TypedMessageData<VideoChannel *> data(video_channel);
368     Send(MSG_DESTROYVIDEOCHANNEL, &data);
369   }
370 }
371 
DestroyVideoChannel_w(VideoChannel * video_channel)372 void ChannelManager::DestroyVideoChannel_w(VideoChannel *video_channel) {
373   talk_base::CritScope cs(&crit_);
374   // Destroy voice channel.
375   ASSERT(initialized_);
376   VideoChannels::iterator it = std::find(video_channels_.begin(),
377       video_channels_.end(), video_channel);
378   ASSERT(it != video_channels_.end());
379   if (it == video_channels_.end())
380     return;
381 
382   video_channels_.erase(it);
383   delete video_channel;
384 }
385 
CreateSoundclip()386 Soundclip* ChannelManager::CreateSoundclip() {
387   talk_base::TypedMessageData<Soundclip*> data(NULL);
388   Send(MSG_CREATESOUNDCLIP, &data);
389   return data.data();
390 }
391 
CreateSoundclip_w()392 Soundclip* ChannelManager::CreateSoundclip_w() {
393   talk_base::CritScope cs(&crit_);
394 
395   ASSERT(initialized_);
396   ASSERT(worker_thread_ == talk_base::Thread::Current());
397 
398   SoundclipMedia* soundclip_media = media_engine_->CreateSoundclip();
399   if (!soundclip_media) {
400     return NULL;
401   }
402 
403   Soundclip* soundclip = new Soundclip(worker_thread_, soundclip_media);
404   soundclips_.push_back(soundclip);
405   return soundclip;
406 }
407 
DestroySoundclip(Soundclip * soundclip)408 void ChannelManager::DestroySoundclip(Soundclip* soundclip) {
409   if (soundclip) {
410     talk_base::TypedMessageData<Soundclip*> data(soundclip);
411     Send(MSG_DESTROYSOUNDCLIP, &data);
412   }
413 }
414 
DestroySoundclip_w(Soundclip * soundclip)415 void ChannelManager::DestroySoundclip_w(Soundclip* soundclip) {
416   talk_base::CritScope cs(&crit_);
417   // Destroy soundclip.
418   ASSERT(initialized_);
419   Soundclips::iterator it = std::find(soundclips_.begin(),
420       soundclips_.end(), soundclip);
421   ASSERT(it != soundclips_.end());
422   if (it == soundclips_.end())
423     return;
424 
425   soundclips_.erase(it);
426   delete soundclip;
427 }
428 
GetAudioOptions(std::string * in_name,std::string * out_name,int * opts)429 bool ChannelManager::GetAudioOptions(std::string* in_name,
430                                      std::string* out_name, int* opts) {
431   *in_name = audio_in_device_;
432   *out_name = audio_out_device_;
433   *opts = audio_options_;
434   return true;
435 }
436 
SetAudioOptions(const std::string & in_name,const std::string & out_name,int opts)437 bool ChannelManager::SetAudioOptions(const std::string& in_name,
438                                      const std::string& out_name, int opts) {
439   // Get device ids from DeviceManager.
440   Device in_dev, out_dev;
441   if (!device_manager_->GetAudioInputDevice(in_name, &in_dev) ||
442       !device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
443     LOG(LS_WARNING) << "Device manager can't find selected device";
444     return false;
445   }
446 
447   // If we're initialized, pass the settings to the media engine.
448   bool ret = true;
449   if (initialized_) {
450     AudioOptions options(opts, &in_dev, &out_dev);
451     ret = (Send(MSG_SETAUDIOOPTIONS, &options) && options.result);
452   }
453 
454   // If all worked well, save the values for use in GetAudioOptions.
455   if (ret) {
456     audio_options_ = opts;
457     audio_in_device_ = in_name;
458     audio_out_device_ = out_name;
459   }
460   return ret;
461 }
462 
SetAudioOptions_w(int opts,const Device * in_dev,const Device * out_dev)463 bool ChannelManager::SetAudioOptions_w(int opts, const Device* in_dev,
464     const Device* out_dev) {
465   ASSERT(worker_thread_ == talk_base::Thread::Current());
466   ASSERT(initialized_);
467 
468   // Set audio options
469   bool ret = media_engine_->SetAudioOptions(opts);
470 
471   // Set the audio devices
472   if (ret) {
473     talk_base::CritScope cs(&crit_);
474     ret = media_engine_->SetSoundDevices(in_dev, out_dev);
475   }
476 
477   return ret;
478 }
479 
SetOutputVolume(int level)480 bool ChannelManager::SetOutputVolume(int level) {
481   VolumeLevel volume(level);
482   return (Send(MSG_SETOUTPUTVOLUME, &volume) && volume.result);
483 }
484 
SetOutputVolume_w(int level)485 bool ChannelManager::SetOutputVolume_w(int level) {
486   ASSERT(worker_thread_ == talk_base::Thread::Current());
487   ASSERT(initialized_);
488   return media_engine_->SetOutputVolume(level);
489 }
490 
GetVideoOptions(std::string * cam_name)491 bool ChannelManager::GetVideoOptions(std::string* cam_name) {
492   *cam_name = camera_device_;
493   return true;
494 }
495 
SetVideoOptions(const std::string & cam_name)496 bool ChannelManager::SetVideoOptions(const std::string& cam_name) {
497   Device device;
498   if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
499     LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
500     return false;
501   }
502 
503   // If we're running, tell the media engine about it.
504   bool ret = true;
505   if (initialized_) {
506     VideoOptions options(&device);
507     ret = (Send(MSG_SETVIDEOOPTIONS, &options) && options.result);
508   }
509 
510   // If everything worked, retain the name of the selected camera.
511   if (ret) {
512     camera_device_ = device.name;
513   }
514   return ret;
515 }
516 
SetVideoOptions_w(const Device * cam_device)517 bool ChannelManager::SetVideoOptions_w(const Device* cam_device) {
518   ASSERT(worker_thread_ == talk_base::Thread::Current());
519   ASSERT(initialized_);
520 
521   // Set the video input device
522   return media_engine_->SetVideoCaptureDevice(cam_device);
523 }
524 
SetDefaultVideoEncoderConfig(const VideoEncoderConfig & c)525 bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
526   bool ret = true;
527   if (initialized_) {
528     DefaultVideoEncoderConfig config(c);
529     ret = Send(MSG_SETDEFAULTVIDEOENCODERCONFIG, &config) && config.result;
530   }
531   if (ret) {
532     default_video_encoder_config_ = c;
533   }
534   return ret;
535 }
536 
SetDefaultVideoEncoderConfig_w(const VideoEncoderConfig & c)537 bool ChannelManager::SetDefaultVideoEncoderConfig_w(
538     const VideoEncoderConfig& c) {
539   ASSERT(worker_thread_ == talk_base::Thread::Current());
540   ASSERT(initialized_);
541   return media_engine_->SetDefaultVideoEncoderConfig(c);
542 }
543 
SetLocalMonitor(bool enable)544 bool ChannelManager::SetLocalMonitor(bool enable) {
545   LocalMonitor monitor(enable);
546   bool ret = Send(MSG_SETLOCALMONITOR, &monitor) && monitor.result;
547   if (ret) {
548     monitoring_ = enable;
549   }
550   return ret;
551 }
552 
SetLocalMonitor_w(bool enable)553 bool ChannelManager::SetLocalMonitor_w(bool enable) {
554   ASSERT(worker_thread_ == talk_base::Thread::Current());
555   ASSERT(initialized_);
556   return media_engine_->SetLocalMonitor(enable);
557 }
558 
SetLocalRenderer(VideoRenderer * renderer)559 bool ChannelManager::SetLocalRenderer(VideoRenderer* renderer) {
560   bool ret = true;
561   if (initialized_) {
562     LocalRenderer local(renderer);
563     ret = (Send(MSG_SETLOCALRENDERER, &local) && local.result);
564   }
565   if (ret) {
566     local_renderer_ = renderer;
567   }
568   return ret;
569 }
570 
SetLocalRenderer_w(VideoRenderer * renderer)571 bool ChannelManager::SetLocalRenderer_w(VideoRenderer* renderer) {
572   ASSERT(worker_thread_ == talk_base::Thread::Current());
573   ASSERT(initialized_);
574   return media_engine_->SetLocalRenderer(renderer);
575 }
576 
SetVideoCapture(bool capture)577 CaptureResult ChannelManager::SetVideoCapture(bool capture) {
578   bool ret;
579   CaptureParams capture_params(capture);
580   ret = (Send(MSG_SETVIDEOCAPTURE, &capture_params) &&
581          (capture_params.result != CR_FAILURE));
582   if (ret) {
583     capturing_ = capture;
584   }
585   return capture_params.result;
586 }
587 
SetVideoCapture_w(bool capture)588 CaptureResult ChannelManager::SetVideoCapture_w(bool capture) {
589   ASSERT(worker_thread_ == talk_base::Thread::Current());
590   ASSERT(initialized_);
591   return media_engine_->SetVideoCapture(capture);
592 }
593 
SetVoiceLogging(int level,const char * filter)594 void ChannelManager::SetVoiceLogging(int level, const char* filter) {
595   SetMediaLogging(false, level, filter);
596 }
597 
SetVideoLogging(int level,const char * filter)598 void ChannelManager::SetVideoLogging(int level, const char* filter) {
599   SetMediaLogging(true, level, filter);
600 }
601 
SetMediaLogging(bool video,int level,const char * filter)602 void ChannelManager::SetMediaLogging(bool video, int level,
603                                      const char* filter) {
604   // Can be called before initialization; in this case, the worker function
605   // is simply called on the main thread.
606   if (initialized_) {
607     LoggingOptions options(level, filter);
608     Send((video) ? MSG_SETVIDEOLOGGING : MSG_SETVOICELOGGING, &options);
609   } else {
610     SetMediaLogging_w(video, level, filter);
611   }
612 }
613 
SetMediaLogging_w(bool video,int level,const char * filter)614 void ChannelManager::SetMediaLogging_w(bool video, int level,
615                                        const char* filter) {
616   // Can be called before initialization
617   ASSERT(worker_thread_ == talk_base::Thread::Current() || !initialized_);
618   if (video) {
619     media_engine_->SetVideoLogging(level, filter);
620   } else {
621     media_engine_->SetVoiceLogging(level, filter);
622   }
623 }
624 
Send(uint32 id,talk_base::MessageData * data)625 bool ChannelManager::Send(uint32 id, talk_base::MessageData* data) {
626   if (!worker_thread_ || !initialized_) return false;
627   worker_thread_->Send(this, id, data);
628   return true;
629 }
630 
OnVideoCaptureResult(CaptureResult result)631 void ChannelManager::OnVideoCaptureResult(CaptureResult result) {
632   capturing_ = result == CR_SUCCESS;
633   main_thread_->Post(this, MSG_CAMERASTARTED,
634                      new talk_base::TypedMessageData<CaptureResult>(result));
635 }
636 
OnMessage(talk_base::Message * message)637 void ChannelManager::OnMessage(talk_base::Message* message) {
638   talk_base::MessageData* data = message->pdata;
639   switch (message->message_id) {
640     case MSG_CREATEVOICECHANNEL: {
641       CreationParams* p = static_cast<CreationParams*>(data);
642       p->voice_channel =
643           CreateVoiceChannel_w(p->session, p->content_name, p->rtcp);
644       break;
645     }
646     case MSG_DESTROYVOICECHANNEL: {
647       VoiceChannel* p = static_cast<talk_base::TypedMessageData<VoiceChannel*>*>
648           (data)->data();
649       DestroyVoiceChannel_w(p);
650       break;
651     }
652     case MSG_CREATEVIDEOCHANNEL: {
653       CreationParams* p = static_cast<CreationParams*>(data);
654       p->video_channel = CreateVideoChannel_w(p->session, p->content_name,
655                                               p->rtcp, p->voice_channel);
656       break;
657     }
658     case MSG_DESTROYVIDEOCHANNEL: {
659       VideoChannel* p = static_cast<talk_base::TypedMessageData<VideoChannel*>*>
660           (data)->data();
661       DestroyVideoChannel_w(p);
662       break;
663     }
664     case MSG_CREATESOUNDCLIP: {
665       talk_base::TypedMessageData<Soundclip*> *p =
666           static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
667       p->data() = CreateSoundclip_w();
668       break;
669     }
670     case MSG_DESTROYSOUNDCLIP: {
671       talk_base::TypedMessageData<Soundclip*> *p =
672           static_cast<talk_base::TypedMessageData<Soundclip*>*>(data);
673       DestroySoundclip_w(p->data());
674       break;
675     }
676     case MSG_SETAUDIOOPTIONS: {
677       AudioOptions* p = static_cast<AudioOptions*>(data);
678       p->result = SetAudioOptions_w(p->options,
679                                     p->in_device, p->out_device);
680       break;
681     }
682     case MSG_SETOUTPUTVOLUME: {
683       VolumeLevel* p = static_cast<VolumeLevel*>(data);
684       p->result = SetOutputVolume_w(p->level);
685       break;
686     }
687     case MSG_SETLOCALMONITOR: {
688       LocalMonitor* p = static_cast<LocalMonitor*>(data);
689       p->result = SetLocalMonitor_w(p->enable);
690       break;
691     }
692     case MSG_SETVIDEOOPTIONS: {
693       VideoOptions* p = static_cast<VideoOptions*>(data);
694       p->result = SetVideoOptions_w(p->cam_device);
695       break;
696     }
697     case MSG_SETDEFAULTVIDEOENCODERCONFIG: {
698       DefaultVideoEncoderConfig* p =
699           static_cast<DefaultVideoEncoderConfig*>(data);
700       p->result = SetDefaultVideoEncoderConfig_w(p->config);
701       break;
702     }
703     case MSG_SETLOCALRENDERER: {
704       LocalRenderer* p = static_cast<LocalRenderer*>(data);
705       p->result = SetLocalRenderer_w(p->renderer);
706       break;
707     }
708     case MSG_SETVIDEOCAPTURE: {
709       CaptureParams* p = static_cast<CaptureParams*>(data);
710       p->result = SetVideoCapture_w(p->capture);
711       break;
712     }
713     case MSG_SETVOICELOGGING:
714     case MSG_SETVIDEOLOGGING: {
715       LoggingOptions* p = static_cast<LoggingOptions*>(data);
716       bool video = (message->message_id == MSG_SETVIDEOLOGGING);
717       SetMediaLogging_w(video, p->level, p->filter.c_str());
718       break;
719     }
720     case MSG_CAMERASTARTED: {
721       talk_base::TypedMessageData<CaptureResult>* data =
722           static_cast<talk_base::TypedMessageData<CaptureResult>*>(
723               message->pdata);
724       SignalVideoCaptureResult(data->data());
725       delete data;
726       break;
727     }
728   }
729 }
730 
GetDeviceNames(const std::vector<Device> & devs,std::vector<std::string> * names)731 static void GetDeviceNames(const std::vector<Device>& devs,
732                            std::vector<std::string>* names) {
733   names->clear();
734   for (size_t i = 0; i < devs.size(); ++i) {
735     names->push_back(devs[i].name);
736   }
737 }
738 
GetAudioInputDevices(std::vector<std::string> * names)739 bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
740   names->clear();
741   std::vector<Device> devs;
742   bool ret = device_manager_->GetAudioInputDevices(&devs);
743   if (ret)
744     GetDeviceNames(devs, names);
745 
746   return ret;
747 }
748 
GetAudioOutputDevices(std::vector<std::string> * names)749 bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
750   names->clear();
751   std::vector<Device> devs;
752   bool ret = device_manager_->GetAudioOutputDevices(&devs);
753   if (ret)
754     GetDeviceNames(devs, names);
755 
756   return ret;
757 }
758 
GetVideoCaptureDevices(std::vector<std::string> * names)759 bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
760   names->clear();
761   std::vector<Device> devs;
762   bool ret = device_manager_->GetVideoCaptureDevices(&devs);
763   if (ret)
764     GetDeviceNames(devs, names);
765 
766   return ret;
767 }
768 
769 }  // namespace cricket
770