diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 04122b039..8165566f1 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -946,8 +946,6 @@ PRIVATE media/audio/media_audio_track.h media/audio/media_child_ffmpeg_loader.cpp media/audio/media_child_ffmpeg_loader.h - media/player/media_player_button.cpp - media/player/media_player_button.h media/player/media_player_float.cpp media/player/media_player_float.h media/player/media_player_instance.cpp diff --git a/Telegram/Resources/icons/player/panel_close.png b/Telegram/Resources/icons/player/panel_close.png index 2e333de42..9e7594b69 100644 Binary files a/Telegram/Resources/icons/player/panel_close.png and b/Telegram/Resources/icons/player/panel_close.png differ diff --git a/Telegram/Resources/icons/player/panel_close@2x.png b/Telegram/Resources/icons/player/panel_close@2x.png index 1a70b887f..eb6e710bc 100644 Binary files a/Telegram/Resources/icons/player/panel_close@2x.png and b/Telegram/Resources/icons/player/panel_close@2x.png differ diff --git a/Telegram/Resources/icons/player/panel_close@3x.png b/Telegram/Resources/icons/player/panel_close@3x.png index 1ac24a1c6..e9e4d7795 100644 Binary files a/Telegram/Resources/icons/player/panel_close@3x.png and b/Telegram/Resources/icons/player/panel_close@3x.png differ diff --git a/Telegram/Resources/icons/player/player_backward.png b/Telegram/Resources/icons/player/player_backward.png index d2cac60d1..6dd0e1578 100644 Binary files a/Telegram/Resources/icons/player/player_backward.png and b/Telegram/Resources/icons/player/player_backward.png differ diff --git a/Telegram/Resources/icons/player/player_backward@2x.png b/Telegram/Resources/icons/player/player_backward@2x.png index e7afc81f3..ab24effae 100644 Binary files a/Telegram/Resources/icons/player/player_backward@2x.png and b/Telegram/Resources/icons/player/player_backward@2x.png differ diff --git a/Telegram/Resources/icons/player/player_backward@3x.png b/Telegram/Resources/icons/player/player_backward@3x.png index e83867321..5aea6896c 100644 Binary files a/Telegram/Resources/icons/player/player_backward@3x.png and b/Telegram/Resources/icons/player/player_backward@3x.png differ diff --git a/Telegram/Resources/icons/player/player_forward.png b/Telegram/Resources/icons/player/player_forward.png index 9a28263a7..adda5406f 100644 Binary files a/Telegram/Resources/icons/player/player_forward.png and b/Telegram/Resources/icons/player/player_forward.png differ diff --git a/Telegram/Resources/icons/player/player_forward@2x.png b/Telegram/Resources/icons/player/player_forward@2x.png index d1de2c67a..2c31059d8 100644 Binary files a/Telegram/Resources/icons/player/player_forward@2x.png and b/Telegram/Resources/icons/player/player_forward@2x.png differ diff --git a/Telegram/Resources/icons/player/player_forward@3x.png b/Telegram/Resources/icons/player/player_forward@3x.png index c59050a84..8e37465ec 100644 Binary files a/Telegram/Resources/icons/player/player_forward@3x.png and b/Telegram/Resources/icons/player/player_forward@3x.png differ diff --git a/Telegram/Resources/icons/player/player_mini_full.png b/Telegram/Resources/icons/player/player_mini_full.png index a56beec23..a0c01b157 100644 Binary files a/Telegram/Resources/icons/player/player_mini_full.png and b/Telegram/Resources/icons/player/player_mini_full.png differ diff --git a/Telegram/Resources/icons/player/player_mini_full@2x.png b/Telegram/Resources/icons/player/player_mini_full@2x.png index 919fa5588..fdb27f196 100644 Binary files a/Telegram/Resources/icons/player/player_mini_full@2x.png and b/Telegram/Resources/icons/player/player_mini_full@2x.png differ diff --git a/Telegram/Resources/icons/player/player_mini_full@3x.png b/Telegram/Resources/icons/player/player_mini_full@3x.png index 554968fce..2dfdb6411 100644 Binary files a/Telegram/Resources/icons/player/player_mini_full@3x.png and b/Telegram/Resources/icons/player/player_mini_full@3x.png differ diff --git a/Telegram/Resources/icons/player/player_mini_half.png b/Telegram/Resources/icons/player/player_mini_half.png index b73618710..e89fe4200 100644 Binary files a/Telegram/Resources/icons/player/player_mini_half.png and b/Telegram/Resources/icons/player/player_mini_half.png differ diff --git a/Telegram/Resources/icons/player/player_mini_half@2x.png b/Telegram/Resources/icons/player/player_mini_half@2x.png index 34c4263dc..e261f0808 100644 Binary files a/Telegram/Resources/icons/player/player_mini_half@2x.png and b/Telegram/Resources/icons/player/player_mini_half@2x.png differ diff --git a/Telegram/Resources/icons/player/player_mini_half@3x.png b/Telegram/Resources/icons/player/player_mini_half@3x.png index 308a16a04..4ad6f3b5e 100644 Binary files a/Telegram/Resources/icons/player/player_mini_half@3x.png and b/Telegram/Resources/icons/player/player_mini_half@3x.png differ diff --git a/Telegram/Resources/icons/player/player_mini_off.png b/Telegram/Resources/icons/player/player_mini_off.png index a650f55d2..08d5de9f1 100644 Binary files a/Telegram/Resources/icons/player/player_mini_off.png and b/Telegram/Resources/icons/player/player_mini_off.png differ diff --git a/Telegram/Resources/icons/player/player_mini_off@2x.png b/Telegram/Resources/icons/player/player_mini_off@2x.png index c3150639b..fa16cb764 100644 Binary files a/Telegram/Resources/icons/player/player_mini_off@2x.png and b/Telegram/Resources/icons/player/player_mini_off@2x.png differ diff --git a/Telegram/Resources/icons/player/player_mini_off@3x.png b/Telegram/Resources/icons/player/player_mini_off@3x.png index f4792b216..6d62c0164 100644 Binary files a/Telegram/Resources/icons/player/player_mini_off@3x.png and b/Telegram/Resources/icons/player/player_mini_off@3x.png differ diff --git a/Telegram/Resources/icons/player/player_order.png b/Telegram/Resources/icons/player/player_order.png index ed2b10e71..2d44eefc6 100644 Binary files a/Telegram/Resources/icons/player/player_order.png and b/Telegram/Resources/icons/player/player_order.png differ diff --git a/Telegram/Resources/icons/player/player_order@2x.png b/Telegram/Resources/icons/player/player_order@2x.png index 2ae4fc734..76e30a792 100644 Binary files a/Telegram/Resources/icons/player/player_order@2x.png and b/Telegram/Resources/icons/player/player_order@2x.png differ diff --git a/Telegram/Resources/icons/player/player_order@3x.png b/Telegram/Resources/icons/player/player_order@3x.png index a372bff44..be44a9930 100644 Binary files a/Telegram/Resources/icons/player/player_order@3x.png and b/Telegram/Resources/icons/player/player_order@3x.png differ diff --git a/Telegram/Resources/icons/player/player_pause.png b/Telegram/Resources/icons/player/player_pause.png index f7001be9d..b40213cbb 100644 Binary files a/Telegram/Resources/icons/player/player_pause.png and b/Telegram/Resources/icons/player/player_pause.png differ diff --git a/Telegram/Resources/icons/player/player_pause@2x.png b/Telegram/Resources/icons/player/player_pause@2x.png index 61e268caf..a8e819654 100644 Binary files a/Telegram/Resources/icons/player/player_pause@2x.png and b/Telegram/Resources/icons/player/player_pause@2x.png differ diff --git a/Telegram/Resources/icons/player/player_pause@3x.png b/Telegram/Resources/icons/player/player_pause@3x.png index 8cc548561..71d9fd6eb 100644 Binary files a/Telegram/Resources/icons/player/player_pause@3x.png and b/Telegram/Resources/icons/player/player_pause@3x.png differ diff --git a/Telegram/Resources/icons/player/player_play.png b/Telegram/Resources/icons/player/player_play.png index 3488f2692..816e5ef1e 100644 Binary files a/Telegram/Resources/icons/player/player_play.png and b/Telegram/Resources/icons/player/player_play.png differ diff --git a/Telegram/Resources/icons/player/player_play@2x.png b/Telegram/Resources/icons/player/player_play@2x.png index 7c283f331..a4e130c4a 100644 Binary files a/Telegram/Resources/icons/player/player_play@2x.png and b/Telegram/Resources/icons/player/player_play@2x.png differ diff --git a/Telegram/Resources/icons/player/player_play@3x.png b/Telegram/Resources/icons/player/player_play@3x.png index aa280b9a2..0a101f3f6 100644 Binary files a/Telegram/Resources/icons/player/player_play@3x.png and b/Telegram/Resources/icons/player/player_play@3x.png differ diff --git a/Telegram/Resources/icons/player/player_repeat.png b/Telegram/Resources/icons/player/player_repeat.png index 1667941e7..b13c3c025 100644 Binary files a/Telegram/Resources/icons/player/player_repeat.png and b/Telegram/Resources/icons/player/player_repeat.png differ diff --git a/Telegram/Resources/icons/player/player_repeat@2x.png b/Telegram/Resources/icons/player/player_repeat@2x.png index ae686e152..10a955139 100644 Binary files a/Telegram/Resources/icons/player/player_repeat@2x.png and b/Telegram/Resources/icons/player/player_repeat@2x.png differ diff --git a/Telegram/Resources/icons/player/player_repeat@3x.png b/Telegram/Resources/icons/player/player_repeat@3x.png index 01afab9b3..441f65bfc 100644 Binary files a/Telegram/Resources/icons/player/player_repeat@3x.png and b/Telegram/Resources/icons/player/player_repeat@3x.png differ diff --git a/Telegram/Resources/icons/player/player_repeat_single.png b/Telegram/Resources/icons/player/player_repeat_single.png index d3d81db04..d45a8a363 100644 Binary files a/Telegram/Resources/icons/player/player_repeat_single.png and b/Telegram/Resources/icons/player/player_repeat_single.png differ diff --git a/Telegram/Resources/icons/player/player_repeat_single@2x.png b/Telegram/Resources/icons/player/player_repeat_single@2x.png index 0bb671ed1..5c162addb 100644 Binary files a/Telegram/Resources/icons/player/player_repeat_single@2x.png and b/Telegram/Resources/icons/player/player_repeat_single@2x.png differ diff --git a/Telegram/Resources/icons/player/player_repeat_single@3x.png b/Telegram/Resources/icons/player/player_repeat_single@3x.png index a6aa0c883..3b2a35b95 100644 Binary files a/Telegram/Resources/icons/player/player_repeat_single@3x.png and b/Telegram/Resources/icons/player/player_repeat_single@3x.png differ diff --git a/Telegram/Resources/icons/player/player_reverse.png b/Telegram/Resources/icons/player/player_reverse.png deleted file mode 100644 index dea0be2df..000000000 Binary files a/Telegram/Resources/icons/player/player_reverse.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/player_reverse@2x.png b/Telegram/Resources/icons/player/player_reverse@2x.png deleted file mode 100644 index d3af5baf6..000000000 Binary files a/Telegram/Resources/icons/player/player_reverse@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/player_reverse@3x.png b/Telegram/Resources/icons/player/player_reverse@3x.png deleted file mode 100644 index 9b01d7a1b..000000000 Binary files a/Telegram/Resources/icons/player/player_reverse@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/player_shuffle.png b/Telegram/Resources/icons/player/player_shuffle.png index 1986e7329..da4e9c76b 100644 Binary files a/Telegram/Resources/icons/player/player_shuffle.png and b/Telegram/Resources/icons/player/player_shuffle.png differ diff --git a/Telegram/Resources/icons/player/player_shuffle@2x.png b/Telegram/Resources/icons/player/player_shuffle@2x.png index 3c2751ac8..862395114 100644 Binary files a/Telegram/Resources/icons/player/player_shuffle@2x.png and b/Telegram/Resources/icons/player/player_shuffle@2x.png differ diff --git a/Telegram/Resources/icons/player/player_shuffle@3x.png b/Telegram/Resources/icons/player/player_shuffle@3x.png index f743ba906..69ad651d4 100644 Binary files a/Telegram/Resources/icons/player/player_shuffle@3x.png and b/Telegram/Resources/icons/player/player_shuffle@3x.png differ diff --git a/Telegram/Resources/icons/player/player_speed.png b/Telegram/Resources/icons/player/player_speed.png new file mode 100644 index 000000000..fe29a80c6 Binary files /dev/null and b/Telegram/Resources/icons/player/player_speed.png differ diff --git a/Telegram/Resources/icons/player/player_speed@2x.png b/Telegram/Resources/icons/player/player_speed@2x.png new file mode 100644 index 000000000..c1c387372 Binary files /dev/null and b/Telegram/Resources/icons/player/player_speed@2x.png differ diff --git a/Telegram/Resources/icons/player/player_speed@3x.png b/Telegram/Resources/icons/player/player_speed@3x.png new file mode 100644 index 000000000..286a4a3b9 Binary files /dev/null and b/Telegram/Resources/icons/player/player_speed@3x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5.png new file mode 100644 index 000000000..f3fb2c8b7 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5@2x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5@2x.png new file mode 100644 index 000000000..23be463ef Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5@2x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5@3x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5@3x.png new file mode 100644 index 000000000..030a4e04e Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_0.5@3x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0.png new file mode 100644 index 000000000..bfa0669d2 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0@2x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0@2x.png new file mode 100644 index 000000000..6cb73540f Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0@2x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0@3x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0@3x.png new file mode 100644 index 000000000..e78836e41 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.0@3x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2.png new file mode 100644 index 000000000..a75d3573b Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2@2x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2@2x.png new file mode 100644 index 000000000..93c3cc58a Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2@2x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2@3x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2@3x.png new file mode 100644 index 000000000..38fdf1ead Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.2@3x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5.png new file mode 100644 index 000000000..95fef6aa8 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5@2x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5@2x.png new file mode 100644 index 000000000..a376a4e52 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5@2x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5@3x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5@3x.png new file mode 100644 index 000000000..ebdcebda1 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.5@3x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7.png new file mode 100644 index 000000000..1cc20e56d Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7@2x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7@2x.png new file mode 100644 index 000000000..7bd696eb6 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7@2x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7@3x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7@3x.png new file mode 100644 index 000000000..16dc797bc Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_1.7@3x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0.png new file mode 100644 index 000000000..f0245ccb2 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0@2x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0@2x.png new file mode 100644 index 000000000..a43c31618 Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0@2x.png differ diff --git a/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0@3x.png b/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0@3x.png new file mode 100644 index 000000000..227902b9d Binary files /dev/null and b/Telegram/Resources/icons/player/speed/audiospeed_menu_2.0@3x.png differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed0.5.png b/Telegram/Resources/icons/player/voice_speed/voice_speed0.5.png deleted file mode 100644 index 7ddf83762..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed0.5.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed0.5@2x.png b/Telegram/Resources/icons/player/voice_speed/voice_speed0.5@2x.png deleted file mode 100644 index 5c0b085c9..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed0.5@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed0.5@3x.png b/Telegram/Resources/icons/player/voice_speed/voice_speed0.5@3x.png deleted file mode 100644 index 8e1bcc9f2..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed0.5@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed1.5.png b/Telegram/Resources/icons/player/voice_speed/voice_speed1.5.png deleted file mode 100644 index c0ec78670..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed1.5.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed1.5@2x.png b/Telegram/Resources/icons/player/voice_speed/voice_speed1.5@2x.png deleted file mode 100644 index 5c6f8f846..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed1.5@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed1.5@3x.png b/Telegram/Resources/icons/player/voice_speed/voice_speed1.5@3x.png deleted file mode 100644 index 866d92903..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed1.5@3x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed2.png b/Telegram/Resources/icons/player/voice_speed/voice_speed2.png deleted file mode 100644 index a5d8a007e..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed2.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed2@2x.png b/Telegram/Resources/icons/player/voice_speed/voice_speed2@2x.png deleted file mode 100644 index a20348d5c..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed2@2x.png and /dev/null differ diff --git a/Telegram/Resources/icons/player/voice_speed/voice_speed2@3x.png b/Telegram/Resources/icons/player/voice_speed/voice_speed2@3x.png deleted file mode 100644 index 78163c01f..000000000 Binary files a/Telegram/Resources/icons/player/voice_speed/voice_speed2@3x.png and /dev/null differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1dfb10eb9..0f027b85f 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3552,8 +3552,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_voice_speed_slow" = "Slow"; "lng_voice_speed_normal" = "Normal"; +"lng_voice_speed_medium" = "Medium"; "lng_voice_speed_fast" = "Fast"; "lng_voice_speed_very_fast" = "Very fast"; +"lng_voice_speed_super_fast" = "Super fast"; "lng_view_button_user" = "View user"; "lng_view_button_bot" = "View bot"; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 2a312bb4a..2af5b16d2 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -3193,6 +3193,9 @@ void HistoryItem::createComponents(const MTPDmessage &data) { } } const auto id = data.vreply_to_msg_id().v; + if (data.is_reply_to_scheduled()) { + int a = 0; + } config.replyTo = data.is_reply_to_scheduled() ? _history->owner().scheduledMessages().localMessageId(id) : id; diff --git a/Telegram/SourceFiles/media/audio/media_audio.cpp b/Telegram/SourceFiles/media/audio/media_audio.cpp index ac098e396..ee5303374 100644 --- a/Telegram/SourceFiles/media/audio/media_audio.cpp +++ b/Telegram/SourceFiles/media/audio/media_audio.cpp @@ -491,7 +491,7 @@ void Mixer::Track::updateWithSpeedPosition() { int64 Mixer::Track::SpeedIndependentPosition( int64 position, float64 speed) { - Expects(speed < 2.5); + Expects(speed <= Audio::kSpeedMax); return int64(base::SafeRound(position * speed)); } @@ -499,7 +499,7 @@ int64 Mixer::Track::SpeedIndependentPosition( int64 Mixer::Track::SpeedDependentPosition( int64 position, float64 speed) { - Expects(speed >= 0.5); + Expects(speed >= Audio::kSpeedMin); return int64(base::SafeRound(position / speed)); } diff --git a/Telegram/SourceFiles/media/player/media_player.style b/Telegram/SourceFiles/media/player/media_player.style index fb4f989f8..f26a53945 100644 --- a/Telegram/SourceFiles/media/player/media_player.style +++ b/Telegram/SourceFiles/media/player/media_player.style @@ -10,6 +10,50 @@ using "ui/basic.style"; using "ui/widgets/widgets.style"; using "overview/overview.style"; +MediaPlayerButton { + playPosition: point; + playOuter: size; + pausePosition: point; + pauseOuter: size; + pauseStroke: pixels; + cancelPosition: point; + cancelOuter: size; + cancelStroke: pixels; + + rippleAreaPosition: point; + rippleAreaSize: pixels; + ripple: RippleAnimation; + + duration: int; +} + +MediaSpeedButton { + width: pixels; + height: pixels; + font: font; + icon: icon; +} + +MediaSpeedMenu { + menu: Menu; + iconFg: color; + iconFgActive: color; + textFgActive: color; + activeCheck: icon; + activeCheckSkip: pixels; + sliderStyle: TextStyle; + sliderPadding: margins; + sliderWidth: pixels; + slider: MediaSlider; +} + +mediaSpeedButton: MediaSpeedButton { + width: 24px; + height: 24px; + font: font(11px semibold); + icon: icon{{ "player/player_speed", menuIconFg }}; +} + mediaPlayerButton: MediaPlayerButton { playPosition: point(2px, 0px); playOuter: size(17px, 15px); @@ -25,6 +69,8 @@ mediaPlayerButton: MediaPlayerButton { ripple: RippleAnimation(defaultRippleAnimation) { color: lightButtonBgOver; } + + duration: 200; } mediaPlayerWideWidth: 460px; mediaPlayerHeight: 35px; @@ -96,59 +142,64 @@ mediaPlayerCancelIcon: icon{ { "player/panel_close", mediaPlayerActiveFg } }; -mediaPlayerSpeedButton: IconButton { - width: 31px; - height: 30px; - - icon: icon { - { "player/voice_speed/voice_speed2", mediaPlayerActiveFg } - }; - iconPosition: point(3px, 10px); - - rippleAreaPosition: point(3px, 5px); - rippleAreaSize: 25px; - ripple: RippleAnimation(defaultRippleAnimation) { - color: lightButtonBgOver; - } +mediaPlayerSpeedSize: size(30px, 30px); +mediaPlayerSpeedRadius: 4px; +mediaPlayerSpeedRipple: RippleAnimation(defaultRippleAnimation) { + color: lightButtonBgOver; } -mediaPlayerSpeedDisabledIcon: icon { - { "player/voice_speed/voice_speed2", menuIconFg } -}; -mediaPlayerSpeedDisabledIconOver: icon { - { "player/voice_speed/voice_speed2", menuIconFgOver } -}; -mediaPlayerSpeedSlowIcon: icon { - { "player/voice_speed/voice_speed0.5", mediaPlayerActiveFg } -}; -mediaPlayerSpeedSlowDisabledIcon: icon { - { "player/voice_speed/voice_speed0.5", menuIconFg } -}; -mediaPlayerSpeedSlowDisabledIconOver: icon { - { "player/voice_speed/voice_speed0.5", menuIconFgOver } -}; -mediaPlayerSpeedFastIcon: icon { - { "player/voice_speed/voice_speed1.5", mediaPlayerActiveFg } -}; -mediaPlayerSpeedFastDisabledIcon: icon { - { "player/voice_speed/voice_speed1.5", menuIconFg } -}; -mediaPlayerSpeedFastDisabledIconOver: icon { - { "player/voice_speed/voice_speed1.5", menuIconFgOver } -}; mediaPlayerSpeedDisabledRippleBg: windowBgOver; mediaPlayerMenu: DropdownMenu(defaultDropdownMenu) { wrap: InnerDropdown(defaultInnerDropdown) { - scrollPadding: margins(0px, 8px, 0px, 8px); + scrollPadding: margins(0px, 4px, 0px, 4px); padding: margins(10px, 2px, 10px, 10px); } } -mediaPlayerSpeedMenu: Menu(defaultMenu) { - itemIconPosition: point(6px, 5px); - itemPadding: margins(34px, 8px, 17px, 7px); -} mediaPlayerMenuCheck: icon {{ "player/player_check", mediaPlayerActiveFg }}; +mediaSpeedMenu: MediaSpeedMenu { + menu: Menu(menuWithIcons) { + separator: MenuSeparator(defaultMenuSeparator) { + padding: margins(0px, 4px, 0px, 4px); + width: 6px; + } + itemPadding: margins(54px, 7px, 54px, 9px); + itemFgDisabled: mediaPlayerActiveFg; + } + iconFg: menuIconColor; + iconFgActive: mediaPlayerActiveFg; + textFgActive: mediaPlayerActiveFg; + activeCheck: mediaPlayerMenuCheck; + activeCheckSkip: 8px; + sliderStyle: TextStyle(defaultTextStyle) { + font: font(12px semibold); + } + sliderPadding: margins(50px, 8px, 12px, 8px); + sliderWidth: 122px; + slider: MediaSlider(defaultContinuousSlider) { + activeFg: mediaPlayerActiveFg; + inactiveFg: windowBgOver; + activeFgOver: mediaPlayerActiveFg; + inactiveFgOver: windowBgOver; + activeFgDisabled: windowBgOver; + receivedTillFg: windowBgOver; + width: 6px; + seekSize: size(6px, 6px); + } +} +mediaSpeedSlow: icon {{ "player/speed/audiospeed_menu_0.5", menuIconColor }}; +mediaSpeedSlowActive: icon {{ "player/speed/audiospeed_menu_0.5", mediaPlayerActiveFg }}; +mediaSpeedNormal: icon {{ "player/speed/audiospeed_menu_1.0", menuIconColor }}; +mediaSpeedNormalActive: icon {{ "player/speed/audiospeed_menu_1.0", mediaPlayerActiveFg }}; +mediaSpeedMedium: icon {{ "player/speed/audiospeed_menu_1.2", menuIconColor }}; +mediaSpeedMediumActive: icon {{ "player/speed/audiospeed_menu_1.2", mediaPlayerActiveFg }}; +mediaSpeedFast: icon {{ "player/speed/audiospeed_menu_1.5", menuIconColor }}; +mediaSpeedFastActive: icon {{ "player/speed/audiospeed_menu_1.5", mediaPlayerActiveFg }}; +mediaSpeedVeryFast: icon {{ "player/speed/audiospeed_menu_1.7", menuIconColor }}; +mediaSpeedVeryFastActive: icon {{ "player/speed/audiospeed_menu_1.7", mediaPlayerActiveFg }}; +mediaSpeedSuperFast: icon {{ "player/speed/audiospeed_menu_2.0", menuIconColor }}; +mediaSpeedSuperFastActive: icon {{ "player/speed/audiospeed_menu_2.0", mediaPlayerActiveFg }}; + mediaPlayerVolumeIcon0: icon { { "player/player_mini_off", mediaPlayerActiveFg }, }; @@ -211,8 +262,6 @@ mediaPlayerPlayback: FilledSlider { duration: 150; } -mediaPlayerButtonTransformDuration: 200; - mediaPlayerPanelMarginLeft: 10px; mediaPlayerPanelMarginBottom: 10px; mediaPlayerPanelWidth: 344px; diff --git a/Telegram/SourceFiles/media/player/media_player_button.cpp b/Telegram/SourceFiles/media/player/media_player_button.cpp index c646727c0..a8e059599 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.cpp +++ b/Telegram/SourceFiles/media/player/media_player_button.cpp @@ -8,18 +8,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/player/media_player_button.h" #include "ui/painter.h" -#include "styles/style_widgets.h" +#include "styles/style_media_player.h" -namespace Media { -namespace Player { +#include -PlayButtonLayout::PlayButtonLayout(const style::MediaPlayerButton &st, Fn callback) +namespace Media::Player { +namespace { + +[[nodiscard]] QString SpeedText(float64 speed) { + return QString::number(base::SafeRound(speed * 10) / 10.) + 'X'; +} + +} // namespace + +PlayButtonLayout::PlayButtonLayout( + const style::MediaPlayerButton &st, + Fn callback) : _st(st) , _callback(std::move(callback)) { } void PlayButtonLayout::setState(State state) { - if (_nextState == state) return; + if (_nextState == state) { + return; + } _nextState = state; if (!_transformProgress.animating()) { @@ -238,8 +250,95 @@ void PlayButtonLayout::animationCallback() { } void PlayButtonLayout::startTransform(float64 from, float64 to) { - _transformProgress.start([this] { animationCallback(); }, from, to, st::mediaPlayerButtonTransformDuration); + _transformProgress.start( + [=] { animationCallback(); }, + from, + to, + _st.duration); } -} // namespace Player -} // namespace Media +SpeedButtonLayout::SpeedButtonLayout( + const style::MediaSpeedButton &st, + Fn callback, + float64 speed) +: _st(st) +, _speed(speed) +, _oldSpeed(speed) +, _nextSpeed(speed) +, _metrics(_st.font->f) +, _text(SpeedText(speed)) +, _textWidth(_metrics.horizontalAdvance(_text)) +, _oldText(_text) +, _oldTextWidth(_textWidth) +, _callback(std::move(callback)) { +} + +void SpeedButtonLayout::setSpeed(float64 speed) { + speed = base::SafeRound(speed * 10.) / 10.; + if (_nextSpeed == speed) { + return; + } + + _nextSpeed = speed; + if (!_transformProgress.animating()) { + _oldSpeed = _speed; + _oldColor = _lastPaintColor; + _oldText = _text; + _oldTextWidth = _textWidth; + _speed = _nextSpeed; + _text = SpeedText(_speed); + _textWidth = _metrics.horizontalAdvance(_text); + _transformBackward = false; + if (_speed != _speed) { + startTransform(0., 1.); + if (_callback) _callback(); + } + } else if (_oldSpeed == _nextSpeed) { + std::swap(_oldSpeed, _speed); + std::swap(_oldColor, _lastPaintColor); + std::swap(_oldText, _text); + std::swap(_oldTextWidth, _textWidth); + startTransform( + _transformBackward ? 0. : 1., + _transformBackward ? 1. : 0.); + _transformBackward = !_transformBackward; + } +} + +void SpeedButtonLayout::finishTransform() { + _transformProgress.stop(); + _transformBackward = false; + if (_callback) _callback(); +} + +void SpeedButtonLayout::paint(QPainter &p, const QColor &color) { + _lastPaintColor = color; + + _st.icon.paint(p, 0, 0, _st.width, color); + + p.setPen(color); + p.setFont(_st.font); + + p.drawText( + QPointF( + (_st.width - _textWidth) / 2., + (_st.height - _metrics.height()) / 2. + _metrics.ascent()), + _text); +} + +void SpeedButtonLayout::animationCallback() { + if (!_transformProgress.animating()) { + const auto finalSpeed = _nextSpeed; + _nextSpeed = _speed; + setSpeed(finalSpeed); + } + _callback(); +} + +void SpeedButtonLayout::startTransform(float64 from, float64 to) { + // No animation for now. + _transformProgress.stop(); + animationCallback(); +} + +} // namespace Media::Player diff --git a/Telegram/SourceFiles/media/player/media_player_button.h b/Telegram/SourceFiles/media/player/media_player_button.h index 74e448563..22e2d6be4 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.h +++ b/Telegram/SourceFiles/media/player/media_player_button.h @@ -7,12 +7,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "ui/abstract_button.h" #include "ui/effects/animations.h" -#include "styles/style_media_player.h" -namespace Media { -namespace Player { +#include + +namespace style { +struct MediaPlayerButton; +struct MediaSpeedButton; +} // namespace style + +namespace Media::Player { class PlayButtonLayout { public: @@ -48,5 +52,40 @@ private: }; -} // namespace Player -} // namespace Media +class SpeedButtonLayout { +public: + SpeedButtonLayout( + const style::MediaSpeedButton &st, + Fn callback, + float64 speed); + + void setSpeed(float64 speed); + void finishTransform(); + void paint(QPainter &p, const QColor &color); + +private: + void animationCallback(); + void startTransform(float64 from, float64 to); + + const style::MediaSpeedButton &_st; + + float64 _speed = 1.; + float64 _oldSpeed = 1.; + float64 _nextSpeed = 1.; + std::optional _lastPaintColor; + std::optional _oldColor; + Ui::Animations::Simple _transformProgress; + bool _transformBackward = false; + + QFontMetricsF _metrics; + + QString _text; + float64 _textWidth = 0; + QString _oldText; + float64 _oldTextWidth = 0; + + Fn _callback; + +}; + +} // namespace Media::Player diff --git a/Telegram/SourceFiles/media/player/media_player_dropdown.cpp b/Telegram/SourceFiles/media/player/media_player_dropdown.cpp index 71aa31d11..73afd0dcb 100644 --- a/Telegram/SourceFiles/media/player/media_player_dropdown.cpp +++ b/Telegram/SourceFiles/media/player/media_player_dropdown.cpp @@ -7,12 +7,213 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "media/player/media_player_dropdown.h" +#include "base/timer.h" +#include "lang/lang_keys.h" #include "ui/cached_round_corners.h" +#include "ui/widgets/menu/menu.h" +#include "ui/widgets/menu/menu_action.h" +#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/shadow.h" +#include "ui/painter.h" #include "styles/style_media_player.h" #include "styles/style_widgets.h" +#include "base/debug_log.h" + namespace Media::Player { +namespace { + +constexpr auto kSpeedMin = 0.5; +constexpr auto kSpeedMax = 2.5; +constexpr auto kSpeedDebounceTimeout = crl::time(1000); + +[[nodiscard]] float64 SpeedToSliderValue(float64 speed) { + return (speed - kSpeedMin) / (kSpeedMax - kSpeedMin); +} + +[[nodiscard]] float64 SliderValueToSpeed(float64 value) { + const auto speed = value * (kSpeedMax - kSpeedMin) + kSpeedMin; + return base::SafeRound(speed * 10) / 10.; +} + +constexpr auto kSpeedStickedValues = + std::array, 7>{{ + { 0.8, 0.05 }, + { 1.0, 0.05 }, + { 1.2, 0.05 }, + { 1.5, 0.05 }, + { 1.7, 0.05 }, + { 2.0, 0.05 }, + { 2.2, 0.05 }, + }}; + +class SpeedSliderItem final : public Ui::Menu::ItemBase { +public: + SpeedSliderItem( + not_null parent, + const style::MediaSpeedMenu &st, + rpl::producer value); + + not_null action() const override; + bool isEnabled() const override; + + [[nodiscard]] float64 current() const; + [[nodiscard]] rpl::producer changing() const; + [[nodiscard]] rpl::producer changed() const; + [[nodiscard]] rpl::producer debouncedChanges() const; + +protected: + int contentHeight() const override; + +private: + void setExternalValue(float64 speed); + void setSliderValue(float64 speed); + + const base::unique_qptr _slider; + const not_null _dummyAction; + const style::MediaSpeedMenu &_st; + Ui::Text::String _text; + int _height = 0; + + rpl::event_stream _changing; + rpl::event_stream _changed; + rpl::event_stream _debounced; + base::Timer _debounceTimer; + rpl::variable _last = 0.; + +}; + +SpeedSliderItem::SpeedSliderItem( + not_null parent, + const style::MediaSpeedMenu &st, + rpl::producer value) +: Ui::Menu::ItemBase(parent, st.menu) +, _slider(base::make_unique_q(this, st.slider)) +, _dummyAction(new QAction(parent)) +, _st(st) +, _height(st.sliderPadding.top() + + st.menu.itemStyle.font->height + + st.sliderPadding.bottom()) +, _debounceTimer([=] { _debounced.fire(current()); }) { + initResizeHook(parent->sizeValue()); + enableMouseSelecting(); + enableMouseSelecting(_slider.get()); + + setMinWidth(st.sliderPadding.left() + + st.sliderWidth + + st.sliderPadding.right()); + _slider->setAlwaysDisplayMarker(true); + + sizeValue( + ) | rpl::start_with_next([=](const QSize &size) { + const auto geometry = QRect(QPoint(), size); + const auto padding = _st.sliderPadding; + const auto inner = geometry - padding; + _slider->setGeometry( + padding.left(), + inner.y(), + (geometry.width() - padding.left() - padding.right()), + inner.height()); + }, lifetime()); + + paintRequest( + ) | rpl::start_with_next([=](const QRect &clip) { + auto p = Painter(this); + + p.fillRect(clip, _st.menu.itemBg); + + const auto left = (_st.sliderPadding.left() - _text.maxWidth()) / 2; + const auto top = _st.menu.itemPadding.top(); + p.setPen(_st.menu.itemFg); + _text.drawLeftElided(p, left, top, _text.maxWidth(), width()); + }, lifetime()); + + _slider->setChangeProgressCallback([=](float64 value) { + const auto speed = SliderValueToSpeed(value); + if (current() != speed) { + _last = speed; + _changing.fire_copy(speed); + _debounceTimer.callOnce(kSpeedDebounceTimeout); + } + }); + + _slider->setChangeFinishedCallback([=](float64 value) { + const auto speed = SliderValueToSpeed(value); + _last = speed; + _changed.fire_copy(speed); + _debounced.fire_copy(speed); + _debounceTimer.cancel(); + }); + + std::move( + value + ) | rpl::start_with_next([=](float64 external) { + setExternalValue(external); + }, lifetime()); + + _last.value( + ) | rpl::start_with_next([=](float64 value) { + const auto text = QString::number(value, 'f', 1) + 'x'; + if (_text.toString() != text) { + _text.setText(_st.sliderStyle, text); + update(); + } + }, lifetime()); + + _slider->setAdjustCallback([=](float64 value) { + const auto speed = SliderValueToSpeed(value); + for (const auto &snap : kSpeedStickedValues) { + if (speed > (snap.first - snap.second) + && speed < (snap.first + snap.second)) { + return SpeedToSliderValue(snap.first); + } + } + return value; + }); +} + +void SpeedSliderItem::setExternalValue(float64 speed) { + if (!_slider->isChanging()) { + setSliderValue(speed); + } +} + +void SpeedSliderItem::setSliderValue(float64 speed) { + const auto value = SpeedToSliderValue(speed); + _slider->setValue(value); + _last = speed; + _changed.fire_copy(speed); +} + +not_null SpeedSliderItem::action() const { + return _dummyAction; +} + +bool SpeedSliderItem::isEnabled() const { + return false; +} + +int SpeedSliderItem::contentHeight() const { + return _height; +} + +float64 SpeedSliderItem::current() const { + return _last.current(); +} + +rpl::producer SpeedSliderItem::changing() const { + return _changing.events(); +} + +rpl::producer SpeedSliderItem::changed() const { + return _changed.events(); +} + +rpl::producer SpeedSliderItem::debouncedChanges() const { + return _debounced.events(); +} + +} // namespace Dropdown::Dropdown(QWidget *parent) : RpWidget(parent) @@ -178,4 +379,109 @@ bool Dropdown::eventFilter(QObject *obj, QEvent *e) { return false; } +void FillSpeedMenu( + not_null menu, + const style::MediaSpeedMenu &st, + rpl::producer value, + Fn callback) { + auto slider = base::make_unique_q( + menu, + st, + rpl::duplicate(value)); + + slider->debouncedChanges( + ) | rpl::start_with_next(callback, slider->lifetime()); + + struct State { + rpl::variable realtime; + }; + const auto state = slider->lifetime().make_state(); + state->realtime = rpl::single( + slider->current() + ) | rpl::then(rpl::merge( + slider->changing(), + slider->changed() + )); + + menu->addAction(std::move(slider)); + menu->addSeparator(&st.menu.separator); + + struct SpeedPoint { + float64 speed = 0.; + tr::phrase<> text; + const style::icon &icon; + const style::icon &iconActive; + }; + const auto points = std::vector{ + { + 0.5, + tr::lng_voice_speed_slow, + st::mediaSpeedSlow, + st::mediaSpeedSlowActive }, + { + 1.0, + tr::lng_voice_speed_normal, + st::mediaSpeedNormal, + st::mediaSpeedNormalActive }, + { + 1.2, + tr::lng_voice_speed_medium, + st::mediaSpeedMedium, + st::mediaSpeedMediumActive }, + { + 1.5, + tr::lng_voice_speed_fast, + st::mediaSpeedFast, + st::mediaSpeedFastActive }, + { + 1.7, + tr::lng_voice_speed_very_fast, + st::mediaSpeedVeryFast, + st::mediaSpeedVeryFastActive }, + { + 2.0, + tr::lng_voice_speed_super_fast, + st::mediaSpeedSuperFast, + st::mediaSpeedSuperFastActive }, + }; + for (const auto &point : points) { + const auto speed = point.speed; + const auto text = point.text(tr::now); + const auto icon = &point.icon; + const auto iconActive = &point.iconActive; + auto action = base::make_unique_q( + menu, + st::mediaSpeedMenu.menu, + Ui::Menu::CreateAction(menu, text, [=] { callback(speed); }), + &point.icon, + &point.icon); + const auto raw = action.get(); + const auto check = Ui::CreateChild(raw); + const auto skip = st.activeCheckSkip; + check->resize(st.activeCheck.size()); + check->paintRequest( + ) | rpl::start_with_next([check, icon = &st.activeCheck] { + auto p = QPainter(check); + icon->paint(p, 0, 0, check->width()); + }, check->lifetime()); + raw->sizeValue( + ) | rpl::start_with_next([=, skip = st.activeCheckSkip](QSize size) { + check->moveToRight( + skip, + (size.height() - check->height()) / 2, + size.width()); + }, check->lifetime()); + check->setAttribute(Qt::WA_TransparentForMouseEvents); + state->realtime.value( + ) | rpl::start_with_next([=](float64 now) { + const auto chosen = (speed == now); + const auto overriden = chosen ? iconActive : icon; + raw->setIcon(overriden, overriden); + raw->action()->setEnabled(!chosen); + check->setVisible(chosen); + }, raw->lifetime()); + menu->addAction(std::move(action)); + } +} + } // namespace Media::Player diff --git a/Telegram/SourceFiles/media/player/media_player_dropdown.h b/Telegram/SourceFiles/media/player/media_player_dropdown.h index 67e1dfe54..627c276aa 100644 --- a/Telegram/SourceFiles/media/player/media_player_dropdown.h +++ b/Telegram/SourceFiles/media/player/media_player_dropdown.h @@ -11,6 +11,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animations.h" #include "base/timer.h" +namespace style { +struct MediaSpeedMenu; +} // namespace style + +namespace Ui::Menu { +class Menu; +} // namespace Ui::Menu + namespace Media::Player { class Dropdown final : public Ui::RpWidget { @@ -49,4 +57,10 @@ private: }; +void FillSpeedMenu( + not_null menu, + const style::MediaSpeedMenu &st, + rpl::producer value, + Fn callback); + } // namespace Media::Player diff --git a/Telegram/SourceFiles/media/player/media_player_widget.cpp b/Telegram/SourceFiles/media/player/media_player_widget.cpp index 9695b3f50..9740f893f 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.cpp +++ b/Telegram/SourceFiles/media/player/media_player_widget.cpp @@ -31,12 +31,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/player/media_player_instance.h" #include "media/player/media_player_dropdown.h" #include "media/player/media_player_volume_controller.h" -#include "styles/style_media_player.h" -#include "styles/style_media_view.h" #include "history/history_item.h" #include "history/history_item_helpers.h" #include "storage/storage_account.h" #include "main/main_session.h" +#include "styles/style_media_player.h" +#include "styles/style_media_view.h" +#include "styles/style_chat.h" // expandedMenuSeparator. namespace Media { namespace Player { @@ -44,12 +45,12 @@ namespace Player { class WithDropdownController { public: WithDropdownController( - not_null button, + not_null button, not_null menuParent, Fn menuOverCallback); virtual ~WithDropdownController() = default; - [[nodiscard]] not_null button() const; + [[nodiscard]] not_null button() const; Ui::DropdownMenu *menu() const; void updateDropdownGeometry(); @@ -63,7 +64,7 @@ protected: private: virtual void fillMenu(not_null menu) = 0; - const not_null _button; + const not_null _button; const not_null _menuParent; const Fn _menuOverCallback; base::unique_qptr _menu; @@ -72,6 +73,24 @@ private: }; +class Widget::SpeedButton final : public Ui::RippleButton { +public: + SpeedButton(QWidget *parent); + + void setSpeed(float64 speed, anim::type animated = anim::type::normal); + +private: + void paintEvent(QPaintEvent *e) override; + + QImage prepareRippleMask() const override; + QPoint prepareRippleStartPosition() const override; + + SpeedButtonLayout _layout; + QPoint _layoutPosition; + bool _isDefault = false; + +}; + class Widget::OrderController final : public WithDropdownController { public: OrderController( @@ -83,12 +102,14 @@ private: void fillMenu(not_null menu) override; void updateIcon(); + const not_null _button; + }; class Widget::SpeedController final : public WithDropdownController { public: SpeedController( - not_null button, + not_null button, not_null menuParent, Fn menuOverCallback); @@ -96,7 +117,6 @@ public: private: void fillMenu(not_null menu) override; - void updateIcon(); [[nodiscard]] float64 speed() const; [[nodiscard]] bool isDefault() const; @@ -105,7 +125,7 @@ private: void setSpeed(float64 newSpeed); void save(); - float64 _speed = 2.; + float64 _speed = 1.7; bool _isDefault = true; rpl::event_stream _speedChanged; rpl::event_stream<> _saved; @@ -113,7 +133,7 @@ private: }; WithDropdownController::WithDropdownController( - not_null button, + not_null button, not_null menuParent, Fn menuOverCallback) : _button(button) @@ -135,7 +155,7 @@ WithDropdownController::WithDropdownController( }, button->lifetime()); } -not_null WithDropdownController::button() const { +not_null WithDropdownController::button() const { return _button; } @@ -199,11 +219,48 @@ void WithDropdownController::showMenu() { _menu->showAnimated(Ui::PanelAnimation::Origin::TopRight); } +Widget::SpeedButton::SpeedButton(QWidget *parent) +: RippleButton(parent, st::mediaPlayerSpeedRipple) +, _layout(st::mediaSpeedButton, [=] { update(); }, 2.) +, _isDefault(true) { + resize(st::mediaPlayerSpeedSize); + _layoutPosition = QPoint( + (st::mediaPlayerSpeedSize.width() - st::mediaSpeedButton.width) / 2, + st::mediaPlayerSpeedSize.height() - st::mediaSpeedButton.height); +} + +void Widget::SpeedButton::setSpeed(float64 speed, anim::type animated) { + _isDefault = (speed == 1.); + _layout.setSpeed(speed); + if (animated == anim::type::instant) { + _layout.finishTransform(); + } + update(); +} + +void Widget::SpeedButton::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + + paintRipple( + p, + QPoint(), + _isDefault ? &st::mediaPlayerSpeedDisabledRippleBg->c : nullptr); + + const auto &color = !_isDefault + ? st::mediaPlayerActiveFg + : isOver() + ? st::menuIconFgOver + : st::menuIconFg; + p.translate(_layoutPosition); + _layout.paint(p, color->c); +} + Widget::OrderController::OrderController( not_null button, not_null menuParent, Fn menuOverCallback) -: WithDropdownController(button, menuParent, std::move(menuOverCallback)) { +: WithDropdownController(button, menuParent, std::move(menuOverCallback)) +, _button(button) { button->setClickedCallback([=] { showMenu(); }); @@ -260,25 +317,25 @@ void Widget::OrderController::fillMenu(not_null menu) { void Widget::OrderController::updateIcon() { switch (Core::App().settings().playerOrderMode()) { case OrderMode::Default: - button()->setIconOverride( + _button->setIconOverride( &st::mediaPlayerReverseDisabledIcon, &st::mediaPlayerReverseDisabledIconOver); - button()->setRippleColorOverride( + _button->setRippleColorOverride( &st::mediaPlayerRepeatDisabledRippleBg); break; case OrderMode::Reverse: - button()->setIconOverride(&st::mediaPlayerReverseIcon); - button()->setRippleColorOverride(nullptr); + _button->setIconOverride(&st::mediaPlayerReverseIcon); + _button->setRippleColorOverride(nullptr); break; case OrderMode::Shuffle: - button()->setIconOverride(&st::mediaPlayerShuffleIcon); - button()->setRippleColorOverride(nullptr); + _button->setIconOverride(&st::mediaPlayerShuffleIcon); + _button->setRippleColorOverride(nullptr); break; } } Widget::SpeedController::SpeedController( - not_null button, + not_null button, not_null menuParent, Fn menuOverCallback) : WithDropdownController(button, menuParent, std::move(menuOverCallback)) { @@ -293,45 +350,15 @@ Widget::SpeedController::SpeedController( setSpeed(Core::App().settings().voicePlaybackSpeed()); _speed = Core::App().settings().voicePlaybackSpeed(true); + button->setSpeed(_speed, anim::type::instant); + _speedChanged.events_starting_with( speed() - ) | rpl::start_with_next([=] { - updateIcon(); + ) | rpl::start_with_next([=](float64 speed) { + button->setSpeed(speed); }, button->lifetime()); } -void Widget::SpeedController::updateIcon() { - const auto isDefaultSpeed = isDefault(); - const auto nonDefaultSpeed = lastNonDefaultSpeed(); - - if (nonDefaultSpeed == .5) { - button()->setIconOverride( - (isDefaultSpeed - ? &st::mediaPlayerSpeedSlowDisabledIcon - : &st::mediaPlayerSpeedSlowIcon), - (isDefaultSpeed - ? &st::mediaPlayerSpeedSlowDisabledIconOver - : &st::mediaPlayerSpeedSlowIcon)); - } else if (nonDefaultSpeed == 1.5) { - button()->setIconOverride( - (isDefaultSpeed - ? &st::mediaPlayerSpeedFastDisabledIcon - : &st::mediaPlayerSpeedFastIcon), - (isDefaultSpeed - ? &st::mediaPlayerSpeedFastDisabledIconOver - : &st::mediaPlayerSpeedFastIcon)); - } else { - button()->setIconOverride( - isDefaultSpeed ? &st::mediaPlayerSpeedDisabledIcon : nullptr, - (isDefaultSpeed - ? &st::mediaPlayerSpeedDisabledIconOver - : nullptr)); - } - button()->setRippleColorOverride(isDefaultSpeed - ? &st::mediaPlayerSpeedDisabledRippleBg - : nullptr); -} - rpl::producer<> Widget::SpeedController::saved() const { return _saved.events(); } @@ -367,35 +394,11 @@ void Widget::SpeedController::save() { } void Widget::SpeedController::fillMenu(not_null menu) { - const auto currentSpeed = speed(); - const auto addSpeedAction = [&](float64 speed, QString text) { - const auto callback = [=] { - setSpeed(speed); - save(); - }; - const auto icon = (speed == currentSpeed) - ? &st::mediaPlayerMenuCheck - : nullptr; - auto action = base::make_unique_q( - menu, - st::mediaPlayerSpeedMenu, - Ui::Menu::CreateAction(menu, text, callback), - icon, - icon); - const auto raw = action.get(); - _speedChanged.events( - ) | rpl::start_with_next([=](float64 updatedSpeed) { - const auto icon = (speed == updatedSpeed) - ? &st::mediaPlayerMenuCheck - : nullptr; - raw->setIcon(icon, icon); - }, raw->lifetime()); - menu->addAction(std::move(action)); - }; - addSpeedAction(0.5, tr::lng_voice_speed_slow(tr::now)); - addSpeedAction(1., tr::lng_voice_speed_normal(tr::now)); - addSpeedAction(1.5, tr::lng_voice_speed_fast(tr::now)); - addSpeedAction(2., tr::lng_voice_speed_very_fast(tr::now)); + FillSpeedMenu( + menu->menu(), + st::mediaSpeedMenu, + _speedChanged.events_starting_with(speed()), + [=](float64 speed) { setSpeed(speed); save(); }); } Widget::Widget( @@ -412,7 +415,7 @@ Widget::Widget( , _volumeToggle(rightControls(), st::mediaPlayerVolumeToggle) , _repeatToggle(rightControls(), st::mediaPlayerRepeatButton) , _orderToggle(rightControls(), st::mediaPlayerRepeatButton) -, _speedToggle(rightControls(), st::mediaPlayerSpeedButton) +, _speedToggle(rightControls()) , _close(this, st::mediaPlayerClose) , _shadow(this) , _playbackSlider(this, st::mediaPlayerPlayback) diff --git a/Telegram/SourceFiles/media/player/media_player_widget.h b/Telegram/SourceFiles/media/player/media_player_widget.h index 4d0de3959..e38e8ecc6 100644 --- a/Telegram/SourceFiles/media/player/media_player_widget.h +++ b/Telegram/SourceFiles/media/player/media_player_widget.h @@ -23,21 +23,16 @@ template class FadeWrap; } // namespace Ui -namespace Media { -namespace View { +namespace Media::View { class PlaybackProgress; -} // namespace Clip -} // namespace Media +} // namespace Media::View namespace Window { class SessionController; } // namespace Window -namespace Media { -namespace Player { +namespace Media::Player { -class PlayButton; -class SpeedButton; class Dropdown; struct TrackState; @@ -47,6 +42,7 @@ public: QWidget *parent, not_null dropdownsParent, not_null controller); + ~Widget(); void setCloseCallback(Fn callback); void setShowItemCallback(Fn)> callback); @@ -61,8 +57,6 @@ public: return _togglePlaylistRequests.events(); } - ~Widget(); - private: void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; @@ -134,7 +128,7 @@ private: bool _wontBeOver = false; bool _volumeHidden = false; - class PlayButton; + class SpeedButton; class OrderController; class SpeedController; object_ptr _nameLabel; @@ -146,7 +140,7 @@ private: object_ptr _volumeToggle; object_ptr _repeatToggle; object_ptr _orderToggle; - object_ptr _speedToggle; + object_ptr _speedToggle; object_ptr _close; object_ptr _shadow = { nullptr }; object_ptr _playbackSlider; @@ -159,5 +153,4 @@ private: }; -} // namespace Player -} // namespace Media +} // namespace Media::Player diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp index 316af0105..a5293cfea 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_player.cpp @@ -528,7 +528,8 @@ void Player::fail(Error error) { } void Player::play(const PlaybackOptions &options) { - Expects(options.speed >= 0.5 && options.speed <= 2.); + Expects(options.speed >= Audio::kSpeedMin + && options.speed <= Audio::kSpeedMax); // Looping video with audio is not supported for now. Expects(!options.loop || (options.mode != Mode::Both)); @@ -828,7 +829,7 @@ float64 Player::speed() const { } void Player::setSpeed(float64 speed) { - Expects(speed >= 0.5 && speed <= 2.); + Expects(speed >= Audio::kSpeedMin && speed <= Audio::kSpeedMax); if (!Media::Audio::SupportsSpeedControl()) { speed = 1.; diff --git a/Telegram/SourceFiles/media/view/media_view_pip.cpp b/Telegram/SourceFiles/media/view/media_view_pip.cpp index e27dfa4a8..2df6538e4 100644 --- a/Telegram/SourceFiles/media/view/media_view_pip.cpp +++ b/Telegram/SourceFiles/media/view/media_view_pip.cpp @@ -1093,9 +1093,6 @@ void Pip::handleMousePress(QPoint position, Qt::MouseButton button) { } void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) { - Expects(1 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - const auto weak = Ui::MakeWeak(_panel.widget()); const auto guard = gsl::finally([&] { if (weak) { @@ -1107,21 +1104,11 @@ void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) { } seekUpdate(position); - Assert(2 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - volumeControllerUpdate(position); - Assert(3 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - const auto pressed = base::take(_pressed); if (pressed && *pressed == OverState::Playback) { _panel.setDragDisabled(false); - - Assert(4 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - seekFinish(_playbackProgress->value()); } else if (pressed && *pressed == OverState::VolumeController) { _panel.setDragDisabled(false); @@ -1182,9 +1169,6 @@ void Pip::seekProgress(float64 value) { } void Pip::seekFinish(float64 value) { - Expects(5 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - if (!_lastDurationMs) { return; } @@ -1671,31 +1655,18 @@ void Pip::playbackPauseResume() { } void Pip::restartAtSeekPosition(crl::time position) { - Expects(6 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - if (!_instance.info().video.cover.isNull()) { _preparedCoverStorage = QImage(); _preparedCoverState = ThumbState::Empty; _instance.saveFrameToCover(); } - Assert(7 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - auto options = Streaming::PlaybackOptions(); options.position = position; options.hwAllowed = Core::App().settings().hardwareAcceleratedVideo(); options.audioId = _instance.player().prepareLegacyState().id; - - Assert(8 && _delegate->pipPlaybackSpeed() >= 0.5 - && _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash. - options.speed = _delegate->pipPlaybackSpeed(); - Assert(9 && options.speed >= 0.5 - && options.speed <= 2.); // Debugging strange crash. - _instance.play(options); if (_startPaused) { _instance.pause(); diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index b0e42190b..fea8a0e0c 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -120,6 +120,8 @@ PRIVATE media/clip/media_clip_reader.cpp media/clip/media_clip_reader.h + media/player/media_player_button.cpp + media/player/media_player_button.h media/player/media_player_dropdown.cpp media/player/media_player_dropdown.h diff --git a/Telegram/lib_ui b/Telegram/lib_ui index c80df2cdd..62a62d1fb 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit c80df2cdd2d2838d5e4aab50075e4f6e7c05e380 +Subproject commit 62a62d1fb5abe9dc1e6b9f89af1ccef6fef33c52