Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 24 additions & 35 deletions src/cascadia/TerminalApp/TerminalPaneContent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "TerminalPaneContent.h"

#include <mmsystem.h>
#include <shlwapi.h>

#include "TerminalSettingsCache.h"
#include "../../types/inc/utils.hpp"
Expand Down Expand Up @@ -71,18 +72,6 @@ namespace winrt::TerminalApp::implementation
_removeControlEvents();

_control.Close();

// 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.
if (_bellPlayer)
{
_bellPlayer.Pause();
_bellPlayer.Source(nullptr);
_bellPlayer.Close();
_bellPlayer = nullptr;
_bellPlayerCreated = false;
}
}

winrt::hstring TerminalPaneContent::Icon() const
Expand Down Expand Up @@ -276,8 +265,7 @@ namespace winrt::TerminalApp::implementation
if (sounds && sounds.Size() > 0)
{
winrt::hstring soundPath{ sounds.GetAt(rand() % sounds.Size()).Resolved() };
winrt::Windows::Foundation::Uri uri{ soundPath };
_playBellSound(uri);
_playBellSound(soundPath);
}
else
{
Expand All @@ -298,33 +286,34 @@ namespace winrt::TerminalApp::implementation
}
}

safe_void_coroutine TerminalPaneContent::_playBellSound(winrt::Windows::Foundation::Uri uri)
void TerminalPaneContent::_playBellSound(winrt::hstring soundPath)
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(_control.Dispatcher());
if (auto pane{ weakThis.get() })
std::wstring filePath{ soundPath };
// The settings model resolves bellSound to a filesystem path. We only need
// URI parsing if a file URI string makes it this far.
if (til::starts_with_insensitive_ascii(soundPath, L"file:"))
{
if (!_bellPlayerCreated)
// PathCreateFromUrlW supports writing to the input pointer,
// and the resulting path can never be longer than the URI.
const auto ptr = filePath.data();
auto len = gsl::narrow<DWORD>(filePath.size());
if (FAILED_LOG(PathCreateFromUrlW(ptr, ptr, &len, 0)))
{
// The MediaPlayer might not exist on Windows N SKU.
try
{
_bellPlayerCreated = true;
_bellPlayer = winrt::Windows::Media::Playback::MediaPlayer();
// GH#12258: The media keys (like play/pause) should have no effect on our bell sound.
_bellPlayer.CommandManager().IsEnabled(false);
}
CATCH_LOG();
}
if (_bellPlayer)
{
const auto source{ winrt::Windows::Media::Core::MediaSource::CreateFromUri(uri) };
const auto item{ winrt::Windows::Media::Playback::MediaPlaybackItem(source) };
_bellPlayer.Source(item);
_bellPlayer.Play();
return;
}
filePath.resize(len);
}

if (!til::is_legal_path(filePath))
{
return;
}

// GH#17733: Play bell sounds with Win32 audio APIs so per-app mixer
// volume persists across terminal restarts.
PlaySoundW(filePath.c_str(), nullptr, SND_FILENAME | SND_ASYNC | SND_SENTRY | SND_NODEFAULT);
}

void TerminalPaneContent::_closeTerminalRequestedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::Foundation::IInspectable& /*args*/)
{
Expand Down
5 changes: 1 addition & 4 deletions src/cascadia/TerminalApp/TerminalPaneContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@ namespace winrt::TerminalApp::implementation
std::shared_ptr<TerminalSettingsCache> _cache{};
bool _isDefTermSession{ false };

winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
bool _bellPlayerCreated{ false };

struct ControlEventTokens
{
winrt::Microsoft::Terminal::Control::TermControl::ConnectionStateChanged_revoker _ConnectionStateChanged;
Expand All @@ -84,7 +81,7 @@ namespace winrt::TerminalApp::implementation
void _setupControlEvents();
void _removeControlEvents();

safe_void_coroutine _playBellSound(winrt::Windows::Foundation::Uri uri);
void _playBellSound(winrt::hstring soundPath);

safe_void_coroutine _controlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
void _controlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& sender,
Expand Down
Loading