-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Two belling fixes #12281
Two belling fixes #12281
Changes from all commits
10ac865
3873146
59a6377
2fd955e
bcc2ca0
c4e967c
609e6c5
564b9f2
d442fbd
d2b2ee6
1326dee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,6 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi | |
|
||
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr }; | ||
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr }; | ||
winrt::Windows::Media::Playback::MediaPlayer Pane::s_bellPlayer = { nullptr }; | ||
|
||
Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) : | ||
_control{ control }, | ||
|
@@ -70,36 +69,6 @@ Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFo | |
_FocusFirstChild(); | ||
e.Handled(true); | ||
}); | ||
|
||
if (!s_bellPlayer) | ||
{ | ||
try | ||
{ | ||
s_bellPlayer = winrt::Windows::Media::Playback::MediaPlayer(); | ||
if (s_bellPlayer) | ||
{ | ||
// BODGY | ||
// | ||
// Manually leak a ref to the MediaPlayer we just instantiated. | ||
// We're doing this just like the way we do in AppHost with the | ||
// App itself. | ||
// | ||
// We have to do this because there's some bug in the OS with | ||
// the way a MediaPlayer gets torn down. At time of writing (Nov | ||
// 2021), if you search for `remove_SoundLevelChanged` in the OS | ||
// repo, you'll find a pile of bugs. | ||
// | ||
// We tried moving the MediaPlayer singleton up to the | ||
// TerminalPage, but alas, that teardown had the same problem. | ||
// So _whatever_. We'll leak it here. It needs to last the | ||
// lifetime of the app anyways, and it'll get cleaned up when the | ||
// Terminal is closed, so whatever. | ||
winrt::Windows::Media::Playback::MediaPlayer p{ s_bellPlayer }; | ||
::winrt::detach_abi(p); | ||
} | ||
} | ||
CATCH_LOG(); | ||
} | ||
} | ||
|
||
Pane::Pane(std::shared_ptr<Pane> first, | ||
|
@@ -1061,17 +1030,49 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio | |
|
||
winrt::fire_and_forget Pane::_playBellSound(winrt::Windows::Foundation::Uri uri) | ||
{ | ||
auto weakThis{ shared_from_this() }; | ||
auto weakThis{ weak_from_this() }; | ||
|
||
co_await winrt::resume_foreground(_root.Dispatcher()); | ||
if (auto pane{ weakThis.get() }) | ||
if (auto pane{ weakThis.lock() }) | ||
{ | ||
if (s_bellPlayer) | ||
// BODGY | ||
// GH#12258: We learned that if you leave the MediaPlayer open, and | ||
// press the media keys (like play/pause), then the OS will _replay the | ||
// bell_. So we have to re-create the MediaPlayer each time we want to | ||
// play the bell, to make sure a subsequent play doesn't come through | ||
// and reactivate the old one. | ||
|
||
if (!_bellPlayer) | ||
{ | ||
_bellPlayer = winrt::Windows::Media::Playback::MediaPlayer(); | ||
} | ||
if (_bellPlayer) | ||
{ | ||
const auto source{ winrt::Windows::Media::Core::MediaSource::CreateFromUri(uri) }; | ||
const auto item{ winrt::Windows::Media::Playback::MediaPlaybackItem(source) }; | ||
s_bellPlayer.Source(item); | ||
s_bellPlayer.Play(); | ||
_bellPlayer.Source(item); | ||
_bellPlayer.Play(); | ||
|
||
// This lambda will clean up the bell player when we're done with it. | ||
auto weakThis2{ weak_from_this() }; | ||
_mediaEndedRevoker = _bellPlayer.MediaEnded(winrt::auto_revoke, [weakThis2](auto&&, auto&&) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what series of callbacks do we get for multiple bells? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you bell while another is playing (in this pane), we'll stop the first bell and replace it with the second one, and only get MediaEnded when the last bell in that pane comes to an end. |
||
if (auto self{ weakThis2.lock() }) | ||
{ | ||
if (self->_bellPlayer) | ||
{ | ||
// We need to make sure clear out the current track | ||
// that's being played, again, so that the system can't | ||
// come through and replay it. In testing, we needed to | ||
// do this, closing the MediaPlayer alone wasn't good | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is seriously BODGY too. |
||
// enough. | ||
self->_bellPlayer.Pause(); | ||
self->_bellPlayer.Source(nullptr); | ||
self->_bellPlayer.Close(); | ||
} | ||
self->_mediaEndedRevoker.revoke(); | ||
self->_bellPlayer = nullptr; | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
|
@@ -1173,6 +1174,19 @@ void Pane::Shutdown() | |
// Lock the create/close lock so that another operation won't concurrently | ||
// modify our tree | ||
std::unique_lock lock{ _createCloseLock }; | ||
|
||
// Clear out our media player callbacks, and stop any playing media. This | ||
// will prevent the callback from being triggered after we've closed, and | ||
// also make sure that our sound stops when we're closed. | ||
_mediaEndedRevoker.revoke(); | ||
if (_bellPlayer) | ||
{ | ||
_bellPlayer.Pause(); | ||
_bellPlayer.Source(nullptr); | ||
_bellPlayer.Close(); | ||
} | ||
_bellPlayer = nullptr; | ||
|
||
if (_IsLeaf()) | ||
{ | ||
_control.Close(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this kinda BODGY and we should upstream the request for this? AFAIK MediaPlayer is THE way to be playing sounds/media now and not some legacy API so it should offer a way of not having it get captured by the media overlay controls.