Added Windows SMTC support.
System Media Transport Controls.
This commit is contained in:
parent
690fbe83fd
commit
78dfe940ef
|
@ -923,6 +923,8 @@ PRIVATE
|
|||
platform/win/windows_dlls.h
|
||||
platform/win/windows_event_filter.cpp
|
||||
platform/win/windows_event_filter.h
|
||||
platform/win/windows_system_media_controls_manager.cpp
|
||||
platform/win/windows_system_media_controls_manager.h
|
||||
platform/platform_audio.h
|
||||
platform/platform_file_utilities.h
|
||||
platform/platform_launcher.h
|
||||
|
|
|
@ -139,4 +139,4 @@ bool Launcher::launch(
|
|||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace Platform
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "platform/platform_notifications_manager.h"
|
||||
#include "platform/win/windows_dlls.h"
|
||||
#include "platform/win/windows_event_filter.h"
|
||||
#include "platform/win/windows_system_media_controls_manager.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "mainwindow.h"
|
||||
#include "base/crc32hash.h"
|
||||
|
@ -429,6 +430,10 @@ void MainWindow::initHook() {
|
|||
}
|
||||
|
||||
psInitSysMenu();
|
||||
|
||||
if (IsWindows10OrGreater()) {
|
||||
_smtcManager = std::make_unique<SystemMediaControlsManager>(psHwnd());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::initShadows() {
|
||||
|
|
|
@ -20,6 +20,8 @@ class PopupMenu;
|
|||
|
||||
namespace Platform {
|
||||
|
||||
class SystemMediaControlsManager;
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
public:
|
||||
explicit MainWindow(not_null<Window::Controller*> controller);
|
||||
|
@ -123,6 +125,8 @@ private:
|
|||
HICON ps_iconSmall = nullptr;
|
||||
HICON ps_iconOverlay = nullptr;
|
||||
|
||||
std::unique_ptr<Platform::SystemMediaControlsManager> _smtcManager;
|
||||
|
||||
int _deltaLeft = 0;
|
||||
int _deltaTop = 0;
|
||||
int _deltaRight = 0;
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/win/windows_system_media_controls_manager.h"
|
||||
|
||||
#include "base/observer.h"
|
||||
#include "base/platform/win/base_windows_system_media_controls.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "main/main_session.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "ui/text/format_song_document_name.h"
|
||||
|
||||
namespace Platform {
|
||||
|
||||
SystemMediaControlsManager::SystemMediaControlsManager(HWND hwnd)
|
||||
: _controls(std::make_unique<base::Platform::SystemMediaControlsWin>()) {
|
||||
|
||||
using PlaybackStatus =
|
||||
base::Platform::SystemMediaControlsWin::PlaybackStatus;
|
||||
using Command = base::Platform::SystemMediaControlsWin::Command;
|
||||
|
||||
_controls->init(hwnd);
|
||||
const auto type = AudioMsgId::Type::Song;
|
||||
|
||||
const auto mediaPlayer = Media::Player::instance();
|
||||
|
||||
mediaPlayer->updatedNotifier(
|
||||
) | rpl::filter([=](const Media::Player::TrackState &state) {
|
||||
return state.id.type() == type;
|
||||
}) | rpl::map([=](const Media::Player::TrackState &state) {
|
||||
using namespace Media::Player;
|
||||
if (IsStoppedOrStopping(state.state)) {
|
||||
return PlaybackStatus::Stopped;
|
||||
} else if (IsPausedOrPausing(state.state)) {
|
||||
return PlaybackStatus::Paused;
|
||||
}
|
||||
return PlaybackStatus::Playing;
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=](PlaybackStatus status) {
|
||||
_controls->setPlaybackStatus(status);
|
||||
}, _lifetime);
|
||||
|
||||
rpl::merge(
|
||||
mediaPlayer->stops(type) | rpl::map_to(false),
|
||||
mediaPlayer->startsPlay(type) | rpl::map_to(true)
|
||||
) | rpl::start_with_next([=](bool audio) {
|
||||
if (audio) {
|
||||
_controls->setEnabled(audio);
|
||||
_controls->setIsNextEnabled(mediaPlayer->nextAvailable(type));
|
||||
_controls->setIsPreviousEnabled(
|
||||
mediaPlayer->previousAvailable(type));
|
||||
_controls->setIsPlayPauseEnabled(true);
|
||||
_controls->setIsStopEnabled(true);
|
||||
_controls->setPlaybackStatus(PlaybackStatus::Playing);
|
||||
_controls->updateDisplay();
|
||||
} else {
|
||||
_cachedMediaView.clear();
|
||||
_controls->clearMetadata();
|
||||
}
|
||||
_lifetimeDownload.destroy();
|
||||
}, _lifetime);
|
||||
|
||||
auto trackChanged = base::ObservableViewer(
|
||||
mediaPlayer->trackChangedNotifier()
|
||||
) | rpl::filter([=](AudioMsgId::Type audioType) {
|
||||
return audioType == type;
|
||||
});
|
||||
|
||||
auto unlocked = Core::App().passcodeLockChanges(
|
||||
) | rpl::filter([](bool locked) {
|
||||
return !locked;
|
||||
}) | rpl::map([=] {
|
||||
return type;
|
||||
}) | rpl::before_next([=] {
|
||||
_controls->setEnabled(true);
|
||||
_controls->updateDisplay();
|
||||
});
|
||||
|
||||
rpl::merge(
|
||||
std::move(trackChanged),
|
||||
std::move(unlocked)
|
||||
) | rpl::start_with_next([=](AudioMsgId::Type audioType) {
|
||||
_lifetimeDownload.destroy();
|
||||
|
||||
const auto current = mediaPlayer->current(audioType);
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
const auto document = current.audio();
|
||||
|
||||
const auto &[title, performer] = Ui::Text::FormatSongNameFor(document)
|
||||
.composedName();
|
||||
|
||||
_controls->setArtist(performer);
|
||||
_controls->setTitle(title);
|
||||
|
||||
if (document && document->isSongWithCover()) {
|
||||
const auto view = document->createMediaView();
|
||||
view->thumbnailWanted(current.contextId());
|
||||
_cachedMediaView.push_back(view);
|
||||
if (const auto imagePtr = view->thumbnail()) {
|
||||
_controls->setThumbnail(imagePtr->original());
|
||||
} else {
|
||||
document->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
if (const auto imagePtr = view->thumbnail()) {
|
||||
_controls->setThumbnail(imagePtr->original());
|
||||
_lifetimeDownload.destroy();
|
||||
}
|
||||
}, _lifetimeDownload);
|
||||
_controls->clearThumbnail();
|
||||
}
|
||||
} else {
|
||||
_controls->clearThumbnail();
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
_controls->commandRequests(
|
||||
) | rpl::start_with_next([=](Command command) {
|
||||
switch (command) {
|
||||
case Command::Play: mediaPlayer->play(type); break;
|
||||
case Command::Pause: mediaPlayer->pause(type); break;
|
||||
case Command::Next: mediaPlayer->next(type); break;
|
||||
case Command::Previous: mediaPlayer->previous(type); break;
|
||||
case Command::Stop: mediaPlayer->stop(type); break;
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
Core::App().passcodeLockValue(
|
||||
) | rpl::filter([=](bool locked) {
|
||||
return locked && Core::App().maybeActiveSession();
|
||||
}) | rpl::start_with_next([=] {
|
||||
_controls->setEnabled(false);
|
||||
}, _lifetime);
|
||||
|
||||
}
|
||||
|
||||
SystemMediaControlsManager::~SystemMediaControlsManager() = default;
|
||||
|
||||
} // namespace Platform
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace base::Platform {
|
||||
class SystemMediaControlsWin;
|
||||
} // namespace base::Platform
|
||||
|
||||
namespace Data {
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class SystemMediaControlsManager {
|
||||
public:
|
||||
SystemMediaControlsManager(HWND hwnd);
|
||||
~SystemMediaControlsManager();
|
||||
|
||||
private:
|
||||
const std::unique_ptr<base::Platform::SystemMediaControlsWin> _controls;
|
||||
|
||||
std::vector<std::shared_ptr<Data::DocumentMedia>> _cachedMediaView;
|
||||
|
||||
rpl::lifetime _lifetimeDownload;
|
||||
rpl::lifetime _lifetime;
|
||||
};
|
||||
|
||||
} // namespace Platform
|
|
@ -1 +1 @@
|
|||
Subproject commit 95b23bd09b71c5599b6b89d6c708e7d35b8963aa
|
||||
Subproject commit 54f214213cc67885a57cb246483893272c986c3a
|
Loading…
Reference in New Issue