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, ¶ms)) ? 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, ¶ms)) ? 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