Changeset 186361 in webkit
- Timestamp:
- Jul 6, 2015, 11:04:10 AM (10 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r186330 r186361 1 2015-07-06 Eric Carlson <eric.carlson@apple.com> 2 3 [Mac] Inactive AirPlay route should automatically timeout 4 https://bugs.webkit.org/show_bug.cgi?id=146642 5 <rdar://problem/21602955> 6 7 Automatically clear a media element's AirPlay connection after it has been paused 8 for 60 minutes, or after 8 minutes if it played to the end before pausing. 9 10 Reviewed by Brent Fulgham. 11 12 * Modules/mediasession/WebMediaSessionManager.cpp: 13 (WebCore::WebMediaSessionManager::WebMediaSessionManager): Initialize m_watchdogTimer. 14 (WebCore::WebMediaSessionManager::clientStateDidChange): Schedule watchdog timer configuration 15 if the client started playing or paused. 16 (WebCore::WebMediaSessionManager::configurePlaybackTargetClients): Schedule watchdog timer configuration. 17 (WebCore::WebMediaSessionManager::toString): Print watchdog configuration flag. 18 (WebCore::WebMediaSessionManager::taskTimerFired): Call configureWatchdogTimer. 19 (WebCore::WebMediaSessionManager::configureWatchdogTimer): New, start or stop watchdog timer. 20 (WebCore::WebMediaSessionManager::watchdogTimerFired): Stop monitoring for targets, which 21 clears the route. 22 * Modules/mediasession/WebMediaSessionManager.h: 23 24 * html/HTMLMediaElement.cpp: 25 (WebCore::HTMLMediaElement::mediaState): Set DidPlayToEnd when appropriate. 26 27 * page/MediaProducer.h: Add DidPlayToEnd. 28 29 * platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm: 30 (WebCore::MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac): Clear m_client, call 31 stopMonitoringPlaybackTargets. 32 (WebCore::MediaPlaybackTargetPickerMac::pendingActionTimerFired): Send a neutered 33 MediaPlaybackTarget when m_outputDeviceMenuController is NULL. 34 (WebCore::MediaPlaybackTargetPickerMac::devicePicker): Add logging. 35 (WebCore::MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets): Clear the menu 36 controller to cancel the route. 37 1 38 2015-07-06 Zan Dobersek <zdobersek@igalia.com> 2 39 -
trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.cpp
r186238 r186361 56 56 bool requestedPicker { false }; 57 57 bool configurationRequired { true }; 58 bool playedToEnd { false }; 58 59 }; 59 60 … … 88 89 WebMediaSessionManager::WebMediaSessionManager() 89 90 : m_taskTimer(RunLoop::current(), this, &WebMediaSessionManager::taskTimerFired) 91 , m_watchdogTimer(RunLoop::current(), this, &WebMediaSessionManager::watchdogTimerFired) 90 92 { 91 93 } … … 171 173 if (!flagsAreSet(oldFlags, MediaProducer::RequiresPlaybackTargetMonitoring) && flagsAreSet(newFlags, MediaProducer::RequiresPlaybackTargetMonitoring)) 172 174 scheduleDelayedTask(TargetMonitoringConfigurationTask); 175 176 MediaProducer::MediaStateFlags playingToTargetFlags = MediaProducer::IsPlayingToExternalDevice | MediaProducer::IsPlayingVideo; 177 if ((oldFlags & playingToTargetFlags) != (newFlags & playingToTargetFlags)) { 178 if (flagsAreSet(oldFlags, MediaProducer::IsPlayingVideo) && !flagsAreSet(newFlags, MediaProducer::IsPlayingVideo) && flagsAreSet(newFlags, MediaProducer::DidPlayToEnd)) 179 changedClientState->playedToEnd = true; 180 scheduleDelayedTask(WatchdogTimerConfigurationTask); 181 } 173 182 174 183 if (!m_playbackTarget || !m_playbackTarget->hasActiveRoute()) … … 277 286 state->client.setShouldPlayToPlaybackTarget(state->contextId, true); 278 287 } 288 289 configureWatchdogTimer(); 279 290 } 280 291 … … 307 318 if (tasks & TargetMonitoringConfigurationTask) 308 319 string.append("TargetMonitoringConfigurationTask + "); 320 if (tasks & WatchdogTimerConfigurationTask) 321 string.append("WatchdogTimerConfigurationTask + "); 309 322 if (string.isEmpty()) 310 323 string.append("NoTask"); … … 334 347 if (m_taskFlags & TargetMonitoringConfigurationTask) 335 348 configurePlaybackTargetMonitoring(); 349 if (m_taskFlags & WatchdogTimerConfigurationTask) 350 configureWatchdogTimer(); 336 351 337 352 m_taskFlags = NoTask; … … 348 363 } 349 364 365 void WebMediaSessionManager::configureWatchdogTimer() 366 { 367 static const double watchdogTimerIntervalAfterPausing = 60 * 60; 368 static const double watchdogTimerIntervalAfterPlayingToEnd = 8 * 60; 369 370 if (!m_playbackTarget || !m_playbackTarget->hasActiveRoute()) { 371 m_watchdogTimer.stop(); 372 return; 373 } 374 375 bool stopTimer = false; 376 bool didPlayToEnd = false; 377 for (auto& state : m_clientState) { 378 if (flagsAreSet(state->flags, MediaProducer::IsPlayingToExternalDevice) && flagsAreSet(state->flags, MediaProducer::IsPlayingVideo)) 379 stopTimer = true; 380 if (state->playedToEnd) 381 didPlayToEnd = true; 382 state->playedToEnd = false; 383 } 384 385 if (stopTimer) { 386 m_currentWatchdogInterval = 0; 387 m_watchdogTimer.stop(); 388 LOG(Media, "WebMediaSessionManager::configureWatchdogTimer - timer stopped"); 389 } else { 390 double interval = didPlayToEnd ? watchdogTimerIntervalAfterPlayingToEnd : watchdogTimerIntervalAfterPausing; 391 if (interval != m_currentWatchdogInterval || !m_watchdogTimer.isActive()) { 392 m_watchdogTimer.startOneShot(interval); 393 LOG(Media, "WebMediaSessionManager::configureWatchdogTimer - timer scheduled for %.0f", interval); 394 } 395 m_currentWatchdogInterval = interval; 396 } 397 } 398 399 void WebMediaSessionManager::watchdogTimerFired() 400 { 401 LOG(Media, "WebMediaSessionManager::watchdogTimerFired"); 402 if (!m_playbackTarget) 403 return; 404 405 targetPicker().stopMonitoringPlaybackTargets(); 406 } 407 350 408 } // namespace WebCore 351 409 -
trunk/Source/WebCore/Modules/mediasession/WebMediaSessionManager.h
r185519 r186361 68 68 void configureNewClients(); 69 69 void configurePlaybackTargetMonitoring(); 70 void configureWatchdogTimer(); 70 71 71 72 enum ConfigurationTaskFlags { … … 74 75 TargetClientsConfigurationTask = 1 << 1, 75 76 TargetMonitoringConfigurationTask = 1 << 2, 77 WatchdogTimerConfigurationTask = 1 << 3, 76 78 }; 77 79 typedef unsigned ConfigurationTasks; … … 80 82 void scheduleDelayedTask(ConfigurationTasks); 81 83 void taskTimerFired(); 84 85 void watchdogTimerFired(); 86 82 87 RunLoop::Timer<WebMediaSessionManager> m_taskTimer; 88 RunLoop::Timer<WebMediaSessionManager> m_watchdogTimer; 83 89 84 90 Vector<std::unique_ptr<ClientState>> m_clientState; 85 91 RefPtr<MediaPlaybackTarget> m_playbackTarget; 86 92 ConfigurationTasks m_taskFlags { NoTask }; 93 double m_currentWatchdogInterval { 0 }; 87 94 bool m_externalOutputDeviceAvailable { false }; 88 95 }; -
trunk/Source/WebCore/html/HTMLMediaElement.cpp
r186279 r186361 6373 6373 if (hasActiveVideo && (!requireUserGesture || (hasAudio && !m_initiallyMuted && !loop())) && !m_failedToPlayToWirelessTarget) 6374 6374 state |= ExternalDeviceAutoPlayCandidate; 6375 6376 if (hasActiveVideo && endedPlayback()) 6377 state |= DidPlayToEnd; 6375 6378 #endif 6376 6379 -
trunk/Source/WebCore/page/MediaProducer.h
r183613 r186361 38 38 RequiresPlaybackTargetMonitoring = 1 << 3, 39 39 ExternalDeviceAutoPlayCandidate = 1 << 4, 40 DidPlayToEnd = 1 << 5, 40 41 }; 41 42 typedef unsigned MediaStateFlags; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm
r184788 r186361 84 84 MediaPlaybackTargetPickerMac::~MediaPlaybackTargetPickerMac() 85 85 { 86 m_client = nullptr; 86 87 m_pendingActionTimer.stop(); 87 88 [m_outputDeviceMenuControllerDelegate clearCallback]; 89 90 stopMonitoringPlaybackTargets(); 91 } 92 93 void MediaPlaybackTargetPickerMac::pendingActionTimerFired() 94 { 95 LOG(Media, "MediaPlaybackTargetPickerMac::pendingActionTimerFired - flags = 0x%x", m_pendingActionFlags); 96 97 if (!m_client) 98 return; 99 100 PendingActionFlags pendingActions = m_pendingActionFlags; 101 m_pendingActionFlags = 0; 102 103 if (pendingActions & CurrentDeviceDidChange) { 104 AVOutputContext* context = m_outputDeviceMenuController ? [m_outputDeviceMenuController.get() outputContext] : nullptr; 105 m_client->setPlaybackTarget(WebCore::MediaPlaybackTargetMac::create(context)); 106 } 107 108 if (pendingActions & OutputDeviceAvailabilityChanged) 109 m_client->externalOutputDeviceAvailableDidChange(devicePicker().externalOutputDeviceAvailable); 110 111 } 112 113 void MediaPlaybackTargetPickerMac::availableDevicesDidChange() 114 { 115 LOG(Media, "MediaPlaybackTargetPickerMac::availableDevicesDidChange - available = %i", (int)devicePicker().externalOutputDeviceAvailable); 116 117 if (!m_client) 118 return; 119 120 addPendingAction(OutputDeviceAvailabilityChanged); 121 } 122 123 AVOutputDeviceMenuControllerType *MediaPlaybackTargetPickerMac::devicePicker() 124 { 125 if (!getAVOutputDeviceMenuControllerClass()) 126 return nullptr; 127 128 if (!m_outputDeviceMenuController) { 129 LOG(Media, "MediaPlaybackTargetPickerMac::devicePicker - allocating picker"); 130 131 RetainPtr<AVOutputContextType> context = adoptNS([[getAVOutputContextClass() alloc] init]); 132 m_outputDeviceMenuController = adoptNS([[getAVOutputDeviceMenuControllerClass() alloc] initWithOutputContext:context.get()]); 133 134 [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDeviceAvailableKeyName options:NSKeyValueObservingOptionNew context:nullptr]; 135 [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDevicePickedKeyName options:NSKeyValueObservingOptionNew context:nullptr]; 136 137 LOG(Media, "MediaPlaybackTargetPickerMac::devicePicker - allocated menu controller %p", m_outputDeviceMenuController.get()); 138 139 if (m_outputDeviceMenuController.get().externalOutputDeviceAvailable) 140 availableDevicesDidChange(); 141 } 142 143 return m_outputDeviceMenuController.get(); 144 } 145 146 void MediaPlaybackTargetPickerMac::showPlaybackTargetPicker(const FloatRect& location, bool checkActiveRoute) 147 { 148 if (!m_client || m_showingMenu) 149 return; 150 151 LOG(Media, "MediaPlaybackTargetPickerMac::showPlaybackTargetPicker - checkActiveRoute = %i", (int)checkActiveRoute); 152 153 AVOutputDeviceMenuControllerType *picker = devicePicker(); 154 if (![picker respondsToSelector:@selector(showMenuForRect:appearanceName:allowReselectionOfSelectedOutputDevice:)]) 155 return; 156 157 m_showingMenu = true; 158 if ([picker showMenuForRect:location appearanceName:NSAppearanceNameVibrantLight allowReselectionOfSelectedOutputDevice:!checkActiveRoute]) { 159 if (!checkActiveRoute) 160 currentDeviceDidChange(); 161 } 162 m_showingMenu = false; 163 } 164 165 void MediaPlaybackTargetPickerMac::addPendingAction(PendingActionFlags action) 166 { 167 m_pendingActionFlags |= action; 168 m_pendingActionTimer.startOneShot(pendingActionInterval); 169 } 170 171 void MediaPlaybackTargetPickerMac::currentDeviceDidChange() 172 { 173 LOG(Media, "MediaPlaybackTargetPickerMac::currentDeviceDidChange"); 174 175 if (!m_client) 176 return; 177 178 addPendingAction(CurrentDeviceDidChange); 179 } 180 181 void MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets() 182 { 183 LOG(Media, "MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets"); 184 185 devicePicker(); 186 } 187 188 void MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets() 189 { 190 LOG(Media, "MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets"); 88 191 89 192 if (m_outputDeviceMenuController) { … … 92 195 m_outputDeviceMenuController = nullptr; 93 196 } 94 } 95 96 void MediaPlaybackTargetPickerMac::pendingActionTimerFired() 97 { 98 LOG(Media, "MediaPlaybackTargetPickerMac::pendingActionTimerFired - flags = 0x%x", m_pendingActionFlags); 99 100 if (!m_outputDeviceMenuController || !m_client) 101 return; 102 103 PendingActionFlags pendingActions = m_pendingActionFlags; 104 m_pendingActionFlags = 0; 105 106 if (pendingActions & OutputDeviceAvailabilityChanged) 107 m_client->externalOutputDeviceAvailableDidChange(devicePicker().externalOutputDeviceAvailable); 108 109 if (pendingActions & CurrentDeviceDidChange) { 110 AVOutputDeviceMenuControllerType* devicePicker = this->devicePicker(); 111 if (devicePicker) 112 m_client->setPlaybackTarget(WebCore::MediaPlaybackTargetMac::create([devicePicker outputContext])); 113 } 114 } 115 116 void MediaPlaybackTargetPickerMac::availableDevicesDidChange() 117 { 118 LOG(Media, "MediaPlaybackTargetPickerMac::availableDevicesDidChange - available = %i", (int)devicePicker().externalOutputDeviceAvailable); 119 120 if (!m_client) 121 return; 122 123 addPendingAction(OutputDeviceAvailabilityChanged); 124 } 125 126 AVOutputDeviceMenuControllerType *MediaPlaybackTargetPickerMac::devicePicker() 127 { 128 if (!getAVOutputDeviceMenuControllerClass()) 129 return nullptr; 130 131 if (!m_outputDeviceMenuController) { 132 RetainPtr<AVOutputContextType> context = adoptNS([[getAVOutputContextClass() alloc] init]); 133 m_outputDeviceMenuController = adoptNS([[getAVOutputDeviceMenuControllerClass() alloc] initWithOutputContext:context.get()]); 134 135 [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDeviceAvailableKeyName options:NSKeyValueObservingOptionNew context:nullptr]; 136 [m_outputDeviceMenuController.get() addObserver:m_outputDeviceMenuControllerDelegate.get() forKeyPath:externalOutputDevicePickedKeyName options:NSKeyValueObservingOptionNew context:nullptr]; 137 138 LOG(Media, "MediaPlaybackTargetPickerMac::devicePicker - allocated menu controller %p", m_outputDeviceMenuController.get()); 139 140 if (m_outputDeviceMenuController.get().externalOutputDeviceAvailable) 141 availableDevicesDidChange(); 142 } 143 144 return m_outputDeviceMenuController.get(); 145 } 146 147 void MediaPlaybackTargetPickerMac::showPlaybackTargetPicker(const FloatRect& location, bool checkActiveRoute) 148 { 149 if (!m_client || m_showingMenu) 150 return; 151 152 LOG(Media, "MediaPlaybackTargetPickerMac::showPlaybackTargetPicker - checkActiveRoute = %i", (int)checkActiveRoute); 153 154 AVOutputDeviceMenuControllerType *picker = devicePicker(); 155 if (![picker respondsToSelector:@selector(showMenuForRect:appearanceName:allowReselectionOfSelectedOutputDevice:)]) 156 return; 157 158 m_showingMenu = true; 159 if ([picker showMenuForRect:location appearanceName:NSAppearanceNameVibrantLight allowReselectionOfSelectedOutputDevice:!checkActiveRoute]) { 160 if (!checkActiveRoute) 161 currentDeviceDidChange(); 162 } 163 m_showingMenu = false; 164 } 165 166 void MediaPlaybackTargetPickerMac::addPendingAction(PendingActionFlags action) 167 { 168 m_pendingActionFlags |= action; 169 m_pendingActionTimer.startOneShot(pendingActionInterval); 170 } 171 172 void MediaPlaybackTargetPickerMac::currentDeviceDidChange() 173 { 174 LOG(Media, "MediaPlaybackTargetPickerMac::currentDeviceDidChange"); 175 176 if (!m_client) 177 return; 178 179 addPendingAction(CurrentDeviceDidChange); 180 } 181 182 void MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets() 183 { 184 LOG(Media, "MediaPlaybackTargetPickerMac::startingMonitoringPlaybackTargets"); 185 186 devicePicker(); 187 } 188 189 void MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets() 190 { 191 LOG(Media, "MediaPlaybackTargetPickerMac::stopMonitoringPlaybackTargets"); 192 193 // FIXME: update once rdar://21062536 has been fixed. 197 currentDeviceDidChange(); 194 198 } 195 199
Note:
See TracChangeset
for help on using the changeset viewer.