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 { 65 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 { 80 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 { 89 explicit VolumeLevel(int l) : level(l), result(false) {} 90 int level; 91 bool result; 92 }; 93 94 struct VideoOptions : public talk_base::MessageData { 95 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 { 101 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 { 108 explicit LocalMonitor(bool e) : enable(e), result(false) {} 109 bool enable; 110 bool result; 111 }; 112 113 struct LocalRenderer : public talk_base::MessageData { 114 explicit LocalRenderer(VideoRenderer* r) : renderer(r), result(false) {} 115 VideoRenderer* renderer; 116 bool result; 117 }; 118 119 struct LoggingOptions : public talk_base::MessageData { 120 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 { 126 explicit CaptureParams(bool c) : capture(c), result(CR_FAILURE) {} 127 128 bool capture; 129 CaptureResult result; 130 }; 131 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 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 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 176 ChannelManager::~ChannelManager() { 177 if (initialized_) 178 Terminate(); 179 } 180 181 int ChannelManager::GetCapabilities() { 182 return media_engine_->GetCapabilities() & device_manager_->GetCapabilities(); 183 } 184 185 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 196 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 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 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 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 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 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 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 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 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 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 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 386 Soundclip* ChannelManager::CreateSoundclip() { 387 talk_base::TypedMessageData<Soundclip*> data(NULL); 388 Send(MSG_CREATESOUNDCLIP, &data); 389 return data.data(); 390 } 391 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 408 void ChannelManager::DestroySoundclip(Soundclip* soundclip) { 409 if (soundclip) { 410 talk_base::TypedMessageData<Soundclip*> data(soundclip); 411 Send(MSG_DESTROYSOUNDCLIP, &data); 412 } 413 } 414 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 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 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 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 480 bool ChannelManager::SetOutputVolume(int level) { 481 VolumeLevel volume(level); 482 return (Send(MSG_SETOUTPUTVOLUME, &volume) && volume.result); 483 } 484 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 491 bool ChannelManager::GetVideoOptions(std::string* cam_name) { 492 *cam_name = camera_device_; 493 return true; 494 } 495 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 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 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 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 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 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 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 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 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 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 594 void ChannelManager::SetVoiceLogging(int level, const char* filter) { 595 SetMediaLogging(false, level, filter); 596 } 597 598 void ChannelManager::SetVideoLogging(int level, const char* filter) { 599 SetMediaLogging(true, level, filter); 600 } 601 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 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 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 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 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 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 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 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 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