Merge remote-tracking branch 'tdesktop/dev' into dev

This commit is contained in:
Eric Kotato 2020-03-14 18:17:17 +03:00
commit 9c7d8cc1e1
56 changed files with 1756 additions and 613 deletions

View file

@ -71,7 +71,7 @@ jobs:
libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \ libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \
autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \ autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \
libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \ libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \
libvorbis-dev libenchant-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \
libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \ libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \
libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \ libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \
libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \ libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \
@ -323,7 +323,7 @@ jobs:
run: | run: |
cd $LibrariesPath cd $LibrariesPath
git clone -b openal-soft-1.19.1 --depth=1 $GIT/kcat/openal-soft.git git clone -b openal-soft-1.20.1 --depth=1 $GIT/kcat/openal-soft.git
cd openal-soft/build cd openal-soft/build
cmake -D LIBTYPE:STRING=STATIC .. cmake -D LIBTYPE:STRING=STATIC ..
make -j$(nproc) make -j$(nproc)
@ -342,14 +342,15 @@ jobs:
run: | run: |
cd $LibrariesPath cd $LibrariesPath
opensslDir=openssl_${OPENSSL_VER}
git clone -b OpenSSL_${OPENSSL_VER}-stable --depth=1 \ git clone -b OpenSSL_${OPENSSL_VER}-stable --depth=1 \
$GIT/openssl/openssl openssl_${OPENSSL_VER} $GIT/openssl/openssl $opensslDir
cd openssl_${OPENSSL_VER} cd $opensslDir
./config --prefix=$LibrariesPath/openssl-cache ./config --prefix=$LibrariesPath/openssl-cache
make -j$(nproc) make -j$(nproc)
sudo make install sudo make install_sw
cd .. cd ..
rm -rf openssl_${OPENSSL_VER} rm -rf $opensslDir
- name: OpenSSL install. - name: OpenSSL install.
run: | run: |
cd $LibrariesPath cd $LibrariesPath

View file

@ -26,11 +26,11 @@ jobs:
GIT: "https://github.com" GIT: "https://github.com"
PREFIX: "/usr/local/macos" PREFIX: "/usr/local/macos"
MACOSX_DEPLOYMENT_TARGET: "10.12" MACOSX_DEPLOYMENT_TARGET: "10.12"
XZ: "xz-5.0.5" XZ: "xz-5.2.4"
QT: "5_12_5" QT: "5_12_5"
OPENSSL_VER: "1_1_1" OPENSSL_VER: "1_1_1"
QT_PREFIX: "/usr/local/desktop-app/Qt-5.12.5" QT_PREFIX: "/usr/local/desktop-app/Qt-5.12.5"
LIBICONV_VER: "libiconv-1.15" LIBICONV_VER: "libiconv-1.16"
UPLOAD_ARTIFACT: "false" UPLOAD_ARTIFACT: "false"
ONLY_CACHE: "false" ONLY_CACHE: "false"
MANUAL_CACHING: "2" MANUAL_CACHING: "2"

View file

@ -47,6 +47,10 @@ jobs:
md5cache=$(md5sum CMAKE_CACHE_KEY.txt | cut -c -32) md5cache=$(md5sum CMAKE_CACHE_KEY.txt | cut -c -32)
echo ::set-env name=CMAKE_CACHE_KEY::$md5cache echo ::set-env name=CMAKE_CACHE_KEY::$md5cache
awk -v RS="" -v ORS="\n\n" '/^ ffmpeg:/' snap/snapcraft.yaml > FFMPEG_CACHE_KEY.txt
md5cache=$(md5sum FFMPEG_CACHE_KEY.txt | cut -c -32)
echo ::set-env name=FFMPEG_CACHE_KEY::$md5cache
- name: CMake cache. - name: CMake cache.
id: cache-cmake id: cache-cmake
uses: actions/cache@v1 uses: actions/cache@v1
@ -58,6 +62,17 @@ jobs:
if: steps.cache-cmake.outputs.cache-hit != 'true' if: steps.cache-cmake.outputs.cache-hit != 'true'
run: snapcraft build --destructive-mode cmake run: snapcraft build --destructive-mode cmake
- name: FFmpeg cache.
id: cache-ffmpeg
uses: actions/cache@v1
with:
path: parts/ffmpeg
key: ${{ runner.OS }}-ffmpeg-${{ env.CACHE_KEY }}-${{ env.FFMPEG_CACHE_KEY }}
- name: FFmpeg build.
if: steps.cache-ffmpeg.outputs.cache-hit != 'true'
run: snapcraft build --destructive-mode ffmpeg
- name: Kotatogram Desktop snap build. - name: Kotatogram Desktop snap build.
if: env.ONLY_CACHE == 'false' if: env.ONLY_CACHE == 'false'
run: snapcraft --destructive-mode run: snapcraft --destructive-mode
@ -80,5 +95,5 @@ jobs:
- name: Remove unneeded directories for cache. - name: Remove unneeded directories for cache.
run: | run: |
rm -rf parts/cmake/{build,src,ubuntu} rm -rf parts/{cmake,ffmpeg}/{build,src,ubuntu}
rm -rf parts/cmake/state/{stage,prime} rm -rf parts/{cmake,ffmpeg}/state/{stage,prime}

View file

@ -22,6 +22,9 @@ project(Telegram
) )
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Telegram) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Telegram)
get_filename_component(third_party_loc "Telegram/ThirdParty" REALPATH)
get_filename_component(submodules_loc "Telegram" REALPATH)
include(cmake/variables.cmake) include(cmake/variables.cmake)
include(cmake/nice_target_sources.cmake) include(cmake/nice_target_sources.cmake)
include(cmake/target_link_static_libraries.cmake) include(cmake/target_link_static_libraries.cmake)

View file

@ -39,4 +39,4 @@ Full list of features will rewritten later, for now you can use one of `control-
[flatpak]: https://flathub.org/apps/details/io.github.kotatogram [flatpak]: https://flathub.org/apps/details/io.github.kotatogram
[changelog]: https://github.com/kotatogram/kotatogram-desktop/blob/dev/kotatogram_changes.txt [changelog]: https://github.com/kotatogram/kotatogram-desktop/blob/dev/kotatogram_changes.txt
[preview_image]: https://github.com/kotatogram/kotatogram-desktop/blob/dev/docs/assets/ktg_preview.png "Preview of Kotatogram Desktop" [preview_image]: https://github.com/kotatogram/kotatogram-desktop/blob/dev/docs/assets/ktg_preview.png "Preview of Kotatogram Desktop"
[preview_image_url]: https://github.com/kotatogram/kotatogram-desktop/blob/dev/docs/assets/ktg_preview.png [preview_image_url]: https://github.com/kotatogram/kotatogram-desktop/blob/dev/docs/assets/ktg_preview.png

View file

@ -94,6 +94,7 @@ PRIVATE
desktop-app::external_lz4 desktop-app::external_lz4
desktop-app::external_rlottie desktop-app::external_rlottie
desktop-app::external_zlib desktop-app::external_zlib
desktop-app::external_minizip
desktop-app::external_qt desktop-app::external_qt
desktop-app::external_qr_code_generator desktop-app::external_qr_code_generator
desktop-app::external_crash_reports desktop-app::external_crash_reports
@ -1219,14 +1220,15 @@ endif()
if (LINUX AND DESKTOP_APP_USE_PACKAGED) if (LINUX AND DESKTOP_APP_USE_PACKAGED)
include(GNUInstallDirs) include(GNUInstallDirs)
configure_file("../lib/xdg/kotatogramdesktop.appdata.xml.in" "${CMAKE_CURRENT_BINARY_DIR}/kotatogramdesktop.appdata.xml" @ONLY)
install(TARGETS Telegram RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}") install(TARGETS Telegram RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon16.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon32.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon48.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon64.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon128.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon256.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/256x256/apps" RENAME "telegram.png")
install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "kotatogram.png") install(FILES "Resources/art/icon512.png" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/512x512/apps" RENAME "telegram.png")
install(FILES "../lib/xdg/kotatogramdesktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.desktop") install(FILES "../lib/xdg/kotatogramdesktop.desktop" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.desktop")
install(FILES "../lib/xdg/kotatogramdesktop.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.appdata.xml") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kotatogramdesktop.appdata.xml" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo" RENAME "${TDESKTOP_LAUNCHER_BASENAME}.appdata.xml")
endif() endif()

View file

@ -0,0 +1,225 @@
diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile
index 00f93bf59f..52da7036f3 100644
--- a/libavcodec/aarch64/Makefile
+++ b/libavcodec/aarch64/Makefile
@@ -6,6 +6,7 @@ OBJS-$(CONFIG_H264DSP) += aarch64/h264dsp_init_aarch64.o
OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o
OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o
OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o
+OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o
OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o
OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o
OBJS-$(CONFIG_VIDEODSP) += aarch64/videodsp_init.o
@@ -21,6 +22,7 @@ OBJS-$(CONFIG_VC1DSP) += aarch64/vc1dsp_init_aarch64.o
OBJS-$(CONFIG_VORBIS_DECODER) += aarch64/vorbisdsp_init.o
OBJS-$(CONFIG_VP9_DECODER) += aarch64/vp9dsp_init_10bpp_aarch64.o \
aarch64/vp9dsp_init_12bpp_aarch64.o \
+ aarch64/vp9mc_aarch64.o \
aarch64/vp9dsp_init_aarch64.o
# ARMv8 optimizations
@@ -41,8 +43,7 @@ NEON-OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_neon.o
NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \
aarch64/hpeldsp_neon.o
NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o
-NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o \
- aarch64/simple_idct_neon.o
+NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/simple_idct_neon.o
NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o
NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o
NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o
diff --git a/libavcodec/aarch64/idctdsp_init_aarch64.c b/libavcodec/aarch64/idctdsp_init_aarch64.c
index 0406e60830..742a3372e3 100644
--- a/libavcodec/aarch64/idctdsp_init_aarch64.c
+++ b/libavcodec/aarch64/idctdsp_init_aarch64.c
@@ -21,6 +21,8 @@
*/
#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/arm/cpu.h"
#include "libavcodec/avcodec.h"
#include "libavcodec/idctdsp.h"
#include "idct.h"
@@ -28,7 +30,9 @@
av_cold void ff_idctdsp_init_aarch64(IDCTDSPContext *c, AVCodecContext *avctx,
unsigned high_bit_depth)
{
- if (!avctx->lowres && !high_bit_depth) {
+ int cpu_flags = av_get_cpu_flags();
+
+ if (have_neon(cpu_flags) && !avctx->lowres && !high_bit_depth) {
if (avctx->idct_algo == FF_IDCT_AUTO ||
avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
avctx->idct_algo == FF_IDCT_SIMPLENEON) {
diff --git a/libavcodec/aarch64/vp9mc_16bpp_neon.S b/libavcodec/aarch64/vp9mc_16bpp_neon.S
index cac6428709..53b372c262 100644
--- a/libavcodec/aarch64/vp9mc_16bpp_neon.S
+++ b/libavcodec/aarch64/vp9mc_16bpp_neon.S
@@ -25,31 +25,6 @@
// const uint8_t *ref, ptrdiff_t ref_stride,
// int h, int mx, int my);
-function ff_vp9_copy128_aarch64, export=1
-1:
- ldp x5, x6, [x2]
- ldp x7, x8, [x2, #16]
- stp x5, x6, [x0]
- ldp x9, x10, [x2, #32]
- stp x7, x8, [x0, #16]
- subs w4, w4, #1
- ldp x11, x12, [x2, #48]
- stp x9, x10, [x0, #32]
- stp x11, x12, [x0, #48]
- ldp x5, x6, [x2, #64]
- ldp x7, x8, [x2, #80]
- stp x5, x6, [x0, #64]
- ldp x9, x10, [x2, #96]
- stp x7, x8, [x0, #80]
- ldp x11, x12, [x2, #112]
- stp x9, x10, [x0, #96]
- stp x11, x12, [x0, #112]
- add x2, x2, x3
- add x0, x0, x1
- b.ne 1b
- ret
-endfunc
-
function ff_vp9_avg64_16_neon, export=1
mov x5, x0
sub x1, x1, #64
diff --git a/libavcodec/aarch64/vp9mc_aarch64.S b/libavcodec/aarch64/vp9mc_aarch64.S
new file mode 100644
index 0000000000..f17a8cf04a
--- /dev/null
+++ b/libavcodec/aarch64/vp9mc_aarch64.S
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016 Google Inc.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/aarch64/asm.S"
+
+// All public functions in this file have the following signature:
+// typedef void (*vp9_mc_func)(uint8_t *dst, ptrdiff_t dst_stride,
+// const uint8_t *ref, ptrdiff_t ref_stride,
+// int h, int mx, int my);
+
+function ff_vp9_copy128_aarch64, export=1
+1:
+ ldp x5, x6, [x2]
+ ldp x7, x8, [x2, #16]
+ stp x5, x6, [x0]
+ ldp x9, x10, [x2, #32]
+ stp x7, x8, [x0, #16]
+ subs w4, w4, #1
+ ldp x11, x12, [x2, #48]
+ stp x9, x10, [x0, #32]
+ stp x11, x12, [x0, #48]
+ ldp x5, x6, [x2, #64]
+ ldp x7, x8, [x2, #80]
+ stp x5, x6, [x0, #64]
+ ldp x9, x10, [x2, #96]
+ stp x7, x8, [x0, #80]
+ ldp x11, x12, [x2, #112]
+ stp x9, x10, [x0, #96]
+ stp x11, x12, [x0, #112]
+ add x2, x2, x3
+ add x0, x0, x1
+ b.ne 1b
+ ret
+endfunc
+
+function ff_vp9_copy64_aarch64, export=1
+1:
+ ldp x5, x6, [x2]
+ ldp x7, x8, [x2, #16]
+ stp x5, x6, [x0]
+ ldp x9, x10, [x2, #32]
+ stp x7, x8, [x0, #16]
+ subs w4, w4, #1
+ ldp x11, x12, [x2, #48]
+ stp x9, x10, [x0, #32]
+ stp x11, x12, [x0, #48]
+ add x2, x2, x3
+ add x0, x0, x1
+ b.ne 1b
+ ret
+endfunc
+
+function ff_vp9_copy32_aarch64, export=1
+1:
+ ldp x5, x6, [x2]
+ ldp x7, x8, [x2, #16]
+ stp x5, x6, [x0]
+ subs w4, w4, #1
+ stp x7, x8, [x0, #16]
+ add x2, x2, x3
+ add x0, x0, x1
+ b.ne 1b
+ ret
+endfunc
diff --git a/libavcodec/aarch64/vp9mc_neon.S b/libavcodec/aarch64/vp9mc_neon.S
index f67624ca04..abf2bae9db 100644
--- a/libavcodec/aarch64/vp9mc_neon.S
+++ b/libavcodec/aarch64/vp9mc_neon.S
@@ -25,23 +25,6 @@
// const uint8_t *ref, ptrdiff_t ref_stride,
// int h, int mx, int my);
-function ff_vp9_copy64_aarch64, export=1
-1:
- ldp x5, x6, [x2]
- ldp x7, x8, [x2, #16]
- stp x5, x6, [x0]
- ldp x9, x10, [x2, #32]
- stp x7, x8, [x0, #16]
- subs w4, w4, #1
- ldp x11, x12, [x2, #48]
- stp x9, x10, [x0, #32]
- stp x11, x12, [x0, #48]
- add x2, x2, x3
- add x0, x0, x1
- b.ne 1b
- ret
-endfunc
-
function ff_vp9_avg64_neon, export=1
mov x5, x0
1:
@@ -64,19 +47,6 @@ function ff_vp9_avg64_neon, export=1
ret
endfunc
-function ff_vp9_copy32_aarch64, export=1
-1:
- ldp x5, x6, [x2]
- ldp x7, x8, [x2, #16]
- stp x5, x6, [x0]
- subs w4, w4, #1
- stp x7, x8, [x0, #16]
- add x2, x2, x3
- add x0, x0, x1
- b.ne 1b
- ret
-endfunc
-
function ff_vp9_avg32_neon, export=1
1:
ld1 {v2.16b, v3.16b}, [x2], x3

View file

@ -2239,6 +2239,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_linux_menu_undo" = "Undo"; "lng_linux_menu_undo" = "Undo";
"lng_linux_menu_redo" = "Redo"; "lng_linux_menu_redo" = "Redo";
"lng_linux_menu_tools" = "Tools";
"lng_linux_menu_help" = "Help";
"lng_linux_no_audio_prefs" = "You don't have any audio configuration applications installed."; "lng_linux_no_audio_prefs" = "You don't have any audio configuration applications installed.";

View file

@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop" <Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE" ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A" Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="1.9.19.0" /> Version="1.9.20.0" />
<Properties> <Properties>
<DisplayName>Telegram Desktop</DisplayName> <DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName> <PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>

View file

@ -1503,7 +1503,8 @@ void ApiWrap::applyLastParticipantsList(
channel->mgInfo->lastAdmins.clear(); channel->mgInfo->lastAdmins.clear();
channel->mgInfo->lastRestricted.clear(); channel->mgInfo->lastRestricted.clear();
channel->mgInfo->lastParticipants.clear(); channel->mgInfo->lastParticipants.clear();
channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate; channel->mgInfo->lastParticipantsStatus = MegagroupInfo::LastParticipantsUpToDate
| MegagroupInfo::LastParticipantsOnceReceived;
auto botStatus = channel->mgInfo->botStatus; auto botStatus = channel->mgInfo->botStatus;
const auto emptyAdminRights = MTP_chatAdminRights(MTP_flags(0)); const auto emptyAdminRights = MTP_chatAdminRights(MTP_flags(0));

View file

@ -206,8 +206,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
if (_chat) { if (_chat) {
maxListSize += (_chat->participants.empty() ? _chat->lastAuthors.size() : _chat->participants.size()); maxListSize += (_chat->participants.empty() ? _chat->lastAuthors.size() : _chat->participants.size());
} else if (_channel && _channel->isMegagroup()) { } else if (_channel && _channel->isMegagroup()) {
if (_channel->mgInfo->lastParticipants.empty() || _channel->lastParticipantsCountOutdated()) { if (!_channel->lastParticipantsRequestNeeded()) {
} else {
maxListSize += _channel->mgInfo->lastParticipants.size(); maxListSize += _channel->mgInfo->lastParticipants.size();
} }
} }
@ -274,7 +273,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
} }
} else if (_channel && _channel->isMegagroup()) { } else if (_channel && _channel->isMegagroup()) {
QMultiMap<int32, UserData*> ordered; QMultiMap<int32, UserData*> ordered;
if (_channel->mgInfo->lastParticipants.empty() || _channel->lastParticipantsCountOutdated()) { if (_channel->lastParticipantsRequestNeeded()) {
Auth().api().requestLastParticipants(_channel); Auth().api().requestLastParticipants(_channel);
} else { } else {
mrows.reserve(mrows.size() + _channel->mgInfo->lastParticipants.size()); mrows.reserve(mrows.size() + _channel->mgInfo->lastParticipants.size());

View file

@ -133,27 +133,22 @@ void DownloadDictionaryInBackground(
const auto id = langs[counter]; const auto id = langs[counter];
counter++; counter++;
const auto destroyer = [=] { const auto destroyer = [=] {
// This is a temporary workaround.
const auto copyId = id;
const auto copyLangs = langs;
const auto copySession = session;
const auto copyCounter = counter;
BackgroundLoader = nullptr; BackgroundLoader = nullptr;
BackgroundLoaderChanged.fire(0); BackgroundLoaderChanged.fire(0);
if (DictionaryExists(copyId)) { if (DictionaryExists(id)) {
auto dicts = copySession->settings().dictionariesEnabled(); auto dicts = session->settings().dictionariesEnabled();
if (!ranges::contains(dicts, copyId)) { if (!ranges::contains(dicts, id)) {
dicts.push_back(copyId); dicts.push_back(id);
copySession->settings().setDictionariesEnabled(std::move(dicts)); session->settings().setDictionariesEnabled(std::move(dicts));
copySession->saveSettingsDelayed(); session->saveSettingsDelayed();
} }
} }
if (copyCounter >= copyLangs.size()) { if (counter >= langs.size()) {
return; return;
} }
DownloadDictionaryInBackground(copySession, copyCounter, copyLangs); DownloadDictionaryInBackground(session, counter, langs);
}; };
if (DictionaryExists(id)) { if (DictionaryExists(id)) {
destroyer(); destroyer();
@ -194,20 +189,21 @@ DictLoader::DictLoader(
} }
void DictLoader::unpack(const QString &path) { void DictLoader::unpack(const QString &path) {
Expects(_destroyCallback);
crl::async([=] { crl::async([=] {
const auto success = Spellchecker::UnpackDictionary(path, id()); const auto success = Spellchecker::UnpackDictionary(path, id());
if (success) { if (success) {
QFile(path).remove(); QFile(path).remove();
destroy();
return;
} }
crl::on_main(success ? _destroyCallback : [=] { fail(); }); crl::on_main([=] { fail(); });
}); });
} }
void DictLoader::destroy() { void DictLoader::destroy() {
Expects(_destroyCallback); Expects(_destroyCallback);
_destroyCallback(); crl::on_main(_destroyCallback);
} }
void DictLoader::fail() { void DictLoader::fail() {

View file

@ -60,6 +60,7 @@ private:
void unpack(const QString &path) override; void unpack(const QString &path) override;
void fail() override; void fail() override;
// Be sure to always call it in the main thread.
Fn<void()> _destroyCallback; Fn<void()> _destroyCallback;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;

View file

@ -18,33 +18,6 @@ namespace {
std::map<int, const char*> BetaLogs() { std::map<int, const char*> BetaLogs() {
return { return {
{
1008005,
"\xE2\x80\xA2 Create new themes based on your color "
"and wallpaper choices.\n"
"\xE2\x80\xA2 Share your themes with other users via links.\n"
"\xE2\x80\xA2 Update your theme for all its users "
"when you change something.\n"
},
{
1009000,
"\xE2\x80\xA2 System spell checker on Windows 8+ and macOS 10.12+.\n"
},
{
1009002,
"\xE2\x80\xA2 Videos in chats start playing automatically.\n"
"\xE2\x80\xA2 Resume playback from where you left off "
"when watching long videos.\n"
"\xE2\x80\xA2 Control videos, GIFs and round video messages "
"automatic playback in "
"Settings > Advanced > Automatic media download.\n"
"\xE2\x80\xA2 Spell checker on Linux using Enchant.\n"
},
{ {
1009010, 1009010,
"\xE2\x80\xA2 Switch to the Picture-in-Picture mode " "\xE2\x80\xA2 Switch to the Picture-in-Picture mode "
@ -63,12 +36,19 @@ std::map<int, const char*> BetaLogs() {
"\xE2\x80\xA2 Bug fixes and other minor improvements." "\xE2\x80\xA2 Bug fixes and other minor improvements."
}, },
{ {
1009017, 1009017,
"\xE2\x80\xA2 Spell checker on Windows 7.\n" "\xE2\x80\xA2 Spell checker on Windows 7.\n"
"\xE2\x80\xA2 Bug fixes and other minor improvements." "\xE2\x80\xA2 Bug fixes and other minor improvements."
},
{
1009020,
"\xE2\x80\xA2 Fix crash in shared links search.\n"
"\xE2\x80\xA2 Fix blurred thumbnails in albums with video files.\n"
"\xE2\x80\xA2 Fix a possible crash in animated stickers rendering."
} }
}; };
}; };

View file

@ -247,6 +247,7 @@ void Launcher::init() {
prepareSettings(); prepareSettings();
QApplication::setApplicationName(qsl("KotatogramDesktop")); QApplication::setApplicationName(qsl("KotatogramDesktop"));
QApplication::setApplicationDisplayName(AppName.utf16());
#if defined(Q_OS_LINUX) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) #if defined(Q_OS_LINUX) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
QApplication::setDesktopFileName(Platform::GetLauncherFilename()); QApplication::setDesktopFileName(Platform::GetLauncherFilename());

View file

@ -274,7 +274,7 @@ void Sandbox::socketError(QLocalSocket::LocalSocketError e) {
psCheckLocalSocket(_localServerName); psCheckLocalSocket(_localServerName);
if (!_localServer.listen(_localServerName)) { if (!_localServer.listen(_localServerName)) {
LOG(("Failed to start listening to %1 server, error %2").arg(_localServerName).arg(int(_localServer.serverError()))); LOG(("Failed to start listening to %1 server: %2").arg(_localServerName).arg(_localServer.errorString()));
return App::quit(); return App::quit();
} }
#endif // !Q_OS_WINRT #endif // !Q_OS_WINRT

View file

@ -341,6 +341,20 @@ bool ChannelData::isGroupAdmin(not_null<UserData*> user) const {
return false; return false;
} }
bool ChannelData::lastParticipantsRequestNeeded() const {
if (!mgInfo) {
return false;
} else if (mgInfo->lastParticipantsCount == membersCount()) {
mgInfo->lastParticipantsStatus
&= ~MegagroupInfo::LastParticipantsCountOutdated;
}
return mgInfo->lastParticipants.empty()
|| !(mgInfo->lastParticipantsStatus
& MegagroupInfo::LastParticipantsOnceReceived)
|| (mgInfo->lastParticipantsStatus
& MegagroupInfo::LastParticipantsCountOutdated);
}
QString ChannelData::adminRank(not_null<UserData*> user) const { QString ChannelData::adminRank(not_null<UserData*> user) const {
if (!isGroupAdmin(user)) { if (!isGroupAdmin(user)) {
return QString(); return QString();

View file

@ -73,6 +73,7 @@ public:
enum LastParticipantsStatus { enum LastParticipantsStatus {
LastParticipantsUpToDate = 0x00, LastParticipantsUpToDate = 0x00,
LastParticipantsOnceReceived = 0x01,
LastParticipantsCountOutdated = 0x02, LastParticipantsCountOutdated = 0x02,
}; };
mutable int lastParticipantsStatus = LastParticipantsUpToDate; mutable int lastParticipantsStatus = LastParticipantsUpToDate;
@ -219,21 +220,8 @@ public:
void markForbidden(); void markForbidden();
[[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const; [[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const;
[[nodiscard]] bool lastParticipantsRequestNeeded() const;
[[nodiscard]] QString adminRank(not_null<UserData*> user) const; [[nodiscard]] QString adminRank(not_null<UserData*> user) const;
[[nodiscard]] bool lastParticipantsCountOutdated() const {
if (!mgInfo
|| !(mgInfo->lastParticipantsStatus
& MegagroupInfo::LastParticipantsCountOutdated)) {
return false;
}
if (mgInfo->lastParticipantsCount == membersCount()) {
mgInfo->lastParticipantsStatus
&= ~MegagroupInfo::LastParticipantsCountOutdated;
return false;
}
return true;
}
[[nodiscard]] bool isMegagroup() const { [[nodiscard]] bool isMegagroup() const {
return flags() & MTPDchannel::Flag::f_megagroup; return flags() & MTPDchannel::Flag::f_megagroup;
} }

View file

@ -42,7 +42,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
constexpr auto kMemoryForCache = 32 * 1024 * 1024; // Updated Mar 3, 2020: Increase the size of the memory cache for media, to prevent items still being displayed from being unloaded.
constexpr auto kMemoryForCache = 128 * 1024 * 1024; // was 32, updated to 128
const auto kAnimatedStickerDimensions = QSize(512, 512); const auto kAnimatedStickerDimensions = QSize(512, 512);
using FilePathResolve = DocumentData::FilePathResolve; using FilePathResolve = DocumentData::FilePathResolve;

View file

@ -5171,6 +5171,8 @@ int HistoryWidget::countInitialScrollTop() {
} }
void HistoryWidget::createUnreadBarIfBelowVisibleArea(int withScrollTop) { void HistoryWidget::createUnreadBarIfBelowVisibleArea(int withScrollTop) {
Expects(_history != nullptr);
if (_history->unreadBar()) { if (_history->unreadBar()) {
return; return;
} }
@ -5292,7 +5294,7 @@ void HistoryWidget::updateHistoryGeometry(
newScrollTop = countInitialScrollTop(); newScrollTop = countInitialScrollTop();
_historyInited = true; _historyInited = true;
_scrollToAnimation.stop(); _scrollToAnimation.stop();
} else if (wasAtBottom && !loadedDown) { } else if (wasAtBottom && !loadedDown && !_history->unreadBar()) {
newScrollTop = countAutomaticScrollTop(); newScrollTop = countAutomaticScrollTop();
} else { } else {
newScrollTop = std::min( newScrollTop = std::min(

View file

@ -280,6 +280,16 @@ bool Element::isUnderCursor() const {
return _delegate->elementUnderCursor(this); return _delegate->elementUnderCursor(this);
} }
bool Element::isLastAndSelfMessage() const {
if (!hasOutLayout()) {
return false;
}
if (const auto last = data()->_history->lastMessage()) {
return last == data();
}
return false;
}
void Element::setPendingResize() { void Element::setPendingResize() {
_flags |= Flag::NeedsResize; _flags |= Flag::NeedsResize;
if (_context == Context::History) { if (_context == Context::History) {

View file

@ -158,6 +158,8 @@ public:
bool pendingResize() const; bool pendingResize() const;
bool isUnderCursor() const; bool isUnderCursor() const;
bool isLastAndSelfMessage() const;
bool isAttachedToPrevious() const; bool isAttachedToPrevious() const;
bool isAttachedToNext() const; bool isAttachedToNext() const;

View file

@ -896,7 +896,7 @@ void TopBarWidget::updateOnlineDisplay() {
} }
} else if (const auto channel = _activeChat.peer()->asChannel()) { } else if (const auto channel = _activeChat.peer()->asChannel()) {
if (channel->isMegagroup() && channel->membersCount() > 0 && channel->membersCount() <= Global::ChatSizeMax()) { if (channel->isMegagroup() && channel->membersCount() > 0 && channel->membersCount() <= Global::ChatSizeMax()) {
if (channel->mgInfo->lastParticipants.empty() || channel->lastParticipantsCountOutdated()) { if (channel->lastParticipantsRequestNeeded()) {
session().api().requestLastParticipants(channel); session().api().requestLastParticipants(channel);
} }
const auto self = session().user(); const auto self = session().user();

View file

@ -1180,7 +1180,7 @@ void Gif::validateGroupedCache(
const auto height = geometry.height(); const auto height = geometry.height();
const auto options = Option::Smooth const auto options = Option::Smooth
| Option::RoundedLarge | Option::RoundedLarge
| (blur ? Option(0) : Option::Blurred) | (blur ? Option::Blurred : Option(0))
| ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None) | ((corners & RectPart::TopLeft) ? Option::RoundedTopLeft : Option::None)
| ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None) | ((corners & RectPart::TopRight) ? Option::RoundedTopRight : Option::None)
| ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None) | ((corners & RectPart::BottomLeft) ? Option::RoundedBottomLeft : Option::None)
@ -1494,7 +1494,8 @@ bool Gif::dataLoaded() const {
bool Gif::needInfoDisplay() const { bool Gif::needInfoDisplay() const {
return _parent->data()->isSending() return _parent->data()->isSending()
|| _data->uploading() || _data->uploading()
|| _parent->isUnderCursor(); || _parent->isUnderCursor()
|| _parent->isLastAndSelfMessage();
} }
bool Gif::needCornerStatusDisplay() const { bool Gif::needCornerStatusDisplay() const {

View file

@ -464,7 +464,9 @@ bool GroupedMedia::computeNeedBubble() const {
} }
bool GroupedMedia::needInfoDisplay() const { bool GroupedMedia::needInfoDisplay() const {
return (_parent->data()->id < 0 || _parent->isUnderCursor()); return (_parent->data()->id < 0
|| _parent->isUnderCursor()
|| _parent->isLastAndSelfMessage());
} }
} // namespace HistoryView } // namespace HistoryView

View file

@ -435,6 +435,7 @@ bool UnwrappedMedia::needInfoDisplay() const {
return (_parent->data()->id < 0) return (_parent->data()->id < 0)
|| (_parent->isUnderCursor()) || (_parent->isUnderCursor())
|| (_parent->displayRightAction()) || (_parent->displayRightAction())
|| (_parent->isLastAndSelfMessage())
|| (_parent->hasOutLayout() || (_parent->hasOutLayout()
&& !Adaptive::ChatWide() && !Adaptive::ChatWide()
&& _content->alwaysShowOutTimestamp()); && _content->alwaysShowOutTimestamp());

View file

@ -523,7 +523,9 @@ bool Photo::dataLoaded() const {
} }
bool Photo::needInfoDisplay() const { bool Photo::needInfoDisplay() const {
return (_parent->data()->id < 0 || _parent->isUnderCursor()); return (_parent->data()->id < 0
|| _parent->isUnderCursor()
|| _parent->isLastAndSelfMessage());
} }
void Photo::validateGroupedCache( void Photo::validateGroupedCache(

View file

@ -82,7 +82,7 @@ bool PlaybackErrorHappened() {
void EnumeratePlaybackDevices() { void EnumeratePlaybackDevices() {
auto deviceNames = QStringList(); auto deviceNames = QStringList();
auto devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER); auto devices = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
Assert(devices != nullptr); Assert(devices != nullptr);
while (*devices != 0) { while (*devices != 0) {
auto deviceName8Bit = QByteArray(devices); auto deviceName8Bit = QByteArray(devices);
@ -92,7 +92,7 @@ void EnumeratePlaybackDevices() {
} }
LOG(("Audio Playback Devices: %1").arg(deviceNames.join(';'))); LOG(("Audio Playback Devices: %1").arg(deviceNames.join(';')));
if (auto device = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER)) { if (auto device = alcGetString(nullptr, ALC_DEFAULT_ALL_DEVICES_SPECIFIER)) {
LOG(("Audio Playback Default Device: %1").arg(QString::fromLocal8Bit(device))); LOG(("Audio Playback Default Device: %1").arg(QString::fromLocal8Bit(device)));
} else { } else {
LOG(("Audio Playback Default Device: (null)")); LOG(("Audio Playback Default Device: (null)"));

View file

@ -62,16 +62,12 @@ Instance::Instance() : _inner(new Inner(&_thread)) {
void Instance::check() { void Instance::check() {
_available = false; _available = false;
if (auto defaultDevice = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) { if (auto device = alcCaptureOpenDevice(nullptr, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5)) {
if (auto device = alcCaptureOpenDevice(defaultDevice, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5)) { auto error = ErrorHappened(device);
auto error = ErrorHappened(device); alcCaptureCloseDevice(device);
alcCaptureCloseDevice(device); _available = !error;
_available = !error;
} else {
LOG(("Audio Error: Could not open capture device!"));
}
} else { } else {
LOG(("Audio Error: No capture device found!")); LOG(("Audio Error: Could not open capture device!"));
} }
} }
@ -177,9 +173,7 @@ void Instance::Inner::onInit() {
void Instance::Inner::onStart() { void Instance::Inner::onStart() {
// Start OpenAL Capture // Start OpenAL Capture
const ALCchar *dName = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); d->device = alcCaptureOpenDevice(nullptr, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5);
DEBUG_LOG(("Audio Info: Capture device name '%1'").arg(dName));
d->device = alcCaptureOpenDevice(dName, kCaptureFrequency, AL_FORMAT_MONO16, kCaptureFrequency / 5);
if (!d->device) { if (!d->device) {
LOG(("Audio Error: capture device not present!")); LOG(("Audio Error: capture device not present!"));
emit error(); emit error();

View file

@ -7,10 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/details/mtproto_dump_to_text.h" #include "mtproto/details/mtproto_dump_to_text.h"
#include "base/zlib_help.h"
#include "scheme-dump_to_text.h" #include "scheme-dump_to_text.h"
#include "scheme.h" #include "scheme.h"
#include "zlib.h"
namespace MTP::details { namespace MTP::details {
bool DumpToTextCore(DumpToTextBuffer &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons) { bool DumpToTextCore(DumpToTextBuffer &to, const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons, uint32 level, mtpPrime vcons) {

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include "statusnotifieritem.h" #include "statusnotifieritem.h"
#include <QtCore/QTemporaryFile> #include <QtCore/QTemporaryFile>
#include <QtDBus/QDBusObjectPath>
#include <dbusmenuexporter.h>
#endif #endif
namespace Platform { namespace Platform {
@ -38,13 +40,41 @@ public:
public slots: public slots:
void psShowTrayMenu(); void psShowTrayMenu();
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
void onSNIOwnerChanged(
const QString &service,
const QString &oldOwner,
const QString &newOwner);
void psLinuxUndo();
void psLinuxRedo();
void psLinuxCut();
void psLinuxCopy();
void psLinuxPaste();
void psLinuxDelete();
void psLinuxSelectAll();
void psLinuxBold();
void psLinuxItalic();
void psLinuxUnderline();
void psLinuxStrikeOut();
void psLinuxMonospace();
void psLinuxClearFormat();
void onVisibleChanged(bool visible);
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
protected: protected:
void initHook() override;
void unreadCounterChangedHook() override; void unreadCounterChangedHook() override;
void updateGlobalMenuHook() override;
void initTrayMenuHook() override; void initTrayMenuHook() override;
bool hasTrayIcon() const override; bool hasTrayIcon() const override;
void workmodeUpdated(DBIWorkMode mode) override; void workmodeUpdated(DBIWorkMode mode) override;
void createGlobalMenu() override;
QSystemTrayIcon *trayIcon = nullptr; QSystemTrayIcon *trayIcon = nullptr;
QMenu *trayIconMenu = nullptr; QMenu *trayIconMenu = nullptr;
@ -68,9 +98,32 @@ private:
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
StatusNotifierItem *_sniTrayIcon = nullptr; StatusNotifierItem *_sniTrayIcon = nullptr;
std::unique_ptr<QTemporaryFile> _trayIconFile = nullptr; std::unique_ptr<QTemporaryFile> _trayIconFile = nullptr;
std::unique_ptr<QTemporaryFile> _trayToolTipIconFile = nullptr;
void setSNITrayIcon(const QIcon &icon); DBusMenuExporter *_mainMenuExporter = nullptr;
QDBusObjectPath _mainMenuPath;
QMenu *psMainMenu = nullptr;
QAction *psLogout = nullptr;
QAction *psUndo = nullptr;
QAction *psRedo = nullptr;
QAction *psCut = nullptr;
QAction *psCopy = nullptr;
QAction *psPaste = nullptr;
QAction *psDelete = nullptr;
QAction *psSelectAll = nullptr;
QAction *psContacts = nullptr;
QAction *psAddContact = nullptr;
QAction *psNewGroup = nullptr;
QAction *psNewChannel = nullptr;
QAction *psBold = nullptr;
QAction *psItalic = nullptr;
QAction *psUnderline = nullptr;
QAction *psStrikeOut = nullptr;
QAction *psMonospace = nullptr;
QAction *psClearFormat = nullptr;
void setSNITrayIcon(int counter, bool muted, bool firstShow = false);
void attachToSNITrayIcon(); void attachToSNITrayIcon();
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION

View file

@ -7,18 +7,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "platform/linux/notifications_manager_linux.h" #include "platform/linux/notifications_manager_linux.h"
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include "platform/linux/specific_linux.h" #include "platform/linux/specific_linux.h"
#include "history/history.h" #include "history/history.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "facades.h" #include "facades.h"
#include <QtWidgets/QApplication>
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <QtCore/QVersionNumber> #include <QtCore/QVersionNumber>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply> #include <QtDBus/QDBusReply>
#include <QtDBus/QDBusError>
#include <QtDBus/QDBusMetaType> #include <QtDBus/QDBusMetaType>
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <QtWidgets/QApplication>
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
@ -38,50 +40,101 @@ namespace {
constexpr auto kService = "org.freedesktop.Notifications"_cs; constexpr auto kService = "org.freedesktop.Notifications"_cs;
constexpr auto kObjectPath = "/org/freedesktop/Notifications"_cs; constexpr auto kObjectPath = "/org/freedesktop/Notifications"_cs;
constexpr auto kInterface = kService; constexpr auto kInterface = kService;
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
std::vector<QString> GetServerInformation( bool InhibitedNotSupported = false;
const std::shared_ptr<QDBusInterface> &notificationInterface) {
std::vector<QString> ComputeServerInformation() {
std::vector<QString> serverInformation; std::vector<QString> serverInformation;
const auto serverInformationReply = notificationInterface
->call(qsl("GetServerInformation"));
if (serverInformationReply.type() == QDBusMessage::ReplyMessage) { const auto message = QDBusMessage::createMethodCall(
for (const auto &arg : serverInformationReply.arguments()) { kService.utf16(),
if (static_cast<QMetaType::Type>(arg.type()) kObjectPath.utf16(),
== QMetaType::QString) { kInterface.utf16(),
serverInformation.push_back(arg.toString()); qsl("GetServerInformation"));
} else {
LOG(("Native notification error: " const auto reply = QDBusConnection::sessionBus().call(message);
"all elements in GetServerInformation "
"should be strings")); if (reply.type() == QDBusMessage::ReplyMessage) {
} ranges::transform(
} reply.arguments(),
} else if (serverInformationReply.type() == QDBusMessage::ErrorMessage) { ranges::back_inserter(serverInformation),
LOG(("Native notification error: %1") &QVariant::toString
.arg(serverInformationReply.errorMessage())); );
} else if (reply.type() == QDBusMessage::ErrorMessage) {
LOG(("Native notification error: %1").arg(reply.errorMessage()));
} else { } else {
LOG(("Native notification error: " LOG(("Native notification error: "
"error while getting information about notification daemon")); "invalid reply from GetServerInformation"));
} }
return serverInformation; return serverInformation;
} }
QStringList GetCapabilities( std::vector<QString> GetServerInformation() {
const std::shared_ptr<QDBusInterface> &notificationInterface) { static const auto ServerInformation = ComputeServerInformation();
const QDBusReply<QStringList> capabilitiesReply = notificationInterface return ServerInformation;
->call(qsl("GetCapabilities")); }
if (capabilitiesReply.isValid()) { QStringList ComputeCapabilities() {
return capabilitiesReply.value(); const auto message = QDBusMessage::createMethodCall(
kService.utf16(),
kObjectPath.utf16(),
kInterface.utf16(),
qsl("GetCapabilities"));
const QDBusReply<QStringList> reply = QDBusConnection::sessionBus().call(
message);
if (reply.isValid()) {
return reply.value();
} else { } else {
LOG(("Native notification error: %1") LOG(("Native notification error: %1").arg(reply.error().message()));
.arg(capabilitiesReply.error().message()));
} }
return {}; return {};
} }
QStringList GetCapabilities() {
static const auto Capabilities = ComputeCapabilities();
return Capabilities;
}
bool Inhibited() {
auto message = QDBusMessage::createMethodCall(
kService.utf16(),
kObjectPath.utf16(),
kPropertiesInterface.utf16(),
qsl("Get"));
message.setArguments({
qsl("org.freedesktop.Notifications"),
qsl("Inhibited")
});
const QDBusReply<QVariant> reply = QDBusConnection::sessionBus().call(
message);
constexpr auto notSupportedErrors = {
QDBusError::ServiceUnknown,
QDBusError::InvalidArgs,
};
if (reply.isValid()) {
return reply.value().toBool();
} else if (ranges::contains(notSupportedErrors, reply.error().type())) {
InhibitedNotSupported = true;
} else {
if (reply.error().type() == QDBusError::AccessDenied) {
InhibitedNotSupported = true;
}
LOG(("Native notification error: %1").arg(reply.error().message()));
}
return false;
}
QVersionNumber ParseSpecificationVersion( QVersionNumber ParseSpecificationVersion(
const std::vector<QString> &serverInformation) { const std::vector<QString> &serverInformation) {
if (serverInformation.size() >= 4) { if (serverInformation.size() >= 4) {
@ -94,10 +147,31 @@ QVersionNumber ParseSpecificationVersion(
return QVersionNumber(); return QVersionNumber();
} }
QString GetImageKey(const QVersionNumber &specificationVersion) {
if (!specificationVersion.isNull()) {
const auto majorVersion = specificationVersion.majorVersion();
const auto minorVersion = specificationVersion.minorVersion();
if ((majorVersion == 1 && minorVersion >= 2) || majorVersion > 1) {
return qsl("image-data");
} else if (majorVersion == 1 && minorVersion == 1) {
return qsl("image_data");
} else if ((majorVersion == 1 && minorVersion < 1)
|| majorVersion < 1) {
return qsl("icon_data");
} else {
LOG(("Native notification error: unknown specification version"));
}
} else {
LOG(("Native notification error: specification version is null"));
}
return QString();
}
} }
NotificationData::NotificationData( NotificationData::NotificationData(
const std::shared_ptr<QDBusInterface> &notificationInterface,
const base::weak_ptr<Manager> &manager, const base::weak_ptr<Manager> &manager,
const QString &title, const QString &title,
const QString &subtitle, const QString &subtitle,
@ -105,12 +179,14 @@ NotificationData::NotificationData(
PeerId peerId, PeerId peerId,
MsgId msgId, MsgId msgId,
bool hideReplyButton) bool hideReplyButton)
: _notificationInterface(notificationInterface) : _dbusConnection(QDBusConnection::sessionBus())
, _manager(manager) , _manager(manager)
, _title(title) , _title(title)
, _imageKey(GetImageKey(ParseSpecificationVersion(
GetServerInformation())))
, _peerId(peerId) , _peerId(peerId)
, _msgId(msgId) { , _msgId(msgId) {
const auto capabilities = GetCapabilities(_notificationInterface); const auto capabilities = GetCapabilities();
if (capabilities.contains(qsl("body-markup"))) { if (capabilities.contains(qsl("body-markup"))) {
_body = subtitle.isEmpty() _body = subtitle.isEmpty()
@ -127,19 +203,16 @@ NotificationData::NotificationData(
if (capabilities.contains(qsl("actions"))) { if (capabilities.contains(qsl("actions"))) {
_actions << qsl("default") << QString(); _actions << qsl("default") << QString();
_notificationInterface->connection().connect( _actions
kService.utf16(), << qsl("mail-mark-read")
kObjectPath.utf16(), << tr::lng_context_mark_read(tr::now);
kInterface.utf16(),
qsl("ActionInvoked"),
this,
SLOT(notificationClicked(uint,QString)));
if (capabilities.contains(qsl("inline-reply")) && !hideReplyButton) { if (capabilities.contains(qsl("inline-reply")) && !hideReplyButton) {
_actions << qsl("inline-reply") _actions
<< qsl("inline-reply")
<< tr::lng_notification_reply(tr::now); << tr::lng_notification_reply(tr::now);
_notificationInterface->connection().connect( _dbusConnection.connect(
kService.utf16(), kService.utf16(),
kObjectPath.utf16(), kObjectPath.utf16(),
kInterface.utf16(), kInterface.utf16(),
@ -148,9 +221,18 @@ NotificationData::NotificationData(
SLOT(notificationReplied(uint,QString))); SLOT(notificationReplied(uint,QString)));
} else { } else {
// icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html // icon name according to https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
_actions << qsl("mail-reply-sender") _actions
<< qsl("mail-reply-sender")
<< tr::lng_notification_reply(tr::now); << tr::lng_notification_reply(tr::now);
} }
_dbusConnection.connect(
kService.utf16(),
kObjectPath.utf16(),
kInterface.utf16(),
qsl("ActionInvoked"),
this,
SLOT(actionInvoked(uint,QString)));
} }
if (capabilities.contains(qsl("action-icons"))) { if (capabilities.contains(qsl("action-icons"))) {
@ -172,10 +254,9 @@ NotificationData::NotificationData(
} }
_hints["category"] = qsl("im.received"); _hints["category"] = qsl("im.received");
_hints["desktop-entry"] = GetLauncherBasename(); _hints["desktop-entry"] = GetLauncherBasename();
_notificationInterface->connection().connect( _dbusConnection.connect(
kService.utf16(), kService.utf16(),
kObjectPath.utf16(), kObjectPath.utf16(),
kInterface.utf16(), kInterface.utf16(),
@ -184,65 +265,56 @@ NotificationData::NotificationData(
SLOT(notificationClosed(uint))); SLOT(notificationClosed(uint)));
} }
bool NotificationData::show(bool hideNameAndPhoto) { bool NotificationData::show() {
const QDBusReply<uint> notifyReply = _notificationInterface->call( const auto iconName = _imageKey.isEmpty() || !_hints.contains(_imageKey)
qsl("Notify"), ? GetIconName()
: QString();
auto message = QDBusMessage::createMethodCall(
kService.utf16(),
kObjectPath.utf16(),
kInterface.utf16(),
qsl("Notify"));
message.setArguments({
AppName.utf16(), AppName.utf16(),
uint(0), uint(0),
hideNameAndPhoto iconName,
? qsl("telegram")
: QString(),
_title, _title,
_body, _body,
_actions, _actions,
_hints, _hints,
-1); -1
});
if (notifyReply.isValid()) { const QDBusReply<uint> reply = _dbusConnection.call(
_notificationId = notifyReply.value(); message);
if (reply.isValid()) {
_notificationId = reply.value();
} else { } else {
LOG(("Native notification error: %1") LOG(("Native notification error: %1").arg(reply.error().message()));
.arg(notifyReply.error().message()));
} }
return notifyReply.isValid(); return reply.isValid();
} }
bool NotificationData::close() { void NotificationData::close() {
const QDBusReply<void> closeReply = _notificationInterface auto message = QDBusMessage::createMethodCall(
->call(qsl("CloseNotification"), _notificationId); kService.utf16(),
kObjectPath.utf16(),
kInterface.utf16(),
qsl("CloseNotification"));
if (!closeReply.isValid()) { message.setArguments({
LOG(("Native notification error: %1") _notificationId
.arg(closeReply.error().message())); });
}
return closeReply.isValid(); _dbusConnection.send(message);
} }
void NotificationData::setImage(const QString &imagePath) { void NotificationData::setImage(const QString &imagePath) {
const auto specificationVersion = ParseSpecificationVersion( if (_imageKey.isEmpty()) {
GetServerInformation(_notificationInterface));
QString imageKey;
if (!specificationVersion.isNull()) {
const auto majorVersion = specificationVersion.majorVersion();
const auto minorVersion = specificationVersion.minorVersion();
if ((majorVersion == 1 && minorVersion >= 2) || majorVersion > 1) {
imageKey = qsl("image-data");
} else if (majorVersion == 1 && minorVersion == 1) {
imageKey = qsl("image_data");
} else if ((majorVersion == 1 && minorVersion < 1)
|| majorVersion < 1) {
imageKey = qsl("icon_data");
} else {
LOG(("Native notification error: unknown specification version"));
return;
}
} else {
LOG(("Native notification error: specification version is null"));
return; return;
} }
@ -253,20 +325,21 @@ void NotificationData::setImage(const QString &imagePath) {
(const char*)image.constBits(), (const char*)image.constBits(),
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
image.byteCount()); image.byteCount());
#else #else // Qt < 5.10.0
image.sizeInBytes()); image.sizeInBytes());
#endif #endif // Qt >= 5.10.0
ImageData imageData; const auto imageData = ImageData{
imageData.width = image.width(); image.width(),
imageData.height = image.height(); image.height(),
imageData.rowStride = image.bytesPerLine(); image.bytesPerLine(),
imageData.hasAlpha = true; true,
imageData.bitsPerSample = 8; 8,
imageData.channels = 4; 4,
imageData.data = imageBytes; imageBytes
};
_hints[imageKey] = QVariant::fromValue(imageData); _hints[_imageKey] = QVariant::fromValue(imageData);
} }
void NotificationData::notificationClosed(uint id) { void NotificationData::notificationClosed(uint id) {
@ -278,19 +351,23 @@ void NotificationData::notificationClosed(uint id) {
} }
} }
void NotificationData::notificationClicked(uint id, const QString &actionId) { void NotificationData::actionInvoked(uint id, const QString &actionName) {
if (id != _notificationId) { if (id != _notificationId) {
return; return;
} }
if (actionId != qsl("default") && actionId != qsl("mail-reply-sender")) { if (actionName == qsl("default")
return; || actionName == qsl("mail-reply-sender")) {
const auto manager = _manager;
crl::on_main(manager, [=] {
manager->notificationActivated(_peerId, _msgId);
});
} else if (actionName == qsl("mail-mark-read")) {
const auto manager = _manager;
crl::on_main(manager, [=] {
manager->notificationReplied(_peerId, _msgId, {});
});
} }
const auto manager = _manager;
crl::on_main(manager, [=] {
manager->notificationActivated(_peerId, _msgId);
});
} }
void NotificationData::notificationReplied(uint id, const QString &text) { void NotificationData::notificationReplied(uint id, const QString &text) {
@ -306,7 +383,8 @@ QDBusArgument &operator<<(
QDBusArgument &argument, QDBusArgument &argument,
const NotificationData::ImageData &imageData) { const NotificationData::ImageData &imageData) {
argument.beginStructure(); argument.beginStructure();
argument << imageData.width argument
<< imageData.width
<< imageData.height << imageData.height
<< imageData.rowStride << imageData.rowStride
<< imageData.hasAlpha << imageData.hasAlpha
@ -321,7 +399,8 @@ const QDBusArgument &operator>>(
const QDBusArgument &argument, const QDBusArgument &argument,
NotificationData::ImageData &imageData) { NotificationData::ImageData &imageData) {
argument.beginStructure(); argument.beginStructure();
argument >> imageData.width argument
>> imageData.width
>> imageData.height >> imageData.height
>> imageData.rowStride >> imageData.rowStride
>> imageData.hasAlpha >> imageData.hasAlpha
@ -331,20 +410,39 @@ const QDBusArgument &operator>>(
argument.endStructure(); argument.endStructure();
return argument; return argument;
} }
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
bool SkipAudio() {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
if (Supported()
&& GetCapabilities().contains(qsl("inhibitions"))
&& !InhibitedNotSupported) {
return Inhibited();
}
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return false;
}
bool SkipToast() {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
if (Supported()
&& GetCapabilities().contains(qsl("inhibitions"))
&& !InhibitedNotSupported) {
return Inhibited();
}
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return false;
}
bool Supported() { bool Supported() {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
static const auto Available = QDBusInterface( static const auto Available = !GetServerInformation().empty();
kService.utf16(),
kObjectPath.utf16(),
kInterface.utf16()
).isValid();
return Available; return Available;
#else #else // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return false; return false;
#endif #endif // TDESKTOP_DISABLE_DBUS_INTEGRATION
} }
std::unique_ptr<Window::Notifications::Manager> Create( std::unique_ptr<Window::Notifications::Manager> Create(
@ -353,34 +451,36 @@ std::unique_ptr<Window::Notifications::Manager> Create(
if (Global::NativeNotifications() && Supported()) { if (Global::NativeNotifications() && Supported()) {
return std::make_unique<Manager>(system); return std::make_unique<Manager>(system);
} }
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return nullptr; return nullptr;
} }
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
Manager::Private::Private(Manager *manager, Type type) Manager::Private::Private(not_null<Manager*> manager, Type type)
: _cachedUserpics(type) : _cachedUserpics(type)
, _manager(manager) , _manager(manager) {
, _notificationInterface(
std::make_shared<QDBusInterface>(
kService.utf16(),
kObjectPath.utf16(),
kInterface.utf16())) {
qDBusRegisterMetaType<NotificationData::ImageData>(); qDBusRegisterMetaType<NotificationData::ImageData>();
const auto specificationVersion = ParseSpecificationVersion( const auto serverInformation = GetServerInformation();
GetServerInformation(_notificationInterface)); const auto capabilities = GetCapabilities();
const auto capabilities = GetCapabilities(_notificationInterface); if (!serverInformation.empty()) {
LOG(("Notification daemon product name: %1")
.arg(serverInformation[0]));
LOG(("Notification daemon vendor name: %1")
.arg(serverInformation[1]));
LOG(("Notification daemon version: %1")
.arg(serverInformation[2]));
if (!specificationVersion.isNull()) {
LOG(("Notification daemon specification version: %1") LOG(("Notification daemon specification version: %1")
.arg(specificationVersion.toString())); .arg(serverInformation[3]));
} }
if (!capabilities.empty()) { if (!capabilities.isEmpty()) {
const auto capabilitiesString = capabilities.join(", "); LOG(("Notification daemon capabilities: %1")
LOG(("Notification daemon capabilities: %1").arg(capabilitiesString)); .arg(capabilities.join(", ")));
} }
} }
@ -393,7 +493,6 @@ void Manager::Private::showNotification(
bool hideNameAndPhoto, bool hideNameAndPhoto,
bool hideReplyButton) { bool hideReplyButton) {
auto notification = std::make_shared<NotificationData>( auto notification = std::make_shared<NotificationData>(
_notificationInterface,
_manager, _manager,
title, title,
subtitle, subtitle,
@ -421,7 +520,7 @@ void Manager::Private::showNotification(
i = _notifications.insert(peer->id, QMap<MsgId, Notification>()); i = _notifications.insert(peer->id, QMap<MsgId, Notification>());
} }
_notifications[peer->id].insert(msgId, notification); _notifications[peer->id].insert(msgId, notification);
if (!notification->show(hideNameAndPhoto)) { if (!notification->show()) {
i = _notifications.find(peer->id); i = _notifications.find(peer->id);
if (i != _notifications.cend()) { if (i != _notifications.cend()) {
i->remove(msgId); i->remove(msgId);
@ -465,7 +564,7 @@ Manager::Private::~Private() {
clearAll(); clearAll();
} }
Manager::Manager(Window::Notifications::System *system) Manager::Manager(not_null<Window::Notifications::System*> system)
: NativeManager(system) : NativeManager(system)
, _private(std::make_unique<Private>(this, Private::Type::Rounded)) { , _private(std::make_unique<Private>(this, Private::Type::Rounded)) {
} }
@ -501,7 +600,7 @@ void Manager::doClearAllFast() {
void Manager::doClearFromHistory(not_null<History*> history) { void Manager::doClearFromHistory(not_null<History*> history) {
_private->clearFromHistory(history); _private->clearFromHistory(history);
} }
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
} // namespace Notifications } // namespace Notifications
} // namespace Platform } // namespace Platform

View file

@ -12,28 +12,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <QtDBus/QDBusInterface> #include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusArgument> #include <QtDBus/QDBusArgument>
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
inline bool SkipAudio() {
return false;
}
inline bool SkipToast() {
return false;
}
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
class NotificationData : public QObject { class NotificationData : public QObject {
Q_OBJECT Q_OBJECT
public: public:
NotificationData( NotificationData(
const std::shared_ptr<QDBusInterface> &notificationInterface,
const base::weak_ptr<Manager> &manager, const base::weak_ptr<Manager> &manager,
const QString &title, const QString &title,
const QString &subtitle, const QString &subtitle,
@ -47,8 +38,8 @@ public:
NotificationData(NotificationData &&other) = delete; NotificationData(NotificationData &&other) = delete;
NotificationData &operator=(NotificationData &&other) = delete; NotificationData &operator=(NotificationData &&other) = delete;
bool show(bool hideNameAndPhoto); bool show();
bool close(); void close();
void setImage(const QString &imagePath); void setImage(const QString &imagePath);
struct ImageData { struct ImageData {
@ -59,13 +50,14 @@ public:
}; };
private: private:
std::shared_ptr<QDBusInterface> _notificationInterface; QDBusConnection _dbusConnection;
base::weak_ptr<Manager> _manager; base::weak_ptr<Manager> _manager;
QString _title; QString _title;
QString _body; QString _body;
QStringList _actions; QStringList _actions;
QVariantMap _hints; QVariantMap _hints;
QString _imageKey;
uint _notificationId; uint _notificationId;
PeerId _peerId; PeerId _peerId;
@ -73,7 +65,7 @@ private:
private slots: private slots:
void notificationClosed(uint id); void notificationClosed(uint id);
void notificationClicked(uint id, const QString &actionId); void actionInvoked(uint id, const QString &actionName);
void notificationReplied(uint id, const QString &text); void notificationReplied(uint id, const QString &text);
}; };
@ -91,7 +83,7 @@ class Manager
: public Window::Notifications::NativeManager : public Window::Notifications::NativeManager
, public base::has_weak_ptr { , public base::has_weak_ptr {
public: public:
Manager(Window::Notifications::System *system); Manager(not_null<Window::Notifications::System*> system);
void clearNotification(PeerId peerId, MsgId msgId); void clearNotification(PeerId peerId, MsgId msgId);
~Manager(); ~Manager();
@ -116,7 +108,7 @@ private:
class Manager::Private { class Manager::Private {
public: public:
using Type = Window::Notifications::CachedUserpics::Type; using Type = Window::Notifications::CachedUserpics::Type;
explicit Private(Manager *manager, Type type); explicit Private(not_null<Manager*> manager, Type type);
void showNotification( void showNotification(
not_null<PeerData*> peer, not_null<PeerData*> peer,
@ -138,13 +130,12 @@ private:
Window::Notifications::CachedUserpics _cachedUserpics; Window::Notifications::CachedUserpics _cachedUserpics;
base::weak_ptr<Manager> _manager; base::weak_ptr<Manager> _manager;
std::shared_ptr<QDBusInterface> _notificationInterface;
}; };
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
} // namespace Notifications } // namespace Notifications
} // namespace Platform } // namespace Platform
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
Q_DECLARE_METATYPE(Platform::Notifications::NotificationData::ImageData) Q_DECLARE_METATYPE(Platform::Notifications::NotificationData::ImageData)
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION

View file

@ -26,7 +26,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <QtDBus/QDBusInterface> #include <QtDBus/QDBusInterface>
#endif #include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusReply>
#include <QtDBus/QDBusError>
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
@ -44,9 +48,10 @@ namespace {
constexpr auto kDesktopFile = ":/misc/kotatogramdesktop.desktop"_cs; constexpr auto kDesktopFile = ":/misc/kotatogramdesktop.desktop"_cs;
constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs; constexpr auto kSnapLauncherDir = "/var/lib/snapd/desktop/applications/"_cs;
constexpr auto kIconName = "telegram"_cs;
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
void SandboxAutostart(bool autostart) { void SandboxAutostart(bool autostart, bool silent = false) {
QVariantMap options; QVariantMap options;
options["reason"] = tr::lng_settings_auto_start(tr::now); options["reason"] = tr::lng_settings_auto_start(tr::now);
options["autostart"] = autostart; options["autostart"] = autostart;
@ -56,20 +61,29 @@ void SandboxAutostart(bool autostart) {
}); });
options["dbus-activatable"] = false; options["dbus-activatable"] = false;
const auto requestBackgroundReply = QDBusInterface( auto message = QDBusMessage::createMethodCall(
qsl("org.freedesktop.portal.Desktop"), qsl("org.freedesktop.portal.Desktop"),
qsl("/org/freedesktop/portal/desktop"), qsl("/org/freedesktop/portal/desktop"),
qsl("org.freedesktop.portal.Background") qsl("org.freedesktop.portal.Background"),
).call(qsl("RequestBackground"), QString(), options); qsl("RequestBackground"));
if (requestBackgroundReply.type() == QDBusMessage::ErrorMessage) { message.setArguments({
LOG(("Flatpak autostart error: %1") QString(),
.arg(requestBackgroundReply.errorMessage())); options
} else if (requestBackgroundReply.type() != QDBusMessage::ReplyMessage) { });
LOG(("Flatpak autostart error: invalid reply"));
if (silent) {
QDBusConnection::sessionBus().send(message);
} else {
const QDBusReply<void> reply = QDBusConnection::sessionBus().call(
message);
if (!reply.isValid()) {
LOG(("Flatpak autostart error: %1").arg(reply.error().message()));
}
} }
} }
#endif #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
bool RunShellCommand(const QByteArray &command) { bool RunShellCommand(const QByteArray &command) {
auto result = system(command.constData()); auto result = system(command.constData());
@ -120,7 +134,10 @@ void FallbackFontConfig() {
#endif // TDESKTOP_USE_FONT_CONFIG_FALLBACK #endif // TDESKTOP_USE_FONT_CONFIG_FALLBACK
} }
bool GenerateDesktopFile(const QString &targetPath, const QString &args) { bool GenerateDesktopFile(
const QString &targetPath,
const QString &args,
bool silent = false) {
DEBUG_LOG(("App Info: placing .desktop file to %1").arg(targetPath)); DEBUG_LOG(("App Info: placing .desktop file to %1").arg(targetPath));
if (!QDir(targetPath).exists()) QDir().mkpath(targetPath); if (!QDir(targetPath).exists()) QDir().mkpath(targetPath);
@ -142,7 +159,9 @@ bool GenerateDesktopFile(const QString &targetPath, const QString &args) {
fileText = s.readAll(); fileText = s.readAll();
source.close(); source.close();
} else { } else {
LOG(("App Error: Could not open '%1' for read").arg(sourceFile)); if (!silent) {
LOG(("App Error: Could not open '%1' for read").arg(sourceFile));
}
return false; return false;
} }
@ -150,23 +169,28 @@ bool GenerateDesktopFile(const QString &targetPath, const QString &args) {
if (target.open(QIODevice::WriteOnly)) { if (target.open(QIODevice::WriteOnly)) {
#ifdef DESKTOP_APP_USE_PACKAGED #ifdef DESKTOP_APP_USE_PACKAGED
fileText = fileText.replace( fileText = fileText.replace(
QRegularExpression(qsl("^Exec=(.*) -- %u$"), QRegularExpression(
qsl("^Exec=(.*) -- %u$"),
QRegularExpression::MultilineOption), QRegularExpression::MultilineOption),
qsl("Exec=\\1") qsl("Exec=\\1")
+ (args.isEmpty() ? QString() : ' ' + args)); + (args.isEmpty() ? QString() : ' ' + args));
#else #else // DESKTOP_APP_USE_PACKAGED
fileText = fileText.replace( fileText = fileText.replace(
QRegularExpression(qsl("^TryExec=.*$"), QRegularExpression(
qsl("^TryExec=.*$"),
QRegularExpression::MultilineOption), QRegularExpression::MultilineOption),
qsl("TryExec=") qsl("TryExec=")
+ EscapeShell(QFile::encodeName(cExeDir() + cExeName()))); + QFile::encodeName(cExeDir() + cExeName())
.replace('\\', qsl("\\\\")));
fileText = fileText.replace( fileText = fileText.replace(
QRegularExpression(qsl("^Exec=.*$"), QRegularExpression(
qsl("^Exec=.*$"),
QRegularExpression::MultilineOption), QRegularExpression::MultilineOption),
qsl("Exec=") qsl("Exec=")
+ EscapeShell(QFile::encodeName(cExeDir() + cExeName())) + EscapeShell(QFile::encodeName(cExeDir() + cExeName()))
.replace('\\', qsl("\\\\"))
+ (args.isEmpty() ? QString() : ' ' + args)); + (args.isEmpty() ? QString() : ' ' + args));
#endif #endif // !DESKTOP_APP_USE_PACKAGED
target.write(fileText.toUtf8()); target.write(fileText.toUtf8());
target.close(); target.close();
@ -175,7 +199,9 @@ bool GenerateDesktopFile(const QString &targetPath, const QString &args) {
return true; return true;
} else { } else {
LOG(("App Error: Could not open '%1' for write").arg(targetFile)); if (!silent) {
LOG(("App Error: Could not open '%1' for write").arg(targetFile));
}
return false; return false;
} }
} }
@ -189,9 +215,7 @@ void SetApplicationIcon(const QIcon &icon) {
} }
bool InSandbox() { bool InSandbox() {
static const auto Sandbox = QFileInfo::exists( static const auto Sandbox = QFileInfo::exists(qsl("/.flatpak-info"));
QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)
+ qsl("/flatpak-info"));
return Sandbox; return Sandbox;
} }
@ -208,12 +232,18 @@ bool IsXDGDesktopPortalPresent() {
"org.freedesktop.portal.Desktop", "org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop").isValid(); "/org/freedesktop/portal/desktop").isValid();
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION #endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return XDGDesktopPortalPresent; return XDGDesktopPortalPresent;
} }
bool UseXDGDesktopPortal() { bool UseXDGDesktopPortal() {
static const auto UsePortal = qEnvironmentVariableIsSet("TDESKTOP_USE_PORTAL") static const auto UsePortal = [&] {
&& IsXDGDesktopPortalPresent(); const auto envVar = qEnvironmentVariableIsSet("TDESKTOP_USE_PORTAL");
const auto portalPresent = IsXDGDesktopPortalPresent();
return envVar && portalPresent;
}();
return UsePortal; return UsePortal;
} }
@ -309,7 +339,6 @@ QString GetLauncherBasename() {
return possibleBasenames[0]; return possibleBasenames[0];
}(); }();
LOG(("Launcher filename is %1.desktop").arg(LauncherBasename));
return LauncherBasename; return LauncherBasename;
} }
@ -319,6 +348,55 @@ QString GetLauncherFilename() {
return LauncherFilename; return LauncherFilename;
} }
QString GetIconName() {
static const auto IconName = InSandbox()
? GetLauncherBasename()
: kIconName.utf16();
return IconName;
}
std::optional<crl::time> LastUserInputTime() {
// TODO: a fallback pure-X11 implementation, this one covers only major DEs on X11 and Wayland
// an example: https://stackoverflow.com/q/9049087
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
static auto NotSupported = false;
if (NotSupported) {
return std::nullopt;
}
static const auto message = QDBusMessage::createMethodCall(
qsl("org.freedesktop.ScreenSaver"),
qsl("/org/freedesktop/ScreenSaver"),
qsl("org.freedesktop.ScreenSaver"),
qsl("GetSessionIdleTime"));
const QDBusReply<uint> reply = QDBusConnection::sessionBus().call(
message);
constexpr auto notSupportedErrors = {
QDBusError::ServiceUnknown,
QDBusError::NotSupported,
};
if (reply.isValid()) {
return (crl::now() - static_cast<crl::time>(reply.value()));
} else if (ranges::contains(notSupportedErrors, reply.error().type())) {
NotSupported = true;
} else {
if (reply.error().type() == QDBusError::AccessDenied) {
NotSupported = true;
}
LOG(("Unable to get last user input time: %1: %2")
.arg(reply.error().name())
.arg(reply.error().message()));
}
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
return std::nullopt;
}
} // namespace Platform } // namespace Platform
namespace { namespace {
@ -395,15 +473,18 @@ QString getHomeDir() {
QString psAppDataPath() { QString psAppDataPath() {
// We should not use ~/.TelegramDesktop, since it's a fork. // We should not use ~/.TelegramDesktop, since it's a fork.
/*
// auto home = getHomeDir(); auto home = getHomeDir();
// if (!home.isEmpty()) { if (!home.isEmpty()) {
// auto oldPath = home + qsl(".TelegramDesktop/"); auto oldPath = home + qsl(".TelegramDesktop/");
// auto oldSettingsBase = oldPath + qsl("tdata/settings"); auto oldSettingsBase = oldPath + qsl("tdata/settings");
// if (QFile(oldSettingsBase + '0').exists() || QFile(oldSettingsBase + '1').exists()) { if (QFile(oldSettingsBase + '0').exists()
// return oldPath; || QFile(oldSettingsBase + '1').exists()
// } || QFile(oldSettingsBase + 's').exists()) {
// } return oldPath;
}
}
*/
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/'; return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + '/';
} }
@ -432,8 +513,12 @@ int psFixPrevious() {
namespace Platform { namespace Platform {
void start() { void start() {
LOG(("Launcher filename: %1").arg(GetLauncherFilename()));
FallbackFontConfig(); FallbackFontConfig();
qputenv("PULSE_PROP_application.name", AppName.utf8());
qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1());
#ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG #ifdef TDESKTOP_FORCE_GTK_FILE_DIALOG
LOG(("Checking for XDG Desktop Portal...")); LOG(("Checking for XDG Desktop Portal..."));
// this can give us a chance to use a proper file dialog for current session // this can give us a chance to use a proper file dialog for current session
@ -454,24 +539,29 @@ void start() {
void finish() { void finish() {
} }
void RegisterCustomScheme() { void RegisterCustomScheme(bool force) {
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
auto home = getHomeDir(); const auto home = getHomeDir();
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) if (home.isEmpty() || cExeName().isEmpty())
return; // don't update desktop file for alpha version return;
if (Core::UpdaterDisabled())
static const auto disabledByEnv = qEnvironmentVariableIsSet(
"TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION");
// don't update desktop file for alpha version or if updater is disabled
if ((cAlphaVersion() || Core::UpdaterDisabled() || disabledByEnv)
&& !force)
return; return;
const auto applicationsPath = QStandardPaths::writableLocation( const auto applicationsPath = QStandardPaths::writableLocation(
QStandardPaths::ApplicationsLocation) + '/'; QStandardPaths::ApplicationsLocation) + '/';
#ifndef TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
GenerateDesktopFile(applicationsPath, qsl("-- %u")); GenerateDesktopFile(applicationsPath, qsl("-- %u"));
const auto icons = const auto icons =
QStandardPaths::writableLocation( QStandardPaths::writableLocation(
QStandardPaths::GenericDataLocation) QStandardPaths::GenericDataLocation)
+ qsl("/icons/"); + qsl("/icons/");
if (!QDir(icons).exists()) QDir().mkpath(icons); if (!QDir(icons).exists()) QDir().mkpath(icons);
@ -485,10 +575,9 @@ void RegisterCustomScheme() {
} }
if (!iconExists) { if (!iconExists) {
if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) { if (QFile(qsl(":/gui/art/logo_256.png")).copy(icon)) {
DEBUG_LOG(("App Info: Icon copied to 'tdata'")); DEBUG_LOG(("App Info: Icon copied to '%1'").arg(icon));
} }
} }
#endif // !TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION
RunShellCommand("update-desktop-database " RunShellCommand("update-desktop-database "
+ EscapeShell(QFile::encodeName(applicationsPath))); + EscapeShell(QFile::encodeName(applicationsPath)));
@ -559,14 +648,14 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) {
} }
void psAutoStart(bool start, bool silent) { void psAutoStart(bool start, bool silent) {
auto home = getHomeDir(); const auto home = getHomeDir();
if (home.isEmpty() || cAlphaVersion() || cExeName().isEmpty()) if (home.isEmpty() || cExeName().isEmpty())
return; return;
if (InSandbox()) { if (InSandbox()) {
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION #ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
SandboxAutostart(start); SandboxAutostart(start, silent);
#endif #endif // !DESKTOP_APP_USE_PACKAGED
} else { } else {
const auto autostart = [&] { const auto autostart = [&] {
if (InSnap()) { if (InSnap()) {
@ -578,12 +667,12 @@ void psAutoStart(bool start, bool silent) {
} else { } else {
return QStandardPaths::writableLocation( return QStandardPaths::writableLocation(
QStandardPaths::GenericConfigLocation) QStandardPaths::GenericConfigLocation)
+ qsl("/autostart/"); + qsl("/autostart/");
} }
}(); }();
if (start) { if (start) {
GenerateDesktopFile(autostart, qsl("-autostart")); GenerateDesktopFile(autostart, qsl("-autostart"), silent);
} else { } else {
QFile::remove(autostart + GetLauncherFilename()); QFile::remove(autostart + GetLauncherFilename());
} }

View file

@ -35,9 +35,7 @@ QString SingleInstanceLocalServerName(const QString &hash);
QString GetLauncherBasename(); QString GetLauncherBasename();
QString GetLauncherFilename(); QString GetLauncherFilename();
inline std::optional<crl::time> LastUserInputTime() { QString GetIconName();
return std::nullopt;
}
inline void IgnoreApplicationActivationRightNow() { inline void IgnoreApplicationActivationRightNow() {
} }

View file

@ -481,6 +481,8 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
@implementation PinnedDialogButton { @implementation PinnedDialogButton {
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
rpl::lifetime _peerChangedLifetime; rpl::lifetime _peerChangedLifetime;
base::has_weak_ptr _guard;
bool isWaitingUserpicLoad; bool isWaitingUserpicLoad;
} }
@ -518,7 +520,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
) | rpl::filter([](const Window::Theme::BackgroundUpdate &update) { ) | rpl::filter([](const Window::Theme::BackgroundUpdate &update) {
return update.paletteChanged(); return update.paletteChanged();
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
crl::on_main([=] { crl::on_main(&_guard, [=] {
if (_number <= kSavedMessagesId || UseEmptyUserpic(_peer)) { if (_number <= kSavedMessagesId || UseEmptyUserpic(_peer)) {
[self updateUserpic]; [self updateUserpic];
} else if (_peer } else if (_peer

View file

@ -136,7 +136,7 @@ void RemoveQuarantine(const QString &path) {
removexattr(local.data(), kQuarantineAttribute, 0); removexattr(local.data(), kQuarantineAttribute, 0);
} }
void RegisterCustomScheme() { void RegisterCustomScheme(bool force) {
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]);
DEBUG_LOG(("App Info: set default handler for 'tg' scheme result: %1").arg(result)); DEBUG_LOG(("App Info: set default handler for 'tg' scheme result: %1").arg(result));

View file

@ -28,7 +28,7 @@ enum class SystemSettingsType {
void SetWatchingMediaKeys(bool watching); void SetWatchingMediaKeys(bool watching);
void SetApplicationIcon(const QIcon &icon); void SetApplicationIcon(const QIcon &icon);
void RegisterCustomScheme(); void RegisterCustomScheme(bool force = false);
PermissionStatus GetPermissionStatus(PermissionType type); PermissionStatus GetPermissionStatus(PermissionType type);
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback); void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback);
void OpenSystemSettingsForPermission(PermissionType type); void OpenSystemSettingsForPermission(PermissionType type);

View file

@ -404,7 +404,7 @@ namespace {
namespace Platform { namespace Platform {
void RegisterCustomScheme() { void RegisterCustomScheme(bool force) {
if (cExeName().isEmpty()) { if (cExeName().isEmpty()) {
return; return;
} }

View file

@ -192,7 +192,7 @@ void GroupMembersWidget::refreshMembers() {
fillChatMembers(chat); fillChatMembers(chat);
} else if (const auto megagroup = peer()->asMegagroup()) { } else if (const auto megagroup = peer()->asMegagroup()) {
auto &megagroupInfo = megagroup->mgInfo; auto &megagroupInfo = megagroup->mgInfo;
if (megagroupInfo->lastParticipants.empty() || megagroup->lastParticipantsCountOutdated()) { if (megagroup->lastParticipantsRequestNeeded()) {
Auth().api().requestLastParticipants(megagroup); Auth().api().requestLastParticipants(megagroup);
} }
fillMegagroupMembers(megagroup); fillMegagroupMembers(megagroup);

View file

@ -112,10 +112,12 @@ auto GenerateCodes() {
} }
}); });
}); });
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
codes.emplace(qsl("registertg"), [](::Main::Session *session) { codes.emplace(qsl("registertg"), [](::Main::Session *session) {
Platform::RegisterCustomScheme(); Platform::RegisterCustomScheme(true);
Ui::Toast::Show("Forced custom scheme register."); Ui::Toast::Show("Forced custom scheme register.");
}); });
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
codes.emplace(qsl("export"), [](::Main::Session *session) { codes.emplace(qsl("export"), [](::Main::Session *session) {
session->data().startExport(); session->data().startExport();
}); });

View file

@ -3167,7 +3167,7 @@ void writeFileLocation(MediaKey location, const FileLocation &local) {
return; return;
} }
if (i.value().first != location) { if (i.value().first != location) {
for (FileLocations::iterator j = _fileLocations.find(i.value().first), e = _fileLocations.end(); (j != e) && (j.key() == i.value().first);) { for (FileLocations::iterator j = _fileLocations.find(i.value().first), e = _fileLocations.end(); (j != e) && (j.key() == i.value().first); ++j) {
if (j.value() == i.value().second) { if (j.value() == i.value().second) {
_fileLocations.erase(j); _fileLocations.erase(j);
break; break;
@ -3682,7 +3682,21 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
// Read orders of installed and featured stickers. // Read orders of installed and featured stickers.
if (outOrder) { if (outOrder) {
stickers.stream >> *outOrder; auto outOrderCount = quint32();
stickers.stream >> outOrderCount;
if (!_checkStreamStatus(stickers.stream) || outOrderCount > 1000) {
return failed();
}
outOrder->reserve(outOrderCount);
for (auto i = 0; i != outOrderCount; ++i) {
auto value = uint64();
stickers.stream >> value;
if (!_checkStreamStatus(stickers.stream)) {
outOrder->clear();
return failed();
}
outOrder->push_back(value);
}
} }
if (!_checkStreamStatus(stickers.stream)) { if (!_checkStreamStatus(stickers.stream)) {
return failed(); return failed();

View file

@ -117,9 +117,9 @@ QIcon CreateOfficialIcon(Main::Account *account) {
QIcon CreateIcon(Main::Account *account) { QIcon CreateIcon(Main::Account *account) {
auto result = CreateOfficialIcon(account); auto result = CreateOfficialIcon(account);
if (Platform::IsLinux()) { #ifdef Q_OS_LINUX
return QIcon::fromTheme("kotatogram", result); return QIcon::fromTheme(Platform::GetIconName(), result);
} #endif
return result; return result;
} }

View file

@ -1,7 +1,7 @@
AppVersion 1009019 AppVersion 1009020
AppVersionStrMajor 1.9 AppVersionStrMajor 1.9
AppVersionStrSmall 1.9.19 AppVersionStrSmall 1.9.20
AppVersionStr 1.9.19 AppVersionStr 1.9.20
BetaChannel 1 BetaChannel 1
AlphaVersion 0 AlphaVersion 0
AppVersionOriginal 1.9.19.beta AppVersionOriginal 1.9.20.beta

View file

@ -7,8 +7,6 @@
option(TDESKTOP_FORCE_GTK_FILE_DIALOG "Force using GTK file dialog (Linux only)." OFF) option(TDESKTOP_FORCE_GTK_FILE_DIALOG "Force using GTK file dialog (Linux only)." OFF)
option(TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME "Disable automatic 'tg://' URL scheme handler registration." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME "Disable automatic 'tg://' URL scheme handler registration." ${DESKTOP_APP_USE_PACKAGED})
option(TDESKTOP_DISABLE_NETWORK_PROXY "Disable all code for working through Socks5 or MTProxy." OFF) option(TDESKTOP_DISABLE_NETWORK_PROXY "Disable all code for working through Socks5 or MTProxy." OFF)
option(TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION "Disable automatic '.desktop' file generation (Linux only)." ${DESKTOP_APP_USE_PACKAGED})
option(TDESKTOP_DISABLE_GTK_INTEGRATION "Disable all code for GTK integration (Linux only)." ON)
option(TDESKTOP_USE_PACKAGED_TGVOIP "Find libtgvoip using CMake instead of bundled one." ${DESKTOP_APP_USE_PACKAGED}) option(TDESKTOP_USE_PACKAGED_TGVOIP "Find libtgvoip using CMake instead of bundled one." ${DESKTOP_APP_USE_PACKAGED})
option(TDESKTOP_API_TEST "Use test API credentials." OFF) option(TDESKTOP_API_TEST "Use test API credentials." OFF)
set(TDESKTOP_API_ID "0" CACHE STRING "Provide 'api_id' for the Telegram API access.") set(TDESKTOP_API_ID "0" CACHE STRING "Provide 'api_id' for the Telegram API access.")
@ -43,12 +41,12 @@ if (TDESKTOP_API_ID STREQUAL "0" OR TDESKTOP_API_HASH STREQUAL "")
" ") " ")
endif() endif()
if (NOT DESKTOP_APP_SPECIAL_TARGET STREQUAL "") if (NOT DESKTOP_APP_USE_PACKAGED)
set(TDESKTOP_FORCE_GTK_FILE_DIALOG ON) set(TDESKTOP_FORCE_GTK_FILE_DIALOG ON)
endif() endif()
if (TDESKTOP_FORCE_GTK_FILE_DIALOG) if (NOT TDESKTOP_FORCE_GTK_FILE_DIALOG)
set(TDESKTOP_DISABLE_GTK_INTEGRATION OFF) set(TDESKTOP_DISABLE_GTK_INTEGRATION ON)
endif() endif()
if (DESKTOP_APP_DISABLE_SPELLCHECK) if (DESKTOP_APP_DISABLE_SPELLCHECK)
@ -77,10 +75,6 @@ if (TDESKTOP_DISABLE_NETWORK_PROXY)
target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_NETWORK_PROXY) target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_NETWORK_PROXY)
endif() endif()
if (TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION)
target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_DESKTOP_FILE_GENERATION)
endif()
if (TDESKTOP_DISABLE_GTK_INTEGRATION) if (TDESKTOP_DISABLE_GTK_INTEGRATION)
target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_GTK_INTEGRATION) target_compile_definitions(Telegram PRIVATE TDESKTOP_DISABLE_GTK_INTEGRATION)
endif() endif()

@ -1 +1 @@
Subproject commit 17b6a6d53252b3e3ff02b113e352c152bd697896 Subproject commit 0f6c9f4acbdc2412a1a941b4ee96b150589b8369

@ -1 +1 @@
Subproject commit dbb92ddbef82988d426ef7a0ffa40a698cdc3fd3 Subproject commit 25f44d99915101e7a832cb38bd9b2cee47508c94

View file

@ -1,3 +1,9 @@
1.9.20 beta (14.03.20)
- Fix crash in shared links search.
- Fix blurred thumbnails in albums with video files.
- Fix a possible crash in animated stickers rendering.
1.9.19 beta (25.02.20) 1.9.19 beta (25.02.20)
- Bug fixes and other minor improvements. - Bug fixes and other minor improvements.

2
cmake

@ -1 +1 @@
Subproject commit 81e27ccc0e7bf27405569ce98582860dfc9ea9bb Subproject commit 9280064cc8a5e8f8acc4cdda3a6a905379d3df0d

View file

@ -1,4 +1,4 @@
## Build instructions for GYP/CMake under Ubuntu 14.04 ## Build instructions for CMake under Ubuntu 14.04
### Prepare folder ### Prepare folder
@ -17,7 +17,7 @@ You will need GCC 8 installed. To install them and all the required dependencies
libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \ libgtk2.0-dev libice-dev libsm-dev libicu-dev libdrm-dev dh-autoreconf \
autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \ autoconf automake build-essential libxml2-dev libass-dev libfreetype6-dev \
libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \ libgpac-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev \
libvorbis-dev libenchant-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \ libvorbis-dev libxcb1-dev libxcb-image0-dev libxcb-shm0-dev \
libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \ libxcb-xfixes0-dev libxcb-keysyms1-dev libxcb-icccm4-dev libatspi2.0-dev \
libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \ libxcb-render-util0-dev libxcb-util0-dev libxcb-xkb-dev libxrender-dev \
libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \ libasound-dev libpulse-dev libxcb-sync0-dev libxcb-randr0-dev libegl1-mesa-dev \
@ -198,7 +198,7 @@ Go to ***BuildPath*** and run
git clone git://repo.or.cz/openal-soft.git git clone git://repo.or.cz/openal-soft.git
cd openal-soft cd openal-soft
git checkout openal-soft-1.19.1 git checkout openal-soft-1.20.1
cd build cd build
if [ `uname -p` == "i686" ]; then if [ `uname -p` == "i686" ]; then
cmake -D LIBTYPE:STRING=STATIC -D ALSOFT_UTILS:BOOL=OFF .. cmake -D LIBTYPE:STRING=STATIC -D ALSOFT_UTILS:BOOL=OFF ..
@ -214,7 +214,7 @@ Go to ***BuildPath*** and run
git checkout OpenSSL_1_1_1-stable git checkout OpenSSL_1_1_1-stable
./config --prefix=/usr/local/desktop-app/openssl-1.1.1 ./config --prefix=/usr/local/desktop-app/openssl-1.1.1
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install_sw
cd .. cd ..
git clone https://github.com/xkbcommon/libxkbcommon.git git clone https://github.com/xkbcommon/libxkbcommon.git

View file

@ -18,7 +18,6 @@ You will require **api_id** and **api_hash** to access the Telegram API servers.
## Install third party software ## Install third party software
Strawberry
* Download **Strawberry Perl** installer from [http://strawberryperl.com/](http://strawberryperl.com/) and install to ***BuildPath*\\ThirdParty\\Strawberry** * Download **Strawberry Perl** installer from [http://strawberryperl.com/](http://strawberryperl.com/) and install to ***BuildPath*\\ThirdParty\\Strawberry**
* Download **NASM** installer from [http://www.nasm.us](http://www.nasm.us) and install to ***BuildPath*\\ThirdParty\\NASM** * Download **NASM** installer from [http://www.nasm.us](http://www.nasm.us) and install to ***BuildPath*\\ThirdParty\\NASM**
* Download **Yasm** executable from [http://yasm.tortall.net/Download.html](http://yasm.tortall.net/Download.html), rename to *yasm.exe* and put to ***BuildPath*\\ThirdParty\\yasm** * Download **Yasm** executable from [http://yasm.tortall.net/Download.html](http://yasm.tortall.net/Download.html), rename to *yasm.exe* and put to ***BuildPath*\\ThirdParty\\yasm**

View file

@ -30,7 +30,7 @@ By git in Terminal go to **/home/user/TBuild** and run
Install dev libraries Install dev libraries
sudo apt-get install libexif-dev liblzma-dev libz-dev libssl-dev libappindicator-dev libunity-dev libenchant-dev sudo apt-get install libexif-dev liblzma-dev libz-dev libssl-dev libappindicator-dev libunity-dev
#### zlib 1.2.8 #### zlib 1.2.8

View file

@ -1,4 +1,4 @@
## Build instructions for Xcode 10.1 ## Build instructions for Xcode 11
### Prepare folder ### Prepare folder
@ -8,18 +8,14 @@ Choose a folder for the future build, for example **/Users/user/TBuild**. It wil
You will require **api_id** and **api_hash** to access the Telegram API servers. To learn how to obtain them [click here][api_credentials]. You will require **api_id** and **api_hash** to access the Telegram API servers. To learn how to obtain them [click here][api_credentials].
### Download libraries
Download [**xz-5.0.5**](http://tukaani.org/xz/xz-5.0.5.tar.gz) and unpack to ***BuildPath*/Libraries/macos/xz-5.0.5**
Download [**libiconv-1.15**](http://www.gnu.org/software/libiconv/#downloading) and unpack to ***BuildPath*/Libraries/macos/libiconv-1.15**
### Clone source code and prepare libraries ### Clone source code and prepare libraries
Go to ***BuildPath*** and run Go to ***BuildPath*** and run
MAKE_THREADS_CNT=-j8 MAKE_THREADS_CNT=-j8
MACOSX_DEPLOYMENT_TARGET=10.12 MACOSX_DEPLOYMENT_TARGET=10.12
UNGUARDED="-Werror=unguarded-availability-new"
MIN_VER="-mmacosx-version-min=10.12"
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install automake cmake fdk-aac git lame libass libtool libvorbis libvpx ninja opus sdl shtool texi2html theora wget x264 xvid yasm pkg-config gnu-tar brew install automake cmake fdk-aac git lame libass libtool libvorbis libvpx ninja opus sdl shtool texi2html theora wget x264 xvid yasm pkg-config gnu-tar
@ -45,24 +41,29 @@ Go to ***BuildPath*** and run
sudo ./setup.py install sudo ./setup.py install
cd ../.. cd ../..
mkdir -p Libraries/macos
cd Libraries/macos cd Libraries/macos
LibrariesPath=`pwd` LibrariesPath=`pwd`
git clone https://github.com/desktop-app/patches.git git clone https://github.com/desktop-app/patches.git
cd patches cd patches
git checkout 4f1cffb git checkout 4f1cffb
cd ../ cd ..
git clone --branch 0.10.0 https://github.com/ericniebler/range-v3 git clone --branch 0.10.0 https://github.com/ericniebler/range-v3
cd xz-5.0.5 xz_ver=5.2.4
CFLAGS="-mmacosx-version-min=10.12" LDFLAGS="-mmacosx-version-min=10.12" ./configure --prefix=/usr/local/macos wget https://tukaani.org/xz/xz-$xz_ver.tar.gz
tar -xvzf xz-$xz_ver.tar.gz
rm xz-$xz_ver.tar.gz
cd xz-$xz_ver
CFLAGS="$MIN_VER" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install
cd .. cd ..
git clone https://github.com/desktop-app/zlib.git git clone https://github.com/desktop-app/zlib.git
cd zlib cd zlib
CFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" LDFLAGS="-mmacosx-version-min=10.12" ./configure --prefix=/usr/local/macos CFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install
cd .. cd ..
@ -70,7 +71,7 @@ Go to ***BuildPath*** and run
git clone https://github.com/openssl/openssl openssl_1_1_1 git clone https://github.com/openssl/openssl openssl_1_1_1
cd openssl_1_1_1 cd openssl_1_1_1
git checkout OpenSSL_1_1_1-stable git checkout OpenSSL_1_1_1-stable
./Configure --prefix=/usr/local/macos darwin64-x86_64-cc -static -mmacosx-version-min=10.12 ./Configure --prefix=/usr/local/macos darwin64-x86_64-cc -static $MIN_VER
make build_libs $MAKE_THREADS_CNT make build_libs $MAKE_THREADS_CNT
cd .. cd ..
@ -78,13 +79,17 @@ Go to ***BuildPath*** and run
cd opus cd opus
git checkout v1.3 git checkout v1.3
./autogen.sh ./autogen.sh
CFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" CPPFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" LDFLAGS="-mmacosx-version-min=10.12" ./configure --prefix=/usr/local/macos CFLAGS="$MIN_VER $UNGUARDED" CPPFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install
cd .. cd ..
cd libiconv-1.15 libiconv_ver=1.16
CFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" CPPFLAGS="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" LDFLAGS="-mmacosx-version-min=10.12" ./configure --enable-static --prefix=/usr/local/macos wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-$libiconv_ver.tar.gz
tar -xvzf libiconv-$libiconv_ver.tar.gz
rm libiconv-$libiconv_ver.tar.gz
cd libiconv-$libiconv_ver
CFLAGS="$MIN_VER $UNGUARDED" CPPFLAGS="$MIN_VER $UNGUARDED" LDFLAGS="$MIN_VER" ./configure --enable-static --prefix=/usr/local/macos
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install
cd .. cd ..
@ -97,9 +102,9 @@ Go to ***BuildPath*** and run
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/X11/lib/pkgconfig PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/X11/lib/pkgconfig
./configure --prefix=/usr/local/macos \ ./configure --prefix=/usr/local/macos \
--extra-cflags="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" \ --extra-cflags="$MIN_VER $UNGUARDED" \
--extra-cxxflags="-mmacosx-version-min=10.12 -Werror=unguarded-availability-new" \ --extra-cxxflags="$MIN_VER $UNGUARDED" \
--extra-ldflags="-mmacosx-version-min=10.12" \ --extra-ldflags="$MIN_VER" \
--enable-protocol=file --enable-libopus \ --enable-protocol=file --enable-libopus \
--disable-programs \ --disable-programs \
--disable-doc \ --disable-doc \
@ -205,7 +210,7 @@ Go to ***BuildPath*** and run
cd openal-soft cd openal-soft
git checkout v1.19 git checkout v1.19
cd build cd build
CFLAGS='-Werror=unguarded-availability-new' CPPFLAGS='-Werror=unguarded-availability-new' cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/local/macos -D ALSOFT_EXAMPLES=OFF -D LIBTYPE:STRING=STATIC -D CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.12 .. CFLAGS=$UNGUARDED CPPFLAGS=$UNGUARDED cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/local/macos -D ALSOFT_EXAMPLES=OFF -D LIBTYPE:STRING=STATIC -D CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.12 ..
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install
cd ../.. cd ../..
@ -241,7 +246,19 @@ Go to ***BuildPath*** and run
git apply ../../patches/qtbase_5_12_5.diff git apply ../../patches/qtbase_5_12_5.diff
cd .. cd ..
./configure -prefix "/usr/local/desktop-app/Qt-5.12.5" -debug-and-release -force-debug-info -opensource -confirm-license -static -opengl desktop -no-openssl -securetransport -nomake examples -nomake tests -platform macx-clang ./configure -prefix "/usr/local/desktop-app/Qt-5.12.5" \
-debug-and-release \
-force-debug-info \
-opensource \
-confirm-license \
-static \
-opengl desktop \
-no-openssl \
-securetransport \
-nomake examples \
-nomake tests \
-platform macx-clang
make $MAKE_THREADS_CNT make $MAKE_THREADS_CNT
sudo make install sudo make install
cd .. cd ..

View file

@ -20,7 +20,7 @@
<url type="help">https://github.com/kotatogram/kotatogram-desktop/issues</url> <url type="help">https://github.com/kotatogram/kotatogram-desktop/issues</url>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot type="default">
<image>https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/docs/assets/preview.png</image> <image>https://github.com/kotatogram/kotatogram-desktop/blob/dev/docs/assets/ktg_preview.png</image>
</screenshot> </screenshot>
</screenshots> </screenshots>
<keywords> <keywords>
@ -98,6 +98,7 @@
<content_attribute id="money-purchasing">none</content_attribute> <content_attribute id="money-purchasing">none</content_attribute>
<content_attribute id="money-gambling">none</content_attribute> <content_attribute id="money-gambling">none</content_attribute>
</content_rating> </content_rating>
<launchable type="desktop-id">@TDESKTOP_LAUNCHER_BASENAME@.desktop</launchable>
<provides> <provides>
<binary>kotatogram-desktop</binary> <binary>kotatogram-desktop</binary>
</provides> </provides>

View file

@ -6,6 +6,13 @@ base: core18
grade: stable grade: stable
confinement: strict confinement: strict
architectures:
- build-on: amd64
- build-on: i386
- build-on: arm64
- build-on: armhf
- build-on: ppc64el
apps: apps:
kotatogram-desktop: kotatogram-desktop:
command: bin/desktop-launch kotatogram-desktop command: bin/desktop-launch kotatogram-desktop
@ -14,9 +21,12 @@ apps:
environment: environment:
# Use GTK3 cursor theme, icon theme and open/save file dialogs. # Use GTK3 cursor theme, icon theme and open/save file dialogs.
QT_QPA_PLATFORMTHEME: gtk3 QT_QPA_PLATFORMTHEME: gtk3
# Wayland support is still too bad. # The blocker is https://github.com/ubuntu/snapcraft-desktop-helpers/issues/172
DISABLE_WAYLAND: 1 DISABLE_WAYLAND: 1
plugs: plugs:
- alsa
- audio-playback
- audio-record
- desktop - desktop
- desktop-legacy - desktop-legacy
- home - home
@ -44,6 +54,10 @@ plugs:
target: $SNAP/data-dir/sounds target: $SNAP/data-dir/sounds
default-provider: gtk-common-themes default-provider: gtk-common-themes
layout:
/usr/share/alsa:
bind: $SNAP/usr/share/alsa
parts: parts:
kotatogram: kotatogram:
plugin: cmake plugin: cmake
@ -56,17 +70,11 @@ parts:
- qtbase5-private-dev - qtbase5-private-dev
- libmapbox-variant-dev - libmapbox-variant-dev
- libasound2-dev - libasound2-dev
- libavcodec-dev
- libavformat-dev
- libavutil-dev
- libswscale-dev
- libswresample-dev
- libdbusmenu-qt5-dev - libdbusmenu-qt5-dev
- libhunspell-dev - libhunspell-dev
- liblz4-dev - liblz4-dev
- liblzma-dev - liblzma-dev
- libminizip-dev - libminizip-dev
- libopenal-dev
- libopus-dev - libopus-dev
- libpulse-dev - libpulse-dev
- libssl-dev - libssl-dev
@ -74,17 +82,11 @@ parts:
stage-packages: stage-packages:
- qt5-image-formats-plugins - qt5-image-formats-plugins
- libasound2 - libasound2
- libavcodec57
- libavformat57
- libavutil55
- libswscale4
- libswresample2
- libdbusmenu-qt5-2 - libdbusmenu-qt5-2
- libhunspell-1.6-0 - libhunspell-1.6-0
- liblz4-1 - liblz4-1
- liblzma5 - liblzma5
- libminizip1 - libminizip1
- libopenal1
- libopus0 - libopus0
- libpulse0 - libpulse0
- libssl1.1 - libssl1.1
@ -119,9 +121,16 @@ parts:
after: after:
- cmake - cmake
- desktop-qt5 - desktop-qt5
- ffmpeg
- openal
- range-v3 - range-v3
- xxhash - xxhash
patches:
plugin: dump
source: Telegram/Patches
prime: [-./*]
desktop-qt5: desktop-qt5:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: qt source-subdir: qt
@ -176,6 +185,138 @@ parts:
- libtinfo5 - libtinfo5
prime: [-./*] prime: [-./*]
ffmpeg:
source: https://github.com/FFmpeg/FFmpeg.git
source-depth: 1
source-branch: release/4.2
plugin: autotools
build-packages:
- libtool
- pkg-config
- texi2html
- yasm
- libass-dev
- libfreetype6-dev
- libgpac-dev
- liblzma-dev
- libopus-dev
- libsdl1.2-dev
- libtheora-dev
- libva-dev
- libvdpau-dev
- libvorbis-dev
- libxcb1-dev
- libxcb-shm0-dev
- libxcb-xfixes0-dev
- zlib1g-dev
stage-packages:
- freeglut3
- libass9
- libfreetype6
- libgpac4
- liblzma5
- libopus0
- libslang2
- libsdl1.2debian
- libtheora0
- libva2
- libva-drm2
- libvdpau1
- libvorbis0a
- libxcb1
- libxcb-shm0
- libxcb-xfixes0
- zlib1g
configflags:
- --prefix=/usr
- --disable-debug
- --disable-programs
- --disable-doc
- --disable-everything
- --disable-neon
- --enable-gpl
- --enable-version3
- --enable-libopus
- --enable-decoder=aac
- --enable-decoder=aac_latm
- --enable-decoder=aasc
- --enable-decoder=flac
- --enable-decoder=gif
- --enable-decoder=h264
- --enable-decoder=h264_vdpau
- --enable-decoder=mp1
- --enable-decoder=mp1float
- --enable-decoder=mp2
- --enable-decoder=mp2float
- --enable-decoder=mp3
- --enable-decoder=mp3adu
- --enable-decoder=mp3adufloat
- --enable-decoder=mp3float
- --enable-decoder=mp3on4
- --enable-decoder=mp3on4float
- --enable-decoder=mpeg4
- --enable-decoder=mpeg4_vdpau
- --enable-decoder=msmpeg4v2
- --enable-decoder=msmpeg4v3
- --enable-decoder=opus
- --enable-decoder=vorbis
- --enable-decoder=wavpack
- --enable-decoder=wmalossless
- --enable-decoder=wmapro
- --enable-decoder=wmav1
- --enable-decoder=wmav2
- --enable-decoder=wmavoice
- --enable-encoder=libopus
- --enable-hwaccel=h264_vaapi
- --enable-hwaccel=h264_vdpau
- --enable-hwaccel=mpeg4_vaapi
- --enable-hwaccel=mpeg4_vdpau
- --enable-parser=aac
- --enable-parser=aac_latm
- --enable-parser=flac
- --enable-parser=h264
- --enable-parser=mpeg4video
- --enable-parser=mpegaudio
- --enable-parser=opus
- --enable-parser=vorbis
- --enable-demuxer=aac
- --enable-demuxer=flac
- --enable-demuxer=gif
- --enable-demuxer=h264
- --enable-demuxer=mov
- --enable-demuxer=mp3
- --enable-demuxer=ogg
- --enable-demuxer=wav
- --enable-muxer=ogg
- --enable-muxer=opus
override-pull: |
snapcraftctl pull
patch -p1 < "$SNAPCRAFT_STAGE/ffmpeg.diff"
after:
- patches
openal:
source: https://github.com/kcat/openal-soft.git
source-depth: 1
source-tag: openal-soft-1.20.1
plugin: cmake
build-packages:
- libasound2-dev
- libpulse-dev
- libsndio-dev
- portaudio19-dev
stage-packages:
- libasound2
- libpulse0
- libportaudio2
- libsndio6.1
configflags:
- -DCMAKE_BUILD_TYPE=Release
- -DALSOFT_EXAMPLES=OFF
- -DALSOFT_TESTS=OFF
- -DALSOFT_UTILS=OFF
- -DALSOFT_CONFIG=OFF
range-v3: range-v3:
source: https://github.com/ericniebler/range-v3.git source: https://github.com/ericniebler/range-v3.git
source-depth: 1 source-depth: 1