Compare commits
406
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
590a219f22 | ||
|
|
e68ff6d01c | ||
|
|
d5fcee258e | ||
|
|
d0bf9ecb99 | ||
|
|
068071d263 | ||
|
|
e9064602a6 | ||
|
|
71f574fce9 | ||
|
|
c2a7a9742f | ||
|
|
38a1018817 | ||
|
|
58d877a1e6 | ||
|
|
ea97b5a3f2 | ||
|
|
ea5085bfc7 | ||
|
|
26dd42bf0d | ||
|
|
8a5e0a26f9 | ||
|
|
6b22eb5af0 | ||
|
|
cbafceb01e | ||
|
|
843325d6c7 | ||
|
|
11a1ce02a8 | ||
|
|
8bc3012eb4 | ||
|
|
e108ec5105 | ||
|
|
57b1c07c33 | ||
|
|
f07076910a | ||
|
|
ce74b42e3e | ||
|
|
47e4831bca | ||
|
|
1a15e1578f | ||
|
|
94e8fce0f2 | ||
|
|
e40b9f6e10 | ||
|
|
e44182ee71 | ||
|
|
e1a32deb01 | ||
|
|
9261999563 | ||
|
|
1f5ed15cb9 | ||
|
|
49ad94e2f8 | ||
|
|
faad08c203 | ||
|
|
4237746082 | ||
|
|
989cecaf64 | ||
|
|
a6e3220054 | ||
|
|
0095677485 | ||
|
|
311111f7d8 | ||
|
|
1c590dd38c | ||
|
|
4d4dc7e8ca | ||
|
|
df7e69db9f | ||
|
|
d6f53b7485 | ||
|
|
8e8fe9871c | ||
|
|
9887e6cbc0 | ||
|
|
62ec82a85a | ||
|
|
bae859ff7c | ||
|
|
443183d4cd | ||
|
|
f762a6d8c1 | ||
|
|
4c30f20fed | ||
|
|
1faa7a13fc | ||
|
|
b7438cd452 | ||
|
|
387ea1153a | ||
|
|
d42138cc87 | ||
|
|
b64e23a4ce | ||
|
|
5b717c468b | ||
|
|
a277a5cfa1 | ||
|
|
2bcc2b4622 | ||
|
|
226d187275 | ||
|
|
72148cb630 | ||
|
|
58abc9d38a | ||
|
|
d166a66797 | ||
|
|
81e7627ad1 | ||
|
|
28f821e482 | ||
|
|
832674b5b3 | ||
|
|
28ff9be4ac | ||
|
|
89255083b9 | ||
|
|
3a8788896f | ||
|
|
22d5667995 | ||
|
|
bdfb92a736 | ||
|
|
4e3da60708 | ||
|
|
f7d5d31108 | ||
|
|
1d11e11ee6 | ||
|
|
d14e1189f2 | ||
|
|
378abb7d4b | ||
|
|
51d330e6f3 | ||
|
|
3963eb41ce | ||
|
|
af12a936d6 | ||
|
|
cc6661321d | ||
|
|
e70a8689bb | ||
|
|
6511812f2e | ||
|
|
668642d893 | ||
|
|
151281f58c | ||
|
|
f01057a244 | ||
|
|
e494a6f1a6 | ||
|
|
b43d967f69 | ||
|
|
6b94a459de | ||
|
|
1109b81870 | ||
|
|
9f404d37f6 | ||
|
|
32be492e82 | ||
|
|
c4de93e4d1 | ||
|
|
e5c817b955 | ||
|
|
cc2dcd1abb | ||
|
|
4b343157a2 | ||
|
|
52f330d6be | ||
|
|
435d530b14 | ||
|
|
a2d1288e06 | ||
|
|
72500ef1a8 | ||
|
|
6e67e63c32 | ||
|
|
634ccf7835 | ||
|
|
da6363d6cc | ||
|
|
0447eb3ca2 | ||
|
|
d49addb1ae | ||
|
|
bade37f9f2 | ||
|
|
5581c9f8e9 | ||
|
|
342984283c | ||
|
|
d313c4b79b | ||
|
|
eb3bb80669 | ||
|
|
c56bbb68f6 | ||
|
|
f5a54fc7e7 | ||
|
|
f2f653815b | ||
|
|
4edfc8db71 | ||
|
|
f368c8fd8c | ||
|
|
a0f7854c52 | ||
|
|
fb9e17621f | ||
|
|
d5b2c2c45c | ||
|
|
0e6abff8ff | ||
|
|
a762edafc7 | ||
|
|
d1bf0c711c | ||
|
|
996322c335 | ||
|
|
54d7c276bf | ||
|
|
234f364b33 | ||
|
|
0d019b9499 | ||
|
|
f4d144d53e | ||
|
|
49bff407ad | ||
|
|
1e2df2d6d8 | ||
|
|
7c3d83704b | ||
|
|
2796d9be83 | ||
|
|
4233a323b7 | ||
|
|
cf5d8df35d | ||
|
|
86f16fc7af | ||
|
|
7024e1526f | ||
|
|
d2b256f943 | ||
|
|
dcf1b9df98 | ||
|
|
0f0e8a5974 | ||
|
|
f703f1e357 | ||
|
|
3815759cd3 | ||
|
|
72242e328c | ||
|
|
c38805fa92 | ||
|
|
1ae12c868e | ||
|
|
9f3789eac5 | ||
|
|
a956177d6a | ||
|
|
b900c44188 | ||
|
|
e521c07102 | ||
|
|
e696298bc9 | ||
|
|
b65fbe83f4 | ||
|
|
ce6782a131 | ||
|
|
a37746440a | ||
|
|
eaf62c2770 | ||
|
|
147392f317 | ||
|
|
63d56acd88 | ||
|
|
28d07b370f | ||
|
|
d648ba9c93 | ||
|
|
a82dae6251 | ||
|
|
f99a17339b | ||
|
|
198266c081 | ||
|
|
756c2f8b56 | ||
|
|
abdba9922a | ||
|
|
7ca4095571 | ||
|
|
c3128c9855 | ||
|
|
20ae6c37cb | ||
|
|
3c2fdca5fc | ||
|
|
395c7ad140 | ||
|
|
630b54933d | ||
|
|
2293280316 | ||
|
|
14116b9cd2 | ||
|
|
4c7db5d5c9 | ||
|
|
f26bc80421 | ||
|
|
f934e99254 | ||
|
|
b6cd3c4a2b | ||
|
|
76763b9be1 | ||
|
|
1606f91124 | ||
|
|
cf8c982228 | ||
|
|
e94362854d | ||
|
|
40f3d5eab1 | ||
|
|
dc3b35bffa | ||
|
|
52c654179f | ||
|
|
a07a3c162f | ||
|
|
e4f8f96517 | ||
|
|
6fdb0321d6 | ||
|
|
be9b0d57e9 | ||
|
|
b4c6749a76 | ||
|
|
a98e3c7b92 | ||
|
|
26e7bbbdb8 | ||
|
|
efa7dd674a | ||
|
|
ef59e9d418 | ||
|
|
e1678a76ba | ||
|
|
56ffb52ce5 | ||
|
|
f0a2d2e79a | ||
|
|
182e77a68d | ||
|
|
98ccbfe99d | ||
|
|
53bfc641b4 | ||
|
|
1aabf2eefc | ||
|
|
0d54dfb660 | ||
|
|
8093f16f16 | ||
|
|
bac6ac3362 | ||
|
|
2f914d9f60 | ||
|
|
d3293d22ab | ||
|
|
4de3fdae81 | ||
|
|
9518c73415 | ||
|
|
05be539411 | ||
|
|
f12c4e3109 | ||
|
|
004ef28a15 | ||
|
|
afa9b25aff | ||
|
|
303ce7c816 | ||
|
|
e7cbd07b80 | ||
|
|
923ae5fc96 | ||
|
|
51a3b3c68e | ||
|
|
ef1582c67c | ||
|
|
2091e39b90 | ||
|
|
ab02e72f1f | ||
|
|
d498d6a407 | ||
|
|
6dc6e9538c | ||
|
|
3b0cbefe85 | ||
|
|
38e152fc52 | ||
|
|
0f111b43be | ||
|
|
ffbeab0b14 | ||
|
|
8860b62eec | ||
|
|
93433d8714 | ||
|
|
211a0c6f93 | ||
|
|
aadfc71200 | ||
|
|
1532adedb1 | ||
|
|
16ce656201 | ||
|
|
a398723bdb | ||
|
|
f7a4788e73 | ||
|
|
15425c7b01 | ||
|
|
96c2a505a7 | ||
|
|
b58e3fc2d4 | ||
|
|
4b1cbf11ad | ||
|
|
1037ac8c02 | ||
|
|
572f3c4c94 | ||
|
|
e48d6c8bb6 | ||
|
|
d717e7dff9 | ||
|
|
cb16ebb812 | ||
|
|
2c1df5e9e4 | ||
|
|
c3873d05ac | ||
|
|
4fca0ca0c5 | ||
|
|
c02f369a0f | ||
|
|
2e68ec0880 | ||
|
|
c7b22b348e | ||
|
|
f4c8172201 | ||
|
|
9fa7757efd | ||
|
|
fc2c359bd7 | ||
|
|
f17987b3e7 | ||
|
|
7c2bbf3a98 | ||
|
|
4320921a96 | ||
|
|
306a4c866c | ||
|
|
2bfd142300 | ||
|
|
bec70c37db | ||
|
|
a7e9588a90 | ||
|
|
463bdde0a0 | ||
|
|
c83d7f582b | ||
|
|
62385df312 | ||
|
|
dad015195b | ||
|
|
b89fed88ee | ||
|
|
613dd1eb51 | ||
|
|
b7754e7d60 | ||
|
|
644c343e95 | ||
|
|
c9d530be76 | ||
|
|
aa0268694f | ||
|
|
8e873e726d | ||
|
|
dca3373056 | ||
|
|
6d57cad22c | ||
|
|
b67fdc384f | ||
|
|
32f98a7c9b | ||
|
|
2b8ac69916 | ||
|
|
ad6fe5e633 | ||
|
|
1ad6586a07 | ||
|
|
0249604199 | ||
|
|
1a93e0d944 | ||
|
|
347613a7f2 | ||
|
|
424c67a268 | ||
|
|
64d7a911fa | ||
|
|
961dca328d | ||
|
|
433d95969c | ||
|
|
15f439c38e | ||
|
|
ca4d5d8b77 | ||
|
|
06338900dc | ||
|
|
8ec674fbef | ||
|
|
58eefc29eb | ||
|
|
9312331755 | ||
|
|
1d25f46f52 | ||
|
|
a775cd58be | ||
|
|
ae5ed3b10b | ||
|
|
8aab91568e | ||
|
|
6647346314 | ||
|
|
bfb41310ad | ||
|
|
c3371adda4 | ||
|
|
9bcf017c8d | ||
|
|
2c0b13ff9f | ||
|
|
abfd901a82 | ||
|
|
135b8859d6 | ||
|
|
f8637b686c | ||
|
|
53f466c976 | ||
|
|
762976159e | ||
|
|
de1a872f74 | ||
|
|
3f39fc9e90 | ||
|
|
e8e6a5f1e2 | ||
|
|
51a9799281 | ||
|
|
73078eb5e7 | ||
|
|
d138b5c67b | ||
|
|
ef3846df6b | ||
|
|
a31494d83f | ||
|
|
b131fcc7d9 | ||
|
|
e6379db384 | ||
|
|
f50cf92e9a | ||
|
|
e9e0e4f143 | ||
|
|
dfc0b8cbcd | ||
|
|
473b4ee83e | ||
|
|
f40c9fd497 | ||
|
|
0ca21344f8 | ||
|
|
d4d85a8b58 | ||
|
|
cfd4b3de53 | ||
|
|
96c5f344cc | ||
|
|
d6e8ddca11 | ||
|
|
db63766cc7 | ||
|
|
048e876710 | ||
|
|
d7e74e2a5f | ||
|
|
722b78e49b | ||
|
|
734caa0280 | ||
|
|
69901cb69c | ||
|
|
e230adf223 | ||
|
|
07584b73f4 | ||
|
|
1b29a028a6 | ||
|
|
736d1789c9 | ||
|
|
01f22c517a | ||
|
|
edd171c97b | ||
|
|
873c791262 | ||
|
|
068a5b756a | ||
|
|
db35f2a5e6 | ||
|
|
c06bb7ad03 | ||
|
|
1c63395497 | ||
|
|
ba79cd6b5a | ||
|
|
a458b36ed3 | ||
|
|
1c51c183f0 | ||
|
|
7a69653933 | ||
|
|
f9a286b136 | ||
|
|
87e1a7ef90 | ||
|
|
e5561d0256 | ||
|
|
998ba22a21 | ||
|
|
a79fb43569 | ||
|
|
0365309415 | ||
|
|
c0df2785df | ||
|
|
e0ae3f0c93 | ||
|
|
b95850013b | ||
|
|
4ec46a10bf | ||
|
|
05e9949487 | ||
|
|
7b1bce6297 | ||
|
|
b6fa3b3aa9 | ||
|
|
5b5e41a563 | ||
|
|
8fcac61500 | ||
|
|
0420a694f7 | ||
|
|
78cf01b0e8 | ||
|
|
b5f8ae8d85 | ||
|
|
58c183df56 | ||
|
|
2272f88db9 | ||
|
|
d7f1a408fd | ||
|
|
b7c99086e9 | ||
|
|
28c5b7d562 | ||
|
|
c163b6b995 | ||
|
|
7e62862bd3 | ||
|
|
89402fb770 | ||
|
|
4717953a06 | ||
|
|
eefab11079 | ||
|
|
25d5749970 | ||
|
|
5e4c45038f | ||
|
|
7967d37f14 | ||
|
|
1ee5a49c72 | ||
|
|
44aedfd702 | ||
|
|
5e4fcb7d35 | ||
|
|
d6dcce1a88 | ||
|
|
e34530bf7d | ||
|
|
56b440f689 | ||
|
|
e2cebadaef | ||
|
|
49d55d73d1 | ||
|
|
a9ec57a008 | ||
|
|
f4e11ba490 | ||
|
|
44176b49ac | ||
|
|
79ff9230ba | ||
|
|
d6682dbfe3 | ||
|
|
ef53ac4b1a | ||
|
|
c503d0607a | ||
|
|
5f63abd8bb | ||
|
|
e2530e94cf | ||
|
|
1f3e1ff98e | ||
|
|
f7353bfcd5 | ||
|
|
bdeca89a95 | ||
|
|
a707a0523f | ||
|
|
70243a6e59 | ||
|
|
2f4cb7868a | ||
|
|
1fa0a3f4b2 | ||
|
|
f24a74d195 | ||
|
|
38c448335f | ||
|
|
9afeae2ccc | ||
|
|
583973a731 | ||
|
|
dc5c25cf42 | ||
|
|
a4fcc55638 | ||
|
|
1aa7559fe7 | ||
|
|
6f4ec382e8 | ||
|
|
a67631ec92 | ||
|
|
d861b7cc59 | ||
|
|
87fd82b43b | ||
|
|
0902b4aa19 | ||
|
|
7ccb638662 | ||
|
|
c35c563878 | ||
|
|
84cdaade07 | ||
|
|
f3dec29198 |
No files matched your search
Symlink
+1
@@ -0,0 +1 @@
|
||||
org.kde.audiotube.json
|
||||
@@ -1,2 +1,9 @@
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
# SPDX-FileCopyrightText: 2021 Bhushan Shah <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
*.kdev4
|
||||
CMakeLists.txt.user
|
||||
flatpak/flatpak-builder-tools/
|
||||
build/
|
||||
@@ -0,0 +1,7 @@
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
include:
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/reuse-lint.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/flatpak.yml
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: AudioTube
|
||||
Upstream-Contact: Jonah Brüchert <[email protected]>
|
||||
Source: https://invent.kde.org/plasma-mobile/audiotube
|
||||
|
||||
# Sample paragraph, commented out:
|
||||
#
|
||||
# Files: ...
|
||||
# Copyright: $YEAR $NAME <$CONTACT>
|
||||
# License: ...
|
||||
# Comment: ...
|
||||
|
||||
Files: README.md
|
||||
Copyright: 2021 Jonah Brüchert <[email protected]>
|
||||
License: CC0-1.0
|
||||
|
||||
Files: org.kde.audiotube.desktop
|
||||
org.kde.audiotube.json
|
||||
Copyright: 2021 Jonah Brüchert <[email protected]>
|
||||
License: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
Files: logo.png
|
||||
org.kde.audiotube.svg
|
||||
Copyright: 2021 Mathis Brüchert <[email protected]>
|
||||
License: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
+25
-6
@@ -1,18 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
project(audiotube)
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
|
||||
# KDE Applications version, managed by release script.
|
||||
set(RELEASE_SERVICE_VERSION_MAJOR "23")
|
||||
set(RELEASE_SERVICE_VERSION_MINOR "03")
|
||||
set(RELEASE_SERVICE_VERSION_MICRO "70")
|
||||
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||
|
||||
project(audiotube VERSION ${RELEASE_SERVICE_VERSION})
|
||||
|
||||
include(FeatureSummary)
|
||||
|
||||
set(QT5_MIN_VERSION 5.15)
|
||||
set(KF5_MIN_VERSION 5.81)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
@@ -21,11 +31,20 @@ include(ECMSetupVersion)
|
||||
include(ECMGenerateHeaders)
|
||||
include(ECMPoQmTools)
|
||||
|
||||
ecm_setup_version(${PROJECT_VERSION}
|
||||
VARIABLE_PREFIX AUDIOTUBE
|
||||
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/version.h
|
||||
)
|
||||
|
||||
kde_enable_exceptions()
|
||||
|
||||
find_package(Qt5 ${QT5_MIN_VERSION} REQUIRED COMPONENTS Core Gui Qml QuickControls2 Svg DBus)
|
||||
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Kirigami2 I18n)
|
||||
find_package(Qt${QT_MAJOR_VERSION} ${QT5_MIN_VERSION} REQUIRED COMPONENTS Core Gui Qml QuickControls2 Svg Sql Widgets)
|
||||
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Kirigami2 I18n CoreAddons Crash WindowSystem)
|
||||
find_package(pybind11 REQUIRED)
|
||||
find_package(Ytdlp REQUIRED RUNTIME)
|
||||
find_package(YTMusicAPI 0.24.0 REQUIRED RUNTIME)
|
||||
|
||||
ki18n_install(po)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
Copyright (c) <year> <owner>. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,119 @@
|
||||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES
|
||||
NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE
|
||||
AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION
|
||||
ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE
|
||||
OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS
|
||||
LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION
|
||||
OR WORKS PROVIDED HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer exclusive
|
||||
Copyright and Related Rights (defined below) upon the creator and subsequent
|
||||
owner(s) (each and all, an "owner") of an original work of authorship and/or
|
||||
a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later claims
|
||||
of infringement build upon, modify, incorporate in other works, reuse and
|
||||
redistribute as freely as possible in any form whatsoever and for any purposes,
|
||||
including without limitation commercial purposes. These owners may contribute
|
||||
to the Commons to promote the ideal of a free culture and the further production
|
||||
of creative, cultural and scientific works, or to gain reputation or greater
|
||||
distribution for their Work in part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with
|
||||
a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or
|
||||
her Copyright and Related Rights in the Work and the meaning and intended
|
||||
legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be protected
|
||||
by copyright and related or neighboring rights ("Copyright and Related Rights").
|
||||
Copyright and Related Rights include, but are not limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work, subject
|
||||
to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal protection
|
||||
of databases, and under any national implementation thereof, including any
|
||||
amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time extensions),
|
||||
(iii) in any current or future medium and for any number of copies, and (iv)
|
||||
for any purpose whatsoever, including without limitation commercial, advertising
|
||||
or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the
|
||||
benefit of each member of the public at large and to the detriment of Affirmer's
|
||||
heirs and successors, fully intending that such Waiver shall not be subject
|
||||
to revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account Affirmer's
|
||||
express Statement of Purpose. In addition, to the extent the Waiver is so
|
||||
judged Affirmer hereby grants to each affected person a royalty-free, non
|
||||
transferable, non sublicensable, non exclusive, irrevocable and unconditional
|
||||
license to exercise Affirmer's Copyright and Related Rights in the Work (i)
|
||||
in all territories worldwide, (ii) for the maximum duration provided by applicable
|
||||
law or treaty (including future time extensions), (iii) in any current or
|
||||
future medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional purposes
|
||||
(the "License"). The License shall be deemed effective as of the date CC0
|
||||
was applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder of
|
||||
the License, and in such case Affirmer hereby affirms that he or she will
|
||||
not (i) exercise any of his or her remaining Copyright and Related Rights
|
||||
in the Work or (ii) assert any associated claims and causes of action with
|
||||
respect to the Work, in either case contrary to Affirmer's express Statement
|
||||
of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered,
|
||||
licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or other
|
||||
defects, accuracy, or the present or absence of errors, whether or not discoverable,
|
||||
all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims
|
||||
responsibility for obtaining any necessary consents, permissions or other
|
||||
rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a party
|
||||
to this document and has no duty or obligation with respect to this CC0 or
|
||||
use of the Work.
|
||||
@@ -2,11 +2,17 @@
|
||||
|
||||
AudioTube is a client for YouTube Music.
|
||||
|
||||
<a href='https://flathub.org/apps/details/org.kde.audiotube'><img width='190px' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-i-en.png'/></a>
|
||||
|
||||
## Links
|
||||
* Project page: https://invent.kde.org/plasma-mobile/audiotube
|
||||
* File issues: https://bugs.kde.org/describecomponents.cgi?product=audiotube
|
||||
|
||||
# Dependencies
|
||||
|
||||
It depends on Qt and Kirigami in addition to a few python packages:
|
||||
It depends on Qt, Kirigami, KI18n, KCoreAddons and KCrash in addition to a few python packages:
|
||||
* ytmusicapi
|
||||
* youtube_dl
|
||||
* yt_dlp
|
||||
|
||||
YouTube uses webp images for the cover art, so you will need to install qtimageformats.
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import ytmusicapi; print(ytmusicapi.version('ytmusicapi'))" RESULT_VARIABLE YTMUSICAPI_CHECK_RESULT OUTPUT_VARIABLE YTMusicAPI_VERSION)
|
||||
|
||||
string(STRIP ${YTMusicAPI_VERSION} YTMusicAPI_VERSION)
|
||||
|
||||
if (${YTMUSICAPI_CHECK_RESULT} EQUAL 0)
|
||||
set(YTMusicAPI_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(YTMusicAPI
|
||||
FOUND_VAR
|
||||
YTMusicAPI_FOUND
|
||||
REQUIRED_VARS
|
||||
Python3_EXECUTABLE
|
||||
VERSION_VAR
|
||||
YTMusicAPI_VERSION
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import yt_dlp" RESULT_VARIABLE YTDLP_CHECK_RESULT)
|
||||
|
||||
if (${YTDLP_CHECK_RESULT} EQUAL 0)
|
||||
set(Ytdlp_FOUND TRUE)
|
||||
endif()
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "python3-youtube_dl",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"youtube_dl\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/94/a0/b8325b524700daae1c04a6156473ab7091d44071353f1d7c9e66b9c7f019/youtube_dl-2021.4.26.tar.gz",
|
||||
"sha256": "6f311ffaf8b88cdcf27a2301a2272455e213bdb780aa447246933a3da4532879"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "python3-yt-dlp",
|
||||
"buildsystem": "simple",
|
||||
"build-commands": [
|
||||
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"yt-dlp\" --no-build-isolation"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/2a/18/70c32fe9357f3eea18598b23aa9ed29b1711c3001835f7cf99a9818985d0/Brotli-1.0.9.zip",
|
||||
"sha256": "4d1b810aa0ed773f81dceda2cc7b403d01057458730e309856356d4ef4188438"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/71/4c/3db2b8021bd6f2f0ceb0e088d6b2d49147671f25832fb17970e9b583d742/certifi-2022.12.7-py3-none-any.whl",
|
||||
"sha256": "4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/03/ee/114d7016d2e34f341e212fefb5e7bd87785077ebcfff0ad23a497c70eea1/mutagen-1.46.0-py3-none-any.whl",
|
||||
"sha256": "8af0728aa2d5c3ee5a727e28d0627966641fddfe804c23eabb5926a4d770aed5"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/5d/22/575c7dd7c86843e07a791cfa2143e7292d6b380f5a7cce966a49b9d6c9f4/pycryptodomex-3.16.0.tar.gz",
|
||||
"sha256": "e9ba9d8ed638733c9e95664470b71d624a6def149e2db6cc52c1aca5a6a2df1d"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/85/dc/549a807a53c13fd4a8dac286f117a7a71260defea9ec0c05d6027f2ae273/websockets-10.4.tar.gz",
|
||||
"sha256": "eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/a7/49/b49e0ae6fdc959235ecb89a3a5be77dd050493dc30845f89482fb83e38b4/yt_dlp-2023.1.6-py2.py3-none-any.whl",
|
||||
"sha256": "bcac3231e2022cad128a83f69948c845b364b2a85fde53415378f7c199808849"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
@@ -7,33 +7,33 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/cb/cf/871177f1fc795c6c10787bc0e1f27bb6cf7b81dbde399fd35860472cecbc/urllib3-1.26.4.tar.gz",
|
||||
"sha256": "e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
|
||||
"url": "https://files.pythonhosted.org/packages/71/4c/3db2b8021bd6f2f0ceb0e088d6b2d49147671f25832fb17970e9b583d742/certifi-2022.12.7-py3-none-any.whl",
|
||||
"sha256": "4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ea/b7/e0e3c1c467636186c39925827be42f16fee389dc404ac29e930e9136be70/idna-2.10.tar.gz",
|
||||
"sha256": "b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"
|
||||
"url": "https://files.pythonhosted.org/packages/96/d7/1675d9089a1f4677df5eb29c3f8b064aa1e70c1251a0a8a127803158942d/charset-normalizer-3.0.1.tar.gz",
|
||||
"sha256": "ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/ee/2d/9cdc2b527e127b4c9db64b86647d567985940ac3698eeabc7ffaccb4ea61/chardet-4.0.0.tar.gz",
|
||||
"sha256": "0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"
|
||||
"url": "https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl",
|
||||
"sha256": "90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/06/a9/cd1fd8ee13f73a4d4f491ee219deeeae20afefa914dfb4c130cfc9dc397a/certifi-2020.12.5.tar.gz",
|
||||
"sha256": "1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"
|
||||
"url": "https://files.pythonhosted.org/packages/d2/f4/274d1dbe96b41cf4e0efb70cbced278ffd61b5c7bb70338b62af94ccb25b/requests-2.28.2-py3-none-any.whl",
|
||||
"sha256": "64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/6b/47/c14abc08432ab22dc18b9892252efaf005ab44066de871e72a38d6af464b/requests-2.25.1.tar.gz",
|
||||
"sha256": "27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"
|
||||
"url": "https://files.pythonhosted.org/packages/fe/ca/466766e20b767ddb9b951202542310cba37ea5f2d792dae7589f1741af58/urllib3-1.26.14-py2.py3-none-any.whl",
|
||||
"sha256": "75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://files.pythonhosted.org/packages/61/b5/da439d5f75db7ff17790b19136c835f9a315530436ee7bc9d75aeea2f6e5/ytmusicapi-0.16.0.tar.gz",
|
||||
"sha256": "ffde3fb5a78123ac59dee37fc1f32793f34f9a4fa3d3e69a1fc08064112c2b5d"
|
||||
"url": "https://files.pythonhosted.org/packages/14/a9/5ba638ca601c74f169e0e0b055526566f2fa6b6402233a29aba607dca58e/ytmusicapi-0.25.0-py3-none-any.whl",
|
||||
"sha256": "be355bb3409c0e6c25a95ffd92213bd216561cdd8a0493a36a82d1726ff6efb9"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
set -e
|
||||
|
||||
export GIT_CLONE_ARGS="--depth 1 --single-branch"
|
||||
@@ -12,5 +16,5 @@ else
|
||||
git -C flatpak-builder-tools pull
|
||||
fi
|
||||
|
||||
./flatpak-builder-tools/pip/flatpak-pip-generator youtube_dl
|
||||
./flatpak-builder-tools/pip/flatpak-pip-generator yt-dlp
|
||||
./flatpak-builder-tools/pip/flatpak-pip-generator ytmusicapi
|
||||
@@ -1,12 +1,203 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
-->
|
||||
<component type="desktop-application">
|
||||
<id>org.kde.audiotube</id>
|
||||
<name>AudioTube</name>
|
||||
<name xml:lang="ar">تيوب الصوتي</name>
|
||||
<name xml:lang="az">AudioTube</name>
|
||||
<name xml:lang="ca">AudioTube</name>
|
||||
<name xml:lang="ca-valencia">AudioTube</name>
|
||||
<name xml:lang="cs">AudioTube</name>
|
||||
<name xml:lang="de">AudioTube</name>
|
||||
<name xml:lang="en-GB">AudioTube</name>
|
||||
<name xml:lang="es">AudioTube</name>
|
||||
<name xml:lang="eu">AudioTube</name>
|
||||
<name xml:lang="fi">AudioTube</name>
|
||||
<name xml:lang="fr">AudioTube</name>
|
||||
<name xml:lang="hi">ओडियो-ट्यूब</name>
|
||||
<name xml:lang="id">AudioTube</name>
|
||||
<name xml:lang="it">AudioTube</name>
|
||||
<name xml:lang="ka">AudioTube</name>
|
||||
<name xml:lang="ko">AudioTube</name>
|
||||
<name xml:lang="nl">AudioTube</name>
|
||||
<name xml:lang="nn">AudioTube</name>
|
||||
<name xml:lang="pa">ਆਡੀਓ-ਟਿਊਬ</name>
|
||||
<name xml:lang="pl">AudioTube</name>
|
||||
<name xml:lang="pt">AudioTube</name>
|
||||
<name xml:lang="pt-BR">AudioTube</name>
|
||||
<name xml:lang="ro">AudioTube</name>
|
||||
<name xml:lang="ru">AudioTube</name>
|
||||
<name xml:lang="sk">AudioTube</name>
|
||||
<name xml:lang="sl">AudioTube</name>
|
||||
<name xml:lang="sv">AudioTube</name>
|
||||
<name xml:lang="tr">AudioTube</name>
|
||||
<name xml:lang="uk">AudioTube</name>
|
||||
<name xml:lang="x-test">xxAudioTubexx</name>
|
||||
<name xml:lang="zh-CN">AudioTube</name>
|
||||
<summary>Convergent YouTube Music client</summary>
|
||||
<summary xml:lang="ar">عميل موسيقى يوتيوب متعدد المنصات</summary>
|
||||
<summary xml:lang="az">Birləşmiş YouTube Musiqi müştərisi</summary>
|
||||
<summary xml:lang="ca">Client convergent de música de YouTube</summary>
|
||||
<summary xml:lang="ca-valencia">Client convergent de música de YouTube</summary>
|
||||
<summary xml:lang="de">Konvergentes YouTube-Musikprogramm</summary>
|
||||
<summary xml:lang="en-GB">Convergent YouTube Music client</summary>
|
||||
<summary xml:lang="es">Cliente de música de YouTube convergente</summary>
|
||||
<summary xml:lang="eu">YouTube Music bezero konbergentea</summary>
|
||||
<summary xml:lang="fi">Mukautuva YouTube Music -asiakas</summary>
|
||||
<summary xml:lang="fr">Client convergent pour musique sur YouTube</summary>
|
||||
<summary xml:lang="hi">अभिसृत यूट्यूब संगीत क्लाएंट</summary>
|
||||
<summary xml:lang="id">Klien YouTube Music konvergen</summary>
|
||||
<summary xml:lang="it">Client YouTube Music convergente</summary>
|
||||
<summary xml:lang="ka">YouTube Music -ის კონვერგენტული კლიენტი</summary>
|
||||
<summary xml:lang="ko">올인원 YouTube Music 클라이언트</summary>
|
||||
<summary xml:lang="nl">Convergente muziekclient van YouTube</summary>
|
||||
<summary xml:lang="nn">YouTube Music-klient, tilpassa ulike brukarflater</summary>
|
||||
<summary xml:lang="pl">Adaptacyjny program do YouTube Music</summary>
|
||||
<summary xml:lang="pt">Cliente de música do YouTube convergente</summary>
|
||||
<summary xml:lang="pt-BR">Um cliente convergente para o YouTube Music</summary>
|
||||
<summary xml:lang="ro">Client convergent de muzică pentru YouTube</summary>
|
||||
<summary xml:lang="ru">Клиент для YouTube Music</summary>
|
||||
<summary xml:lang="sl">Konvergentni odjemalec glasbe YouTube</summary>
|
||||
<summary xml:lang="sv">Konvergent YouTube-musikprogram</summary>
|
||||
<summary xml:lang="tr">Yakınsak YouTube Müzik İstemcisi</summary>
|
||||
<summary xml:lang="uk">Зручний музичний клієнт YouTube</summary>
|
||||
<summary xml:lang="x-test">xxConvergent YouTube Music clientxx</summary>
|
||||
<summary xml:lang="zh-CN">桌面和移动设备通用 YouTube Music 客户端</summary>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-2.0+</project_license>
|
||||
<developer_name>KDE Community</developer_name>
|
||||
<developer_name xml:lang="ar">مجتمع كدي</developer_name>
|
||||
<developer_name xml:lang="az">KDE İcması</developer_name>
|
||||
<developer_name xml:lang="ca">La comunitat KDE</developer_name>
|
||||
<developer_name xml:lang="ca-valencia">La comunitat KDE</developer_name>
|
||||
<developer_name xml:lang="cs">Komunita KDE</developer_name>
|
||||
<developer_name xml:lang="de">KDE-Gemeinschaft</developer_name>
|
||||
<developer_name xml:lang="en-GB">KDE Community</developer_name>
|
||||
<developer_name xml:lang="es">Comunidad KDE</developer_name>
|
||||
<developer_name xml:lang="eu">KDE komunitatea</developer_name>
|
||||
<developer_name xml:lang="fi">KDE-yhteisö</developer_name>
|
||||
<developer_name xml:lang="fr">Communauté de KDE</developer_name>
|
||||
<developer_name xml:lang="hi">केडीई समुदाय</developer_name>
|
||||
<developer_name xml:lang="id">Komunitas KDE</developer_name>
|
||||
<developer_name xml:lang="it">Comunità KDE</developer_name>
|
||||
<developer_name xml:lang="ka">KDE-ის საზოგადოება</developer_name>
|
||||
<developer_name xml:lang="ko">KDE 커뮤니티</developer_name>
|
||||
<developer_name xml:lang="nl">KDE-gemeenschap</developer_name>
|
||||
<developer_name xml:lang="nn">KDE-fellesskapet</developer_name>
|
||||
<developer_name xml:lang="pa">ਕੇਡੀਈ ਕਮਿਊਨਟੀ</developer_name>
|
||||
<developer_name xml:lang="pl">Społeczność KDE</developer_name>
|
||||
<developer_name xml:lang="pt">Comunidade do KDE</developer_name>
|
||||
<developer_name xml:lang="pt-BR">A Comunidade KDE</developer_name>
|
||||
<developer_name xml:lang="ro">Comunitatea KDE</developer_name>
|
||||
<developer_name xml:lang="ru">Сообщество KDE</developer_name>
|
||||
<developer_name xml:lang="sk">KDE komunita</developer_name>
|
||||
<developer_name xml:lang="sl">Skupnost KDE</developer_name>
|
||||
<developer_name xml:lang="sv">KDE-gemenskapen</developer_name>
|
||||
<developer_name xml:lang="tr">KDE Topluluğu</developer_name>
|
||||
<developer_name xml:lang="uk">Спільнота KDE</developer_name>
|
||||
<developer_name xml:lang="x-test">xxKDE Communityxx</developer_name>
|
||||
<developer_name xml:lang="zh-CN">KDE 社区</developer_name>
|
||||
<content_rating type="oars-1.0"/>
|
||||
<url type="homepage">https://apps.kde.org/en/audiotube</url>
|
||||
<releases>
|
||||
<release version="23.01" date="2023-01-30">
|
||||
<url>https://plasma-mobile.org/2023/01/30/january-blog-post/</url>
|
||||
</release>
|
||||
<release version="22.11" date="2022-11-30">
|
||||
<url>https://plasma-mobile.org/2022/11/30/plasma-mobile-gear-22-11/</url>
|
||||
</release>
|
||||
<release version="22.09" date="2022-09-27">
|
||||
<url>https://www.plasma-mobile.org/2022/09/27/plasma-mobile-gear-22-09/</url>
|
||||
</release>
|
||||
<release version="22.06" date="2022-06-24">
|
||||
<url>https://www.plasma-mobile.org/2022/06/28/plasma-mobile-gear-22-06/</url>
|
||||
<description>
|
||||
<ul>
|
||||
<li>Add library page which shows favourites and most played songs</li>
|
||||
<li>Improve layout of the search popup</li>
|
||||
<li>General performance improvements including startup</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="22.04" date="2022-04-26">
|
||||
<url>https://www.plasma-mobile.org/2022/04/26/plasma-mobile-gear-22-04/</url>
|
||||
<description>
|
||||
<ul>
|
||||
<li>Update the version of ytmusicapi</li>
|
||||
<li>General code-refactoring and translation updates</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="22.02" date="2022-02-09">
|
||||
<url>https://www.plasma-mobile.org/2022/02/09/plasma-mobile-gear-22-02/</url>
|
||||
<description>
|
||||
<ul>
|
||||
<li>Update the version of ytmusicapi</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="21.12" date="2021-12-07">
|
||||
<url>https://www.plasma-mobile.org/2021/12/07/plasma-mobile-gear-21-12/</url>
|
||||
</release>
|
||||
<release version="21.08" date="2021-08-31">
|
||||
<url>https://www.plasma-mobile.org/2021/08/31/plasma-mobile-gear-21-08/</url>
|
||||
</release>
|
||||
</releases>
|
||||
<launchable type="desktop-id">org.kde.audiotube.desktop</launchable>
|
||||
<screenshots>
|
||||
<screenshot>
|
||||
<image>https://cdn.kde.org/screenshots/audiotube/library.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://cdn.kde.org/screenshots/audiotube/player.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://cdn.kde.org/screenshots/audiotube/desktop.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://cdn.kde.org/screenshots/audiotube/mobile_album.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://cdn.kde.org/screenshots/audiotube/mobile_playlist.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<recommends>
|
||||
<control>pointing</control>
|
||||
<control>keyboard</control>
|
||||
<control>touch</control>
|
||||
</recommends>
|
||||
<description>
|
||||
<p>AudioTube can search YouTube Music, list albums and artists, play automatically generated playlists, albums and allows to put your own playlist together.</p>
|
||||
<p xml:lang="ar">يمكن لتيوب الصوتي البحث في موسيقى يوتيوب، وعرض الألبومات والفنانين، وتشغيل القوائم والألبومات المولدة تلقائيًا، ويسمح لك بوضع قائمة التشغيل الخاصة بك معًا.</p>
|
||||
<p xml:lang="az">AudioTube YouTube Musiqi, albomların və ifaçıların siyahısı üzrə axtarış etməyə, yaradılmış mahnı siyahısı və albomları avtomatik oxutmağa və öz mahnı siyahınızı yaratmağa imkan verir.</p>
|
||||
<p xml:lang="ca">L'AudioTube pot cercar música a YouTube, llistar àlbums i artistes, reproduir llistes de reproducció generades automàticament, àlbums i permet crear la vostra pròpia llista de reproducció.</p>
|
||||
<p xml:lang="ca-valencia">L'AudioTube pot buscar música a YouTube, llistar àlbums i artistes, reproduir llistes de reproducció generades automàticament, àlbums i permet crear la vostra pròpia llista de reproducció.</p>
|
||||
<p xml:lang="de">AudioTube kann Musik auf YouTube durchsuchen, Alben und Interpreten auflisten, automatisch generierte Wiedergabelisten und Alben abspielen und erlaubt es, eine eigene Wiedergabeliste zusammenzustellen.</p>
|
||||
<p xml:lang="en-GB">AudioTube can search YouTube Music, list albums and artists, play automatically generated playlists, albums and allows to put your own playlist together.</p>
|
||||
<p xml:lang="es">AudioTube puede buscar música de YouTube, listar álbumes y artistas, reproducir las listas de reproducción generadas, álbumes y le permite crear su propia lista de reproducción.</p>
|
||||
<p xml:lang="eu">AudioTube-k YouTube Music-en bilatu dezake, albumak eta artistak zerrendatu, automatikoki sortutako jotze-zerrendak eta albumak jo, eta zure jotze-zerrenda osatzeko aukera eskaintzen dizu.</p>
|
||||
<p xml:lang="fi">AudioTube osaa etsiä YouTube Music -haun, albumien ja artistien luettelun, luotujen soittolistojen automaattisen toiston ja omien soittolistojen kokoamisen.</p>
|
||||
<p xml:lang="fr">AudioTube peut effectuer des recherches de musiques sur la partie « Musique » de YouTube, établir une liste d'albums et d'artistes, lire des listes de lecture générées automatiquement, des albums et permet de composer sa propre liste de lecture.</p>
|
||||
<p xml:lang="hi">ऑडियोट्यूब यूट्यूब संगीत खोज सकता है, एल्बम और कलाकारों की सूची बना सकता है, स्वचालित रूप से उत्पन्न की गई गीतसूची, एल्बम बजा सकता है और आपकी अपनी खुद की प्लेलिस्ट को एक साथ रखने में मदद करता है।</p>
|
||||
<p xml:lang="id">AudioTube dapat menelusuri YouTube Music, daftarkan album dan artis, putar daftar putar dan yang dibuat secara otomatis dan album, dan memungkinkan Anda untuk membuat daftar putar Anda sendiri.</p>
|
||||
<p xml:lang="it">AudioTube può eseguire ricerche su YouTube Music, elencare album e artisti, riprodurre scalette e album generati automaticamente e ti consente di creare la tua scaletta.</p>
|
||||
<p xml:lang="ka">AudioTube -ს შეუძლია მოძებნოს მუსიკა YouTube-ზე, გაჩვენოთ ალბომებისა და შემსრულებლების სია, დაუკრას დაგენერირებული დასაკრავი სიები, ალბომები და საშუალებას გაძლევთ, თქვენი დასაკრავი სია შექმნათ.</p>
|
||||
<p xml:lang="ko">AudioTube는 YouTube Music을 검색하고, 앨범과 아티스트를 표시하고, 자동 생성된 재생 목록, 앨범을 재생하고, 사용자 정의 재생 목록을 만들 수 있습니다.</p>
|
||||
<p xml:lang="nl">AudioTube kan in YouTube Music zoeken, een lijst maken van albums en artiesten, automatically gegenereerde afspeellijsten, albums afspelen en biedt u het samenstellen van uw eigen afspeellijst.</p>
|
||||
<p xml:lang="nn">Med AudioTube kan du søkja på YouTube Music, visa album og artistar, spela automatiske genererte spelelister og album samt laga eigne spelelister.</p>
|
||||
<p xml:lang="pl">AudioTube może przeszukiwać serwis YouTube Music, wypisać albumy i wykonawców, odtwarzać samoczynnie utworzone listy odtwarzania, albumy oraz umożliwia tworzenie własnych list odtwarzania.</p>
|
||||
<p xml:lang="pt">O AudioTube consegue pesquisar no YouTube Music, enumerar os álbuns e artistas, reproduzir listas geradas automaticamente, álbuns e permite-lhe reproduzir as suas próprias listas de reprodução.</p>
|
||||
<p xml:lang="pt-BR">O AudioTube pode pesquisar no YouTube Music, listar álbuns e artistas, rodar listas de reprodução geradas automaticamente, álbuns inteiros, e criar a sua própria lista de reprodução.</p>
|
||||
<p xml:lang="ru">AudioTube позволяет выполнять поиск в сервисе YouTube Music, просматривать списки найденных альбомов и исполнителей, проигрывать автоматически созданные списки воспроизведения и альбомы, а также использовать свои собственные списки воспроизведения.</p>
|
||||
<p xml:lang="sl">AudioTube lahko išče po YouTube Music, izdela sezname albumov in avtorjev, samodejno predvaja generirane sezname, albume in sestavlja vaše sezname predvajanja.</p>
|
||||
<p xml:lang="sv">AudioTube kan söka på YouTube Music, lista album och artister, spela upp automatiskt genererade spellistor, albums och låter dig sammanställa egna spellistor.</p>
|
||||
<p xml:lang="tr">AudioTube, YouTube Müzik'te arama yapabilir; albümleri, sanatçıları listeler; kendiliğinden oluşturulmuş çalma listelerini, albümleri çalar ve kendi çalma listenizi oluşturmanıza izin verir.</p>
|
||||
<p xml:lang="uk">AudioTube може виконувати пошук на YouTube Music, показувати списки альбомів та виконавців, відтворювати створені автоматично списки відтворення, альбоми та надає вам змогу створювати власні списки відворення.</p>
|
||||
<p xml:lang="x-test">xxAudioTube can search YouTube Music, list albums and artists, play automatically generated playlists, albums and allows to put your own playlist together.xx</p>
|
||||
<p xml:lang="zh-CN">AudioTube 可以搜索 YouTube Music 的内容,列出专辑和艺人,播放自动生成的播放列表,还可以自行制作播放列表。</p>
|
||||
</description>
|
||||
</component>
|
||||
@@ -1,6 +1,68 @@
|
||||
[Desktop Entry]
|
||||
Name=AudioTube
|
||||
Name[ar]=تيوب الصوتي
|
||||
Name[az]=AudioTube
|
||||
Name[ca]=AudioTube
|
||||
Name[ca@valencia]=AudioTube
|
||||
Name[cs]=AudioTube
|
||||
Name[de]=AudioTube
|
||||
Name[en_GB]=AudioTube
|
||||
Name[es]=AudioTube
|
||||
Name[eu]=AudioTube
|
||||
Name[fi]=AudioTube
|
||||
Name[fr]=AudioTube
|
||||
Name[hi]=ओडियो-ट्यूब
|
||||
Name[id]=AudioTube
|
||||
Name[it]=AudioTube
|
||||
Name[ka]=AudioTube
|
||||
Name[ko]=AudioTube
|
||||
Name[nl]=AudioTube
|
||||
Name[nn]=AudioTube
|
||||
Name[pa]=ਆਡੀਓ-ਟਿਊਬ
|
||||
Name[pl]=AudioTube
|
||||
Name[pt]=AudioTube
|
||||
Name[pt_BR]=AudioTube
|
||||
Name[ro]=AudioTube
|
||||
Name[ru]=AudioTube
|
||||
Name[sk]=AudioTube
|
||||
Name[sl]=AudioTube
|
||||
Name[sv]=AudioTube
|
||||
Name[tr]=AudioTube
|
||||
Name[uk]=AudioTube
|
||||
Name[x-test]=xxAudioTubexx
|
||||
Name[zh_CN]=AudioTube
|
||||
Comment=YouTube Music client
|
||||
Comment[ar]=عميل يوتيوب ميوزيك
|
||||
Comment[az]=YouTube Musiqi müştərisi
|
||||
Comment[ca]=Client de música de YouTube
|
||||
Comment[ca@valencia]=Client de música de YouTube
|
||||
Comment[cs]=Hudební klient YouTube
|
||||
Comment[de]=YouTube-Musikprogramm
|
||||
Comment[en_GB]=YouTube Music client
|
||||
Comment[es]=Cliente de música de YouTube
|
||||
Comment[eu]=YouTube Music bezeroa
|
||||
Comment[fi]=YouTube Music -asiakas
|
||||
Comment[fr]=Client de musique sur Youtube
|
||||
Comment[hi]=यूट्यूब संगीत क्लाएंट
|
||||
Comment[id]=Klien YouTube Music
|
||||
Comment[it]=Client YouTube Music
|
||||
Comment[ka]=YouTube Music -ის კლიენტი
|
||||
Comment[ko]=YouTube Music 클라이언트
|
||||
Comment[nl]=Muziekclient van YouTube
|
||||
Comment[nn]=YouTube Music-klient
|
||||
Comment[pa]=ਯੂਟਿਊਬ ਸੰਗੀਤ ਕਲਾਈਂਟ
|
||||
Comment[pl]=Program do YouTube Music
|
||||
Comment[pt]=Cliente do YouTube Music
|
||||
Comment[pt_BR]=Cliente YouTube Music
|
||||
Comment[ro]=Client de muzică pentru YouTube
|
||||
Comment[ru]=Клиент для YouTube Music
|
||||
Comment[sk]=Hudobný klient YouTube
|
||||
Comment[sl]=Glasbeni odjemalec Youtube
|
||||
Comment[sv]=YouTube-musikprogram
|
||||
Comment[tr]=YouTube Müzik istemcisi
|
||||
Comment[uk]=Музичний клієнт YouTube
|
||||
Comment[x-test]=xxYouTube Music clientxx
|
||||
Comment[zh_CN]=YouTube Music 客户端
|
||||
Version=1.0
|
||||
Exec=audiotube
|
||||
Icon=org.kde.audiotube
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "org.kde.audiotube",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "5.15",
|
||||
"runtime-version": "5.15-22.08",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"command": "audiotube",
|
||||
"tags": ["nightly"],
|
||||
@@ -21,14 +21,14 @@
|
||||
],
|
||||
|
||||
"modules": [
|
||||
"flatpak/python3-youtube_dl.json",
|
||||
"flatpak/python3-yt-dlp.json",
|
||||
"flatpak/python3-ytmusicapi.json",
|
||||
{
|
||||
"name": "pybind11",
|
||||
"config-opts": ["-DPYBIND11_FINDPYTHON=ON", "-DPYBIND11_TEST=OFF"],
|
||||
"buildsystem": "cmake-ninja",
|
||||
"builddir": true,
|
||||
"sources": [ { "type": "git", "url": "https://github.com/pybind/pybind11", "tag": "v2.6.2" } ]
|
||||
"sources": [ { "type": "git", "url": "https://github.com/pybind/pybind11", "tag": "v2.10.3" } ]
|
||||
},
|
||||
{
|
||||
"name": "org.kde.audiotube",
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Zayed Al-Saidi <[email protected]>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-02-02 11:59+0400\n"
|
||||
"Last-Translator: Zayed Al-Saidi <[email protected]>\n"
|
||||
"Language-Team: ar\n"
|
||||
"Language: ar\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
|
||||
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||
"X-Generator: Lokalize 21.12.3\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "زايد السعيدي"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "شغّل"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "اخلط"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "افتح في المتصفّح"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "الألبوم • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "المزيد"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "راديو"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "الفنّانون"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "تشغيل الفيديو غير مدعوم حتى الآن. هل تريد تشغيل صوت فقط من \"%1\"؟"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "الألبومات"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "فردي"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "أغاني"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "الفيديوهات"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "حسنًا"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "ألغِ"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "المفضلة"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "أظهر الكلّ"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "الأكثر تشغيلا"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "الأغاني المشغلة"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "تيوب الصوتي"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "المشغل الآن"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "صُفّ"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "الكلمات"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "أزل المسار"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "لا يوجد وسائط تعمل"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "المكتبة"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "ابحث"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "الأغاني المشغلة"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "قائمة غير معروفة من الأغاني"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "لا يوجد أي أغنية بعد"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "قائمة التشغيل"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "البحوث الأخيرة:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "الفنّانون"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "قوائم التّشغيل"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "مجهول"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "لا يوجد تطابق من البحوث الأخيرة"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "أزل من تاريخ البحث"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr " اطوِ الشريط الجانبي"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "شغل التالي"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "أضف للطابور"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "أزل المفضلة"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "أضف للمفضلة"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "أزل من التّاريخ"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "الأغاني المفضّلة"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "عُد"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "اعثر على موسيقى على موسيقى يوتيوب"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "أضف إلى قائمة التّشغيل"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "شغل التالي"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "امسح"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "ألبث"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "وسع"
|
||||
@@ -0,0 +1,278 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Kheyyam Gojayev <[email protected]>, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-06-19 12:16+0400\n"
|
||||
"Last-Translator: Kheyyam <[email protected]>\n"
|
||||
"Language-Team: Azerbaijani <[email protected]>\n"
|
||||
"Language: az\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 22.04.2\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Xəyyam Qocayev"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Başladın"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Qarışıq"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "İfaçılar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Video göstərilməsi hələlik dəstəklənmir. Siz yalnız \"%1\" videosunun səsini "
|
||||
"oynatmaq istəyirsiniz?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albomlar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Musiqilər"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Mahnılar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videolar"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OLDU"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "İmtina"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Süçilmişlər"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Hamısı göstərilsin"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Daha çox dinlənilən"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Played Songs"
|
||||
msgid "played Songs"
|
||||
msgstr "Oxudulan mahnılar"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "İndi səslənir"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Növbə"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Mahnını silin"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Media faylı oynadılmır"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Axtarın"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Oxudulan mahnılar"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Naməlum mahnı siyahısı"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Hələlik burada mahnılar yoxdur"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "Mahnı siyahıları"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "İfaçılar"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Mahnı siyahıları"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Bilinməyən"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Sonrakını oxudun"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Süçilmişlər"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Add Favourite"
|
||||
msgstr "Süçilmişlər"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Seçilmiş mahnılar"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Geriyə"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Musiqini YouTube Musiqi-də tapın"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Mahnı siyahısına əlavə edin"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Sonrakını başladın"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Təmizləyin"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Fasilə"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Açmaq"
|
||||
@@ -0,0 +1,252 @@
|
||||
# Translation of audiotube.po to Catalan
|
||||
# Copyright (C) 2021-2023 This_file_is_part_of_KDE
|
||||
# This file is distributed under the license LGPL version 2.1 or
|
||||
# version 3 or later versions approved by the membership of KDE e.V.
|
||||
#
|
||||
# Antoni Bella Pérez <[email protected]>, 2021.
|
||||
# Josep M. Ferrer <[email protected]>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 10:54+0100\n"
|
||||
"Last-Translator: Josep M. Ferrer <[email protected]>\n"
|
||||
"Language-Team: Catalan <[email protected]>\n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 20.12.0\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Antoni Bella"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Reprodueix"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Barreja"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Obre en el navegador"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Àlbum • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Més"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Ràdio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Encara no s'admet la reproducció de vídeo. Voleu reproduir només l'àudio de "
|
||||
"«%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Àlbums"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Individuals"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Cançons"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Vídeos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "D'acord"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Preferides"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Mostra-ho tot"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Les més reproduïdes"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Cançons reproduïdes"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Ara s'està reproduint"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Cua"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Lletra"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Elimina la pista"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "No s'està reproduint cap suport"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Biblioteca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Cançons reproduïdes"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Llista desconeguda de cançons"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Encara no hi ha cap cançó"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Llista de reproducció"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Cerques anteriors:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistes"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Llistes de reproducció"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Desconeguda"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "No hi ha cerques anteriors coincidents"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "elimina de l'historial de cerques"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Redueix la barra lateral"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Reprodueix el següent"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Afegeix a la cua"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Elimina de les preferides"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Afegeix a les preferides"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Elimina de l'historial"
|
||||
@@ -0,0 +1,252 @@
|
||||
# Translation of audiotube.po to Catalan (Valencian)
|
||||
# Copyright (C) 2021-2023 This_file_is_part_of_KDE
|
||||
# This file is distributed under the license LGPL version 2.1 or
|
||||
# version 3 or later versions approved by the membership of KDE e.V.
|
||||
#
|
||||
# Antoni Bella Pérez <[email protected]>, 2021.
|
||||
# Josep M. Ferrer <[email protected]>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 10:54+0100\n"
|
||||
"Last-Translator: Josep M. Ferrer <[email protected]>\n"
|
||||
"Language-Team: Catalan <[email protected]>\n"
|
||||
"Language: ca@valencia\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 20.12.0\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Antoni Bella"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Reproduïx"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Barreja"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Obri en el navegador"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Àlbum • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Més"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Ràdio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Encara no s'admet la reproducció de vídeo. Voleu reproduir només l'àudio de "
|
||||
"«%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Àlbums"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Individuals"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Cançons"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Vídeos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "D'acord"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Preferides"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Mostra-ho tot"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Les més reproduïdes"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Cançons reproduïdes"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Ara s'està reproduint"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Cua"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Lletra"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Elimina la pista"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "No s'està reproduint cap suport"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Biblioteca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Busca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Cançons reproduïdes"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Llista desconeguda de cançons"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Encara no hi ha cap cançó"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Llista de reproducció"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Busques anteriors:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistes"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Llistes de reproducció"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Desconeguda"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "No hi ha busques anteriors coincidents"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "elimina de l'historial de busques"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Reduïx la barra lateral"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Reproduïx el següent"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Afig a la cua"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Elimina de les preferides"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Afig a les preferides"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Elimina de l'historial"
|
||||
@@ -0,0 +1,249 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Vit Pelcak <[email protected]>, 2021, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-06-28 13:58+0200\n"
|
||||
"Last-Translator: Vit Pelcak <[email protected]>\n"
|
||||
"Language-Team: Czech <[email protected]>\n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Lokalize 22.04.2\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Vít Pelčák"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Přehrát"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Zamíchat"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Otevřít v prohlížeči"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Více"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Rádio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Umělec"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Přehrávání videa ještě není podporováno. Chcete z \"%1\" přehrávat pouze "
|
||||
"zvuk?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Alba"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Samotné"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Písně"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videa"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušit"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Oblíbené"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Zobrazit vše"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Nejčastěji hrané"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Nyní přehrávám"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Fronta"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Text písně"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Odstranit skladbu"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Nepřehrává se žádné médium"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Knihovna"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Hledat"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Přehrané skladby"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Neznámý seznam skladeb"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Zatím zde nejsou žádné skladby"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Seznam skladeb"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Umělci"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Seznamy skladeb"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Neznámý"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Přehrát následující"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,278 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Burkhard Lück <[email protected]>, 2021.
|
||||
# Frederik Schwarzer <[email protected]>, 2021, 2022, 2023.
|
||||
# Frank Steinmetzger <[email protected]>, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-14 23:47+0100\n"
|
||||
"Last-Translator: Frederik Schwarzer <[email protected]>\n"
|
||||
"Language-Team: German <[email protected]>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Deutsches KDE-Übersetzerteam"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Wiedergabe"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Zufällig"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "In Browser öffnen"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Mehr"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Interpret"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Die Video-Wiedergabe wird noch nicht unterstützt. Möchten Sie nur die "
|
||||
"Audiospur von „%1“ abspielen?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Alben"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singles"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Songs"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favoriten"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Alle anzeigen"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Am meisten abgespielt"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Abgespielte Stücke"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Aktueller Titel"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Warteschlange"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Liedtext"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Stück entfernen"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Es werden keine Medien wiedergegeben"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Bibliothek"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Suchen"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Abgespielte Stücke"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Unbekannte Liste von Liedern"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Bisher keine Lieder hier"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Wiedergabeliste"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Vorherige Suchvorgänge:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Interpreten"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Wiedergabelisten"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Unbekannt"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Seitenleiste einklappen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Nächste Wiedergabe"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Zur Warteschlange hinzufügen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Favoriten entfernen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Favoriten hinzufügen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Lieblingsstücke"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Zurück"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Musik auf YouTube suchen"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Zur Wiedergabeliste hinzufügen"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Nächste Wiedergabe"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Löschen"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pause"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Erweitern"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Nur Audio abspielen"
|
||||
@@ -0,0 +1,277 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Steve Allewell <[email protected]>, 2021, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-12-31 15:53+0000\n"
|
||||
"Last-Translator: Steve Allewell <[email protected]>\n"
|
||||
"Language-Team: English <[email protected]>\n"
|
||||
"Language: en_GB\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 21.12.3\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Steve Allewell"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Play"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Shuffle"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Open in Browser"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "More"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artist"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albums"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singles"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Songs"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favourites"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Show All"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Most played"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "played Songs"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Now Playing"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Queue"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Lyrics"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Remove Track"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "No media playing"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Library"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Played Songs"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Unknown list of songs"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "No songs here yet"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Playlist"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Previous Searches:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artists"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Playlists"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Unknown"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Previous Searches:"
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Previous Searches:"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Collapse Sidebar"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Play Next"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Add to queue"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Remove Favourite"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Add Favourite"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Favourite Songs"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Back"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Find music on YouTube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Add to Playlist"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Play next"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Clear"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pause"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Expand"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Play only Audio"
|
||||
@@ -0,0 +1,278 @@
|
||||
# Spanish translations for audiotube.po package.
|
||||
# Copyright (C) 2021 This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Automatically generated, 2021.
|
||||
# Eloy Cuadra <[email protected]>, 2021, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-29 00:58+0100\n"
|
||||
"Last-Translator: Eloy Cuadra <[email protected]>\n"
|
||||
"Language-Team: Spanish <[email protected]>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Eloy Cuadra"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Reproducir"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Desordenar"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Abrir en el navegador"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Álbum • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Más"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"La reproducción de vídeo aún no está permitida. ¿Desea reproducir solo el "
|
||||
"sonido de «%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Álbumes"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Sencillos"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Canciones"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Vídeos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Aceptar"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favoritas"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Mostrar todas"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Más reproducidas"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "canciones reproducidas"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Reproduciendo"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Cola"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Letra"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Eliminar pista"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Ningún medio en reproducción"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Biblioteca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Canciones reproducidas"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Lista de canciones desconocida"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Todavía no contiene canciones"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Lista de reproducción"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Búsquedas anteriores:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistas"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Listas de reproducción"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Desconocido"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "No hay búsquedas anteriores coincidentes"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "eliminar del historial de búsqueda"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Contraer la barra lateral"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Reproducir siguiente"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Añadir a la cola"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Eliminar favorita"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Añadir favorita"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Eliminar del historial"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Canciones favoritas"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Volver"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Encuentre música en YouTube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Añadir a la lista de reproducción"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Reproducir siguiente"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Borrar todo"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pausar"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Expandir"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Reproducir solo el sonido"
|
||||
@@ -0,0 +1,279 @@
|
||||
# Translation for audiotube.po to Euskara/Basque (eu).
|
||||
# Copyright (C) 2021-2023 This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# KDE euskaratzeko proiektuko arduraduna <[email protected]>.
|
||||
#
|
||||
# Translators:
|
||||
# Iñigo Salvador Azurmendi <[email protected]>, 2021, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 21:02+0100\n"
|
||||
"Last-Translator: Iñigo Salvador Azurmendi <[email protected]>\n"
|
||||
"Language-Team: Basque <[email protected]>\n"
|
||||
"Language: eu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Iñigo Salvador Azurmendi"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Jo"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Nahastu"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Ireki arakatzailean"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Albuma • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Gehiago"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Irratia"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Oraindik ez dago bideoa atzera jotzeko euskarririk. «%1»(r)en audioa "
|
||||
"bakarrik jo nahi duzu?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albumak"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Banakoa"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Abestiak"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Bideoak"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Ados"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Utzi"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Gogokoak"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Erakutsi denak"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Gehien jotakoa"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "jotako abestiak"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Orain jotzen"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Ilara"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Hitzak"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Kendu pista"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Ez da euskarririk jotzen ari"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Liburutegia"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Bilatu"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Jotako abestiak"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Abesti zerrenda ezezaguna"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Hemen oraindik ez dago abestirik"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Jotze-zerrenda"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Aurreko bilaketak:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistak"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Jotze-zerrendak"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Ezezaguna"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Ez dago bat datorren aurreko bilaketarik"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "Kendu bilaketa-historiatik"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Tolestu Alboko-barra"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Jo hurrengoa"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Gehitu ilaran"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Kendu gogokoa"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Gehitu gogokoa"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Kendu historiatik"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Gogoko abestiak"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Atzera"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Aurkitu musika «Youtube Music»en"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Gehitu jotze-zerrendara"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Jo hurrengoa"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Garbitu"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Eten"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Zabaldu"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Audio bakarrik jo"
|
||||
@@ -0,0 +1,280 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Tommi Nieminen <[email protected]>, 2021, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-10-24 07:57+0300\n"
|
||||
"Last-Translator: Tommi Nieminen <[email protected]>\n"
|
||||
"Language-Team: Finnish <[email protected]>\n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 20.12.0\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Tommi Nieminen"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Toista"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Sekoita"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Avaa selaimeen"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "Artistit"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Videotoistoa ei vielä tueta. Haluatko toistaa videosta ”%1” vain äänen?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albumit"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singlet"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Kappaleet"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videot"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Peru"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Suosikit"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Näytä kaikki"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Soitetuimmat"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Played Songs"
|
||||
msgid "played Songs"
|
||||
msgstr "Soitetut kappaleet"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Nyt soi"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Jono"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Poista raita"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Mitään ei toisteta"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Etsi"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Soitetut kappaleet"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Tuntematon kappaleluettelo"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Ei vielä kappaleita"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "Soittolistat"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistit"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Soittolistat"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Tuntematon"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Toista seuraava"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Suosikit"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Add Favourite"
|
||||
msgstr "Suosikit"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Suosikkikappaleet"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Takaisin"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Etsi musiikkia Youtube Musicista"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Lisää soittolistaan"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Toista seuraava"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Tyhjennä"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Tauko"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Laajenna"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Toista vain ääni"
|
||||
@@ -0,0 +1,274 @@
|
||||
# Xavier Besnard <[email protected]>, 2021, 2022.
|
||||
# Xavier BESNARD <xavier.besnard]neuf.fr>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-29 10:52+0100\n"
|
||||
"Last-Translator: Xavier BESNARD <xavier.besnard]neuf.fr>\n"
|
||||
"Language-Team: fr\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Xavier Besnard"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Lire"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Mélanger"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Ouvrir dans un navigateur"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Et plus encore"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artiste"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"La lecture de vidéos n'est pas encore prise en charge. Voulez-vous vraiment "
|
||||
"lire uniquement l'audio de « %1 » ?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albums"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Titres uniques"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Chansons"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Vidéos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Ok"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favoris"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Tout afficher"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Les plus lus"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Titres lus"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "En cours de lecture"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Mettre en file d'attente"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Paroles"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Supprimer une piste"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Aucun média en lecture"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Bibliothèque"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Rechercher"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Titres lus"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Liste inconnue de titres"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Aucun titre ici encore"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Liste de lecture"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Recherches précédentes :"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistes"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Listes de lecture"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Inconnu"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Aucune correspondance avec les recherches précédentes"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "supprimer de l'historique de recherche"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Réduire la barre latérale"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Lire le suivant"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Ajouter à la file de lecture"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Supprimer un favori"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Ajouter un favori"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Supprimer de l'historique"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Titres favoris"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "En arrière"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Rechercher de la musique sur « YouTube Music »"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Ajouter à la liste de lecture"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Lire le suivant"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Effacer"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pause"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Développer"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Ne lire que l'audio"
|
||||
@@ -0,0 +1,272 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Raghavendra Kamath <[email protected]>, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2021-09-17 20:09+0530\n"
|
||||
"Last-Translator: Raghavendra Kamath <[email protected]>\n"
|
||||
"Language-Team: kde-hindi\n"
|
||||
"Language: hi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
||||
"X-Generator: Lokalize 21.08.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "राघवेंद्र कामत"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "बजाएँ"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "फेंटें"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "रेडियो"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "कलाकार"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"वीडियो चलाना अभी तक समर्थित नहीं है। क्या आप केवल \"%1\" का ध्वनी चलाना चाहते हैं?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "एल्बम्स"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "एक गीत"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "गीत"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "वीडियो"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "ओडियो-ट्यूब"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "No media playing"
|
||||
msgid "Now Playing"
|
||||
msgstr "कोई मीडिया नहीं बजा रहा है"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "गाना हटाएँ"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "कोई मीडिया नहीं बजा रहा है"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "खोजें"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "गीत-सूचीयाँ"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "कलाकार"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "गीत-सूचीयाँ"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "अज्ञात"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "अगला बजाएँ"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "यूट्यूब संगीत पर संगीत ढूंढें"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "गीत-सूची में जोड़ें"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "अगला बजाएँ"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "साफ करें"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "रोकें"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "विस्तृत करें"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "केवल ध्वनी चलाएँ"
|
||||
@@ -0,0 +1,264 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Linerly <[email protected]>, 2022, 2023.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-13 08:23+0700\n"
|
||||
"Last-Translator: Linerly <[email protected]>\n"
|
||||
"Language-Team: Indonesian <[email protected]>\n"
|
||||
"Language: id\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Linerly"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Putar"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Acak"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Buka di Peramban"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Lainnya"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artis"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Pemutaran video belum didukung. Apakah Anda ingin memutar audionya dari "
|
||||
"\"%1\" saja?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Album"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Single"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Lagu"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Video"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Oke"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Batalkan"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favorit"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Tampilkan Semua"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Paling banyak diputar"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Lagu yang telah diputar"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Sekarang Diputarkan"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Antrean"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Lirik"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Hapus Trek"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Tidak ada media yang diputarkan"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Cari"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Lagu yang telah diputar"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Daftar lagu yang tidak diketahui"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Belum ada lagu di sini"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Daftar Putar"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artis"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Daftar Putar"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Tidak diketahui"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Putar Berikutnya"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Tambahkan ke antrean"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Hapus Favorit"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Tambahkan Favorit"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Lagu Favorit"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Kembali"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Cari musik di YouTube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Tambahkan ke Daftar Putar"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Putar berikutnya"
|
||||
@@ -0,0 +1,276 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Vincenzo Reale <[email protected]>, 2021, 2022, 2023.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 19:12+0100\n"
|
||||
"Last-Translator: Vincenzo Reale <[email protected]>\n"
|
||||
"Language-Team: Italian <[email protected]>\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Vincenzo Reale"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Riproduci"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Mescola"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Apri nel browser"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Altro"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"La riproduzione dei video non è ancora supportata. Vuoi riprodurre solo "
|
||||
"l'audio di «%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Album"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singoli"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Brani"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Video"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Annulla"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Preferiti"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Mostra tutto"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Più riprodotti"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Brani riprodotti"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "In riproduzione"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Coda"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Testi"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Rimuovi traccia"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Nessun supporto in riproduzione"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Raccolta"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Brani riprodotti"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Elenco di brani sconosciuto"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Non c'è ancora alcun brano"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Scaletta"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Ricerche precedenti:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artisti"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Scalette"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Sconosciuto"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Nessuna ricerca precedente corrispondente"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "rimuovi dalla cronologia delle ricerche"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Contrai la barra laterale"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Riproduci successivo"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Aggiungi alla coda"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Rimuovi preferito"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Aggiungi preferito"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Rimuovi dalla cronologia"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Brani preferiti"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Indietro"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Trova musica su Youtube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Aggiungi alla scaletta"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Riproduci successivo"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Pulisci"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pausa"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Espandi"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Riproduci solo l'audio"
|
||||
@@ -0,0 +1,244 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2021-05-29 19:15-0700\n"
|
||||
"Last-Translator: Japanese KDE translation team <[email protected]>\n"
|
||||
"Language-Team: Japanese <[email protected]>\n"
|
||||
"Language: ja\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Accelerator-Marker: &\n"
|
||||
"X-Text-Markup: kde4\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr ""
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,264 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 08:44+0100\n"
|
||||
"Last-Translator: Temuri Doghonadze <[email protected]>\n"
|
||||
"Language-Team: Georgian <[email protected]>\n"
|
||||
"Language: ka\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Temuri Doghonadze"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "დაკვრა"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "შემთხვევით"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "ბრაუზერში გახსნა"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "ალბომი • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "მეტი"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "რადიო"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "შემსრულებელი"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"ვიდეოს დაკვრა ჯერ მხარდაჭერილი არაა. გნებავთ \"%1\"-ის მხოლოდ ხმა დავუკრა?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "ალბომები"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "სინგლები"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "სიმღერები"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "ვიდეო"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "კარგი"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "გაუქმენა"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "რჩეულები"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "ყველას ჩვენება"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "ხშირად დაკრულები"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "დაკრული სიმღერები"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "მიმდინარეობს დაკვრა"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "რიგი"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "ლირიკა"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "აუდიობილიკის წაშლა"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "არაფერს ვუკრავ"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "ბიბლიოთეკა"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "ძებნა"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "დაკრული სიმღერები"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "უცნობი სიმღერების სია"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "აქ ჯერ სიმღერები არაა"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "დასაკრავი სია"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "წინა ძებნები:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "შემსრულებლები"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "დასაკრავი სიები"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "უცნობი"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "წინა ძებნებს არ ემთხვევა"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "ძებნის ისტორიიდან წაშლა"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "გვერდითი ზოლის ჩაკეცვა"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "შემდეგის დაკვრა"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "რიგში ჩამატება"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "რჩეულის წაშლა"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "რჩეულის დამატება"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "ისტორიიდან წაშლა"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "რჩეული სიმღერები"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "უკან"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "იპოვეთ მუსიკა YouTube Music-ზე"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "დასაკრავი სიაში დამატება"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "შემდეგის დაკვრა"
|
||||
@@ -0,0 +1,279 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Shinjo Park <[email protected]>, 2021, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-10-03 14:20+0200\n"
|
||||
"Last-Translator: Shinjo Park <[email protected]>\n"
|
||||
"Language-Team: Korean <[email protected]>\n"
|
||||
"Language: ko\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Lokalize 21.12.3\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "박신조"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "재생"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "무순서 재생"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "브라우저로 열기"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "라디오"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "아티스트"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "비디오 재생은 지원하지 않습니다. \"%1\"의 오디오만 재생하시겠습니까?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "앨범"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "싱글"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "곡"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "비디오"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "확인"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "책갈피"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "모두 표시"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "가장 많이 재생됨"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Played Songs"
|
||||
msgid "played Songs"
|
||||
msgstr "재생한 노래"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "지금 재생 중"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "대기열에 추가"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "트랙 삭제"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "재생 중인 미디어 없음"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "검색"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "재생한 노래"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "알 수 없는 노래 목록"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "목록에 등록된 곡 없음"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "재생 목록"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "아티스트"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "재생 목록"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "알 수 없음"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "다음 재생"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Remove Favourite"
|
||||
msgstr "책갈피"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Add Favourite"
|
||||
msgstr "책갈피"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "책갈피에 등록된 노래"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "뒤로"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "YouTube Music에서 음악 찾기"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "재생 목록에 추가"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "다음 재생"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "지우기"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "일시 정지"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "확장"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "오디오만 재생"
|
||||
@@ -0,0 +1,276 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Freek de Kruijf <[email protected]>, 2021, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 12:41+0100\n"
|
||||
"Last-Translator: Freek de Kruijf <[email protected]>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Freek de Kruijf - 2021 t/m 2023"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Afspelen"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Willekeurig afspelen"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "In browser openen"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Meer"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artiest"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Afspelen van video wordt nog niet ondersteund. Wilt u alleen het geluid van "
|
||||
"\"%1\" afspelen?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albums"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Enkelvoudige"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Songs"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Video's"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Annuleren"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favorieten"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Alles tonen"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Meest afgespeeld"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "afgespeelde songs"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Speelt nu"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Wachtrij"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Liedteksten"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Track verwijderen"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Er speelt geen medium"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Bibliotheek"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Zoeken"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Afgespeelde songs"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Onbekende lijst met songs"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Er zijn hier nog geen songs"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Afspeellijst"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Vorige zoekopdrachten:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artiesten"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Afspeellijsten"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Onbekend"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Geen overeenkomende vorige zoekopdrachten"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "uit zoekgeschiedenis verwijderen"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Zijbalk invouwen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Volgende afspelen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Aan wachtrij toevoegen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Favoriet verwijderen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Favoriet toevoegen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Uit geschiedenis verwijderen"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Favoriete songs"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Terug"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Muziek zoeken op YouTube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Aan afspeellijst toevoegen"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Volgende afspelen"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Wissen"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pauzeren"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Uitbreiden"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Alleen geluid afspelen"
|
||||
@@ -0,0 +1,250 @@
|
||||
# Translation of audiotube to Norwegian Nynorsk
|
||||
#
|
||||
# Øystein Steffensen-Alværvik <[email protected]>, 2022.
|
||||
# Karl Ove Hufthammer <[email protected]>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-15 12:33+0100\n"
|
||||
"Last-Translator: Karl Ove Hufthammer <[email protected]>\n"
|
||||
"Language-Team: Norwegian Nynorsk <[email protected]>\n"
|
||||
"Language: nn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
"X-Environment: kde\n"
|
||||
"X-Accelerator-Marker: &\n"
|
||||
"X-Text-Markup: kde4\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Øystein Steffensen-Alværvik"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Spel av"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Stokk om"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Opna i nettlesar"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Meir"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artist"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "Videoavspeling er endå ikkje støtta. Vil du spela av lyden til «%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Album"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singelplater"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Songar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videoar"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favorittar"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Vis alle"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Oftast avspela"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Avspela songar"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Spelar no"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Kø"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Songtekst"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Fjern spor"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Inkje medium vert spela"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Bibliotek"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Søk"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Avspela songar"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Ukjend songliste"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Ingen songar enno"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Speleliste"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Tidlegare søk:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistar"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Spelelister"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Ukjend"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Fald saman sidestolpe"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Spel som neste"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Legg i avspelingskøen"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Fjern frå favorittar"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Legg til favorittar"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,271 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# A S Alam <[email protected]>, 2021, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-01-01 09:11-0800\n"
|
||||
"Last-Translator: A S Alam <[email protected]>\n"
|
||||
"Language-Team: Punjabi <[email protected]>\n"
|
||||
"Language: pa\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 21.04.3\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "ਅਮਨਪਰੀਤ ਸਿੰਘ ਆਲਮ ੨੦੨੧"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "alam yellow @ gmail.com"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "ਚਲਾਓ"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "ਰਲਵੇਂ"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "ਰੇਡੀਓ"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "ਕਲਾਕਾਰ"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "ਵਿਡੀਓ ਪਲੇਅਬੈਕ ਹਾਲੇ ਸਹਾਇਕ ਨਹੀਂ ਹੈ। ਕੀ ਤੁਸੀਂ \"%1\" ਦਾ ਆਡੀਓ ਹੀ ਚਲਾਉਣਾ ਚਾਹੋਗੇ?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "ਐਲਬਮਾਂ"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "ਇਕੱਲੇ"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "ਗੀਤ"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "ਵਿਡੀਓ"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "ਠੀਕ ਹੈ"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "ਰੱਦ ਕਰੋ"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "ਆਡੀਓ-ਟਿਊਬ"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "No media playing"
|
||||
msgid "Now Playing"
|
||||
msgstr "ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ ਚੱਲਦਾ"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "ਟਰੈਕ ਨੂੰ ਹਟਾਓ"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ ਚੱਲਦਾ"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "ਖੋਜੋ"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "ਪਲੇਅਲਿਸਟਾਂ"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "ਕਲਾਕਾਰ"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "ਪਲੇਅਲਿਸਟਾਂ"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "ਅਣਪਛਾਤਾ"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "ਅਗਲਾ ਚਲਾਓ"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "ਯੂਟਿਊਬ ਸੰਗੀਤ ਉੱਤੇ ਸੰਗੀਤ ਲੱਭੋ"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "ਪਲੇਅਲਿਸਟ ਵਿੱਚ ਜੋੜੋ"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "ਅਗਲਾ ਚਲਾਓ"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "ਮਿਟਾਓ"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "ਵਿਰਾਮ"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "ਫੈਲਾਓ"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "ਸਿਰਫ਼ ਆਡੀਓ ਹੀ ਚਲਾਓ"
|
||||
@@ -0,0 +1,283 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Łukasz Wojniłowicz <[email protected]>, 2021, 2022.
|
||||
# Ignacy Kajdan <[email protected]>, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-10-18 18:06+0200\n"
|
||||
"Last-Translator: Łukasz Wojniłowicz <[email protected]>\n"
|
||||
"Language-Team: Polish <[email protected]>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Lokalize 22.08.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Łukasz Wojniłowicz, Ignacy Kajdan"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected], [email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Odtwórz"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Wymieszaj"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Otwórz w przeglądarce"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "Wykonawcy"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Odtwarzanie wideo nie jest jeszcze obsługiwane. Czy odtworzyć tylko dźwięk z "
|
||||
"„%1”?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albumy"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Single"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Piosenki"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Filmy"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Anuluj"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Ulubione"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Pokaż wszystkie"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Najczęściej odtwarzane"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Played Songs"
|
||||
msgid "played Songs"
|
||||
msgstr "Odtwarzane utwory"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Teraz odtwarzany"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Kolejka"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Usuń utwór"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Nic nie jest odtwarzane"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Szukaj"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Odtwarzane utwory"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Nieznana lista utworów"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Jeszcze nie ma tutaj utworów"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "Listy odtwarzania"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Wykonawcy"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Listy odtwarzania"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Nieznany"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Odtwórz następny"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Ulubione"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Add Favourite"
|
||||
msgstr "Ulubione"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Ulubione utwory"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Wstecz"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Znajdź muzykę w serwisie YouTube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Dodaj do listy odtwarzania"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Odtwórz następny"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Wyczyść"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Wstrzymaj"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Rozwiń"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Odtwórz tylko dźwięk"
|
||||
@@ -0,0 +1,252 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-22 23:00+0000\n"
|
||||
"Last-Translator: José Nuno Coelho Pires <[email protected]>\n"
|
||||
"Language-Team: Portuguese <[email protected]>\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-POFile-SpellExtra: Singles AudioTube YouTube Music\n"
|
||||
"X-POFile-IgnoreConsistency: Singles\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "José Nuno Pires"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Reproduzir"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Baralhar"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Abrir no Navegador"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Álbum • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Mais"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Rádio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"A reprodução de vídeos ainda não é suportada. Deseja reproduzir apenas o "
|
||||
"áudio de \"%1\"?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Álbuns"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "'Singles'"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Músicas"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Vídeos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favoritos"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Mostrar Tudo"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Mais Tocadas"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Músicas tocadas"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Agora a Ouvir"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Fila"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Letras Musicais"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Remover a Faixa"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Nada em reprodução"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Biblioteca"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Procurar"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Músicas Tocadas"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Lista de músicas desconhecida"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Ainda sem músicas aqui"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Lista de Reprodução"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Pesquisas Anteriores:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistas"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Listas de Reprodução"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Desconhecido"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Sem pesquisas anteriores correspondentes"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Remove from History"
|
||||
msgid "remove from search history"
|
||||
msgstr "Remover do Histórico"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Fechar a Barra Lateral"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Reproduzir o Seguinte"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Adicionar à fila"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Remover o Favorito"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Adicionar aos Favoritos"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Remover do Histórico"
|
||||
@@ -0,0 +1,278 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Luiz Fernando Ranghetti <[email protected]>, 2021, 2022.
|
||||
# Thiago Masato Costa Sueto <[email protected]>, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-12-20 10:48-0300\n"
|
||||
"Last-Translator: Luiz Fernando Ranghetti <[email protected]>\n"
|
||||
"Language-Team: Portuguese <[email protected]>\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Lokalize 21.12.3\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Luiz Fernando Ranghetti"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Reproduzir"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Embaralhar"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Abrir no navegador"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Álbum • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Mais"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Rádio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Artista"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"A reprodução de vídeos ainda não é suportada. Deseja reproduzir apenas o "
|
||||
"áudio de \"%1\"?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Álbuns"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singles"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Músicas"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Vídeos"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favoritas"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Mostrar tudo"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Mais reproduzidas"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Played Songs"
|
||||
msgid "played Songs"
|
||||
msgstr "Músicas reproduzidas"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Reproduzindo agora"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Fila"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Letras"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Remover faixa"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Nenhuma mídia em reprodução"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Pesquisar"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Músicas reproduzidas"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Lista de músicas desconhecida"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Nenhuma música ainda"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Lista de músicas"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artistas"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Listas de músicas"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Desconhecido"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Reproduzir próxima"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Adicionar à fila"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Remover das favoritas"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Adicionar favorita"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Músicas favoritas"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Voltar"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Encontre músicas no YouTube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Adicionar à lista de reprodução"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Reproduzir próxima"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Limpar"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pausar"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Expandir"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Reproduzir apenas áudio"
|
||||
@@ -0,0 +1,264 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Alexander Yavorsky <[email protected]>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-28 13:37+0300\n"
|
||||
"Last-Translator: Alexander Yavorsky <[email protected]>\n"
|
||||
"Language-Team: Russian <[email protected]>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
|
||||
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Lokalize 21.08.3\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Александр Яворский, Павел Чернышов"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected], [email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Воспроизвести"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Перемешать"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Открыть в браузере"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Альбом • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Дополнительно"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Радио"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Исполнитель"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Воспроизведение видео пока не поддерживается. Воспроизвести звук трека «%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Альбомы"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Синглы"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Треки"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Видеозаписи"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "ОК"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Избранное"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Показать все"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Часто воспроизводимые"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Воспроизведённые треки"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Текущий трек"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Очередь воспроизведения"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Текст песни"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Удалить дорожку"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Ничего не воспроизводится"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Библиотека"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Поиск"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Воспроизведённые треки"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Неизвестный список треков"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Пока нет ни одного трека"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Список воспроизведения"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Предыдущие поисковые запросы:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Исполнители"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Списки воспроизведения"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Неизвестный тип"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Не найдено соответствующих предыдущих поисковых запросов"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Свернуть боковую панель"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Воспроизвести следующим"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Добавить в очередь воспроизведения"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Убрать из избранного"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Добавить в избранное"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Удалить из журнала"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Избранные треки"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Назад"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Найти музыку в YouTube Music"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Очистить"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Приостановить"
|
||||
@@ -0,0 +1,261 @@
|
||||
# translation of audiotube.po Slovak
|
||||
# Roman Paholik <[email protected]>, 2021, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-04-07 18:01+0200\n"
|
||||
"Last-Translator: Roman Paholik <[email protected]>\n"
|
||||
"Language-Team: Slovak <[email protected]>\n"
|
||||
"Language: sk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 21.12.3\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Roman Paholík"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Prehrať"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Zamiešať"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Rádio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "Interpreti"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albumy"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Samotné"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videá"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušiť"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "No media playing"
|
||||
msgid "Now Playing"
|
||||
msgstr "Neprehráva sa žiadne médium"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Neprehráva sa žiadne médium"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Hľadať"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "Zoznamy skladieb"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Interpreti"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Zoznamy skladieb"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Neznáme"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Play"
|
||||
msgid "Play Next"
|
||||
msgstr "Prehrať"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Pridať do zoznamu skladieb"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Vyčistiť"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Pozastaviť"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Rozvinúť"
|
||||
@@ -0,0 +1,275 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Matjaž Jeran <[email protected]>, 2021, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-28 09:50+0100\n"
|
||||
"Last-Translator: Matjaž Jeran <[email protected]>\n"
|
||||
"Language-Team: Slovenian <[email protected]>\n"
|
||||
"Language: sl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
|
||||
"%100==4 ? 3 : 0);\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Matjaž Jeran"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Predvajaj"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Premešaj"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Odpri v brskalniku"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Album • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Več"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Avtor"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "Video playback še ni podprt. Ali želite predvajati samo zvok \"%1\"?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albumi"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singli"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Glasba"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videposnetki"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "V redu"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Prekliči"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Priljubljene"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Prikaži vse"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Največkrat predvajane"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "predvajane pesmi"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Pravkar predvajano"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Čakalna vrsta"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Besedilo"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Odstrani sled"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Niče se ne predvaja"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Knjižnica"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Išči"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Predvajane pesmi"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Neznan seznam pesmi"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Tu še ni nobene pesmi"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Seznam predvajanja"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Prejšnja iskanja:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Avtorji"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Seznami predvajanja"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Neznano"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Ni zadetkov iz prejšnjih iskanj"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "odstrani iz zgodovine iskanj"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Strni stransko vrstico"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Predvajaj naslednjo"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Dodaj v v čakalno vrsto"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Odstrani priljubljenega"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Dodaj priljubljenega"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Odstrani iz zgodovine"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Priljubljene pesmi"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Nazaj"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Najdi glasbo na Youtube Music"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Dodaj v seznam predvajanja"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Predvajaj naslednjo"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Očisti"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Premor"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Razširi"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Predvajaj samo zvok"
|
||||
@@ -0,0 +1,279 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Stefan Asserhäll <[email protected]>, 2021, 2022.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-24 14:57+0200\n"
|
||||
"Last-Translator: Stefan Asserhäll <[email protected]>\n"
|
||||
"Language-Team: Swedish <[email protected]>\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 20.08.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Stefan Asserhäll"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Spela"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Blanda"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Öppna i webbläsare"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radio"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Artists"
|
||||
msgid "Artist"
|
||||
msgstr "Artister"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "Videouppspelning stöds inte ännu. Vill du bara spela ljudet på \"%1\"?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Album"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Singlar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Låtar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videor"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Ok"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Favoriter"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Visa alla"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Mest spelade"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Played Songs"
|
||||
msgid "played Songs"
|
||||
msgstr "Spelade låtar"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Spelar nu"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Köa"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Ta bort spår"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Inga media spelar"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Sök"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Spelade låtar"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Okänd låtlista"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Inga låtar här ännu"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Playlists"
|
||||
msgid "Playlist"
|
||||
msgstr "Spellistor"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Artister"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Spellistor"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Okänd"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Spela nästa"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Favoriter"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, fuzzy, kde-format
|
||||
#| msgid "Favourites"
|
||||
msgid "Add Favourite"
|
||||
msgstr "Favoriter"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Favoritlåtar"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Bakåt"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Sök efter musik på YouTube musik"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Lägg till i spellista"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Spela nästa"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Rensa"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Paus"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Expandera"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Spela bara ljud"
|
||||
@@ -0,0 +1,273 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
#
|
||||
# Emir SARI <[email protected]>, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 18:30+0300\n"
|
||||
"Last-Translator: Emir SARI <[email protected]>\n"
|
||||
"Language-Team: Turkish <[email protected]>\n"
|
||||
"Language: tr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Lokalize 22.12.1\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Emir SARI"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Çal"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Karıştır"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Tarayıcıda Aç"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Albüm • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Daha Fazla"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Radyo"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Sanatçı"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Video oynatımı henüz desteklenmiyor. \"%1\" videosunun yalnızca sesinin "
|
||||
"çalınmasını ister misiniz?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Albümler"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Tekliler"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Şarkılar"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Videolar"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Tamam"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "İptal"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Beğeniler"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Tümünü Göster"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "En Çok Çalınanlar"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Çalınan Şarkılar"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Şimdi Çalınıyor"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Kuyruk"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Şarkı Sözleri"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Parçayı Kaldır"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Ortam çalmıyor"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Kitaplık"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Ara"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Çalınan Şarkılar"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Bilinmeyen şarkılar listesi"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Burada henüz şarkı yok"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Çalma Listesi"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Önceki Aramalar:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Sanatçılar"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Çalma Listeleri"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Bilinmiyor"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Eşleşen daha önceden yapılmış arama yok"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "arama geçmişinden kaldır"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Kenar Çubuğunu Daralt"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Sonrakini Çal"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Kuyruğa ekle"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Beğenilerden Kaldır"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Beğenilere Ekle"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Geçmişten Kaldır"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Beğenilen Şarkılar"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Geri"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "YouTube Müzik'te müzik bul"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Çalma Listesine Ekle"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Sonrakini çal"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Temizle"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Duraklat"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Genişlet"
|
||||
@@ -0,0 +1,277 @@
|
||||
# Copyright (C) YEAR This file is copyright:
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Yuri Chornoivan <[email protected]>, 2021, 2022, 2023.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-27 10:54+0200\n"
|
||||
"Last-Translator: Fracture dept <[email protected]>\n"
|
||||
"Language-Team: Ukrainian <[email protected]>\n"
|
||||
"Language: uk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
|
||||
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Lokalize 20.12.0\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Юрій Чорноіван"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "Відтворити"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "Перемішати"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "Відкрити у переглядачі"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr "Альбом • %1"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr "Більше"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "Радіо"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr "Виконавець"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
"Підтримки відтворення відео ще не передбачено. Хочете, щоб було відтворено "
|
||||
"лише звукову частину «%1»?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "Альбоми"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "Одинарні"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "Пісні"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "Відео"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "Гаразд"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "Скасувати"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "Улюблені"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "Показати всі"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "Часто слухали"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr "Відтворені композиції"
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "Зараз відтворюємо"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "Додати до черги"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr "Текст"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "Вилучити композицію"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "Відтворення не відбувається"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr "Бібліотека"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "Пошук"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "Відтворені композиції"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "Невідомий список композицій"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "Тут ще немає композицій"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr "Список відтворення"
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr "Попередні пошуки:"
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "Виконавці"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "Списки відтворення"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "Невідомий"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr "Немає відповідних попередніх пошуків"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr "вилучити з журналу пошуку"
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr "Згорнути бічну панель"
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "Відтворити наступну"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr "Додати до черги"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr "Вилучити з улюблених"
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr "Додати до улюблених"
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr "Вилучити із журналу"
|
||||
|
||||
#~ msgid "Favourite Songs"
|
||||
#~ msgstr "Улюблені композиції"
|
||||
|
||||
#~ msgid "Back"
|
||||
#~ msgstr "Назад"
|
||||
|
||||
#~ msgid "Find music on YouTube Music"
|
||||
#~ msgstr "Шукати музику на сайті «Музика Youtube»"
|
||||
|
||||
#~ msgid "Add to Playlist"
|
||||
#~ msgstr "Додати до списку відтворення"
|
||||
|
||||
#~ msgid "Play next"
|
||||
#~ msgstr "Відтворити наступну"
|
||||
|
||||
#~ msgid "Clear"
|
||||
#~ msgstr "Спорожнити"
|
||||
|
||||
#~ msgid "Pause"
|
||||
#~ msgstr "Призупинити"
|
||||
|
||||
#~ msgid "Expand"
|
||||
#~ msgstr "Розгорнути"
|
||||
|
||||
#~ msgid "Play only Audio"
|
||||
#~ msgstr "Відтворити лише звук"
|
||||
@@ -0,0 +1,247 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: kdeorg\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2023-01-12 10:32\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: kdeorg\n"
|
||||
"X-Crowdin-Project-ID: 269464\n"
|
||||
"X-Crowdin-Language: zh-CN\n"
|
||||
"X-Crowdin-File: /kf5-trunk/messages/audiotube/audiotube.pot\n"
|
||||
"X-Crowdin-File-ID: 25474\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr "Qi Binye, Tyson Tan"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr "[email protected], [email protected]"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr "播放"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr "随机播放"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr "在浏览器中打开"
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr "电台"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr "视频播放尚未被支持。您想要只播放“%1”中的音频吗?"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr "专辑"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr "单曲"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr "曲目"
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr "视频"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr "确定"
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr "收藏夹"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr "显示全部"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr "最常播放"
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr "AudioTube"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr "正在播放"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr "播放队列"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr "移除曲目"
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr "没有正在播放的媒体"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr "搜索"
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr "已播放歌曲"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr "未知歌曲列表"
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr "此处无歌曲"
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr "艺人"
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr "播放列表"
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr "播放下一首"
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,248 @@
|
||||
# Chinese translations for audiotube package
|
||||
# audiotube 套件的正體中文翻譯.
|
||||
# Copyright (C) 2022 This file is copyright:
|
||||
# This file is distributed under the same license as the audiotube package.
|
||||
# Automatically generated, 2022.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: audiotube\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2023-01-30 01:00+0000\n"
|
||||
"PO-Revision-Date: 2022-05-30 00:47+0000\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: zh_TW\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#, kde-format
|
||||
msgctxt "NAME OF TRANSLATORS"
|
||||
msgid "Your names"
|
||||
msgstr ""
|
||||
|
||||
#, kde-format
|
||||
msgctxt "EMAIL OF TRANSLATORS"
|
||||
msgid "Your emails"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:22 contents/ui/PlaylistPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Play"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:29 contents/ui/ArtistPage.qml:32
|
||||
#: contents/ui/PlaylistPage.qml:33
|
||||
#, kde-format
|
||||
msgid "Shuffle"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:37 contents/ui/ArtistPage.qml:39
|
||||
#, kde-format
|
||||
msgid "Open in Browser"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:44
|
||||
#, kde-format
|
||||
msgid "Album • %1"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/AlbumPage.qml:88 contents/ui/ArtistPage.qml:126
|
||||
#: contents/ui/PlaybackHistory.qml:80 contents/ui/PlaylistPage.qml:91
|
||||
#: contents/ui/SearchPage.qml:130
|
||||
#, kde-format
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:27
|
||||
#, kde-format
|
||||
msgid "Radio"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:46
|
||||
#, kde-format
|
||||
msgid "Artist"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:68 contents/ui/SearchPage.qml:70
|
||||
#, kde-format
|
||||
msgid ""
|
||||
"Video playback is not supported yet. Do you want to play only the audio of "
|
||||
"\"%1\"?"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:85 contents/ui/SearchPage.qml:26
|
||||
#, kde-format
|
||||
msgid "Albums"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:87
|
||||
#, kde-format
|
||||
msgid "Singles"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:89 contents/ui/SearchPage.qml:32
|
||||
#, kde-format
|
||||
msgid "Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ArtistPage.qml:91 contents/ui/SearchPage.qml:34
|
||||
#, kde-format
|
||||
msgid "Videos"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:16
|
||||
#, kde-format
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/ConfirmationMessage.qml:21
|
||||
#, kde-format
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:28 contents/ui/LibraryPage.qml:44
|
||||
#: contents/ui/NavigationBar.qml:46 contents/ui/NavigationBar.qml:51
|
||||
#: contents/ui/Sidebar.qml:124 contents/ui/Sidebar.qml:131
|
||||
#, kde-format
|
||||
msgid "Favourites"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:39 contents/ui/LibraryPage.qml:225
|
||||
#, kde-format
|
||||
msgid "Show All"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:214
|
||||
#, kde-format
|
||||
msgid "Most played"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/LibraryPage.qml:230
|
||||
#, kde-format
|
||||
msgid "played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/main.qml:109
|
||||
#, kde-format
|
||||
msgid "AudioTube"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:107
|
||||
#, kde-format
|
||||
msgid "Now Playing"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:132
|
||||
#, kde-format
|
||||
msgid "Queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:157
|
||||
#, kde-format
|
||||
msgid "Lyrics"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:274
|
||||
#, kde-format
|
||||
msgid "Remove Track"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/MaximizedPlayerPage.qml:316
|
||||
#: contents/ui/MinimizedPlayerControls.qml:90
|
||||
#, kde-format
|
||||
msgid "No media playing"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:24 contents/ui/Sidebar.qml:93
|
||||
#, kde-format
|
||||
msgid "Library"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:35 contents/ui/Sidebar.qml:109
|
||||
#, kde-format
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/NavigationBar.qml:58 contents/ui/NavigationBar.qml:63
|
||||
#: contents/ui/Sidebar.qml:143 contents/ui/Sidebar.qml:150
|
||||
#, kde-format
|
||||
msgid "Played Songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:15
|
||||
#, kde-format
|
||||
msgid "Unknown list of songs"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaybackHistory.qml:27
|
||||
#, kde-format
|
||||
msgid "No songs here yet"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/PlaylistPage.qml:42
|
||||
#, kde-format
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:16
|
||||
#, kde-format
|
||||
msgid "Previous Searches:"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:28
|
||||
#, kde-format
|
||||
msgid "Artists"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:30
|
||||
#, kde-format
|
||||
msgid "Playlists"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchPage.qml:37
|
||||
#, kde-format
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:287
|
||||
#, kde-format
|
||||
msgid "No matching previous searches"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SearchWithDropdown.qml:322
|
||||
#, kde-format
|
||||
msgid "remove from search history"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/Sidebar.qml:179
|
||||
#, kde-format
|
||||
msgid "Collapse Sidebar"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:113 contents/ui/SongMenu.qml:172
|
||||
#, kde-format
|
||||
msgid "Play Next"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:122 contents/ui/SongMenu.qml:178
|
||||
#, kde-format
|
||||
msgid "Add to queue"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Remove Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:132 contents/ui/SongMenu.qml:185
|
||||
#, kde-format
|
||||
msgid "Add Favourite"
|
||||
msgstr ""
|
||||
|
||||
#: contents/ui/SongMenu.qml:148 contents/ui/SongMenu.qml:200
|
||||
#, kde-format
|
||||
msgid "Remove from History"
|
||||
msgstr ""
|
||||
+7
-2
@@ -1,2 +1,7 @@
|
||||
ytmusicapi==0.16.0
|
||||
youtube_dl
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
# SPDX-FileCopyrightText: 2021 Kuba Prussak <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
ytmusicapi==0.25.0
|
||||
yt-dlp
|
||||
+27
-8
@@ -1,4 +1,6 @@
|
||||
add_subdirectory(mpris2)
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
add_library(ytm STATIC
|
||||
ytmusic.cpp
|
||||
@@ -8,6 +10,14 @@ target_link_libraries(ytm PUBLIC pybind11::embed)
|
||||
target_include_directories(ytm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(ytm PRIVATE -DRANDALL_WAS_HERE)
|
||||
|
||||
add_library(asyncdatabase STATIC
|
||||
asyncdatabase.cpp
|
||||
asyncdatabase_p.h
|
||||
)
|
||||
|
||||
target_include_directories(asyncdatabase PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(asyncdatabase PUBLIC Qt::Sql)
|
||||
|
||||
add_subdirectory(example)
|
||||
|
||||
add_executable(audiotube
|
||||
@@ -21,21 +31,30 @@ add_executable(audiotube
|
||||
playlistmodel.cpp
|
||||
playlistutils.cpp
|
||||
errorhandler.cpp
|
||||
playerutils.cpp
|
||||
abstractytmusicmodel.cpp
|
||||
multiiterableview.h
|
||||
library.cpp
|
||||
resources.qrc
|
||||
blur.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(audiotube
|
||||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Qml
|
||||
Qt5::Quick
|
||||
Qt5::QuickControls2
|
||||
Qt5::Svg
|
||||
Qt::Core
|
||||
Qt::Gui
|
||||
Qt::Qml
|
||||
Qt::Quick
|
||||
Qt::QuickControls2
|
||||
Qt::Svg
|
||||
Qt::Widgets
|
||||
KF5::I18n
|
||||
KF5::CoreAddons
|
||||
KF5::Crash
|
||||
KF5::WindowSystem
|
||||
ytm
|
||||
mpris2
|
||||
asyncdatabase
|
||||
)
|
||||
|
||||
target_compile_definitions(audiotube PRIVATE -DQT_NO_KEYWORDS -DQT_NO_URL_CAST_FROM_STRING)
|
||||
|
||||
install(TARGETS audiotube ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
@@ -0,0 +1,4 @@
|
||||
#! /usr/bin/env bash
|
||||
# SPDX-FileCopyrightText: 2020 Tobias Fella <[email protected]>
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
$XGETTEXT `find -name \*.cpp -o -name \*.qml -o -name \*.js` -o $podir/audiotube.pot
|
||||
@@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "abstractytmusicmodel.h"
|
||||
|
||||
#include "asyncytmusic.h"
|
||||
|
||||
|
||||
AbstractYTMusicModel::AbstractYTMusicModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool AbstractYTMusicModel::loading() const
|
||||
{
|
||||
return m_loading;
|
||||
}
|
||||
|
||||
void AbstractYTMusicModel::setLoading(bool loading)
|
||||
{
|
||||
if (m_loading == loading)
|
||||
return;
|
||||
|
||||
m_loading = loading;
|
||||
Q_EMIT loadingChanged();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
///
|
||||
/// Base class for all models that work with data from the AsyncYTMusic class.
|
||||
/// It provides a loading property, that is automatically set to false if a query fails.
|
||||
///
|
||||
class AbstractYTMusicModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool loading READ loading WRITE setLoading NOTIFY loadingChanged)
|
||||
|
||||
public:
|
||||
explicit AbstractYTMusicModel(QObject *parent = nullptr);
|
||||
|
||||
bool loading() const;
|
||||
void setLoading(bool loading);
|
||||
Q_SIGNAL void loadingChanged();
|
||||
|
||||
private:
|
||||
bool m_loading = false;
|
||||
};
|
||||
|
||||
+38
-31
@@ -3,29 +3,32 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "albummodel.h"
|
||||
#include "playlistutils.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringBuilder>
|
||||
|
||||
AlbumModel::AlbumModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
: AbstractYTMusicModel(parent)
|
||||
{
|
||||
connect(this, &AlbumModel::browseIdChanged, this, [=] {
|
||||
connect(this, &AlbumModel::browseIdChanged, this, [this] {
|
||||
setLoading(true);
|
||||
YTMusicThread::instance()->fetchAlbum(m_browseId);
|
||||
});
|
||||
connect(&YTMusicThread::instance().get(), &AsyncYTMusic::fetchAlbumFinished, this, [=](const album::Album &album) {
|
||||
setLoading(false);
|
||||
auto future = YTMusicThread::instance()->fetchAlbum(m_browseId);
|
||||
connectFuture(future, this, [=, this](const album::Album &album) {
|
||||
setLoading(false);
|
||||
|
||||
beginResetModel();
|
||||
m_album = album;
|
||||
endResetModel();
|
||||
std::sort(m_album.thumbnails.begin(), m_album.thumbnails.end());
|
||||
beginResetModel();
|
||||
m_album = album;
|
||||
endResetModel();
|
||||
std::sort(m_album.thumbnails.begin(), m_album.thumbnails.end());
|
||||
|
||||
Q_EMIT titleChanged();
|
||||
Q_EMIT thumbnailUrlChanged();
|
||||
Q_EMIT playlistIdChanged();
|
||||
Q_EMIT titleChanged();
|
||||
Q_EMIT artistsChanged();
|
||||
Q_EMIT thumbnailUrlChanged();
|
||||
Q_EMIT playlistIdChanged();
|
||||
});
|
||||
});
|
||||
connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=] {
|
||||
|
||||
connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=, this] {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
@@ -43,12 +46,15 @@ QVariant AlbumModel::data(const QModelIndex &index, int role) const
|
||||
case VideoId:
|
||||
return QString::fromStdString(m_album.tracks[index.row()].video_id.value_or(std::string()));
|
||||
case Artists:
|
||||
return QVariant::fromValue(std::vector<meta::Artist> {
|
||||
{
|
||||
m_album.tracks[index.row()].artists,
|
||||
std::nullopt
|
||||
}
|
||||
});
|
||||
return QVariant::fromValue(m_album.tracks[index.row()].artists);
|
||||
case ThumbnailUrl:
|
||||
if (!m_album.thumbnails.empty()) {
|
||||
return QString::fromStdString(m_album.thumbnails.front().url);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
case ArtistsDisplayString:
|
||||
return PlaylistUtils::artistsToString(m_album.tracks[index.row()].artists);
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
@@ -61,7 +67,9 @@ QHash<int, QByteArray> AlbumModel::roleNames() const
|
||||
return {
|
||||
{Title, "title"},
|
||||
{VideoId, "videoId"},
|
||||
{Artists, "artists"}
|
||||
{Artists, "artists"},
|
||||
{ThumbnailUrl, "thumbnailUrl"},
|
||||
{ArtistsDisplayString, "artistsDisplayString"}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,15 +89,9 @@ QString AlbumModel::title() const
|
||||
return QString::fromStdString(m_album.title);
|
||||
}
|
||||
|
||||
bool AlbumModel::loading() const
|
||||
QString AlbumModel::artists() const
|
||||
{
|
||||
return m_loading;
|
||||
}
|
||||
|
||||
void AlbumModel::setLoading(bool loading)
|
||||
{
|
||||
m_loading = loading;
|
||||
Q_EMIT loadingChanged();
|
||||
return PlaylistUtils::artistsToString(m_album.artists);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,5 +106,10 @@ QUrl AlbumModel::thumbnailUrl() const
|
||||
|
||||
QString AlbumModel::playlistId() const
|
||||
{
|
||||
return QString::fromStdString(m_album.playlist_id);
|
||||
return QString::fromStdString(m_album.audio_playlist_id);
|
||||
}
|
||||
|
||||
QUrl AlbumModel::webUrl() const
|
||||
{
|
||||
return QUrl(YTMUSIC_WEB_BASE_URL % "/playlist?list=" % QString::fromStdString(m_album.audio_playlist_id));
|
||||
}
|
||||
+12
-8
@@ -8,22 +8,26 @@
|
||||
#include <QUrl>
|
||||
|
||||
#include "asyncytmusic.h"
|
||||
#include "abstractytmusicmodel.h"
|
||||
|
||||
class AlbumModel : public QAbstractListModel
|
||||
class AlbumModel : public AbstractYTMusicModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString browseId READ browseId WRITE setBrowseId NOTIFY browseIdChanged REQUIRED)
|
||||
|
||||
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
|
||||
Q_PROPERTY(QString artists READ artists NOTIFY artistsChanged)
|
||||
Q_PROPERTY(QUrl thumbnailUrl READ thumbnailUrl NOTIFY thumbnailUrlChanged)
|
||||
Q_PROPERTY(bool loading READ loading WRITE setLoading NOTIFY loadingChanged)
|
||||
Q_PROPERTY(QString playlistId READ playlistId NOTIFY playlistIdChanged)
|
||||
Q_PROPERTY(QUrl webUrl READ webUrl NOTIFY webUrlChanged)
|
||||
|
||||
public:
|
||||
enum Role {
|
||||
Title = Qt::UserRole + 1,
|
||||
VideoId,
|
||||
Artists
|
||||
Artists,
|
||||
ThumbnailUrl,
|
||||
ArtistsDisplayString
|
||||
};
|
||||
|
||||
explicit AlbumModel(QObject *parent = nullptr);
|
||||
@@ -39,19 +43,19 @@ public:
|
||||
QString title() const;
|
||||
Q_SIGNAL void titleChanged();
|
||||
|
||||
bool loading() const;
|
||||
void setLoading(bool loading);
|
||||
Q_SIGNAL void loadingChanged();
|
||||
|
||||
QString artists() const;
|
||||
Q_SIGNAL void artistsChanged();
|
||||
QUrl thumbnailUrl() const;
|
||||
Q_SIGNAL void thumbnailUrlChanged();
|
||||
|
||||
QString playlistId() const;
|
||||
Q_SIGNAL void playlistIdChanged();
|
||||
|
||||
QUrl webUrl() const;
|
||||
Q_SIGNAL void webUrlChanged();
|
||||
|
||||
private:
|
||||
QString m_browseId;
|
||||
bool m_loading = false;
|
||||
|
||||
album::Album m_album;
|
||||
};
|
||||
+67
-53
@@ -4,52 +4,66 @@
|
||||
|
||||
#include "artistmodel.h"
|
||||
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include <asyncytmusic.h>
|
||||
|
||||
ArtistModel::ArtistModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
: AbstractYTMusicModel(parent)
|
||||
, m_view(albums, singles, songs, videos)
|
||||
{
|
||||
connect(this, &ArtistModel::channelIdChanged, this, [=] {
|
||||
connect(this, &ArtistModel::channelIdChanged, this, [this] {
|
||||
if (m_channelId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
YTMusicThread::instance()->fetchArtist(m_channelId);
|
||||
auto future = YTMusicThread::instance()->fetchArtist(m_channelId);
|
||||
connectFuture(future, this, [=, this](const artist::Artist &artist) {
|
||||
setLoading(false);
|
||||
|
||||
beginResetModel();
|
||||
m_artist = artist;
|
||||
std::sort(m_artist.thumbnails.begin(), m_artist.thumbnails.end());
|
||||
|
||||
albums = m_artist.albums ? m_artist.albums->results : std::vector<artist::Artist::Album>();
|
||||
for (auto &album : albums) {
|
||||
std::sort(album.thumbnails.begin(), album.thumbnails.end());
|
||||
}
|
||||
singles = m_artist.singles ? m_artist.singles->results : std::vector<artist::Artist::Single>();
|
||||
for (auto &single : singles) {
|
||||
std::sort(single.thumbnails.begin(), single.thumbnails.end());
|
||||
}
|
||||
songs = m_artist.songs ? m_artist.songs->results : std::vector<artist::Artist::Song>();
|
||||
for (auto &song : songs) {
|
||||
std::sort(song.thumbnails.begin(), song.thumbnails.end());
|
||||
}
|
||||
videos = m_artist.videos ? m_artist.videos->results : std::vector<artist::Artist::Video>();
|
||||
for (auto &video : videos) {
|
||||
std::sort(video.thumbnails.begin(), video.thumbnails.end());
|
||||
}
|
||||
|
||||
// std::span can't know if the data pointer underneath it was changed, so re-create
|
||||
m_view = MultiIterableView(albums, singles, songs, videos);
|
||||
endResetModel();
|
||||
|
||||
Q_EMIT titleChanged();
|
||||
Q_EMIT thumbnailUrlChanged();
|
||||
});
|
||||
});
|
||||
connect(&YTMusicThread::instance().get(), &AsyncYTMusic::fetchArtistFinished, this, [=](const artist::Artist &artist) {
|
||||
setLoading(false);
|
||||
|
||||
beginResetModel();
|
||||
m_artist = artist;
|
||||
std::sort(m_artist.thumbnails.begin(), m_artist.thumbnails.end());
|
||||
m_view = std::optional(MultiIterableView(m_artist.albums->results,
|
||||
m_artist.singles->results,
|
||||
m_artist.songs->results,
|
||||
m_artist.videos->results));
|
||||
endResetModel();
|
||||
|
||||
|
||||
Q_EMIT titleChanged();
|
||||
Q_EMIT thumbnailUrlChanged();
|
||||
});
|
||||
connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [=] {
|
||||
connect(&YTMusicThread::instance().get(), &AsyncYTMusic::errorOccurred, this, [this] {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
int ArtistModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : m_view ? int(m_view->size()) : 0;
|
||||
return parent.isValid() ? 0 : m_view.size();
|
||||
}
|
||||
|
||||
QVariant ArtistModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!m_view) {
|
||||
return {};
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Title:
|
||||
return QString::fromStdString(std::visit([&](auto&& item) {
|
||||
@@ -65,7 +79,7 @@ QVariant ArtistModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}, m_view.value()[index.row()]));
|
||||
}, m_view[index.row()]));
|
||||
case Type:
|
||||
return std::visit([&](auto&& item) {
|
||||
using T = std::decay_t<decltype(item)>;
|
||||
@@ -80,7 +94,7 @@ QVariant ArtistModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}, m_view.value()[index.row()]);
|
||||
}, m_view[index.row()]);
|
||||
case Artists:
|
||||
return QVariant::fromValue(std::vector<meta::Artist> {
|
||||
{
|
||||
@@ -102,7 +116,14 @@ QVariant ArtistModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}, m_view.value()[index.row()]);
|
||||
}, m_view[index.row()]);
|
||||
case ThumbnailUrl:
|
||||
return std::visit([&](auto&& item) {
|
||||
if (!item.thumbnails.empty()) {
|
||||
return QString::fromStdString(item.thumbnails.front().url);
|
||||
}
|
||||
return QString();
|
||||
}, m_view[index.row()]);
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
@@ -116,7 +137,8 @@ QHash<int, QByteArray> ArtistModel::roleNames() const
|
||||
{Title, "title"},
|
||||
{Type, "type"},
|
||||
{Artists, "artists"},
|
||||
{VideoId, "videoId"}
|
||||
{VideoId, "videoId"},
|
||||
{ThumbnailUrl, "thumbnailUrl"}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -145,33 +167,25 @@ QUrl ArtistModel::thumbnailUrl() const
|
||||
return QUrl(QString::fromStdString(m_artist.thumbnails.back().url));
|
||||
}
|
||||
|
||||
bool ArtistModel::loading() const
|
||||
QUrl ArtistModel::webUrl() const
|
||||
{
|
||||
return m_loading;
|
||||
}
|
||||
|
||||
void ArtistModel::setLoading(bool loading)
|
||||
{
|
||||
m_loading = loading;
|
||||
Q_EMIT loadingChanged();
|
||||
return QUrl(YTMUSIC_WEB_BASE_URL % u"channel/" % QString::fromStdString(m_artist.channel_id));
|
||||
}
|
||||
|
||||
void ArtistModel::triggerItem(int row)
|
||||
{
|
||||
if (m_view) {
|
||||
std::visit([&](auto&& item) {
|
||||
using T = std::decay_t<decltype(item)>;
|
||||
if constexpr(std::is_same_v<T, artist::Artist::Album>) {
|
||||
Q_EMIT openAlbum(QString::fromStdString(item.browse_id));
|
||||
} else if constexpr(std::is_same_v<T, artist::Artist::Single>) {
|
||||
Q_EMIT openAlbum(QString::fromStdString(item.browse_id));
|
||||
} else if constexpr(std::is_same_v<T, artist::Artist::Song>) {
|
||||
Q_EMIT openSong(QString::fromStdString(item.video_id));
|
||||
} else if constexpr(std::is_same_v<T, artist::Artist::Video>) {
|
||||
Q_EMIT openVideo(QString::fromStdString(item.video_id));
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}, m_view.value()[row]);
|
||||
}
|
||||
std::visit([&](auto&& item) {
|
||||
using T = std::decay_t<decltype(item)>;
|
||||
if constexpr(std::is_same_v<T, artist::Artist::Album>) {
|
||||
Q_EMIT openAlbum(QString::fromStdString(item.browse_id));
|
||||
} else if constexpr(std::is_same_v<T, artist::Artist::Single>) {
|
||||
Q_EMIT openAlbum(QString::fromStdString(item.browse_id));
|
||||
} else if constexpr(std::is_same_v<T, artist::Artist::Song>) {
|
||||
Q_EMIT openSong(QString::fromStdString(item.video_id));
|
||||
} else if constexpr(std::is_same_v<T, artist::Artist::Video>) {
|
||||
Q_EMIT openVideo(QString::fromStdString(item.video_id), QString::fromStdString(item.title));
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}, m_view[row]);
|
||||
}
|
||||
+19
-11
@@ -10,9 +10,12 @@
|
||||
#include <optional>
|
||||
|
||||
#include <ytmusic.h>
|
||||
#include "multiiterableview.h"
|
||||
|
||||
class ArtistModel : public QAbstractListModel
|
||||
#include "multiiterableview.h"
|
||||
#include "abstractytmusicmodel.h"
|
||||
|
||||
|
||||
class ArtistModel : public AbstractYTMusicModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -20,7 +23,7 @@ class ArtistModel : public QAbstractListModel
|
||||
|
||||
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
|
||||
Q_PROPERTY(QUrl thumbnailUrl READ thumbnailUrl NOTIFY thumbnailUrlChanged)
|
||||
Q_PROPERTY(bool loading READ loading WRITE setLoading NOTIFY loadingChanged)
|
||||
Q_PROPERTY(QUrl webUrl READ webUrl NOTIFY webUrlChanged)
|
||||
|
||||
public:
|
||||
enum Type {
|
||||
@@ -35,7 +38,8 @@ public:
|
||||
Title,
|
||||
Type,
|
||||
Artists,
|
||||
VideoId
|
||||
VideoId,
|
||||
ThumbnailUrl
|
||||
};
|
||||
|
||||
explicit ArtistModel(QObject *parent = nullptr);
|
||||
@@ -54,22 +58,26 @@ public:
|
||||
QUrl thumbnailUrl() const;
|
||||
Q_SIGNAL void thumbnailUrlChanged();
|
||||
|
||||
bool loading() const;
|
||||
void setLoading(bool loading);
|
||||
Q_SIGNAL void loadingChanged();
|
||||
QUrl webUrl() const;
|
||||
Q_SIGNAL void webUrlChanged();
|
||||
|
||||
Q_INVOKABLE void triggerItem(int row);
|
||||
|
||||
Q_SIGNAL void openAlbum(const QString &browseId);
|
||||
Q_SIGNAL void openSong(const QString &videoId);
|
||||
Q_SIGNAL void openVideo(const QString &videoId);
|
||||
Q_SIGNAL void openVideo(const QString &videoId, const QString &title);
|
||||
|
||||
private:
|
||||
QString m_channelId;
|
||||
bool m_loading = false;
|
||||
|
||||
artist::Artist m_artist;
|
||||
std::optional<MultiIterableView<
|
||||
|
||||
std::vector<artist::Artist::Album> albums;
|
||||
std::vector<artist::Artist::Single> singles;
|
||||
std::vector<artist::Artist::Song> songs;
|
||||
std::vector<artist::Artist::Video> videos;
|
||||
|
||||
MultiIterableView<
|
||||
artist::Artist::Album, artist::Artist::Single, artist::Artist::Song, artist::Artist::Video
|
||||
>> m_view;
|
||||
> m_view;
|
||||
};
|
||||
@@ -0,0 +1,309 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "asyncdatabase.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QUrl>
|
||||
#include <QStringBuilder>
|
||||
#include <QVariant>
|
||||
#include <QSqlResult>
|
||||
#include <QSqlError>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#define SCHAMA_MIGRATIONS_TABLE "__qt_schema_migrations"
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(asyncdatabase)
|
||||
Q_LOGGING_CATEGORY(asyncdatabase, "asyncdatabase")
|
||||
|
||||
namespace asyncdatabase_private {
|
||||
|
||||
// migrations
|
||||
void createInternalTable(QSqlDatabase &database) {
|
||||
QSqlQuery query(QStringLiteral("create table if not exists " SCHAMA_MIGRATIONS_TABLE " ("
|
||||
"version Text primary key not null, "
|
||||
"run_on timestamp not null default current_timestamp)"), database);
|
||||
if (!query.exec()) {
|
||||
printSqlError(query);
|
||||
}
|
||||
}
|
||||
|
||||
void markMigrationRun(QSqlDatabase &database, const QString &name) {
|
||||
qCDebug(asyncdatabase) << "Marking migration" << name << "as done.";
|
||||
|
||||
QSqlQuery query(database);
|
||||
if (!query.prepare(QStringLiteral("insert into " SCHAMA_MIGRATIONS_TABLE " (version) values (:name)"))) {
|
||||
printSqlError(query);
|
||||
}
|
||||
query.bindValue(QStringLiteral(":name"), QVariant(name));
|
||||
if (!query.exec()) {
|
||||
printSqlError(query);
|
||||
}
|
||||
}
|
||||
|
||||
bool checkMigrationAlreadyRun(QSqlDatabase &database, const QString &name) {
|
||||
qCDebug(asyncdatabase) << "Checking whether migration" << name << "is already applied";
|
||||
QSqlQuery query(database);
|
||||
query.prepare(QStringLiteral("select count(*) from " SCHAMA_MIGRATIONS_TABLE " where version = :name"));
|
||||
query.bindValue(QStringLiteral(":name"), QVariant(name));
|
||||
query.exec();
|
||||
|
||||
query.next();
|
||||
int count = query.value(0).toInt();
|
||||
bool isApplied = count > 0;
|
||||
if (isApplied) {
|
||||
qCDebug(asyncdatabase) << "… yes";
|
||||
} else {
|
||||
qDebug(asyncdatabase) << "… no";
|
||||
}
|
||||
return isApplied;
|
||||
}
|
||||
|
||||
void runDatabaseMigrations(QSqlDatabase &database, const QString &migrationDirectory)
|
||||
{
|
||||
createInternalTable(database);
|
||||
|
||||
QDir dir(migrationDirectory);
|
||||
auto entries = dir.entryList(QDir::Filter::Dirs | QDir::Filter::NoDotAndDotDot, QDir::SortFlag::Name);
|
||||
|
||||
for (const auto &entry : entries) {
|
||||
QDir subdir(entry);
|
||||
if (!checkMigrationAlreadyRun(database, subdir.dirName())) {
|
||||
QFile file(migrationDirectory % QDir::separator() % entry % QDir::separator() % "up.sql");
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
qCDebug(asyncdatabase) << "Failed to open migration file" << file.fileName();
|
||||
}
|
||||
qCDebug(asyncdatabase) << "Running migration" << subdir.dirName();
|
||||
|
||||
database.transaction();
|
||||
|
||||
// Hackish
|
||||
const auto statements = file.readAll().split(';');
|
||||
|
||||
bool migrationSuccessful = true;
|
||||
for (const QByteArray &statement : statements) {
|
||||
const auto trimmedStatement = statement.trimmed();
|
||||
QSqlQuery query(database);
|
||||
|
||||
if (!trimmedStatement.isEmpty()) {
|
||||
qCDebug(asyncdatabase) << "Running" << trimmedStatement;
|
||||
if (!query.prepare(trimmedStatement)) {
|
||||
printSqlError(query);
|
||||
} else {
|
||||
bool success = query.exec();
|
||||
migrationSuccessful &= success;
|
||||
if (!success) {
|
||||
printSqlError(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (migrationSuccessful) {
|
||||
database.commit();
|
||||
markMigrationRun(database, subdir.dirName());
|
||||
} else {
|
||||
database.rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
qCDebug(asyncdatabase) << "Migrations finished";
|
||||
}
|
||||
|
||||
struct AsyncSqlDatabasePrivate {
|
||||
QSqlDatabase database;
|
||||
};
|
||||
|
||||
// Internal asynchronous database class
|
||||
QFuture<void> AsyncSqlDatabase::establishConnection(const DatabaseConfiguration &configuration)
|
||||
{
|
||||
return runAsync([=, this] {
|
||||
d->database = QSqlDatabase::addDatabase(configuration.type());
|
||||
if (configuration.databaseName()) {
|
||||
d->database.setDatabaseName(*configuration.databaseName());
|
||||
}
|
||||
if (configuration.hostName()) {
|
||||
d->database.setHostName(*configuration.hostName());
|
||||
}
|
||||
if (configuration.userName()) {
|
||||
d->database.setUserName(*configuration.userName());
|
||||
}
|
||||
if (configuration.password()) {
|
||||
d->database.setPassword(*configuration.password());
|
||||
}
|
||||
|
||||
if (!d->database.open()) {
|
||||
qCDebug(asyncdatabase) << "Failed to open database" << d->database.lastError().text();
|
||||
if (configuration.databaseName()) {
|
||||
qCDebug(asyncdatabase) << "Tried to use database" << *configuration.databaseName();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AsyncSqlDatabase::AsyncSqlDatabase()
|
||||
: QObject()
|
||||
, d(std::make_unique<AsyncSqlDatabasePrivate>())
|
||||
{
|
||||
}
|
||||
|
||||
Row AsyncSqlDatabase::retrieveRow(const QSqlQuery &query) {
|
||||
Row row;
|
||||
int i = 0;
|
||||
|
||||
while (true) {
|
||||
if (query.isValid()) {
|
||||
QVariant value = query.value(i);
|
||||
if (value.isValid()) {
|
||||
row.push_back(std::move(value));
|
||||
i++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
Rows AsyncSqlDatabase::retrieveRows(QSqlQuery &query)
|
||||
{
|
||||
Rows rows;
|
||||
while (query.next()) {
|
||||
rows.push_back(retrieveRow(query));
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
std::optional<Row> AsyncSqlDatabase::retrieveOptionalRow(QSqlQuery &query)
|
||||
{
|
||||
query.next();
|
||||
|
||||
if (query.isValid()) {
|
||||
return retrieveRow(query);
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
QSqlDatabase &AsyncSqlDatabase::db()
|
||||
{
|
||||
return d->database;
|
||||
}
|
||||
|
||||
AsyncSqlDatabase::~AsyncSqlDatabase() = default;
|
||||
|
||||
void printSqlError(const QSqlQuery &query)
|
||||
{
|
||||
qCDebug(asyncdatabase) << "SQL error:" << query.lastError().text();
|
||||
}
|
||||
|
||||
QSqlQuery prepareQuery(const QSqlDatabase &database, const QString &sqlQuery)
|
||||
{
|
||||
qCDebug(asyncdatabase) << "Running" << sqlQuery;
|
||||
QSqlQuery query(database);
|
||||
if (!query.prepare(sqlQuery)) {
|
||||
printSqlError(query);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
QSqlQuery runQuery(QSqlQuery &query)
|
||||
{
|
||||
if (!query.exec()) {
|
||||
printSqlError(query);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct DatabaseConfigurationPrivate : public QSharedData {
|
||||
QString type;
|
||||
std::optional<QString> hostName;
|
||||
std::optional<QString> databaseName;
|
||||
std::optional<QString> userName;
|
||||
std::optional<QString> password;
|
||||
};
|
||||
|
||||
DatabaseConfiguration::DatabaseConfiguration() : d(new DatabaseConfigurationPrivate)
|
||||
{}
|
||||
|
||||
DatabaseConfiguration::~DatabaseConfiguration() = default;
|
||||
DatabaseConfiguration::DatabaseConfiguration(const DatabaseConfiguration &) = default;
|
||||
|
||||
void DatabaseConfiguration::setType(const QString &type) {
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
const QString &DatabaseConfiguration::type() const {
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void DatabaseConfiguration::setHostName(const QString &hostName) {
|
||||
d->hostName = hostName;
|
||||
}
|
||||
|
||||
const std::optional<QString> &DatabaseConfiguration::hostName() const {
|
||||
return d->hostName;
|
||||
}
|
||||
|
||||
void DatabaseConfiguration::setDatabaseName(const QString &databaseName) {
|
||||
d->databaseName = databaseName;
|
||||
}
|
||||
|
||||
const std::optional<QString> &DatabaseConfiguration::databaseName() const {
|
||||
return d->databaseName;
|
||||
}
|
||||
|
||||
void DatabaseConfiguration::setUserName(const QString &userName) {
|
||||
d->userName = userName;
|
||||
}
|
||||
|
||||
const std::optional<QString> &DatabaseConfiguration::userName() const {
|
||||
return d->userName;
|
||||
}
|
||||
|
||||
void DatabaseConfiguration::setPassword(const QString &password) {
|
||||
d->password = password;
|
||||
}
|
||||
|
||||
const std::optional<QString> &DatabaseConfiguration::password() const {
|
||||
return d->password;
|
||||
}
|
||||
|
||||
|
||||
struct ThreadedDatabasePrivate {
|
||||
asyncdatabase_private::AsyncSqlDatabase db;
|
||||
};
|
||||
|
||||
std::unique_ptr<ThreadedDatabase> ThreadedDatabase::establishConnection(DatabaseConfiguration config) {
|
||||
auto threadedDb = std::make_unique<ThreadedDatabase>();
|
||||
threadedDb->setObjectName(QStringLiteral("database thread"));
|
||||
threadedDb->d->db.moveToThread(&*threadedDb);
|
||||
threadedDb->start();
|
||||
threadedDb->d->db.establishConnection(config);
|
||||
return threadedDb;
|
||||
}
|
||||
|
||||
ThreadedDatabase::ThreadedDatabase()
|
||||
: QThread()
|
||||
, d(std::make_unique<ThreadedDatabasePrivate>())
|
||||
{
|
||||
}
|
||||
|
||||
ThreadedDatabase::~ThreadedDatabase()
|
||||
{
|
||||
quit();
|
||||
wait();
|
||||
}
|
||||
|
||||
asyncdatabase_private::AsyncSqlDatabase &ThreadedDatabase::db()
|
||||
{
|
||||
return d->db;
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
class QUrl;
|
||||
class QSqlDatabase;
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QFuture>
|
||||
#include <QSharedDataPointer>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "asyncdatabase_p.h"
|
||||
|
||||
struct DatabaseConfigurationPrivate;
|
||||
|
||||
///
|
||||
/// Options for connecting to a database
|
||||
///
|
||||
class DatabaseConfiguration {
|
||||
public:
|
||||
DatabaseConfiguration();
|
||||
DatabaseConfiguration(const DatabaseConfiguration &);
|
||||
~DatabaseConfiguration();
|
||||
|
||||
/// Set the name of the database driver, for example DATABASE_TYPE_SQLITE or a custom string.
|
||||
void setType(const QString &type);
|
||||
const QString &type() const;
|
||||
|
||||
/// Set the hostname
|
||||
void setHostName(const QString &hostName);
|
||||
const std::optional<QString> &hostName() const;
|
||||
|
||||
/// Set the name of the database (path of the file for SQLite)
|
||||
void setDatabaseName(const QString &databaseName);
|
||||
const std::optional<QString> &databaseName() const;
|
||||
|
||||
/// Set user name
|
||||
void setUserName(const QString &userName);
|
||||
const std::optional<QString> &userName() const;
|
||||
|
||||
/// Set password
|
||||
void setPassword(const QString &password);
|
||||
const std::optional<QString> &password() const;
|
||||
|
||||
private:
|
||||
QSharedDataPointer<DatabaseConfigurationPrivate> d;
|
||||
};
|
||||
|
||||
///
|
||||
/// The SQLite database driver
|
||||
///
|
||||
const QString DATABASE_TYPE_SQLITE = QStringLiteral("QSQLITE");
|
||||
|
||||
template <typename T>
|
||||
concept FromSql = requires(T v, typename T::ColumnTypes row)
|
||||
{
|
||||
typename T::ColumnTypes;
|
||||
{ std::tuple(row) } -> std::same_as<typename T::ColumnTypes>;
|
||||
{ T::fromSql(row) } -> std::same_as<T>;
|
||||
};
|
||||
|
||||
struct ThreadedDatabasePrivate;
|
||||
|
||||
class ThreadedDatabase : public QThread {
|
||||
public:
|
||||
///
|
||||
/// \brief Connect to a database
|
||||
/// \param configuration of the database connection
|
||||
/// \return
|
||||
///
|
||||
static std::unique_ptr<ThreadedDatabase> establishConnection(DatabaseConfiguration config);
|
||||
|
||||
///
|
||||
/// \brief Execute an SQL query on the database, ignoring the result.
|
||||
/// \param SQL query string to execute
|
||||
/// \param Parameters to bind to the placeholders in the SQL Query
|
||||
/// \return
|
||||
///
|
||||
template <typename ...Args>
|
||||
requires std::conjunction_v<std::is_convertible<Args, QVariant>...>
|
||||
auto execute(const QString &sqlQuery, Args... args) -> QFuture<void> {
|
||||
return db().execute(sqlQuery, args...);
|
||||
}
|
||||
|
||||
///
|
||||
/// Run database migrations in the given directory.
|
||||
/// The directory needs to contain a subdirectory for each migration.
|
||||
/// The subdirectories need to be named so that when sorted alphabetically the migrations will be run in the correct order.
|
||||
/// Each subdirectory needs to contain a file named up.sql.
|
||||
///
|
||||
/// \param Directory which contains the migrations.
|
||||
/// \return
|
||||
///
|
||||
auto runMigrations(const QString &migrationDirectory) -> QFuture<void> {
|
||||
return db().runMigrations(migrationDirectory);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Execute an SQL query on the database, retrieving the result.
|
||||
/// \param SQL Query to execute
|
||||
/// \param parameters to bind to the placeholders in the SQL query.
|
||||
/// \return Future of a list of lists of variants.
|
||||
///
|
||||
/// T must provide a tuple of the column types as `using ColumnTypes = std::tuple<...>`
|
||||
/// and a `static T fromSql(ColumnTypes tuple)` deserialization method.
|
||||
///
|
||||
template <typename T, typename ...Args>
|
||||
requires FromSql<T> && std::conjunction_v<std::is_convertible<Args, QVariant>...>
|
||||
auto getResults(const QString &sqlQuery, Args... args) -> QFuture<std::vector<T>> {
|
||||
return db().getResults<T, Args...>(sqlQuery, args...);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Like getResults, but for retrieving just one row.
|
||||
///
|
||||
template <typename T, typename ...Args>
|
||||
requires FromSql<T> && std::conjunction_v<std::is_convertible<Args, QVariant>...>
|
||||
auto getResult(const QString &sqlQuery, Args... args) -> QFuture<std::optional<T>> {
|
||||
return db().getResult<T, Args...>(sqlQuery, args...);
|
||||
}
|
||||
|
||||
ThreadedDatabase();
|
||||
~ThreadedDatabase();
|
||||
|
||||
private:
|
||||
asyncdatabase_private::AsyncSqlDatabase &db();
|
||||
|
||||
std::unique_ptr<ThreadedDatabasePrivate> d;
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Deserialize just a single value from a query result.
|
||||
///
|
||||
template <typename T>
|
||||
struct SingleValue {
|
||||
using ColumnTypes = std::tuple<T>;
|
||||
|
||||
static SingleValue fromSql(ColumnTypes tuple) {
|
||||
auto [value] = tuple;
|
||||
return SingleValue { value };
|
||||
}
|
||||
|
||||
T value;
|
||||
};
|
||||
@@ -0,0 +1,179 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <optional>
|
||||
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlDatabase>
|
||||
#include <QThread>
|
||||
|
||||
class DatabaseConfiguration;
|
||||
|
||||
namespace asyncdatabase_private {
|
||||
|
||||
// Helpers
|
||||
template <typename Tuple, typename Func, std::size_t i>
|
||||
inline constexpr void iterate_impl(Tuple &tup, Func fun)
|
||||
{
|
||||
if constexpr(i >= std::tuple_size_v<std::decay_t<decltype(tup)>>) {
|
||||
return;
|
||||
} else {
|
||||
fun(std::get<i>(tup));
|
||||
return asyncdatabase_private::iterate_impl<Tuple, Func, i + 1>(tup, fun);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Tuple, typename Func>
|
||||
inline constexpr void iterate_tuple(Tuple &tup, Func fun)
|
||||
{
|
||||
asyncdatabase_private::iterate_impl<Tuple, Func, 0>(tup, fun);
|
||||
}
|
||||
|
||||
template <typename T, typename QObjectDerivedType, typename Function>
|
||||
void connectFuture(const QFuture<T> &future, QObjectDerivedType *self, const Function &fun) {
|
||||
auto watcher = std::make_shared<QFutureWatcher<T>>();
|
||||
watcher->setFuture(future);
|
||||
QObject::connect(watcher.get(), &QFutureWatcherBase::finished, self, [self, watcher, fun, future] {
|
||||
if constexpr (std::is_same_v<void, T>) {
|
||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||
fun->*(self);
|
||||
} else {
|
||||
fun();
|
||||
}
|
||||
} else if (future.resultCount() > 0) {
|
||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||
(self->*fun)(watcher->result());
|
||||
} else {
|
||||
fun(watcher->result());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
using Row = std::vector<QVariant>;
|
||||
using Rows = std::vector<Row>;
|
||||
|
||||
template <typename RowTypesTuple>
|
||||
auto parseRow(const Row &row) -> RowTypesTuple
|
||||
{
|
||||
auto tuple = RowTypesTuple();
|
||||
int i = 0;
|
||||
asyncdatabase_private::iterate_tuple(tuple, [&](auto &elem) {
|
||||
elem = row.at(i).value<std::decay_t<decltype(elem)>>();
|
||||
i++;
|
||||
});
|
||||
return tuple;
|
||||
}
|
||||
|
||||
template <typename RowTypesTuple>
|
||||
auto parseRows(const Rows &rows) -> std::vector<RowTypesTuple> {
|
||||
std::vector<RowTypesTuple> parsedRows;
|
||||
parsedRows.reserve(rows.size());
|
||||
std::ranges::transform(rows, std::back_inserter(parsedRows), parseRow<RowTypesTuple>);
|
||||
return parsedRows;
|
||||
}
|
||||
|
||||
void runDatabaseMigrations(QSqlDatabase &database, const QString &migrationDirectory);
|
||||
|
||||
void printSqlError(const QSqlQuery &query);
|
||||
|
||||
// non-template helper functions to allow patching a much as possible in the shared library
|
||||
QSqlQuery prepareQuery(const QSqlDatabase &database, const QString &sqlQuery);
|
||||
QSqlQuery runQuery(QSqlQuery &query);
|
||||
|
||||
struct AsyncSqlDatabasePrivate;
|
||||
|
||||
class AsyncSqlDatabase : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QFuture<void> establishConnection(const DatabaseConfiguration &configuration);
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
auto getResults(const QString &sqlQuery, Args... args) -> QFuture<std::vector<T>> {
|
||||
return runAsync([=, this] {
|
||||
auto query = executeQuery(sqlQuery, args...);
|
||||
const auto rows = parseRows<typename T::ColumnTypes>(retrieveRows(query));
|
||||
|
||||
std::vector<T> deserializedRows;
|
||||
std::ranges::transform(rows, std::back_inserter(deserializedRows), T::fromSql);
|
||||
return deserializedRows;
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T, typename ...Args>
|
||||
auto getResult(const QString &sqlQuery, Args... args) -> QFuture<std::optional<T>> {
|
||||
return runAsync([=, this]() -> std::optional<T> {
|
||||
auto query = executeQuery(sqlQuery, args...);
|
||||
if (const auto row = retrieveOptionalRow(query)) {
|
||||
return T::fromSql(parseRow<typename T::ColumnTypes>(*row));
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
auto execute(const QString &sqlQuery, Args... args) -> QFuture<void> {
|
||||
return runAsync([=, this] {
|
||||
executeQuery(sqlQuery, args...);
|
||||
});
|
||||
}
|
||||
|
||||
auto runMigrations(const QString &migrationDirectory) -> QFuture<void> {
|
||||
return runAsync([=, this] {
|
||||
runDatabaseMigrations(db(), migrationDirectory);
|
||||
});
|
||||
}
|
||||
|
||||
AsyncSqlDatabase();
|
||||
~AsyncSqlDatabase();
|
||||
|
||||
private:
|
||||
template <typename ...Args>
|
||||
QSqlQuery executeQuery(const QString &sqlQuery, Args... args) {
|
||||
auto query = prepareQuery(db(), sqlQuery);
|
||||
auto argsTuple = std::make_tuple<Args...>(std::move(args)...);
|
||||
int i = 0;
|
||||
asyncdatabase_private::iterate_tuple(argsTuple, [&](auto &arg) {
|
||||
query.bindValue(i, arg);
|
||||
i++;
|
||||
});
|
||||
return runQuery(query);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
QFuture<std::invoke_result_t<Functor>> runAsync(Functor func) {
|
||||
using ReturnType = std::invoke_result_t<Functor>;
|
||||
auto interface = std::make_shared<QFutureInterface<ReturnType>>();
|
||||
QMetaObject::invokeMethod(this, [interface, func] {
|
||||
if constexpr (!std::is_same_v<ReturnType, void>) {
|
||||
auto result = func();
|
||||
interface->reportResult(result);
|
||||
} else {
|
||||
func();
|
||||
}
|
||||
|
||||
interface->reportFinished();
|
||||
});
|
||||
|
||||
return interface->future();
|
||||
}
|
||||
|
||||
Row retrieveRow(const QSqlQuery &query);
|
||||
Rows retrieveRows(QSqlQuery &query);
|
||||
std::optional<Row> retrieveOptionalRow(QSqlQuery &query);
|
||||
|
||||
QSqlDatabase &db();
|
||||
|
||||
std::unique_ptr<AsyncSqlDatabasePrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
+64
-103
@@ -6,6 +6,10 @@
|
||||
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QFutureInterface>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <pybind11/embed.h>
|
||||
|
||||
@@ -13,10 +17,21 @@
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
template <typename R, typename T, typename OP>
|
||||
std::optional<R> map_optional(const std::optional<T> &optional, OP op) {
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <ranges>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
|
||||
template <typename T, typename OP>
|
||||
std::optional<std::invoke_result_t<OP, T>> mapOptional(const std::optional<T> &optional, OP op) {
|
||||
if (optional.has_value()) {
|
||||
return op(optional.value());
|
||||
if constexpr (std::is_member_function_pointer<OP>::value) {
|
||||
return (&optional.value()->*op)();
|
||||
} else {
|
||||
return op(optional.value());
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
@@ -37,15 +52,6 @@ AsyncYTMusic::AsyncYTMusic(QObject *parent)
|
||||
qRegisterMetaType<std::vector<meta::Artist>>();
|
||||
qRegisterMetaType<meta::Artist>();
|
||||
|
||||
connect(this, &AsyncYTMusic::startSearch, this, &AsyncYTMusic::internalSearch);
|
||||
connect(this, &AsyncYTMusic::startFetchArtist, this, &AsyncYTMusic::internalFetchArtist);
|
||||
connect(this, &AsyncYTMusic::startFetchAlbum, this, &AsyncYTMusic::internalFetchAlbum);
|
||||
connect(this, &AsyncYTMusic::startFetchSong, this, &AsyncYTMusic::internalFetchSong);
|
||||
connect(this, &AsyncYTMusic::startFetchPlaylist, this, &AsyncYTMusic::internalFetchPlaylist);
|
||||
connect(this, &AsyncYTMusic::startFetchArtistAlbums, this, &AsyncYTMusic::internalFetchArtistAlbums);
|
||||
connect(this, &AsyncYTMusic::startExtractVideoInfo, this, &AsyncYTMusic::internalExtractVideoInfo);
|
||||
connect(this, &AsyncYTMusic::startFetchWatchPlaylist, this, &AsyncYTMusic::internalFetchWatchPlaylist);
|
||||
|
||||
connect(this, &AsyncYTMusic::errorOccurred, this, [](const QString &err) {
|
||||
std::cerr << qPrintable(err);
|
||||
});
|
||||
@@ -54,139 +60,92 @@ AsyncYTMusic::AsyncYTMusic(QObject *parent)
|
||||
//
|
||||
// search
|
||||
//
|
||||
void AsyncYTMusic::search(const QString &query)
|
||||
QFuture<std::vector<search::SearchResultItem>> AsyncYTMusic::search(const QString &query)
|
||||
{
|
||||
Q_EMIT startSearch(query);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalSearch(const QString &query)
|
||||
{
|
||||
try {
|
||||
Q_EMIT searchFinished(m_ytm->search(query.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->search(query.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// fetchArtist
|
||||
//
|
||||
void AsyncYTMusic::fetchArtist(const QString &channelId)
|
||||
QFuture<artist::Artist> AsyncYTMusic::fetchArtist(const QString &channelId)
|
||||
{
|
||||
Q_EMIT startFetchArtist(channelId);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalFetchArtist(const QString &channelId)
|
||||
{
|
||||
try {
|
||||
Q_EMIT fetchArtistFinished(m_ytm->get_artist(channelId.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_artist(channelId.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// fetchAlbum
|
||||
//
|
||||
void AsyncYTMusic::fetchAlbum(const QString &browseId)
|
||||
QFuture<album::Album> AsyncYTMusic::fetchAlbum(const QString &browseId)
|
||||
{
|
||||
Q_EMIT startFetchAlbum(browseId);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalFetchAlbum(const QString &browseId)
|
||||
{
|
||||
try {
|
||||
Q_EMIT fetchAlbumFinished(m_ytm->get_album(browseId.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_album(browseId.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// fetchSong
|
||||
//
|
||||
void AsyncYTMusic::fetchSong(const QString &videoId)
|
||||
QFuture<std::optional<song::Song>> AsyncYTMusic::fetchSong(const QString &videoId)
|
||||
{
|
||||
Q_EMIT startFetchSong(videoId);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalFetchSong(const QString &videoId)
|
||||
{
|
||||
try {
|
||||
Q_EMIT fetchSongFinished(m_ytm->get_song(videoId.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_song(videoId.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// fetchPlaylist
|
||||
//
|
||||
void AsyncYTMusic::fetchPlaylist(const QString &playlistId) {
|
||||
Q_EMIT startFetchPlaylist(playlistId);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalFetchPlaylist(const QString &playlistId)
|
||||
{
|
||||
try {
|
||||
Q_EMIT fetchPlaylistFinished(m_ytm->get_playlist(playlistId.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
QFuture<playlist::Playlist> AsyncYTMusic::fetchPlaylist(const QString &playlistId) {
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_playlist(playlistId.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// fetchArtistAlbum
|
||||
//
|
||||
void AsyncYTMusic::fetchArtistAlbums(const QString &channelId, const QString ¶ms)
|
||||
QFuture<std::vector<artist::Artist::Album>> AsyncYTMusic::fetchArtistAlbums(const QString &channelId, const QString ¶ms)
|
||||
{
|
||||
Q_EMIT startFetchArtistAlbums(channelId, params);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalFetchArtistAlbums(const QString &channelid, const QString ¶ms)
|
||||
{
|
||||
try {
|
||||
Q_EMIT fetchArtistAlbumsFinished(m_ytm->get_artist_albums(channelid.toStdString(), params.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_artist_albums(channelId.toStdString(), params.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// extractVideoInfo
|
||||
//
|
||||
void AsyncYTMusic::extractVideoInfo(const QString &videoId)
|
||||
QFuture<video_info::VideoInfo> AsyncYTMusic::extractVideoInfo(const QString &videoId)
|
||||
{
|
||||
Q_EMIT startExtractVideoInfo(videoId);
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalExtractVideoInfo(const QString &videoId)
|
||||
{
|
||||
try {
|
||||
Q_EMIT extractVideoInfoFinished(m_ytm->extract_video_info(videoId.toStdString()));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->extract_video_info(videoId.toStdString());
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// fetchWatchPlaylist
|
||||
//
|
||||
void AsyncYTMusic::fetchWatchPlaylist(const std::optional<QString> &videoId, const std::optional<QString> &playlistId)
|
||||
QFuture<watch::Playlist> AsyncYTMusic::fetchWatchPlaylist(const std::optional<QString> &videoId, const std::optional<QString> &playlistId)
|
||||
{
|
||||
Q_EMIT startFetchWatchPlaylist(videoId, playlistId);
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_watch_playlist(
|
||||
mapOptional(videoId, &QString::toStdString),
|
||||
mapOptional(playlistId, &QString::toStdString)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void AsyncYTMusic::internalFetchWatchPlaylist(const std::optional<QString> &videoId, const std::optional<QString> &playlistId)
|
||||
QFuture<Lyrics> AsyncYTMusic::fetchLyrics(const QString &browseId)
|
||||
{
|
||||
try {
|
||||
Q_EMIT fetchWatchPlaylistFinished(m_ytm->get_watch_playlist(
|
||||
map_optional<std::string>(videoId, [](const QString &value) { return value.toStdString(); }),
|
||||
map_optional<std::string>(playlistId, [](const QString &value) { return value.toStdString(); })
|
||||
));
|
||||
} catch (const py::error_already_set &err) {
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
return invokeAndCatchOnThread([=, this]() {
|
||||
return m_ytm->get_lyrics(
|
||||
browseId.toStdString()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
YTMusicThread &YTMusicThread::instance()
|
||||
@@ -203,17 +162,19 @@ YTMusicThread::~YTMusicThread()
|
||||
|
||||
AsyncYTMusic *YTMusicThread::operator->()
|
||||
{
|
||||
return &m_ytm;
|
||||
return m_ytm;
|
||||
}
|
||||
|
||||
AsyncYTMusic &YTMusicThread::get()
|
||||
{
|
||||
return m_ytm;
|
||||
return *m_ytm;
|
||||
}
|
||||
|
||||
YTMusicThread::YTMusicThread()
|
||||
: m_ytm(new AsyncYTMusic())
|
||||
{
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, m_ytm, &QObject::deleteLater);
|
||||
setObjectName(QStringLiteral("YTMusicAPI"));
|
||||
m_ytm.moveToThread(this);
|
||||
m_ytm->moveToThread(this);
|
||||
start();
|
||||
}
|
||||
+82
-42
@@ -6,11 +6,15 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <ytmusic.h>
|
||||
|
||||
constexpr QStringView YTMUSIC_WEB_BASE_URL = u"https://music.youtube.com/";
|
||||
|
||||
Q_DECLARE_METATYPE(std::vector<artist::Artist::Album>);
|
||||
Q_DECLARE_METATYPE(std::vector<search::SearchResultItem>)
|
||||
Q_DECLARE_METATYPE(artist::Artist)
|
||||
@@ -37,6 +41,7 @@ public:
|
||||
if (!m_item) {
|
||||
m_item = std::make_unique<T>();
|
||||
}
|
||||
Q_ASSERT(m_item);
|
||||
return m_item;
|
||||
}
|
||||
|
||||
@@ -44,6 +49,53 @@ private:
|
||||
std::unique_ptr<T> m_item = nullptr;
|
||||
};
|
||||
|
||||
///
|
||||
/// Similar to QObject::connect, except that the first two arguments are replaced with a QFuture.
|
||||
///
|
||||
template <typename T, typename QObjectDerivedType, typename Function>
|
||||
void connectFuture(const QFuture<T> &future, QObjectDerivedType *self, const Function &fun) {
|
||||
auto watcher = std::make_shared<QFutureWatcher<T>>();
|
||||
watcher->setFuture(future);
|
||||
QObject::connect(watcher.get(), &QFutureWatcherBase::finished, self, [self, watcher, fun, future]() {
|
||||
if constexpr (std::is_same_v<void, T>) {
|
||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||
(self->*fun)();
|
||||
} else {
|
||||
Q_UNUSED(self);
|
||||
fun();
|
||||
}
|
||||
} else if (future.resultCount() > 0) {
|
||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||
(self->*fun)(watcher->result());
|
||||
} else {
|
||||
Q_UNUSED(self);
|
||||
fun(watcher->result());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///
|
||||
/// Applies a function to a the contained value of a QFuture once it finishes.
|
||||
/// @returns a QFuture that finishes once the future given as first argument finished
|
||||
///
|
||||
template <typename T, typename Func>
|
||||
QFuture<std::invoke_result_t<Func, T>> mapFuture(const QFuture<T> &future, Func mapFunction) {
|
||||
using ReturnType = std::invoke_result_t<Func, T>;
|
||||
auto watcher = std::make_shared<QFutureWatcher<T>>();
|
||||
watcher->setFuture(future);
|
||||
|
||||
auto interface = std::make_shared<QFutureInterface<ReturnType>>();
|
||||
QObject::connect(watcher.get(), &QFutureWatcherBase::finished, watcher.get(), [interface, watcher, mapFunction] {
|
||||
auto result = watcher->result();
|
||||
auto mapped = mapFunction(std::move(result));
|
||||
interface->reportResult(mapped);
|
||||
interface->reportFinished();
|
||||
});
|
||||
|
||||
return interface->future();
|
||||
}
|
||||
|
||||
class AsyncYTMusic : public QObject
|
||||
{
|
||||
friend class YTMusicThread;
|
||||
@@ -52,30 +104,24 @@ class AsyncYTMusic : public QObject
|
||||
|
||||
public:
|
||||
// public functions need to be thread safe
|
||||
void search(const QString &query);
|
||||
Q_SIGNAL void searchFinished(std::vector<search::SearchResultItem>);
|
||||
QFuture<std::vector<search::SearchResultItem>> search(const QString &query);
|
||||
|
||||
void fetchArtist(const QString &channelId);
|
||||
Q_SIGNAL void fetchArtistFinished(artist::Artist);
|
||||
QFuture<artist::Artist> fetchArtist(const QString &channelId);
|
||||
|
||||
void fetchAlbum(const QString &browseId);
|
||||
Q_SIGNAL void fetchAlbumFinished(album::Album);
|
||||
QFuture<album::Album> fetchAlbum(const QString &browseId);
|
||||
|
||||
void fetchSong(const QString &videoId);
|
||||
Q_SIGNAL void fetchSongFinished(song::Song);
|
||||
QFuture<std::optional<song::Song> > fetchSong(const QString &videoId);
|
||||
|
||||
void fetchPlaylist(const QString &playlistId);
|
||||
Q_SIGNAL void fetchPlaylistFinished(playlist::Playlist);
|
||||
QFuture<playlist::Playlist> fetchPlaylist(const QString &playlistId);
|
||||
|
||||
void fetchArtistAlbums(const QString &channelId, const QString ¶ms);
|
||||
Q_SIGNAL void fetchArtistAlbumsFinished(std::vector<artist::Artist::Album>);
|
||||
QFuture<std::vector<artist::Artist::Album>> fetchArtistAlbums(const QString &channelId, const QString ¶ms);
|
||||
|
||||
void extractVideoInfo(const QString &videoId);
|
||||
Q_SIGNAL void extractVideoInfoFinished(video_info::VideoInfo);
|
||||
QFuture<video_info::VideoInfo> extractVideoInfo(const QString &videoId);
|
||||
|
||||
void fetchWatchPlaylist(const std::optional<QString> &videoId = std::nullopt ,
|
||||
QFuture<watch::Playlist> fetchWatchPlaylist(const std::optional<QString> &videoId = std::nullopt ,
|
||||
const std::optional<QString> &playlistId = std::nullopt);
|
||||
Q_SIGNAL void fetchWatchPlaylistFinished(watch::Playlist);
|
||||
|
||||
QFuture<Lyrics> fetchLyrics(const QString &browseId);
|
||||
|
||||
Q_SIGNAL void errorOccurred(const QString &error);
|
||||
|
||||
@@ -83,38 +129,32 @@ protected:
|
||||
explicit AsyncYTMusic(QObject *parent = nullptr);
|
||||
|
||||
private:
|
||||
Q_SIGNAL void startSearch(const QString &query);
|
||||
Q_SLOT void internalSearch(const QString &query);
|
||||
/// Invokes the given function on the thread of the YTMusic object, and handles exceptions that occur while invoking it.
|
||||
template <typename Func>
|
||||
QFuture<std::invoke_result_t<Func>> invokeAndCatchOnThread(Func fun) {
|
||||
using ReturnType = std::invoke_result_t<Func>;
|
||||
auto interface = std::make_shared<QFutureInterface<ReturnType>>();
|
||||
QMetaObject::invokeMethod(this, [=, this]() {
|
||||
try {
|
||||
ReturnType val = fun();
|
||||
interface->reportResult(val);
|
||||
interface->reportFinished();
|
||||
} catch (const std::exception &err) {
|
||||
interface->reportFinished();
|
||||
Q_EMIT errorOccurred(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
});
|
||||
return interface->future();
|
||||
}
|
||||
|
||||
Q_SIGNAL void startFetchArtist(const QString &channelId);
|
||||
Q_SLOT void internalFetchArtist(const QString &channelId);
|
||||
|
||||
Q_SIGNAL void startFetchAlbum(const QString &browseId);
|
||||
Q_SLOT void internalFetchAlbum(const QString &browseId);
|
||||
|
||||
Q_SIGNAL void startFetchSong(const QString &videoId);
|
||||
Q_SLOT void internalFetchSong(const QString &videoId);
|
||||
|
||||
Q_SIGNAL void startFetchPlaylist(const QString &playlistId);
|
||||
Q_SLOT void internalFetchPlaylist(const QString &playlistId);
|
||||
|
||||
Q_SIGNAL void startFetchArtistAlbums(const QString &channelid, const QString ¶ms);
|
||||
Q_SLOT void internalFetchArtistAlbums(const QString &channelid, const QString ¶ms);
|
||||
|
||||
Q_SIGNAL void startExtractVideoInfo(const QString &videoId);
|
||||
Q_SLOT void internalExtractVideoInfo(const QString &videoId);
|
||||
|
||||
Q_SIGNAL void startFetchWatchPlaylist(const std::optional<QString> &videoId, const std::optional<QString> &playlistId);
|
||||
Q_SLOT void internalFetchWatchPlaylist(const std::optional<QString> &videoId, const std::optional<QString> &playlistId);
|
||||
|
||||
// Python interpreter will be ininitalized from the thread calling the methods
|
||||
// Python interpreter will be initialized from the thread calling the methods
|
||||
Lazy<YTMusic> m_ytm;
|
||||
};
|
||||
|
||||
class YTMusicThread : private QThread {
|
||||
public:
|
||||
static YTMusicThread &instance();
|
||||
~YTMusicThread();
|
||||
~YTMusicThread() override;
|
||||
|
||||
AsyncYTMusic *operator->();
|
||||
AsyncYTMusic &get();
|
||||
@@ -122,5 +162,5 @@ public:
|
||||
private:
|
||||
YTMusicThread();
|
||||
|
||||
AsyncYTMusic m_ytm;
|
||||
AsyncYTMusic *m_ytm;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Devin Lin <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "blur.h"
|
||||
|
||||
#include <KWindowEffects>
|
||||
|
||||
#include <QQuickWindow>
|
||||
#include <QQuickItem>
|
||||
|
||||
|
||||
Blur::Blur(QObject *parent): QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void Blur::setBlur(QQuickItem *item, bool blur)
|
||||
{
|
||||
auto setWindows = [item, blur]() {
|
||||
auto reg = QRect(QPoint(0, 0), item->window()->size());
|
||||
KWindowEffects::enableBackgroundContrast(item->window(), blur, 1, 1, 1, reg);
|
||||
KWindowEffects::enableBlurBehind(item->window(), blur, reg);
|
||||
};
|
||||
|
||||
disconnect(item->window(), &QQuickWindow::heightChanged, this, nullptr);
|
||||
disconnect(item->window(), &QQuickWindow::widthChanged, this, nullptr);
|
||||
connect(item->window(), &QQuickWindow::heightChanged, this, setWindows);
|
||||
connect(item->window(), &QQuickWindow::widthChanged, this, setWindows);
|
||||
setWindows();
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Devin Lin <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QQuickItem;
|
||||
|
||||
class Blur : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Blur(QObject *parent = 0);
|
||||
Q_INVOKABLE void setBlur(QQuickItem *item, bool blur);
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick 2.15
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.3
|
||||
@@ -13,37 +13,66 @@ Kirigami.ScrollablePage {
|
||||
property alias browseId: albumModel.browseId
|
||||
title: albumModel.title
|
||||
|
||||
actions {
|
||||
main: Kirigami.Action {
|
||||
icon.name: "media-playback-start"
|
||||
text: i18n("Play")
|
||||
onTriggered: {
|
||||
applicationWindow().playPlaylist(albumModel.playlistId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
header: Kirigami.ItemViewHeader {
|
||||
backgroundImage.source: albumModel.thumbnailUrl
|
||||
id: songList
|
||||
header: ListHeader {
|
||||
visibleActions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playback-start"
|
||||
text: i18n("Play")
|
||||
onTriggered: {
|
||||
applicationWindow().playPlaylist(albumModel.playlistId)
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playlist-shuffle"
|
||||
text: i18n("Shuffle")
|
||||
onTriggered: {
|
||||
applicationWindow().playShufflePlaylist(albumModel.playlistId)
|
||||
}
|
||||
}
|
||||
]
|
||||
overflowActions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("Open in Browser")
|
||||
icon.name: "internet-services"
|
||||
onTriggered: Qt.openUrlExternally(albumModel.webUrl)
|
||||
}
|
||||
]
|
||||
title: albumModel.title
|
||||
imageSourceURL: albumModel.thumbnailUrl
|
||||
subtitle: i18n("Album • %1" , albumModel.artists)
|
||||
width: songList.width
|
||||
}
|
||||
|
||||
|
||||
reuseItems: true
|
||||
|
||||
model: AlbumModel {
|
||||
id: albumModel
|
||||
}
|
||||
SongMenu {
|
||||
id: menu
|
||||
}
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
id: delegateItem
|
||||
alwaysVisibleActions:true
|
||||
|
||||
required property string title
|
||||
required property string videoId
|
||||
required property var artists
|
||||
required property string thumbnailUrl
|
||||
required property string artistsDisplayString
|
||||
required property int index
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
Kirigami.Icon {
|
||||
Layout.fillHeight: true
|
||||
source: "emblem-music-symbolic"
|
||||
Controls.Label {
|
||||
text: (index + 1)
|
||||
font.bold: true
|
||||
leftPadding: 5
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
Layout.preferredWidth: 30
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
@@ -55,18 +84,13 @@ Kirigami.ScrollablePage {
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "go-next"
|
||||
text: i18n("Play next")
|
||||
onTriggered: UserPlaylistModel.playNext(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playlist-append"
|
||||
text: i18n("Add to playlist")
|
||||
onTriggered: UserPlaylistModel.append(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
text: i18n("More")
|
||||
onTriggered: menu.openForSong(delegateItem.videoId, delegateItem.title, delegateItem.artists, delegateItem.artistsDisplayString)
|
||||
}
|
||||
]
|
||||
|
||||
onClicked: play(videoId)
|
||||
onClicked: play(delegateItem.videoId)
|
||||
}
|
||||
|
||||
Controls.BusyIndicator {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick 2.15
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.3
|
||||
@@ -11,14 +11,46 @@ import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
property alias channelId: artistModel.channelId
|
||||
|
||||
property string radioId
|
||||
property string shuffleId
|
||||
title: artistModel.title
|
||||
|
||||
SongMenu {
|
||||
id: menu
|
||||
}
|
||||
ListView {
|
||||
header: Kirigami.ItemViewHeader {
|
||||
backgroundImage.source: artistModel.thumbnailUrl
|
||||
id: songList
|
||||
|
||||
header: ListHeader {
|
||||
visibleActions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("Radio")
|
||||
icon.name: "radio"
|
||||
onTriggered: playPlaylist(radioId)
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18n("Shuffle")
|
||||
icon.name: "media-playlist-shuffle"
|
||||
onTriggered: playPlaylist(shuffleId)
|
||||
}
|
||||
]
|
||||
overflowActions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("Open in Browser")
|
||||
icon.name: "internet-services"
|
||||
onTriggered: Qt.openUrlExternally(artistModel.webUrl)
|
||||
}
|
||||
]
|
||||
title: artistModel.title
|
||||
imageSourceURL: artistModel.thumbnailUrl
|
||||
subtitle: i18n("Artist")
|
||||
rounded: true
|
||||
width: songList.width
|
||||
|
||||
}
|
||||
|
||||
reuseItems: true
|
||||
|
||||
model: ArtistModel {
|
||||
id: artistModel
|
||||
|
||||
@@ -32,10 +64,19 @@ Kirigami.ScrollablePage {
|
||||
play(videoId)
|
||||
}
|
||||
|
||||
onOpenVideo: (videoId) => {
|
||||
askPlayVideoAudio(videoId)
|
||||
onOpenVideo: (videoId, title) => {
|
||||
videoPlayMessage.text = i18n("Video playback is not supported yet. Do you want to play only the audio of \"%1\"?", title)
|
||||
videoPlayMessage.visible = true
|
||||
videoPlayMessage.okAction = () => {
|
||||
play(videoId)
|
||||
videoPlayMessage.visible = false
|
||||
}
|
||||
videoPlayMessage.cancelAction = () => {
|
||||
videoPlayMessage.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.property: "type"
|
||||
section.delegate: Kirigami.ListSectionHeader {
|
||||
text: {
|
||||
@@ -51,30 +92,25 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
id: delegateItem
|
||||
alwaysVisibleActions:true
|
||||
|
||||
required property string title
|
||||
required property int type
|
||||
required property int index
|
||||
required property var artists
|
||||
required property string videoId
|
||||
required property string thumbnailUrl
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
Kirigami.Icon {
|
||||
Layout.fillHeight: true
|
||||
source: {
|
||||
switch (type) {
|
||||
case ArtistModel.Album:
|
||||
return "media-album-cover"
|
||||
case ArtistModel.Single:
|
||||
case ArtistModel.Song:
|
||||
return "emblem-music-symbolic"
|
||||
case ArtistModel.Video:
|
||||
return "emblem-videos-symbolic"
|
||||
}
|
||||
}
|
||||
RoundedImage {
|
||||
source: delegateItem.thumbnailUrl
|
||||
height: 35
|
||||
width: height
|
||||
radius:5
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
@@ -86,16 +122,10 @@ Kirigami.ScrollablePage {
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "go-next"
|
||||
text: i18n("Play next")
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
text: i18n("More")
|
||||
visible: type === ArtistModel.Song
|
||||
onTriggered: UserPlaylistModel.playNext(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playlist-append"
|
||||
text: i18n("Add to playlist")
|
||||
visible: type === ArtistModel.Song
|
||||
onTriggered: UserPlaylistModel.append(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
onTriggered: menu.openForSong(delegateItem.videoId, delegateItem.title, delegateItem.artists, artistModel.title)
|
||||
}
|
||||
]
|
||||
|
||||
@@ -107,4 +137,8 @@ Kirigami.ScrollablePage {
|
||||
visible: artistModel.loading
|
||||
}
|
||||
}
|
||||
|
||||
footer: ConfirmationMessage {
|
||||
id: videoPlayMessage
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: 2021 Dimitris Kardarakos <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
|
||||
property var okAction
|
||||
property var cancelAction
|
||||
|
||||
visible: false
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("OK")
|
||||
|
||||
onTriggered: okAction()
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18n("Cancel")
|
||||
|
||||
onTriggered: cancelAction()
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 2.12 as Controls
|
||||
import QtQuick.Layouts 1.3
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
objectName: "libraryPage"
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
title: "AudioTube"
|
||||
|
||||
rightPadding: 0
|
||||
leftPadding: 0
|
||||
|
||||
SongMenu {
|
||||
id: menu
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Heading {
|
||||
text: i18n("Favourites")
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
leftPadding: 15
|
||||
}
|
||||
|
||||
// Spacer
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Controls.ToolButton {
|
||||
text: i18n("Show All")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
icon.name: "arrow-right"
|
||||
onClicked: {pageStack.push("qrc:/PlaybackHistory.qml", {
|
||||
"dataModel": Library.favourites,
|
||||
"title": i18n("Favourites"),
|
||||
"objectName": "favourites"
|
||||
})}
|
||||
}
|
||||
}
|
||||
|
||||
Controls.ScrollView {
|
||||
leftPadding: 15
|
||||
rightPadding: 25
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
spacing: 20
|
||||
Repeater {
|
||||
Layout.fillWidth: true
|
||||
model: Library.favourites
|
||||
delegate: ColumnLayout {
|
||||
id: delegateItem
|
||||
required property string title
|
||||
required property var artists
|
||||
required property string artistsDisplayString
|
||||
required property string videoId
|
||||
required property int index
|
||||
|
||||
Layout.fillWidth: false
|
||||
Layout.maximumWidth: 200
|
||||
|
||||
Kirigami.ShadowedRectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
id: favCover
|
||||
MouseArea {
|
||||
id: favArea
|
||||
anchors.fill: parent
|
||||
onClicked: play(delegateItem.videoId)
|
||||
hoverEnabled: !Kirigami.Settings.hasTransientTouchInput
|
||||
onEntered: {
|
||||
if (!Kirigami.Settings.hasTransientTouchInput){
|
||||
favSelected.visible = true
|
||||
favTitle.color = Kirigami.Theme.hoverColor
|
||||
favSubtitle.color = Kirigami.Theme.hoverColor
|
||||
favTitle.font.bold = true
|
||||
playAnimationPosition.running = true
|
||||
playAnimationOpacity.running = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onExited:{
|
||||
favSelected.visible = false
|
||||
favTitle.color = Kirigami.Theme.textColor
|
||||
favSubtitle.color = Kirigami.Theme.disabledTextColor
|
||||
favTitle.font.bold = false
|
||||
}
|
||||
}
|
||||
Layout.margins: 5
|
||||
|
||||
width: 200
|
||||
height: 200
|
||||
radius: 10
|
||||
shadow.size: 15
|
||||
shadow.xOffset: 5
|
||||
shadow.yOffset: 5
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
ThumbnailSource {
|
||||
id: thumbnailSource
|
||||
videoId: delegateItem.videoId
|
||||
}
|
||||
RoundedImage {
|
||||
source: thumbnailSource.cachedPath
|
||||
height: 200
|
||||
width: height
|
||||
radius: 10
|
||||
}
|
||||
Rectangle {
|
||||
id: favSelected
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Kirigami.Theme.hoverColor
|
||||
radius: 10
|
||||
opacity: 0.2
|
||||
}
|
||||
Item{
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
NumberAnimation on opacity{
|
||||
id: playAnimationOpacity
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 0; to: 1
|
||||
}
|
||||
NumberAnimation on y {
|
||||
id: playAnimationPosition
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 20; to: 0
|
||||
duration: 100
|
||||
}
|
||||
Rectangle {
|
||||
height: 45
|
||||
width: 45
|
||||
radius: 50
|
||||
color: Kirigami.Theme.hoverColor
|
||||
opacity: 0.8
|
||||
anchors.centerIn: parent
|
||||
|
||||
|
||||
}
|
||||
Kirigami.Icon {
|
||||
x: 100 - 0.43 * height
|
||||
y: 100 - 0.5 * height
|
||||
color: "white"
|
||||
source: "media-playback-start"
|
||||
}
|
||||
}
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 9
|
||||
|
||||
border.color: Kirigami.Theme.hoverColor
|
||||
border.width: 2
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
Controls.Label {
|
||||
id:favTitle
|
||||
text: delegateItem.title
|
||||
Layout.maximumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
leftPadding: 5
|
||||
elide: Text.ElideRight
|
||||
|
||||
}
|
||||
Controls.Label {
|
||||
id: favSubtitle
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: 200
|
||||
leftPadding: 5
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: delegateItem.artistsDisplayString
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
Controls.ToolButton {
|
||||
Layout.fillHeight: true
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
onPressed: menu.openForSong(delegateItem.videoId,
|
||||
delegateItem.title,
|
||||
delegateItem.artists,
|
||||
delegateItem.artistsDisplayString)
|
||||
}
|
||||
|
||||
}
|
||||
Item {
|
||||
height: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
height: 20
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Heading {
|
||||
text: i18n("Most played")
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
leftPadding: 15
|
||||
}
|
||||
|
||||
// Spacer
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Controls.ToolButton {
|
||||
text: i18n("Show All")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
icon.name: "arrow-right"
|
||||
onClicked: {pageStack.push("qrc:/PlaybackHistory.qml", {
|
||||
"dataModel": Library.playbackHistory,
|
||||
"title": i18n("played Songs"),
|
||||
"objectName": "history"
|
||||
})}
|
||||
}
|
||||
}
|
||||
Controls.ScrollView {
|
||||
leftPadding: 15
|
||||
rightPadding: 25
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
spacing: 20
|
||||
Repeater {
|
||||
Layout.fillWidth: true
|
||||
model: Library.mostPlayed
|
||||
delegate: ColumnLayout {
|
||||
id: mpdelegateItem
|
||||
required property string title
|
||||
required property var artists
|
||||
required property string artistsDisplayString
|
||||
required property string videoId
|
||||
|
||||
Layout.fillWidth: false
|
||||
Layout.maximumWidth: 200
|
||||
|
||||
Kirigami.ShadowedRectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
id: recCover
|
||||
MouseArea {
|
||||
id: recArea
|
||||
anchors.fill: parent
|
||||
onClicked: play(mpdelegateItem.videoId)
|
||||
hoverEnabled: !Kirigami.Settings.hasTransientTouchInput
|
||||
onEntered: {
|
||||
if (!Kirigami.Settings.hasTransientTouchInput)
|
||||
recSelected.visible = true
|
||||
recTitle.color = Kirigami.Theme.hoverColor
|
||||
recSubtitle.color = Kirigami.Theme.hoverColor
|
||||
recTitle.font.bold = true
|
||||
playAnimationPositionRec.running = true
|
||||
playAnimationOpacityRec.running = true
|
||||
}
|
||||
onExited:{
|
||||
recSelected.visible = false
|
||||
recTitle.color = Kirigami.Theme.textColor
|
||||
recSubtitle.color = Kirigami.Theme.disabledTextColor
|
||||
recTitle.font.bold = false
|
||||
}
|
||||
|
||||
}
|
||||
Layout.margins: 5
|
||||
|
||||
width: 200
|
||||
height: 200
|
||||
radius: 10
|
||||
shadow.size: 15
|
||||
shadow.xOffset: 5
|
||||
shadow.yOffset: 5
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
ThumbnailSource {
|
||||
id: mpthumbnailSource
|
||||
videoId: mpdelegateItem.videoId
|
||||
}
|
||||
RoundedImage {
|
||||
source: mpthumbnailSource.cachedPath
|
||||
height: 200
|
||||
width: height
|
||||
radius: 10
|
||||
}
|
||||
Rectangle {
|
||||
id: recSelected
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Kirigami.Theme.hoverColor
|
||||
radius: 10
|
||||
opacity: 0.2
|
||||
}
|
||||
Item{
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
NumberAnimation on opacity{
|
||||
id: playAnimationOpacityRec
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 0; to: 1
|
||||
}
|
||||
NumberAnimation on y {
|
||||
id: playAnimationPositionRec
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 20; to: 0
|
||||
duration: 100
|
||||
}
|
||||
Rectangle {
|
||||
height: 45
|
||||
width: 45
|
||||
radius: 50
|
||||
color: Kirigami.Theme.hoverColor
|
||||
opacity: 0.8
|
||||
anchors.centerIn: parent
|
||||
|
||||
|
||||
}
|
||||
Kirigami.Icon {
|
||||
x: 100 - 0.43 * height
|
||||
y: 100 - 0.5 * height
|
||||
color: "white"
|
||||
source: "media-playback-start"
|
||||
}
|
||||
}
|
||||
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 9
|
||||
|
||||
border.color: Kirigami.Theme.hoverColor
|
||||
border.width: 2
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
ColumnLayout {
|
||||
Controls.Label {
|
||||
id: recTitle
|
||||
text: mpdelegateItem.title
|
||||
Layout.maximumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
leftPadding: 5
|
||||
elide: Text.ElideRight
|
||||
|
||||
}
|
||||
Controls.Label {
|
||||
id: recSubtitle
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: 200
|
||||
leftPadding: 5
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: mpdelegateItem.artistsDisplayString
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
Controls.ToolButton {
|
||||
Layout.fillHeight: true
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
onPressed: menu.openForSong(mpdelegateItem.videoId,
|
||||
mpdelegateItem.title,
|
||||
mpdelegateItem.artists,
|
||||
mpdelegateItem.artistsDisplayString)
|
||||
}
|
||||
|
||||
}
|
||||
Item {
|
||||
height: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mathis Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
|
||||
Item {
|
||||
id:root
|
||||
|
||||
required property string imageSourceURL
|
||||
property bool rounded : false
|
||||
required property string title
|
||||
property string subtitle
|
||||
property list<Kirigami.Action> visibleActions
|
||||
property list<Kirigami.Action> overflowActions
|
||||
|
||||
height: root.width > 500 ? 200 : 400
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
|
||||
Image {
|
||||
scale: 1.8
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
|
||||
source: imageSourceURL
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
|
||||
sourceSize.width: 512
|
||||
sourceSize.height: 512
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: HueSaturation {
|
||||
cached: true
|
||||
|
||||
saturation: 1.9
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
cached: true
|
||||
radius: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
gradient: Gradient{
|
||||
GradientStop { position: -1.0; color: "transparent" }
|
||||
GradientStop { position: 1.0; color: Kirigami.Theme.backgroundColor }
|
||||
|
||||
}
|
||||
}
|
||||
GridLayout {
|
||||
width: parent.width
|
||||
|
||||
flow: root.width > 500?GridLayout.LeftToRight:GridLayout.TopToBottom
|
||||
Kirigami.ShadowedRectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
Layout.margins: 30
|
||||
width: 150
|
||||
height: width
|
||||
radius: rounded ? 100 : 10
|
||||
shadow.size: 15
|
||||
shadow.xOffset: 5
|
||||
shadow.yOffset: 5
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
|
||||
RoundedImage {
|
||||
source: imageSourceURL
|
||||
height: parent.height
|
||||
width: height
|
||||
radius: rounded ? 100 : 10
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.leftMargin: 30
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: title
|
||||
font.bold: true
|
||||
font.pixelSize: 22
|
||||
elide: Qt.ElideRight
|
||||
|
||||
}
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: subtitle
|
||||
elide: Qt.ElideRight
|
||||
|
||||
}
|
||||
RowLayout {
|
||||
visible: root.visibleActions.length>0
|
||||
Layout.topMargin: 30
|
||||
Layout.rightMargin: 30
|
||||
|
||||
Repeater {
|
||||
model: root.visibleActions
|
||||
delegate: Controls.RoundButton{
|
||||
required property var modelData
|
||||
Layout.fillWidth: root.width <= 500
|
||||
leftPadding: 20
|
||||
rightPadding: 20
|
||||
icon.name: modelData.icon.name
|
||||
text:modelData.text
|
||||
onClicked: modelData.triggered()
|
||||
}
|
||||
}
|
||||
Controls.Menu {
|
||||
id: overflowMenu
|
||||
Instantiator {
|
||||
model: root.overflowActions
|
||||
onObjectAdded: overflowMenu.insertItem(index, object)
|
||||
onObjectRemoved: overflowMenu.removeItem(object)
|
||||
delegate: Controls.MenuItem {
|
||||
required property var modelData
|
||||
icon.name: modelData.icon.name
|
||||
text:modelData.text
|
||||
onTriggered: modelData.triggered()
|
||||
}
|
||||
}
|
||||
}
|
||||
Controls.RoundButton {
|
||||
onClicked: overflowMenu.popup()
|
||||
visible: root.overflowActions.length > 0
|
||||
icon.name: "overflow-menu"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,920 @@
|
||||
// SPDX-FileCopyrightText: 2020-2022 Devin Lin <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtMultimedia 5.12
|
||||
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property var info // VideoInfoExtractor object
|
||||
required property var audio // Audio object
|
||||
readonly property bool isWidescreen: width >= Kirigami.Units.gridUnit * 50
|
||||
|
||||
signal requestClose()
|
||||
|
||||
// background image
|
||||
|
||||
|
||||
Item {
|
||||
id:bg
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(25, 25, 30, 1)
|
||||
}
|
||||
|
||||
Image {
|
||||
scale: 1.8
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
|
||||
source: info.thumbnail
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
|
||||
sourceSize.width: 512
|
||||
sourceSize.height: 512
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: HueSaturation {
|
||||
cached: true
|
||||
|
||||
lightness: -0.5
|
||||
saturation: 1.9
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
cached: true
|
||||
radius: 100
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
gradient: Gradient{
|
||||
GradientStop { position: 0.0; color: "transparent" }
|
||||
GradientStop { position: 1.1; color: "black" }
|
||||
}
|
||||
}
|
||||
|
||||
// content
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
// hide arrow button
|
||||
ToolButton {
|
||||
id: closeButton
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.maximumHeight: parent.height
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
|
||||
Layout.maximumWidth: parent.height
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 3
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
icon.name: "arrow-down"
|
||||
icon.color: "white"
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
onClicked: root.requestClose()
|
||||
}
|
||||
|
||||
SwipeView {
|
||||
interactive: false
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
clip:true
|
||||
id: swipeView
|
||||
property double specWidth: {
|
||||
let allowedWidth = root.width - Kirigami.Units.largeSpacing * 4;
|
||||
let allowedHeight = root.height - Kirigami.Units.largeSpacing * 16 - (closeButton.height + bottomPlayerControls.height);
|
||||
if (allowedWidth > allowedHeight) {
|
||||
return allowedHeight;
|
||||
} else {
|
||||
return allowedWidth;
|
||||
}
|
||||
}
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
|
||||
Layout.preferredHeight: specWidth
|
||||
|
||||
// music art
|
||||
Flickable {
|
||||
flickableDirection: Flickable.HorizontalFlick
|
||||
clip:true
|
||||
contentWidth: coverArt.width
|
||||
contentHeight: coverArt.height
|
||||
height: swipeView.height
|
||||
width: applicationWindow().width-sideDrawer.width
|
||||
onFlickEnded:{
|
||||
|
||||
if(horizontalVelocity<0){
|
||||
UserPlaylistModel.next()
|
||||
}
|
||||
else{
|
||||
if(UserPlaylistModel.canSkipBack){
|
||||
UserPlaylistModel.previous()
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{
|
||||
height:swipeView.height
|
||||
width:applicationWindow().width-sideDrawer.width
|
||||
Kirigami.ShadowedRectangle {
|
||||
id:coverArt
|
||||
x: 4
|
||||
anchors.centerIn: parent
|
||||
width: swipeView.specWidth
|
||||
height: swipeView.specWidth
|
||||
|
||||
|
||||
color: "transparent"
|
||||
radius: 10
|
||||
shadow.size: 15
|
||||
shadow.xOffset: 5
|
||||
shadow.yOffset: 5
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
RoundedImage {
|
||||
source: info.thumbnail
|
||||
height: parent.height
|
||||
width: height
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout{
|
||||
width: swipeView.width
|
||||
height: swipeView.height
|
||||
ScrollView {
|
||||
Layout.maximumWidth: 900
|
||||
contentWidth: -1
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
clip: true
|
||||
|
||||
//contentY: audio.position / audio.duration
|
||||
|
||||
Label {
|
||||
padding: 20
|
||||
text: UserPlaylistModel.lyrics
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: bottomPlayerControls
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.leftMargin: Kirigami.Units.gridUnit * 2
|
||||
Layout.rightMargin: Kirigami.Units.gridUnit * 2
|
||||
Layout.bottomMargin: Kirigami.Units.gridUnit * 2
|
||||
|
||||
// song name
|
||||
Label {
|
||||
id: mainLabel
|
||||
text: info.title ? info.title : i18n("No media playing")
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
// Hardcoded because the footerbar blur always makes a dark-ish
|
||||
// background, so we don't want to use a color scheme color that
|
||||
// might also be dark
|
||||
color: "white"
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
|
||||
font.weight: Font.Bold
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
// song artist
|
||||
Kirigami.Heading {
|
||||
id: authorLabel
|
||||
text: info.artist ? info.artist : info.channel
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth:600
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
// Hardcoded because the footerbar blur always makes a dark-ish
|
||||
// background, so we don't want to use a color scheme color that
|
||||
// might also be dark
|
||||
opacity: 0.9
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.3
|
||||
font.bold: true
|
||||
Layout.bottomMargin: Kirigami.Units.gridUnit
|
||||
}
|
||||
RowLayout {
|
||||
Layout.topMargin: Kirigami.Units.gridUnit
|
||||
|
||||
id: controlButtonBox
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
anchors.right: !isWidescreen? root.right:null
|
||||
Layout.fillHeight: true
|
||||
spacing: 2
|
||||
|
||||
|
||||
Button {
|
||||
id: skipBackwardButton
|
||||
height: 40
|
||||
width: 40
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
enabled: UserPlaylistModel.canSkipBack
|
||||
onClicked: UserPlaylistModel.previous()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source:"media-skip-backward"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topLeftRadius: 7
|
||||
corners.bottomLeftRadius: 7
|
||||
|
||||
|
||||
color: if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: playPauseButton
|
||||
height: 40
|
||||
width: 60
|
||||
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source: audio.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
color: if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: skipForwardButton
|
||||
height: 40
|
||||
width: 40
|
||||
Layout.rightMargin:isWidescreen?0:10
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
enabled: UserPlaylistModel.canSkip
|
||||
onClicked: UserPlaylistModel.next()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source:"media-skip-forward"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topRightRadius: 7
|
||||
corners.bottomRightRadius: 7
|
||||
color: if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// slider row
|
||||
RowLayout {
|
||||
Layout.topMargin: Kirigami.Units.gridUnit
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: "white"
|
||||
visible: info.title
|
||||
text: PlayerUtils.formatTimestamp(audio.position)
|
||||
}
|
||||
|
||||
Slider {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: audio.duration
|
||||
value: audio.position
|
||||
enabled: audio.seekable
|
||||
onMoved: {
|
||||
console.log("Value:", value);
|
||||
audio.seek(Math.floor(value));
|
||||
}
|
||||
|
||||
Behavior on value {
|
||||
NumberAnimation {
|
||||
duration: 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: "white"
|
||||
visible: info.title
|
||||
text: PlayerUtils.formatTimestamp(audio.duration)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.fillWidth: true
|
||||
// ensure white icons
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
Item {
|
||||
width: queueButton.width
|
||||
visible: wideScreen
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true}
|
||||
|
||||
ToolButton {
|
||||
id: favouriteButton
|
||||
readonly property QtObject favouriteWatcher: Library.favouriteWatcher(info.videoId)
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
onClicked: {
|
||||
if (favouriteWatcher) {
|
||||
if (favouriteWatcher.isFavourite) {
|
||||
Library.removeFavourite(info.videoId)
|
||||
// This would insert slightly ugly data into the database, but let's hope the song is already saved
|
||||
} else {
|
||||
let index = UserPlaylistModel.index(UserPlaylistModel.currentIndex, 0)
|
||||
let videoId = UserPlaylistModel.data(index, UserPlaylistModel.VideoId)
|
||||
let title = UserPlaylistModel.data(index, UserPlaylistModel.Title)
|
||||
let artist = UserPlaylistModel.data(index, UserPlaylistModel.Artists)
|
||||
let album = UserPlaylistModel.data(index, UserPlaylistModel.Album)
|
||||
Library.addFavourite(videoId, title, artist, album)
|
||||
}
|
||||
}
|
||||
}
|
||||
text: "Favourite"
|
||||
icon.name: favouriteWatcher ? (favouriteWatcher.isFavourite ? "starred-symbolic" : "non-starred-symbolic") : ""
|
||||
icon.color: "white"
|
||||
display: AbstractButton.IconOnly
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: shuffleButton
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
|
||||
onClicked: UserPlaylistModel.shufflePlaylist()
|
||||
|
||||
icon.name: "media-playlist-shuffle"
|
||||
icon.color: "white"
|
||||
text: "Shuffle"
|
||||
display: AbstractButton.IconOnly
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: volumeButtonSmallScreen
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
visible: !isWidescreen
|
||||
enabled: !isWidescreen
|
||||
|
||||
icon.name: muteButton.icon.name
|
||||
|
||||
onClicked:{
|
||||
if(!volumeDrawer.opened){
|
||||
volumeDrawer.open()
|
||||
volumeDrawer.interactive = true
|
||||
}
|
||||
else{
|
||||
volumeDrawer.close()
|
||||
}
|
||||
}
|
||||
Drawer {
|
||||
id: volumeDrawer
|
||||
|
||||
edge: Qt.BottomEdge
|
||||
width: applicationWindow().width
|
||||
height: contents.height + 40
|
||||
interactive: false
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topRightRadius: 10
|
||||
corners.topLeftRadius: 10
|
||||
shadow.size: 20
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.5)
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
}
|
||||
onClosed: {
|
||||
interactive = false
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: contents
|
||||
|
||||
width: volumeDrawer.width
|
||||
|
||||
ToolButton{
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
|
||||
icon.name: muteButton.icon.name
|
||||
checkable: true
|
||||
checked: muteButton.checked
|
||||
onClicked: {
|
||||
if(audio.muted)
|
||||
{
|
||||
muteButton.unmuteAudio()
|
||||
}
|
||||
else
|
||||
{
|
||||
muteButton.muteAudio()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
value: volumeSlider.value
|
||||
opacity: volumeSlider.opacity
|
||||
wheelEnabled: true
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
|
||||
onMoved: {
|
||||
volumeSlider.value = value
|
||||
volumeSlider.valueChanged()
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.preferredHeight: Slider.height
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 2.5
|
||||
|
||||
text: volumeLabel.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: muteButton
|
||||
|
||||
function muteAudio() {
|
||||
audio.muted = true
|
||||
volumeSlider.opacity = 0.5
|
||||
checked = true
|
||||
}
|
||||
function unmuteAudio() {
|
||||
audio.muted = false
|
||||
volumeSlider.opacity = 1
|
||||
checked = false
|
||||
}
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
|
||||
onClicked: {
|
||||
if(audio.muted) {
|
||||
unmuteAudio()
|
||||
}
|
||||
else {
|
||||
muteAudio()
|
||||
}
|
||||
}
|
||||
|
||||
icon.name: audio.muted ? "audio-volume-muted" : (volumeSlider.value < .33 ? "audio-volume-low" : (volumeSlider.value < .66 ? "audio-volume-medium" : "audio-volume-high"))
|
||||
checkable: true
|
||||
visible: isWidescreen
|
||||
enabled: isWidescreen
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: volumeSlider
|
||||
enabled: isWidescreen
|
||||
visible: isWidescreen
|
||||
|
||||
property real volume: QtMultimedia.convertVolume(value, QtMultimedia.LogarithmicVolumeScale, QtMultimedia.LinearVolumeScale)
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.preferredWidth: 2*Layout.preferredHeight
|
||||
|
||||
value: 1.0
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
wheelEnabled: true
|
||||
|
||||
onMoved: {
|
||||
valueChanged()
|
||||
}
|
||||
function valueChanged() {
|
||||
audio.volume = volume
|
||||
if(value==0) {
|
||||
muteButton.muteAudio()
|
||||
}
|
||||
else{
|
||||
muteButton.unmuteAudio()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: volumeLabel
|
||||
|
||||
enabled: isWidescreen
|
||||
visible: isWidescreen
|
||||
text: Math.round(volumeSlider.value*100) + i18n("%")
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.preferredHeight: volumeSlider.Layout.preferredHeight
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 2.5
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
property bool lyricsShown: false
|
||||
id: lyricsButton
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
checked: lyricsShown
|
||||
onClicked: {
|
||||
if (!lyricsShown)
|
||||
swipeView.setCurrentIndex(1)
|
||||
else{
|
||||
swipeView.setCurrentIndex(0)
|
||||
}
|
||||
lyricsShown = !lyricsShown
|
||||
}
|
||||
text: "Lyrics"
|
||||
icon.name: "view-media-lyrics"
|
||||
icon.color: "white"
|
||||
display: AbstractButton.IconOnly
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
visible: wideScreen
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: queueButton
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
|
||||
Layout.maximumWidth: height
|
||||
Layout.preferredWidth: height
|
||||
checked: !sideDrawer.collapsed && wideScreen
|
||||
|
||||
onClicked: {
|
||||
if (wideScreen){
|
||||
if (!sideDrawer.collapsed)
|
||||
collapse.running = true
|
||||
else{
|
||||
sideDrawer.visible=true
|
||||
show.running = true
|
||||
}
|
||||
sideDrawer.collapsed = !sideDrawer.collapsed
|
||||
}else{queueDrawer.open()}
|
||||
}
|
||||
|
||||
text: "Queue"
|
||||
display: AbstractButton.IconOnly
|
||||
icon.name: "amarok_playlist"
|
||||
icon.color: "white"
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
visible: !wideScreen
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
onWidthChanged: if(!wideScreen) {collapse.running=true; collapsed=true}
|
||||
property bool collapsed: true
|
||||
id: sideDrawer
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: 0
|
||||
Layout.preferredWidth: 350
|
||||
|
||||
Layout.fillHeight: true
|
||||
visible: false
|
||||
NumberAnimation on Layout.maximumWidth {
|
||||
id: collapse
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: sideDrawer.Layout.preferredWidth; to: 0
|
||||
onFinished: { sideDrawer.visible=false}
|
||||
}
|
||||
NumberAnimation on Layout.maximumWidth {
|
||||
id: show
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 0; to: 350
|
||||
//onFinished: { sideDrawer.visible=false}
|
||||
}
|
||||
Kirigami.Separator{
|
||||
color: "white"
|
||||
opacity: 0.3
|
||||
height: parent.height
|
||||
anchors.left: parent.left
|
||||
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color: "white"
|
||||
opacity: 0.2
|
||||
}
|
||||
ColumnLayout{
|
||||
spacing:0
|
||||
anchors.fill: parent
|
||||
|
||||
ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ListView {
|
||||
spacing: 5
|
||||
rightMargin: 10
|
||||
leftMargin:10
|
||||
topMargin:10
|
||||
bottomMargin: 10
|
||||
clip: true
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
visible: UserPlaylistModel.loading || UserPlaylistModel.loading
|
||||
}
|
||||
|
||||
model: UserPlaylistModel
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
|
||||
id: delegateItem
|
||||
required property string title
|
||||
required property string videoId
|
||||
required property string artists
|
||||
required property bool isCurrent
|
||||
required property int index
|
||||
|
||||
background: Rectangle{
|
||||
radius: 7
|
||||
color:
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else if(parent.highlighted){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(0, 0, 0, 0.4)
|
||||
}
|
||||
|
||||
border.color:
|
||||
if (parent.down){
|
||||
Kirigami.Theme.hoverColor
|
||||
}else if(parent.hovered){
|
||||
Kirigami.Theme.hoverColor
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0)
|
||||
}
|
||||
|
||||
border.width: 1
|
||||
}
|
||||
highlighted: isCurrent
|
||||
onClicked: UserPlaylistModel.skipTo(videoId)
|
||||
RowLayout{
|
||||
Layout.fillWidth: true
|
||||
ThumbnailSource {
|
||||
id: delegateThumbnailSource
|
||||
videoId: delegateItem.videoId
|
||||
}
|
||||
RoundedImage {
|
||||
source: delegateThumbnailSource.cachedPath
|
||||
Layout.margins: 2.5
|
||||
height: delegateItem.height
|
||||
width: height
|
||||
radius: 5
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.margins: 5
|
||||
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Heading {
|
||||
// Layout.leftMargin: 5
|
||||
// Layout.rightMargin: 5
|
||||
// Layout.topMargin: 5
|
||||
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
level: 2
|
||||
text: title
|
||||
}
|
||||
|
||||
Label {
|
||||
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: artists
|
||||
}
|
||||
}
|
||||
}
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("Remove Track")
|
||||
icon.name: "list-remove"
|
||||
icon.color: "white"
|
||||
onTriggered: UserPlaylistModel.remove(delegateItem.videoId)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Drawer {
|
||||
id: queueDrawer
|
||||
onClosed:{sideDrawer.collapsed=true}
|
||||
edge: Qt.BottomEdge
|
||||
width: applicationWindow().width
|
||||
height: applicationWindow().height-50
|
||||
// interactive: false
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topRightRadius: 10
|
||||
corners.topLeftRadius: 10
|
||||
shadow.size: 20
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.5)
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
}
|
||||
|
||||
ColumnLayout{
|
||||
spacing:0
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
Layout.margins: 5
|
||||
radius:50
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: Kirigami.Theme.textColor
|
||||
opacity: 0.7
|
||||
width: 40
|
||||
height: 4
|
||||
|
||||
}
|
||||
ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ListView {
|
||||
topMargin: 10
|
||||
clip: true
|
||||
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
visible: UserPlaylistModel.loading || UserPlaylistModel.loading
|
||||
}
|
||||
|
||||
model: UserPlaylistModel
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
|
||||
id: drawerDelegateItem
|
||||
required property string title
|
||||
required property string videoId
|
||||
required property string artists
|
||||
required property bool isCurrent
|
||||
required property int index
|
||||
|
||||
backgroundColor:"transparent"
|
||||
highlighted: isCurrent
|
||||
onClicked: {
|
||||
queueDrawer.close()
|
||||
UserPlaylistModel.skipTo(videoId)
|
||||
}
|
||||
RowLayout{
|
||||
Layout.fillWidth: true
|
||||
ThumbnailSource {
|
||||
id: drawerDelegateThumbnailSource
|
||||
videoId: drawerDelegateItem.videoId
|
||||
}
|
||||
RoundedImage {
|
||||
source: drawerDelegateThumbnailSource.cachedPath
|
||||
height: 50
|
||||
width: height
|
||||
radius: 5
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Heading {
|
||||
Layout.leftMargin: 5
|
||||
Layout.rightMargin: 5
|
||||
Layout.topMargin: 5
|
||||
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
level: 2
|
||||
text: title
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.margins: 5
|
||||
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: artists
|
||||
}
|
||||
}
|
||||
}
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("Remove Track")
|
||||
icon.name: "list-remove"
|
||||
icon.color: "white"
|
||||
onTriggered: UserPlaylistModel.remove(delegateItem.videoId)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
// SPDX-FileCopyrightText: 2020-2022 Devin Lin <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtMultimedia 5.12
|
||||
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
z: 2000
|
||||
|
||||
required property int progressBarHeight
|
||||
required property int minimizedPlayerContentHeight
|
||||
|
||||
required property var info // VideoInfoExtractor object
|
||||
required property var audio // Audio object
|
||||
|
||||
readonly property bool isWidescreen: width >= Kirigami.Units.gridUnit * 50
|
||||
signal requestOpen()
|
||||
|
||||
Rectangle {
|
||||
id: miniProgressBar
|
||||
z: 1
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
height: root.progressBarHeight
|
||||
color: Kirigami.Theme.highlightColor
|
||||
width: parent.width * (audio.position / audio.duration)
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
width: !isWidescreen? root.width- controlButtonBox.width: root.width
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Rectangle {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
color: Qt.rgba(0, 0, 0, trackClick.containsMouse ? 0.1 : trackClick.pressed ? 0.3 : 0)
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Kirigami.Units.largeSpacing
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
// track image
|
||||
Item {
|
||||
property double imageSize: root.height - Kirigami.Units.largeSpacing * 2
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.maximumWidth: imageSize
|
||||
Layout.preferredWidth: imageSize
|
||||
Layout.maximumHeight: imageSize
|
||||
Layout.minimumHeight: imageSize
|
||||
|
||||
RoundedImage {
|
||||
id: mainIcon
|
||||
anchors.fill: parent
|
||||
visible: !loadingIndicator.visible
|
||||
source: info.thumbnail
|
||||
radius: 5
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: loadingIndicator
|
||||
anchors.centerIn: parent
|
||||
visible: UserPlaylistModel.loading
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// track information
|
||||
ColumnLayout {
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Label {
|
||||
id: mainLabel
|
||||
text: info.title ? info.title : i18n("No media playing")
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.Wrap
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 15
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
// Hardcoded because the footerbar blur always makes a dark-ish
|
||||
// background, so we don't want to use a color scheme color that
|
||||
// might also be dark
|
||||
color: "white"
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
|
||||
Label {
|
||||
id: authorLabel
|
||||
text: info.artist ? info.artist : info.channel
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.Wrap
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
elide: Text.ElideRight
|
||||
maximumLineCount: 1
|
||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 15
|
||||
// Hardcoded because the footerbar blur always makes a dark-ish
|
||||
// background, so we don't want to use a color scheme color that
|
||||
// might also be dark
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
Item{Layout.fillWidth: true}
|
||||
|
||||
}
|
||||
MouseArea {
|
||||
id: trackClick
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: root.requestOpen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: controlButtonBox
|
||||
anchors.centerIn: isWidescreen? root:null
|
||||
anchors.right: !isWidescreen? root.right:null
|
||||
Layout.fillHeight: true
|
||||
spacing: 2
|
||||
|
||||
Label {
|
||||
color: "white"
|
||||
visible: info.title && root.isWidescreen
|
||||
text: PlayerUtils.formatTimestamp(audio.position)
|
||||
Layout.rightMargin: 20
|
||||
}
|
||||
Button {
|
||||
id: skipBackwardButton
|
||||
height: 40
|
||||
width: 40
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
enabled: UserPlaylistModel.canSkipBack
|
||||
onClicked: UserPlaylistModel.previous()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source:"media-skip-backward"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topLeftRadius: 7
|
||||
corners.bottomLeftRadius: 7
|
||||
|
||||
|
||||
color: if (isWidescreen){
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
} else {
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
"transparent"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: playPauseButton
|
||||
height: 40
|
||||
width: 60
|
||||
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source: audio.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
color: if (isWidescreen){
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
} else {
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
"transparent"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
id: skipForwardButton
|
||||
height: 40
|
||||
width: 40
|
||||
Layout.rightMargin:isWidescreen?0:10
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
enabled: UserPlaylistModel.canSkip
|
||||
onClicked: UserPlaylistModel.next()
|
||||
contentItem: Item{
|
||||
Kirigami.Icon {
|
||||
anchors.centerIn:parent
|
||||
source:"media-skip-forward"
|
||||
color: "white"
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
}
|
||||
}
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topRightRadius: 7
|
||||
corners.bottomRightRadius: 7
|
||||
color: if (isWidescreen){
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
Qt.rgba(1, 1, 1, 0.2)
|
||||
}
|
||||
} else {
|
||||
if (parent.down){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.3)
|
||||
}else if(parent.hovered){
|
||||
Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.hoverColor, "transparent", 0.7)
|
||||
}else{
|
||||
"transparent"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Label {
|
||||
color: "white"
|
||||
visible: info.title && root.isWidescreen
|
||||
text: PlayerUtils.formatTimestamp(audio.duration)
|
||||
Layout.leftMargin: 20
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mathis Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Layouts 1.2
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.NavigationTabBar {
|
||||
id: root
|
||||
anchors.bottom: parent.bottom
|
||||
width:parent.width
|
||||
backgroundColor: "transparent"
|
||||
foregroundColor: "white"
|
||||
highlightForegroundColor: "white"
|
||||
shadow: false
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
iconName: "file-library-symbolic"
|
||||
text: i18n("Library")
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "libraryPage"
|
||||
onTriggered: {
|
||||
pageStack.replace("qrc:/LibraryPage.qml")
|
||||
applicationWindow().showSearch = false
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
iconName: "search"
|
||||
text: i18n("Search")
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "searchPage"
|
||||
onTriggered: {
|
||||
pageStack.replace("qrc:/SearchHistoryPage.qml",)
|
||||
applicationWindow().showSearch = true
|
||||
applicationWindow().searchField.forceActiveFocus();
|
||||
}
|
||||
|
||||
},
|
||||
Kirigami.Action {
|
||||
iconName: "non-starred-symbolic"
|
||||
text: i18n("Favourites")
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "favourites"
|
||||
onTriggered: {
|
||||
pageStack.replace("qrc:/PlaybackHistory.qml", {
|
||||
"dataModel": Library.favourites,
|
||||
"title": i18n("Favourites"),
|
||||
"objectName": "favourites"})
|
||||
applicationWindow().showSearch = false
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
iconName: "edit-undo-history"
|
||||
text: i18n("Played Songs")
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "history"
|
||||
onTriggered: {
|
||||
pageStack.replace("qrc:/PlaybackHistory.qml", {
|
||||
"dataModel": Library.playbackHistory,
|
||||
"title": i18n("Played Songs"),
|
||||
"objectName": "history"})
|
||||
applicationWindow().showSearch = false
|
||||
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Controls 2.15 as Controls
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
id: playbackHistoryPage
|
||||
title: i18n("Unknown list of songs")
|
||||
|
||||
property QtObject dataModel
|
||||
SongMenu {
|
||||
id:menu
|
||||
}
|
||||
ListView {
|
||||
id: listView
|
||||
reuseItems: true
|
||||
|
||||
Kirigami.PlaceholderMessage {
|
||||
visible: listView.count < 1
|
||||
text: i18n("No songs here yet")
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
model: playbackHistoryPage.dataModel
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
id: delegateItem
|
||||
alwaysVisibleActions:true
|
||||
|
||||
required property string title
|
||||
required property string videoId
|
||||
required property var artists
|
||||
required property string artistsDisplayString
|
||||
required property int index
|
||||
|
||||
onClicked: {
|
||||
play(videoId)
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
ThumbnailSource {
|
||||
id: thumbnailSource
|
||||
|
||||
videoId: delegateItem.videoId
|
||||
}
|
||||
|
||||
RoundedImage {
|
||||
source: thumbnailSource.cachedPath
|
||||
height: 35
|
||||
width: height
|
||||
radius: 5
|
||||
}
|
||||
ColumnLayout {
|
||||
Controls.Label {
|
||||
text: delegateItem.title
|
||||
Layout.fillWidth: true
|
||||
elide: Qt.ElideRight
|
||||
|
||||
}
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: delegateItem.artistsDisplayString
|
||||
elide: Qt.ElideRight
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
text: i18n("More")
|
||||
onTriggered: menu.openForSong(delegateItem.videoId, delegateItem.title, delegateItem.artists, delegateItem.artistsDisplayString)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+172
-199
@@ -1,233 +1,206 @@
|
||||
// SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
// SPDX-FileCopyrightText: 2021 Bart De Vries <[email protected]>
|
||||
// SPDX-FileCopyrightText: 2020-2022 Devin Lin <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.12 as Controls
|
||||
|
||||
import QtMultimedia 5.12
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
import org.kde.ytmusic 1.0
|
||||
import QtMultimedia 5.12
|
||||
|
||||
ColumnLayout {
|
||||
id: footerLayout
|
||||
|
||||
Flickable {
|
||||
id: footerItem
|
||||
|
||||
property int footerSpacing:0
|
||||
property bool maximized: false
|
||||
|
||||
readonly property int progressBarHeight: Kirigami.Units.gridUnit / 4
|
||||
readonly property int minimizedPlayerContentHeight: Math.round(Kirigami.Units.gridUnit * 3.5)
|
||||
readonly property int minimizedPlayerHeight: minimizedPlayerContentHeight + progressBarHeight
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: maximized ? applicationWindow().height : player.preferredHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
function close() {
|
||||
toClose.restart();
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: playerLayout
|
||||
|
||||
readonly property bool mobile: width > height
|
||||
|
||||
Layout.fillHeight: footerLayout.maximized
|
||||
Layout.fillWidth: true
|
||||
flow: width > height ? GridLayout.LeftToRight : GridLayout.TopToBottom
|
||||
visible: footerLayout.maximized
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
|
||||
source: info.thumbnail
|
||||
fillMode: Image.PreserveAspectFit
|
||||
function resetToBoundsOnFlick() {
|
||||
if (!atYBeginning || !atYEnd) {
|
||||
if (footerItem.verticalVelocity > 0) {
|
||||
toOpen.restart();
|
||||
} else if (footerItem.verticalVelocity < 0) {
|
||||
toClose.restart();
|
||||
} else { // i.e. when verticalVelocity === 0
|
||||
if (contentY > contentHeight / 4) {
|
||||
toOpen.restart();
|
||||
} else {
|
||||
toClose.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetToBoundsOnResize() {
|
||||
if (contentY > contentHeight / 4) {
|
||||
contentY = contentHeight / 2;
|
||||
} else {
|
||||
contentY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NumberAnimation on contentY {
|
||||
id: toOpen
|
||||
from: contentY
|
||||
to: contentHeight / 2
|
||||
duration: Kirigami.Units.longDuration * 2
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
}
|
||||
|
||||
NumberAnimation on contentY {
|
||||
id: toClose
|
||||
from: contentY
|
||||
to: 0
|
||||
duration: Kirigami.Units.longDuration * 2
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
}
|
||||
|
||||
// snap to end
|
||||
MouseArea {
|
||||
anchors.fill: footerLayout
|
||||
propagateComposedEvents: true
|
||||
onPressed: {
|
||||
toOpen.stop();
|
||||
toClose.stop();
|
||||
propagateComposedEvents = true;
|
||||
}
|
||||
onReleased: footerItem.resetToBoundsOnFlick()
|
||||
}
|
||||
|
||||
onMovementStarted: {
|
||||
toOpen.stop();
|
||||
toClose.stop();
|
||||
}
|
||||
onFlickStarted: resetToBoundsOnFlick()
|
||||
onMovementEnded: resetToBoundsOnFlick()
|
||||
onHeightChanged: resetToBoundsOnResize()
|
||||
|
||||
property var videoInfoExtractor: VideoInfoExtractor {
|
||||
id: info
|
||||
|
||||
onSongChanged: audio.play()
|
||||
videoId: UserPlaylistModel.currentVideoId
|
||||
onTitleChanged: {
|
||||
let index = UserPlaylistModel.index(UserPlaylistModel.currentIndex, 0)
|
||||
let videoId = UserPlaylistModel.data(index, UserPlaylistModel.VideoId)
|
||||
let title = UserPlaylistModel.data(index, UserPlaylistModel.Title)
|
||||
let artist = UserPlaylistModel.data(index, UserPlaylistModel.Artists)
|
||||
let album = UserPlaylistModel.data(index, UserPlaylistModel.Album)
|
||||
Library.addPlaybackHistoryItem(videoId, title, artist, album)
|
||||
}
|
||||
}
|
||||
|
||||
property var audioPlayer: Audio {
|
||||
id: audio
|
||||
|
||||
source: info.audioUrl
|
||||
onStatusChanged: {
|
||||
if (status === Audio.EndOfMedia) {
|
||||
console.log("Song ended");
|
||||
UserPlaylistModel.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentHeight: height * 2
|
||||
|
||||
ColumnLayout {
|
||||
id: footerLayout
|
||||
y:-footerSpacing
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
// margin from top
|
||||
Item {
|
||||
Layout.minimumHeight: footerItem.height - footerItem.minimizedPlayerHeight
|
||||
}
|
||||
|
||||
Controls.Control {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Controls.ScrollView {
|
||||
anchors.fill: parent
|
||||
|
||||
ListView {
|
||||
padding: 0
|
||||
implicitHeight: footerItem.minimizedPlayerHeight+footerSpacing
|
||||
|
||||
// minimized player background
|
||||
background: Item {
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
id: playlistView
|
||||
color: Qt.rgba(25, 25, 30, 1)
|
||||
}
|
||||
|
||||
Image {
|
||||
opacity: 0.2
|
||||
source: info.thumbnail
|
||||
asynchronous: true
|
||||
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: HueSaturation {
|
||||
cached: true
|
||||
|
||||
clip: true
|
||||
lightness: -0.7
|
||||
saturation: 3
|
||||
|
||||
Controls.BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
visible: UserPlaylistModel.loading || UserPlaylistModel.loading
|
||||
}
|
||||
|
||||
onCountChanged: {
|
||||
if (count < 1) {
|
||||
footerLayout.maximized = false
|
||||
}
|
||||
}
|
||||
|
||||
model: UserPlaylistModel
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
id: delegateItem
|
||||
required property string title
|
||||
required property string videoId
|
||||
required property string artists
|
||||
required property bool isCurrent
|
||||
|
||||
highlighted: isCurrent
|
||||
onClicked: UserPlaylistModel.skipTo(videoId)
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Heading {
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
level: 2
|
||||
text: title
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
text: artists
|
||||
}
|
||||
}
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
text: i18n("Remove track")
|
||||
icon.name: "list-remove"
|
||||
onTriggered: UserPlaylistModel.remove(delegateItem.videoId)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
header: Controls.ToolBar {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Controls.ToolButton {
|
||||
icon.name: "edit-clear-all"
|
||||
onClicked: UserPlaylistModel.clear()
|
||||
}
|
||||
Controls.ToolButton {
|
||||
icon.name: "media-playlist-shuffle"
|
||||
onClicked: UserPlaylistModel.shufflePlaylist()
|
||||
}
|
||||
}
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
cached: true
|
||||
radius: 64
|
||||
transparentBorder: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: player
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: !footer.maximized
|
||||
|
||||
VideoInfoExtractor {
|
||||
id: info
|
||||
|
||||
onSongChanged: audio.play()
|
||||
videoId: UserPlaylistModel.currentVideoId
|
||||
}
|
||||
|
||||
Audio {
|
||||
id: audio
|
||||
|
||||
source: info.audioUrl
|
||||
onStatusChanged: {
|
||||
if (status === Audio.EndOfMedia) {
|
||||
console.log("Song ended");
|
||||
UserPlaylistModel.next();
|
||||
}
|
||||
|
||||
MinimizedPlayerControls {
|
||||
progressBarHeight: footerItem.progressBarHeight
|
||||
minimizedPlayerContentHeight: footerItem.minimizedPlayerContentHeight
|
||||
height: minimizedPlayerHeight
|
||||
|
||||
focus: true
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
|
||||
info: footerItem.videoInfoExtractor
|
||||
audio: footerItem.audioPlayer
|
||||
|
||||
onRequestOpen: toOpen.start();
|
||||
}
|
||||
}
|
||||
|
||||
Controls.ToolButton {
|
||||
display: Controls.AbstractButton.IconOnly
|
||||
Layout.preferredWidth: parent.height
|
||||
MaximizedPlayerPage {
|
||||
id: maximizedPlayerPage
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
enabled: info.audioUrl != ""
|
||||
text: audio.playbackState === Audio.PlayingState ? i18n("Pause") : i18n("Play")
|
||||
visible: !info.loading
|
||||
icon.name: audio.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start"
|
||||
onClicked: audio.playbackState === Audio.PlayingState ? audio.pause() : audio.play()
|
||||
}
|
||||
|
||||
Controls.ToolButton {
|
||||
display: Controls.AbstractButton.IconOnly
|
||||
Layout.preferredWidth: parent.height
|
||||
Layout.fillHeight: true
|
||||
enabled: UserPlaylistModel.canSkip
|
||||
visible: !info.loading
|
||||
icon.name: "media-skip-forward"
|
||||
onClicked: UserPlaylistModel.next()
|
||||
}
|
||||
|
||||
Controls.BusyIndicator {
|
||||
Layout.fillHeight: true
|
||||
visible: info.loading
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
Kirigami.Heading {
|
||||
level: 3
|
||||
Layout.fillWidth: true
|
||||
elide: Qt.ElideRight
|
||||
text: info.title ? info.title : i18n("No media playing")
|
||||
}
|
||||
|
||||
Controls.Slider {
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: audio.duration
|
||||
value: audio.position
|
||||
enabled: audio.seekable
|
||||
onMoved: {
|
||||
console.log("Value:", value);
|
||||
audio.seek(Math.floor(value));
|
||||
}
|
||||
|
||||
Behavior on value {
|
||||
NumberAnimation {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Controls.ToolButton {
|
||||
display: Controls.AbstractButton.IconOnly
|
||||
Layout.preferredWidth: parent.height
|
||||
text: i18n("Expand")
|
||||
enabled: playlistView.count > 0
|
||||
Layout.fillHeight: true
|
||||
icon.name: footerLayout.maximized ? "arrow-down" : "arrow-up"
|
||||
onClicked: footerLayout.maximized = !footerLayout.maximized
|
||||
implicitHeight: footerItem.height
|
||||
|
||||
info: footerItem.videoInfoExtractor
|
||||
audio: footerItem.audioPlayer
|
||||
|
||||
onRequestClose: toClose.start();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12 as Controls
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
@@ -13,63 +13,87 @@ Kirigami.ScrollablePage {
|
||||
property alias playlistId: playlistModel.playlistId
|
||||
title: playlistModel.title
|
||||
|
||||
actions {
|
||||
main: Kirigami.Action {
|
||||
icon.name: "media-playback-start"
|
||||
text: i18n("Play")
|
||||
onTriggered: {
|
||||
applicationWindow().playPlaylist(playlistModel.playlistId)
|
||||
}
|
||||
}
|
||||
right: Kirigami.Action {
|
||||
icon.name: "media-playlist-shuffle"
|
||||
text: i18n("Shuffle")
|
||||
onTriggered: {
|
||||
applicationWindow().playShufflePlaylist(playlistModel.playlistId)
|
||||
}
|
||||
}
|
||||
SongMenu {
|
||||
id: menu
|
||||
}
|
||||
|
||||
ListView {
|
||||
header: Kirigami.ItemViewHeader {
|
||||
backgroundImage.source: playlistModel.thumbnailUrl
|
||||
id: songList
|
||||
|
||||
header: ListHeader {
|
||||
visibleActions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playback-start"
|
||||
text: i18n("Play")
|
||||
onTriggered: {
|
||||
applicationWindow().playPlaylist(playlistModel.playlistId)
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playlist-shuffle"
|
||||
text: i18n("Shuffle")
|
||||
onTriggered: {
|
||||
applicationWindow().playShufflePlaylist(playlistModel.playlistId)
|
||||
}
|
||||
}
|
||||
]
|
||||
title: playlistModel.title
|
||||
imageSourceURL: playlistModel.thumbnailUrl
|
||||
width: songList.width
|
||||
subtitle: i18n("Playlist")
|
||||
|
||||
}
|
||||
model: PlaylistModel {
|
||||
id: playlistModel
|
||||
}
|
||||
|
||||
reuseItems: true
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
id: delegateItem
|
||||
alwaysVisibleActions:true
|
||||
|
||||
required property string title
|
||||
required property string videoId
|
||||
required property string artists
|
||||
required property var artists
|
||||
required property string thumbnailUrl
|
||||
required property string artistsDisplayString
|
||||
required property int index
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
Kirigami.Icon {
|
||||
Layout.fillHeight: true
|
||||
source: "emblem-music-symbolic"
|
||||
RoundedImage {
|
||||
source: delegateItem.thumbnailUrl
|
||||
height: 35
|
||||
width: height
|
||||
radius: 5
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: title
|
||||
elide: Qt.ElideRight
|
||||
ColumnLayout {
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: title
|
||||
elide: Qt.ElideRight
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
visible: delegateItem.artistsDisplayString
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: delegateItem.artistsDisplayString
|
||||
elide: Qt.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "go-next"
|
||||
text: i18n("Play next")
|
||||
onTriggered: UserPlaylistModel.playNext(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playlist-append"
|
||||
text: i18n("Add to playlist")
|
||||
onTriggered: UserPlaylistModel.append(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
text: i18n("More")
|
||||
onTriggered: menu.openForSong(delegateItem.videoId, delegateItem.title, delegateItem.artists, delegateItem.artistsDisplayString)
|
||||
}
|
||||
]
|
||||
|
||||
onClicked: play(videoId)
|
||||
}
|
||||
|
||||
Controls.BusyIndicator {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mathis Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Item {
|
||||
property alias radius: mask.radius
|
||||
property alias source: image.source
|
||||
id: icon
|
||||
|
||||
Image {
|
||||
id:image
|
||||
source: source
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
sourceSize.width: parent.implicitWidth * Screen.devicePixelRatio
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: mask
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: mask
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// SPDX-FileCopyrightText: Mathis Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import org.kde.kirigami 2.12 as Kirigami
|
||||
import QtQuick.Controls 2.15 as Controls
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
objectName: "searchPage"
|
||||
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
|
||||
ColumnLayout {
|
||||
Controls.ScrollView {
|
||||
Layout.fillWidth: true
|
||||
|
||||
id: recents
|
||||
visible: searchLoader.text && recentsRepeater.count > 0
|
||||
leftPadding: 10
|
||||
topPadding: 10
|
||||
Controls.ScrollBar.horizontal.policy: Controls.ScrollBar.AlwaysOff
|
||||
|
||||
RowLayout {
|
||||
id: recentsLayout
|
||||
spacing: 10
|
||||
Layout.fillWidth: true
|
||||
|
||||
Repeater {
|
||||
id: recentsRepeater
|
||||
Layout.fillWidth: true
|
||||
model: SortFilterModel {
|
||||
filterRole: PlaybackHistoryModel.Title
|
||||
filterRegularExpression: searchLoader.filterExpression
|
||||
sourceModel: Library.playbackHistory
|
||||
}
|
||||
delegate: Kirigami.DelegateRecycler {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
sourceComponent: searchAlbum
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
visible: recents.visible
|
||||
}
|
||||
|
||||
id: completionList
|
||||
|
||||
Repeater {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
model: SortFilterModel {
|
||||
sourceModel: Library.searches
|
||||
filterRegularExpression: searchLoader.filterExpression
|
||||
}
|
||||
|
||||
delegate: Kirigami.AbstractListItem {
|
||||
implicitHeight: Kirigami.Units.gridUnit * 2
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
Kirigami.Icon {
|
||||
source: "search"
|
||||
implicitHeight: Kirigami.Units.gridUnit
|
||||
implicitWidth: Kirigami.Units.gridUnit
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
Controls.Label {
|
||||
text: model.display
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
}
|
||||
onClicked: {
|
||||
searchLoader.text = model.display
|
||||
searchLoader.accepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
@@ -10,20 +10,35 @@ import org.kde.kirigami 2.14 as Kirigami
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
title: i18n("Youtube Music")
|
||||
|
||||
header: Controls.Control {
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
contentItem: Kirigami.SearchField {
|
||||
delaySearch: true
|
||||
selectByMouse: true
|
||||
onAccepted: {
|
||||
searchModel.searchQuery = text
|
||||
}
|
||||
}
|
||||
}
|
||||
id: searchPage
|
||||
property alias searchQuery: searchModel.searchQuery
|
||||
objectName: "searchPage"
|
||||
title: listView.count === 0 && !searchModel.loading? i18n("Previous Searches:") : searchQuery
|
||||
|
||||
ListView {
|
||||
reuseItems: true
|
||||
|
||||
section.delegate: Kirigami.ListSectionHeader {
|
||||
required property string section
|
||||
text: {
|
||||
switch (parseInt(section)) {
|
||||
case SearchModel.Album:
|
||||
return i18n("Albums")
|
||||
case SearchModel.Artist:
|
||||
return i18n("Artists")
|
||||
case SearchModel.Playlist:
|
||||
return i18n("Playlists")
|
||||
case SearchModel.Song:
|
||||
return i18n("Songs")
|
||||
case SearchModel.Video:
|
||||
return i18n("Videos")
|
||||
}
|
||||
|
||||
return i18n("Unknown")
|
||||
}
|
||||
}
|
||||
section.property: "type"
|
||||
id: listView
|
||||
model: SearchModel {
|
||||
id: searchModel
|
||||
|
||||
@@ -33,9 +48,11 @@ Kirigami.ScrollablePage {
|
||||
})
|
||||
}
|
||||
|
||||
onOpenArtist: (channelId) => {
|
||||
onOpenArtist: (channelId, radioId, shuffleId) => {
|
||||
pageStack.push("qrc:/ArtistPage.qml", {
|
||||
"channelId": channelId
|
||||
"channelId": channelId,
|
||||
"radioId": radioId,
|
||||
"shuffleId": shuffleId
|
||||
})
|
||||
}
|
||||
|
||||
@@ -49,57 +66,70 @@ Kirigami.ScrollablePage {
|
||||
play(videoId)
|
||||
}
|
||||
|
||||
onOpenVideo: (videoId) => {
|
||||
askPlayVideoAudio(videoId)
|
||||
onOpenVideo: (videoId, title) => {
|
||||
videoPlayMessage.text = i18n("Video playback is not supported yet. Do you want to play only the audio of \"%1\"?", title)
|
||||
videoPlayMessage.visible = true
|
||||
videoPlayMessage.okAction = function() {
|
||||
play(videoId)
|
||||
videoPlayMessage.visible = false
|
||||
}
|
||||
videoPlayMessage.cancelAction = function() {
|
||||
videoPlayMessage.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SongMenu {
|
||||
id: menu
|
||||
}
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
|
||||
id: delegateItem
|
||||
alwaysVisibleActions:true
|
||||
|
||||
required property int index
|
||||
required property string title
|
||||
required property int type
|
||||
required property string videoId
|
||||
required property var artists
|
||||
required property string artistsDisplayString
|
||||
required property string radioPlaylistId
|
||||
required property string thumbnailUrl
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
Kirigami.Icon {
|
||||
Layout.fillHeight: true
|
||||
source: {
|
||||
switch (type) {
|
||||
case SearchModel.Artist:
|
||||
return "view-media-artist"
|
||||
case SearchModel.Album:
|
||||
return "media-album-cover"
|
||||
case SearchModel.Playlist:
|
||||
return "view-media-playlist"
|
||||
case SearchModel.Song:
|
||||
return "emblem-music-symbolic"
|
||||
case SearchModel.Video:
|
||||
return "emblem-videos-symbolic"
|
||||
}
|
||||
}
|
||||
RoundedImage {
|
||||
source: delegateItem.thumbnailUrl
|
||||
height: 35
|
||||
width: height
|
||||
radius: delegateItem.type === SearchModel.Artist?height/2:5
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: title
|
||||
elide: Qt.ElideRight
|
||||
ColumnLayout {
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: title
|
||||
elide: Qt.ElideRight
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
visible: delegateItem.artistsDisplayString
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: delegateItem.artistsDisplayString
|
||||
elide: Qt.ElideRight
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "go-next"
|
||||
text: i18n("Play next")
|
||||
visible: delegateItem.type === SearchModel.Song
|
||||
onTriggered: UserPlaylistModel.playNext(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
},
|
||||
Kirigami.Action {
|
||||
icon.name: "media-playlist-append"
|
||||
text: i18n("Add to playlist")
|
||||
visible: delegateItem.type === SearchModel.Song
|
||||
onTriggered: UserPlaylistModel.append(delegateItem.videoId, delegateItem.title, delegateItem.artists)
|
||||
icon.name: "view-more-horizontal-symbolic"
|
||||
text: i18n("More")
|
||||
visible: delegateItem.type === SearchModel.Song || delegateItem.type === SearchModel.Video
|
||||
onTriggered: menu.openForSong(delegateItem.videoId, delegateItem.title, delegateItem.artists, delegateItem.artistsDisplayString)
|
||||
}
|
||||
]
|
||||
|
||||
@@ -110,4 +140,8 @@ Kirigami.ScrollablePage {
|
||||
visible: searchModel.loading
|
||||
}
|
||||
}
|
||||
|
||||
footer: ConfirmationMessage {
|
||||
id: videoPlayMessage
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
// SPDX-FileCopyrightText: 2023 Mathis Brüchert <[email protected]>
|
||||
// SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 2.12 as Controls
|
||||
import QtQuick.Layouts 1.3
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
import QtGraphicalEffects 1.0
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Item {
|
||||
function forceFocus(){searchField.forceActiveFocus()}
|
||||
function accepted(){searchField.accepted()}
|
||||
property alias filterExpression: searchField.filterExpression
|
||||
property alias text: searchField.text
|
||||
|
||||
id: root
|
||||
Controls.TextField{
|
||||
id: dummy
|
||||
x:searchField.x
|
||||
y:searchField.y
|
||||
width: searchField.width
|
||||
readOnly: true
|
||||
}
|
||||
Kirigami.SearchField {
|
||||
property var filterExpression: new RegExp(`.*${searchField.text}.*`, "i")
|
||||
|
||||
id: searchField
|
||||
autoAccept: false
|
||||
width: root.width
|
||||
selectByMouse: true
|
||||
onFocusChanged: {
|
||||
if (wideScreen && focus)
|
||||
popup.open()
|
||||
}
|
||||
onAccepted: {
|
||||
popup.close()
|
||||
|
||||
while (pageStack.depth > 0) {
|
||||
pageStack.pop()
|
||||
}
|
||||
|
||||
pageStack.layers.clear()
|
||||
|
||||
if (text) {
|
||||
Library.addSearch(text)
|
||||
pageStack.push("qrc:/SearchPage.qml", {
|
||||
"searchQuery": text,
|
||||
objectName: "searchPage"
|
||||
})
|
||||
} else {
|
||||
wideScreen
|
||||
? pageStack.push("qrc:/LibraryPage.qml")
|
||||
: pageStack.push("qrc:/SearchHistoryPage.qml")
|
||||
}
|
||||
searchField.focus = false
|
||||
|
||||
}
|
||||
}
|
||||
Controls.Popup {
|
||||
id: popup
|
||||
property int expansion: 5
|
||||
property int shadowSize: 15
|
||||
onAboutToShow:{
|
||||
searchField.parent = fieldContainer
|
||||
onOpened: searchField.background.visible = false
|
||||
playOpenHeight.running = true
|
||||
playOpenWidth.running = true
|
||||
playOpenX.running = true
|
||||
playOpenY.running = true
|
||||
playOpenRadius.running = true
|
||||
|
||||
}
|
||||
onAboutToHide:{
|
||||
searchField.parent = root
|
||||
onOpened: searchField.background.visible = true
|
||||
searchField.focus = false
|
||||
playCloseHeight.running = true
|
||||
playCloseWidth.running = true
|
||||
playCloseX.running = true
|
||||
playCloseY.running = true
|
||||
playCloseRadius.running = true
|
||||
|
||||
}
|
||||
|
||||
x: -(popup.shadowSize+popup.expansion)
|
||||
y: -(popup.shadowSize+popup.expansion)
|
||||
|
||||
rightPadding:popup.shadowSize+1
|
||||
leftPadding:popup.shadowSize+1
|
||||
bottomPadding:popup.shadowSize
|
||||
rightInset: popup.shadowSize
|
||||
leftInset: popup.shadowSize
|
||||
bottomInset: popup.shadowSize
|
||||
leftMargin:-popup.shadowSize
|
||||
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
id: bg
|
||||
Kirigami.Theme.inherit: false
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
radius: popup.expansion+2
|
||||
shadow.size: popup.shadowSize
|
||||
shadow.yOffset: popup.expansion
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
|
||||
border.width: 1
|
||||
border.color: Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.3);
|
||||
NumberAnimation on radius{
|
||||
id: playOpenRadius
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 2
|
||||
duration: 100
|
||||
to: popup.expansion+2
|
||||
}
|
||||
NumberAnimation on radius{
|
||||
id: playCloseRadius
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: popup.expansion+2
|
||||
duration: 100
|
||||
to: 2
|
||||
}
|
||||
|
||||
}
|
||||
width: searchField.width + 2*(popup.shadowSize+popup.expansion)
|
||||
height: completionList
|
||||
? (Math.min(content.implicitHeight, Kirigami.Units.gridUnit * 20))+2*(popup.shadowSize+popup.expansion)
|
||||
: (Kirigami.Units.gridUnit * 20)+2*(popup.shadowSize+popup.expansion)
|
||||
|
||||
NumberAnimation on height{
|
||||
id: playOpenHeight
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: searchField.height
|
||||
duration: 200
|
||||
to: completionList
|
||||
? (Math.min(fieldContainer.height+ completionList.count * Kirigami.Units.gridUnit * 2 + recents.implicitHeight, Kirigami.Units.gridUnit * 20))+2*(popup.shadowSize+popup.expansion)
|
||||
: (Kirigami.Units.gridUnit * 20)+2*(popup.shadowSize+popup.expansion)
|
||||
}
|
||||
NumberAnimation on width{
|
||||
id: playOpenWidth
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: searchField.width
|
||||
duration: 100
|
||||
to: searchField.width +2*(popup.shadowSize+popup.expansion)
|
||||
}
|
||||
NumberAnimation on x{
|
||||
id: playOpenX
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 0
|
||||
duration: 100
|
||||
to: -(popup.shadowSize+popup.expansion)
|
||||
}
|
||||
NumberAnimation on y{
|
||||
id: playOpenY
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 0
|
||||
duration: 100
|
||||
to: -popup.expansion
|
||||
}
|
||||
|
||||
|
||||
|
||||
NumberAnimation on height{
|
||||
id: playCloseHeight
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: completionList
|
||||
? (Math.min(content.implicitHeight, Kirigami.Units.gridUnit * 20))+2*(popup.shadowSize+popup.expansion)
|
||||
: (Kirigami.Units.gridUnit * 20)+2*(popup.shadowSize+popup.expansion)
|
||||
duration: 100
|
||||
to: searchField.heigth
|
||||
}
|
||||
NumberAnimation on width{
|
||||
id: playCloseWidth
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: searchField.width + 2*(popup.shadowSize+popup.expansion)
|
||||
duration: 100
|
||||
to: searchField.width + 2*(popup.shadowSize)
|
||||
}
|
||||
NumberAnimation on x{
|
||||
id: playCloseX
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: -(popup.shadowSize+popup.expansion)
|
||||
duration: 100
|
||||
to: -popup.shadowSize
|
||||
}
|
||||
NumberAnimation on y{
|
||||
id: playCloseY
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: - popup.expansion
|
||||
duration: 100
|
||||
to: -0
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
contentItem: ColumnLayout{
|
||||
id: content
|
||||
width: parent.width
|
||||
Controls.Control{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Controls.Control{
|
||||
x: popup.expansion
|
||||
y:-popup.expansion
|
||||
id: fieldContainer
|
||||
height:searchField.height
|
||||
|
||||
}
|
||||
implicitHeight: fieldContainer.height
|
||||
}
|
||||
|
||||
Controls.ScrollView {
|
||||
id: mainScrollView
|
||||
|
||||
clip: true
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
||||
Keys.enabled: false
|
||||
contentWidth: availableWidth
|
||||
|
||||
ColumnLayout {
|
||||
width: mainScrollView.contentWidth
|
||||
|
||||
Controls.ScrollView {
|
||||
id: recents
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: popup.width
|
||||
|
||||
visible: searchField.text && recentsRepeater.count > 0
|
||||
|
||||
leftPadding: 10
|
||||
rightPadding: 40
|
||||
topPadding: 10
|
||||
Controls.ScrollBar.horizontal.policy: Controls.ScrollBar.AlwaysOff
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: popup.width - 23
|
||||
|
||||
Repeater {
|
||||
|
||||
id: recentsRepeater
|
||||
Layout.fillWidth: true
|
||||
model: SortFilterModel {
|
||||
filterRole: PlaybackHistoryModel.Title
|
||||
filterRegularExpression: searchField.filterExpression
|
||||
sourceModel: Library.playbackHistory
|
||||
}
|
||||
delegate: Kirigami.DelegateRecycler {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
width: popup.width
|
||||
sourceComponent: searchAlbum
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Kirigami.Separator{
|
||||
Layout.fillWidth: true
|
||||
visible: searchField.text && recentsRepeater.count > 0
|
||||
implicitWidth: popup.width
|
||||
|
||||
}
|
||||
RowLayout{
|
||||
Layout.margins: 10
|
||||
visible: completionList.count == 0
|
||||
Kirigami.Icon {
|
||||
source: "documentinfo"
|
||||
implicitHeight: Kirigami.Units.gridUnit
|
||||
implicitWidth: Kirigami.Units.gridUnit
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
Controls.Label {
|
||||
text: i18n("No matching previous searches")
|
||||
Layout.fillWidth: true
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
Layout.fillWidth: true
|
||||
|
||||
id: completionList
|
||||
model: SortFilterModel {
|
||||
sourceModel: Library.searches
|
||||
filterRegularExpression: searchField.filterExpression
|
||||
}
|
||||
delegate: Kirigami.AbstractListItem {
|
||||
id: completionDelegate
|
||||
highlighted: focus
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||
Kirigami.Theme.inherit: false
|
||||
Layout.fillWidth: true
|
||||
height: Kirigami.Units.gridUnit * 2
|
||||
contentItem: RowLayout {
|
||||
|
||||
Kirigami.Icon {
|
||||
source: "search"
|
||||
implicitHeight: Kirigami.Units.gridUnit
|
||||
implicitWidth: Kirigami.Units.gridUnit
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
Controls.Label{
|
||||
text: model.display
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Controls.ToolButton {
|
||||
icon.name: "list-remove"
|
||||
text: i18n("remove from search history")
|
||||
display: Controls.AbstractButton.IconOnly
|
||||
onClicked: {
|
||||
Library.removeSearch(model.display)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
onClicked: {
|
||||
searchField.text = model.display
|
||||
searchField.accepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mathis Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.15 as Controls
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Rectangle {
|
||||
property bool collapsed: false
|
||||
id: sidebar
|
||||
width: 200
|
||||
clip:true
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||
Kirigami.Theme.inherit: false
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
NumberAnimation on width{
|
||||
id: collapse
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 200; to: 60
|
||||
}
|
||||
NumberAnimation on width{
|
||||
id: show
|
||||
easing.type: Easing.OutCubic
|
||||
running: false
|
||||
from: 60; to: 200
|
||||
//this is only a workaround to stop the text from disappearing
|
||||
onFinished:{
|
||||
libraryButton.checked =!libraryButton.checked
|
||||
libraryButton.checked =!libraryButton.checked
|
||||
|
||||
favouritesButton.checked =!favouritesButton.checked
|
||||
favouritesButton.checked =!favouritesButton.checked
|
||||
|
||||
historyButton.checked =!historyButton.checked
|
||||
historyButton.checked =!historyButton.checked
|
||||
|
||||
searchButton.checked =!searchButton.checked
|
||||
searchButton.checked =!searchButton.checked
|
||||
|
||||
collapseButton.checked =!collapseButton.checked
|
||||
collapseButton.checked =false
|
||||
|
||||
}
|
||||
}
|
||||
Kirigami.Separator {
|
||||
height: parent.height
|
||||
anchors.right: parent.right
|
||||
z:100
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
}
|
||||
|
||||
Controls.ScrollView {
|
||||
|
||||
id: scrollView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Controls.ScrollBar.vertical.policy: Controls.ScrollBar.AlwaysOff
|
||||
Controls.ScrollBar.horizontal.policy: Controls.ScrollBar.AlwaysOff
|
||||
contentWidth: -1 // disable horizontal scroll
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
width: scrollView.width
|
||||
spacing: 0
|
||||
|
||||
Kirigami.NavigationTabButton {
|
||||
id: libraryButton
|
||||
Layout.fillWidth: true
|
||||
width: column.width - column.Layout.leftMargin - column.Layout.rightMargin
|
||||
implicitHeight: 50
|
||||
display: Controls.AbstractButton.TextBesideIcon
|
||||
text: collapsed? "" : i18n("Library")
|
||||
icon.name: "file-library-symbolic"
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "libraryPage"
|
||||
onClicked: {
|
||||
pageStack.clear()
|
||||
pageStack.push("qrc:/LibraryPage.qml")
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Kirigami.NavigationTabButton {
|
||||
id: searchButton
|
||||
Layout.fillWidth: true
|
||||
width: column.width - column.Layout.leftMargin - column.Layout.rightMargin
|
||||
implicitHeight: 50
|
||||
display: Controls.AbstractButton.TextBesideIcon
|
||||
text: collapsed? "" : i18n("Search")
|
||||
icon.name: "search"
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "searchPage"
|
||||
onClicked: {
|
||||
searchField.forceActiveFocus()
|
||||
focusSearch()
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.NavigationTabButton {
|
||||
id: favouritesButton
|
||||
Layout.fillWidth: true
|
||||
width: column.width - column.Layout.leftMargin - column.Layout.rightMargin
|
||||
implicitHeight: 50
|
||||
display: Controls.AbstractButton.TextBesideIcon
|
||||
text: collapsed ? "" : i18n("Favourites")
|
||||
icon.name: "non-starred-symbolic"
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "favourites"
|
||||
onClicked: {
|
||||
pageStack.clear()
|
||||
pageStack.push("qrc:/PlaybackHistory.qml", {
|
||||
"dataModel": Library.favourites,
|
||||
"title": i18n("Favourites"),
|
||||
"objectName": "favourites"
|
||||
})}
|
||||
|
||||
}
|
||||
|
||||
Kirigami.NavigationTabButton {
|
||||
id: historyButton
|
||||
Layout.fillWidth: true
|
||||
width: column.width - column.Layout.leftMargin - column.Layout.rightMargin
|
||||
implicitHeight: 50
|
||||
display: Controls.AbstractButton.TextBesideIcon
|
||||
text: collapsed? "" : i18n("Played Songs")
|
||||
icon.name: "edit-undo-history"
|
||||
checked: pageStack.currentItem && pageStack.currentItem.objectName == "history"
|
||||
onClicked: {
|
||||
pageStack.clear()
|
||||
pageStack.push("qrc:/PlaybackHistory.qml", {
|
||||
"dataModel": Library.playbackHistory,
|
||||
"title": i18n("Played Songs"),
|
||||
"objectName": "history"
|
||||
})}
|
||||
|
||||
}
|
||||
|
||||
// Kirigami.NavigationTabButton {
|
||||
// Layout.fillWidth: true
|
||||
// width: column.width - column.Layout.leftMargin - column.Layout.rightMargin
|
||||
// implicitHeight: 50
|
||||
// display: Controls.AbstractButton.TextBesideIcon
|
||||
// text: i18n("Charts")
|
||||
// icon.name: "office-chart-line-forecast"
|
||||
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: Kirigami.Units.smallSpacing
|
||||
Layout.leftMargin: Kirigami.Units.smallSpacing
|
||||
}
|
||||
|
||||
Kirigami.NavigationTabButton {
|
||||
id: collapseButton
|
||||
Layout.fillWidth: true
|
||||
width: column.width - column.Layout.leftMargin - column.Layout.rightMargin
|
||||
display: Controls.AbstractButton.TextBesideIcon
|
||||
text: collapsed? "" : i18n("Collapse Sidebar")
|
||||
checked: collapsed == true
|
||||
implicitHeight: 50
|
||||
icon.name: "sidebar-collapse"
|
||||
onClicked: {
|
||||
if (!sidebar.collapsed)
|
||||
collapse.running = true
|
||||
else
|
||||
show.running = true
|
||||
|
||||
sidebar.collapsed = !sidebar.collapsed
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
// SPDX-FileCopyrightText: 2022 Mathis Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as Controls
|
||||
import org.kde.ytmusic 1.0
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
|
||||
Item {
|
||||
function openForSong(videoId, songTitle, artists, artistsDisplayString) {
|
||||
menu.videoId = videoId
|
||||
drawer.videoId = videoId
|
||||
|
||||
menu.songTitle = songTitle
|
||||
drawer.songTitle = songTitle
|
||||
|
||||
menu.artists = artists
|
||||
drawer.artists = artists
|
||||
|
||||
menu.artistsDisplayString = artistsDisplayString
|
||||
drawer.artistsDisplayString = artistsDisplayString
|
||||
|
||||
if (Kirigami.Settings.isMobile) {
|
||||
drawer.interactive = true
|
||||
drawer.open()
|
||||
} else {
|
||||
menu.popup()
|
||||
}
|
||||
}
|
||||
Controls.Drawer {
|
||||
edge: Qt.BottomEdge
|
||||
height:contents.implicitHeight+20
|
||||
width: applicationWindow().width
|
||||
interactive: false
|
||||
background: Kirigami.ShadowedRectangle{
|
||||
corners.topRightRadius: 10
|
||||
corners.topLeftRadius: 10
|
||||
shadow.size: 20
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.5)
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
|
||||
}
|
||||
onClosed: drawer.interactive = false
|
||||
|
||||
id: drawer
|
||||
property string videoId
|
||||
property string songTitle
|
||||
property var artists
|
||||
property string artistsDisplayString
|
||||
ColumnLayout {
|
||||
id: contents
|
||||
anchors.fill: parent
|
||||
ThumbnailSource {
|
||||
id: thumbnailSource
|
||||
videoId: drawer.videoId
|
||||
}
|
||||
|
||||
// Kirigami.Icon {
|
||||
// Layout.margins: Kirigami.Units.smallSpacing
|
||||
// source: "arrow-down"
|
||||
// implicitWidth: Kirigami.Units.gridUnit
|
||||
// implicitHeight: Kirigami.Units.gridUnit
|
||||
// Layout.alignment: Qt.AlignHCenter
|
||||
// }
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
Kirigami.ShadowedRectangle {
|
||||
Layout.margins: 10
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
width: 60
|
||||
height: width
|
||||
radius: 5
|
||||
shadow.size: 15
|
||||
shadow.xOffset: 5
|
||||
shadow.yOffset: 5
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
RoundedImage {
|
||||
source: thumbnailSource.cachedPath
|
||||
height: width
|
||||
width: parent.width
|
||||
radius: parent.radius
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Controls.Label{
|
||||
text: drawer.songTitle
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
|
||||
|
||||
}
|
||||
Controls.Label{
|
||||
text: drawer.artistsDisplayString
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 10
|
||||
Layout.rightMargin: 10
|
||||
|
||||
|
||||
}
|
||||
Kirigami.BasicListItem{
|
||||
|
||||
label: i18n("Play Next")
|
||||
icon: "go-next"
|
||||
onClicked: {
|
||||
UserPlaylistModel.playNext(drawer.videoId, drawer.songTitle, drawer.artists)
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
Kirigami.BasicListItem{
|
||||
|
||||
label: i18n("Add to queue")
|
||||
icon: "media-playlist-append"
|
||||
onClicked: {
|
||||
UserPlaylistModel.append(drawer.videoId, drawer.songTitle, drawer.artists)
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
Kirigami.BasicListItem{
|
||||
readonly property QtObject favouriteWatcher: Library.favouriteWatcher(drawer.videoId)
|
||||
|
||||
label: favouriteWatcher ? (favouriteWatcher.isFavourite ? i18n("Remove Favourite"): i18n("Add Favourite")): ""
|
||||
icon: favouriteWatcher ? (favouriteWatcher.isFavourite ? "starred-symbolic" : "non-starred-symbolic") : ""
|
||||
onClicked: {
|
||||
if (favouriteWatcher) {
|
||||
if (favouriteWatcher.isFavourite) {
|
||||
Library.removeFavourite(drawer.videoId)
|
||||
} else {
|
||||
Library.addFavourite(drawer.videoId, drawer.songTitle, drawer.artistsDisplayString, "")
|
||||
}
|
||||
}
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
Kirigami.BasicListItem{
|
||||
readonly property QtObject wasPlayedWatcher: Library.wasPlayedWatcher(drawer.videoId)
|
||||
|
||||
label: i18n("Remove from History")
|
||||
icon: "list-remove"
|
||||
onClicked: {
|
||||
Library.removePlaybackHistoryItem(drawer.videoId)
|
||||
drawer.close()
|
||||
}
|
||||
visible: wasPlayedWatcher ? wasPlayedWatcher.wasPlayed : false
|
||||
enabled: wasPlayedWatcher ? wasPlayedWatcher.wasPlayed : false
|
||||
}
|
||||
Item{
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Controls.Menu {
|
||||
property string videoId
|
||||
property string songTitle
|
||||
property var artists
|
||||
property string artistsDisplayString
|
||||
id: menu
|
||||
|
||||
Controls.MenuItem {
|
||||
text: i18n("Play Next")
|
||||
icon.name: "go-next"
|
||||
onTriggered: UserPlaylistModel.playNext(menu.videoId, menu.songTitle, menu.artists)
|
||||
}
|
||||
|
||||
Controls.MenuItem {
|
||||
text: i18n("Add to queue")
|
||||
icon.name: "media-playlist-append"
|
||||
onTriggered: UserPlaylistModel.append(menu.videoId, menu.songTitle, menu.artists)
|
||||
}
|
||||
|
||||
Controls.MenuItem {
|
||||
readonly property QtObject favouriteWatcher: Library.favouriteWatcher(menu.videoId)
|
||||
text: favouriteWatcher ? (favouriteWatcher.isFavourite ? i18n("Remove Favourite"): i18n("Add Favourite")): ""
|
||||
icon.name: favouriteWatcher ? (favouriteWatcher.isFavourite ? "starred-symbolic" : "non-starred-symbolic") : ""
|
||||
onTriggered: {
|
||||
if (favouriteWatcher) {
|
||||
if (favouriteWatcher.isFavourite) {
|
||||
Library.removeFavourite(menu.videoId)
|
||||
} else {
|
||||
Library.addFavourite(menu.videoId, menu.songTitle, menu.artistsDisplayString, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Controls.MenuItem{
|
||||
readonly property QtObject wasPlayedWatcher: Library.wasPlayedWatcher(menu.videoId)
|
||||
text: i18n("Remove from History")
|
||||
icon.name: "list-remove"
|
||||
onTriggered: {
|
||||
Library.removePlaybackHistoryItem(menu.videoId)
|
||||
}
|
||||
enabled: wasPlayedWatcher ? wasPlayedWatcher.wasPlayed : false
|
||||
visible: wasPlayedWatcher ? wasPlayedWatcher.wasPlayed : false
|
||||
}
|
||||
}
|
||||
}
|
||||
+205
-13
@@ -3,22 +3,117 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick 2.1
|
||||
import QtQuick.Controls 2.12 as Controls
|
||||
import QtQuick.Layouts 1.3
|
||||
import org.kde.kirigami 2.14 as Kirigami
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import org.kde.ytmusic 1.0
|
||||
|
||||
Kirigami.ApplicationWindow {
|
||||
id: root
|
||||
|
||||
title: i18n("AudioTube")
|
||||
pageStack.globalToolBar.style: wideScreen? Kirigami.ApplicationHeaderStyle.None: Kirigami.ApplicationHeaderStyle.Breadcrumb
|
||||
|
||||
controlsVisible: !footer.maximized
|
||||
color: "transparent"
|
||||
Blur{id:blur}
|
||||
Component.onCompleted: {
|
||||
blur.setBlur(sidebar, true);
|
||||
}
|
||||
|
||||
pageStack.columnView.columnResizeMode: Kirigami.ColumnView.SingleColumn
|
||||
|
||||
property alias searchField: searchLoader // TODO
|
||||
property bool wideScreen: width >= 600
|
||||
property bool showSearch: false // only applicable if not widescreen
|
||||
|
||||
// so that there is still a separator, since the header style is none
|
||||
Kirigami.Separator {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
visible: wideScreen
|
||||
}
|
||||
|
||||
|
||||
Sidebar {
|
||||
id:sidebar
|
||||
visible: wideScreen
|
||||
height: pageStack.height - playerFooter.implicitHeight
|
||||
|
||||
}
|
||||
NavigationBar{
|
||||
id: bottombar
|
||||
visible: !wideScreen
|
||||
|
||||
}
|
||||
|
||||
header: Controls.Control {
|
||||
visible: wideScreen || root.showSearch
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
|
||||
background: Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.fill: parent
|
||||
Kirigami.Theme.inherit: false
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Header
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
|
||||
|
||||
|
||||
Controls.ToolButton {
|
||||
id: back
|
||||
enabled: applicationWindow().pageStack.layers.depth > 1 || (applicationWindow().pageStack.depth > 1 && (applicationWindow().pageStack.currentIndex > 0 || applicationWindow().pageStack.contentItem.contentX > 0)) // Copied from https://invent.kde.org/frameworks/kirigami/-/blob/master/src/controls/templates/private/BackButton.qml#L16
|
||||
icon.name: "draw-arrow-back"
|
||||
onClicked: pageStack.goBack()
|
||||
visible: wideScreen
|
||||
}
|
||||
Controls.ToolButton {
|
||||
icon.name: "draw-arrow-forward"
|
||||
enabled: applicationWindow().pageStack.currentIndex < applicationWindow().pageStack.depth-1
|
||||
onClicked: pageStack.goForward()
|
||||
anchors.left: back.right
|
||||
visible: wideScreen
|
||||
|
||||
|
||||
}
|
||||
|
||||
// spacer
|
||||
Item {
|
||||
visible: wideScreen
|
||||
Layout.fillWidth: !root.wideScreen
|
||||
}
|
||||
SearchWithDropdown {
|
||||
id: searchLoader
|
||||
visible: root.wideScreen || root.showSearch
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
height: back.height
|
||||
width: wideScreen?null:root.width
|
||||
Layout.maximumWidth: wideScreen ? 400 : root.width
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 2*back.width
|
||||
visible: wideScreen
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
title: i18n("AudioTube")
|
||||
|
||||
contextDrawer: Kirigami.ContextDrawer {
|
||||
id: contextDrawer
|
||||
}
|
||||
|
||||
pageStack.initialPage: "qrc:/SearchPage.qml"
|
||||
pageStack.initialPage: "qrc:/LibraryPage.qml"
|
||||
pageStack.clip: true
|
||||
|
||||
function play(videoId) {
|
||||
UserPlaylistModel.initialVideoId = videoId
|
||||
@@ -32,15 +127,7 @@ Kirigami.ApplicationWindow {
|
||||
UserPlaylistModel.shuffle = true
|
||||
UserPlaylistModel.playlistId = playlistId
|
||||
}
|
||||
|
||||
function askPlayVideoAudio(videoId) {
|
||||
showPassiveNotification(i18n("Video playback is not supported yet."),
|
||||
"long",
|
||||
i18n("Play only audio"),
|
||||
function() {
|
||||
play(videoId)
|
||||
})
|
||||
}
|
||||
function focusSearch(){searchLoader.forceFocus()}
|
||||
|
||||
Connections {
|
||||
target: ErrorHandler
|
||||
@@ -50,5 +137,110 @@ Kirigami.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
footer: PlayerFooter {}
|
||||
Component {
|
||||
id: searchAlbum
|
||||
|
||||
ColumnLayout {
|
||||
id: mpdelegateItem
|
||||
|
||||
width: 100
|
||||
Layout.maximumWidth: 70
|
||||
|
||||
Kirigami.ShadowedRectangle {
|
||||
id: recCover
|
||||
MouseArea {
|
||||
id: recArea
|
||||
anchors.fill: parent
|
||||
onClicked: play(model.videoId)
|
||||
hoverEnabled: !Kirigami.Settings.hasTransientTouchInput
|
||||
onEntered: {
|
||||
if (!Kirigami.Settings.hasTransientTouchInput)
|
||||
recSelected.visible = true
|
||||
searchTitle.color = Kirigami.Theme.hoverColor
|
||||
searchTitle.font.bold = true
|
||||
|
||||
|
||||
}
|
||||
onExited:{
|
||||
recSelected.visible = false
|
||||
searchTitle.color = Kirigami.Theme.textColor
|
||||
searchTitle.font.bold = false
|
||||
}
|
||||
|
||||
}
|
||||
Layout.margins: 5
|
||||
|
||||
width: 70
|
||||
height: 70
|
||||
radius: 10
|
||||
shadow.size: 15
|
||||
shadow.xOffset: 5
|
||||
shadow.yOffset: 5
|
||||
shadow.color: Qt.rgba(0, 0, 0, 0.2)
|
||||
Rectangle {
|
||||
width: 70
|
||||
height: 70
|
||||
|
||||
color: "transparent"
|
||||
|
||||
ThumbnailSource {
|
||||
id: thumbnailSource
|
||||
videoId: model ? model.videoId : ""
|
||||
}
|
||||
RoundedImage {
|
||||
source: thumbnailSource.cachedPath
|
||||
height: parent.height
|
||||
width: height
|
||||
radius: 10
|
||||
}
|
||||
Rectangle {
|
||||
id: recSelected
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Kirigami.Theme.hoverColor
|
||||
radius: 10
|
||||
opacity: 0.2
|
||||
}
|
||||
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
|
||||
radius: 9
|
||||
|
||||
border.color: Kirigami.Theme.hoverColor
|
||||
border.width: 2
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
Controls.Label {
|
||||
id: searchTitle
|
||||
leftPadding:5
|
||||
Layout.maximumWidth: 70
|
||||
text: model ? model.title : ""
|
||||
elide: Qt.ElideRight
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.maximumHeight: 40
|
||||
}
|
||||
Item {
|
||||
height: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pageStack.anchors.bottomMargin: wideScreen ? playerFooter.minimizedPlayerHeight: playerFooter.minimizedPlayerHeight+bottombar.height
|
||||
pageStack.anchors.leftMargin: wideScreen ? sidebar.width:0
|
||||
|
||||
// media player
|
||||
PlayerFooter {
|
||||
id: playerFooter
|
||||
anchors.topMargin: -root.header.height
|
||||
anchors.fill: parent
|
||||
footerSpacing: wideScreen ? 0 : bottombar.height
|
||||
|
||||
// only expand flicking area to full screen when it is open
|
||||
z: (contentY === 0) ? -1 : 999
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,6 @@
|
||||
# SPDX-FileCopyrightText: 2021 Jonah Brüchert <[email protected]>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
add_executable(ytm_example main.cpp)
|
||||
target_link_libraries(ytm_example PRIVATE ytm)
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
int main() {
|
||||
const auto ytm = YTMusic();
|
||||
const auto results = ytm.search("arte concert");
|
||||
const auto results = ytm.search("Another one bites the dust");
|
||||
|
||||
std::cout << "Found " << results.size() << " results." << std::endl;
|
||||
|
||||
@@ -42,7 +42,7 @@ int main() {
|
||||
} else if constexpr (std::is_same_v<T, search::Video>) {
|
||||
std::cout << arg.title << std::endl;
|
||||
} else {
|
||||
std::cout << "non excaustive visitor";
|
||||
std::cout << "non exaustive visitor";
|
||||
}
|
||||
}, result);
|
||||
}
|
||||
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "library.h"
|
||||
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include "asyncdatabase.h"
|
||||
|
||||
namespace ranges = std::ranges;
|
||||
|
||||
Library::Library(QObject *parent)
|
||||
: QObject{parent}
|
||||
, m_database(ThreadedDatabase::establishConnection([]() -> DatabaseConfiguration {
|
||||
const auto databaseDirectory = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
// Make sure the database directory exists
|
||||
QDir(databaseDirectory).mkpath(QStringLiteral("."));
|
||||
|
||||
DatabaseConfiguration config;
|
||||
config.setDatabaseName(databaseDirectory % QDir::separator() % "library.sqlite");
|
||||
config.setType(DATABASE_TYPE_SQLITE);
|
||||
return config;
|
||||
}()))
|
||||
{
|
||||
m_database->runMigrations(":/migrations/");
|
||||
}
|
||||
|
||||
Library::~Library() = default;
|
||||
|
||||
Library &Library::instance()
|
||||
{
|
||||
static Library inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
FavouritesModel *Library::favourites()
|
||||
{
|
||||
auto future = m_database->getResults<Song>("select * from favourites natural join songs order by favourites.rowid desc");
|
||||
return new FavouritesModel(std::move(future), this);
|
||||
}
|
||||
|
||||
void Library::addFavourite(const QString &videoId, const QString &title, const QString &artist, const QString &album)
|
||||
{
|
||||
connectFuture(addSong(videoId, title, artist, album), this, [=, this] {
|
||||
connectFuture(m_database->execute("insert or ignore into favourites (video_id) values (?)", videoId), this, &Library::favouritesChanged);
|
||||
});
|
||||
}
|
||||
|
||||
void Library::removeFavourite(const QString &videoId)
|
||||
{
|
||||
connectFuture(m_database->execute("delete from favourites where video_id = ?", videoId), this, &Library::favouritesChanged);
|
||||
}
|
||||
|
||||
FavouriteWatcher *Library::favouriteWatcher(const QString &videoId)
|
||||
{
|
||||
if (videoId.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new FavouriteWatcher(this, videoId);
|
||||
}
|
||||
|
||||
SearchHistoryModel *Library::searches()
|
||||
{
|
||||
return new SearchHistoryModel(m_database->getResults<SingleValue<QString>>("select distinct (search_query) from searches order by search_id desc"), this);
|
||||
}
|
||||
|
||||
void Library::addSearch(const QString &text)
|
||||
{
|
||||
connectFuture(m_database->execute("insert into searches (search_query) values (?)", text), this, &Library::searchesChanged);
|
||||
}
|
||||
|
||||
void Library::removeSearch(const QString &text)
|
||||
{
|
||||
connectFuture(m_database->execute("delete from searches where search_query = ?", text), this, &Library::searchesChanged);
|
||||
}
|
||||
|
||||
PlaybackHistoryModel *Library::playbackHistory()
|
||||
{
|
||||
auto future = m_database->getResults<PlayedSong>("select * from played_songs natural join songs");
|
||||
return new PlaybackHistoryModel(std::move(future), this);
|
||||
}
|
||||
|
||||
void Library::addPlaybackHistoryItem(const QString &videoId, const QString &title, const QString &artist, const QString &album)
|
||||
{
|
||||
connectFuture(addSong(videoId, title, artist, album), this, [=, this] {
|
||||
connectFuture(m_database->execute("insert or ignore into played_songs (video_id, plays) values (?, ?)", videoId, 0), this, [=, this] {
|
||||
connectFuture(m_database->execute("update played_songs set plays = plays + 1 where video_id = ? ", videoId), this, &Library::playbackHistoryChanged);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void Library::removePlaybackHistoryItem(const QString &videoId)
|
||||
{
|
||||
connectFuture(m_database->execute("delete from played_songs where video_id = ?", videoId), this, &Library::playbackHistoryChanged);
|
||||
}
|
||||
|
||||
WasPlayedWatcher *Library::wasPlayedWatcher(const QString& videoId)
|
||||
{
|
||||
if(videoId.isEmpty()){
|
||||
return nullptr;
|
||||
}
|
||||
return new WasPlayedWatcher(this, videoId);
|
||||
}
|
||||
|
||||
|
||||
PlaybackHistoryModel *Library::mostPlayed()
|
||||
{
|
||||
auto future = m_database->getResults<PlayedSong>("select * from played_songs natural join songs order by plays desc limit 10");
|
||||
return new PlaybackHistoryModel(std::move(future), this);
|
||||
}
|
||||
|
||||
QNetworkAccessManager &Library::nam()
|
||||
{
|
||||
return m_networkImageCacher;
|
||||
}
|
||||
|
||||
QFuture<void> Library::addSong(const QString &videoId, const QString &title, const QString &artist, const QString &album)
|
||||
{
|
||||
// replace is used here to update songs from times when we didn't store artist and album
|
||||
return m_database->execute("insert or replace into songs (video_id, title, artist, album) values (?, ?, ?, ?)", videoId, title, artist, album);
|
||||
}
|
||||
|
||||
void ThumbnailSource::setVideoId(const QString &id) {
|
||||
if (m_videoId == id) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_videoId = id;
|
||||
Q_EMIT videoIdChanged();
|
||||
|
||||
const QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) % QDir::separator() % "thumbnails";
|
||||
QDir(cacheDir).mkpath(QStringLiteral("."));
|
||||
const QString cacheLocation = cacheDir % QDir::separator() % id % ".webp";
|
||||
|
||||
if (QFile::exists(cacheLocation)) {
|
||||
setCachedPath(QUrl::fromLocalFile(cacheLocation));
|
||||
return;
|
||||
}
|
||||
|
||||
auto *reply = Library::instance().nam().get(QNetworkRequest(QUrl("https://i.ytimg.com/vi_webp/" % m_videoId % "/maxresdefault.webp")));
|
||||
|
||||
auto storeResult = [this, cacheLocation](QNetworkReply *reply) {
|
||||
QFile file(cacheLocation);
|
||||
file.open(QFile::WriteOnly);
|
||||
file.write(reply->readAll());
|
||||
setCachedPath(QUrl::fromLocalFile(cacheLocation));
|
||||
|
||||
reply->deleteLater();
|
||||
};
|
||||
|
||||
connect(reply, &QNetworkReply::errorOccurred, this, [this, storeResult](auto error) {
|
||||
if (error == QNetworkReply::NetworkError::ContentNotFoundError) {
|
||||
qDebug() << "Naive thumbnail resolution failed, falling back to yt-dlp (slower)";
|
||||
|
||||
connectFuture(YTMusicThread::instance()->extractVideoInfo(m_videoId), this, [this, storeResult](auto info) {
|
||||
auto *reply = Library::instance().nam().get(QNetworkRequest(QUrl(QString::fromStdString(info.thumbnail))));
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, storeResult]() {
|
||||
storeResult(reply);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, storeResult]() {
|
||||
storeResult(reply);
|
||||
});
|
||||
}
|
||||
|
||||
PlaybackHistoryModel::PlaybackHistoryModel(QFuture<std::vector<PlayedSong> > &&songs, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
connectFuture(songs, this, [this](const auto songs) {
|
||||
beginResetModel();
|
||||
m_playedSongs = songs;
|
||||
endResetModel();
|
||||
});
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PlaybackHistoryModel::roleNames() const {
|
||||
return {
|
||||
{Roles::VideoId, "videoId"},
|
||||
{Roles::Title, "title"},
|
||||
{Roles::Artists, "artists"},
|
||||
{Roles::ArtistsDisplayString, "artistsDisplayString"},
|
||||
{Roles::Plays, "plays"}
|
||||
};
|
||||
}
|
||||
|
||||
int PlaybackHistoryModel::rowCount(const QModelIndex &parent) const {
|
||||
return parent.isValid() ? 0 : m_playedSongs.size();
|
||||
}
|
||||
|
||||
QVariant PlaybackHistoryModel::data(const QModelIndex &index, int role) const {
|
||||
switch (role) {
|
||||
case Roles::VideoId:
|
||||
return m_playedSongs.at(index.row()).videoId;
|
||||
case Roles::Title:
|
||||
return m_playedSongs.at(index.row()).title;
|
||||
case Roles::Artists:
|
||||
return QVariant::fromValue(std::vector<meta::Artist> {
|
||||
{
|
||||
m_playedSongs.at(index.row()).artist.toStdString(),
|
||||
{}
|
||||
}
|
||||
});
|
||||
case Roles::ArtistsDisplayString:
|
||||
return m_playedSongs.at(index.row()).artist;
|
||||
case Roles::Plays:
|
||||
return m_playedSongs.at(index.row()).plays;
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
FavouritesModel::FavouritesModel(QFuture<std::vector<Song>> &&songs, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
connectFuture(songs, this, [this](const auto songs) {
|
||||
beginResetModel();
|
||||
m_favouriteSongs = songs;
|
||||
endResetModel();
|
||||
});
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> FavouritesModel::roleNames() const {
|
||||
return {
|
||||
{Roles::VideoId, "videoId"},
|
||||
{Roles::Title, "title"},
|
||||
{Roles::Artists, "artists"},
|
||||
{Roles::ArtistsDisplayString, "artistsDisplayString"}
|
||||
};
|
||||
}
|
||||
|
||||
int FavouritesModel::rowCount(const QModelIndex &parent) const {
|
||||
return parent.isValid() ? 0 : m_favouriteSongs.size();
|
||||
}
|
||||
|
||||
QVariant FavouritesModel::data(const QModelIndex &index, int role) const {
|
||||
switch (role) {
|
||||
case Roles::VideoId:
|
||||
return m_favouriteSongs.at(index.row()).videoId;
|
||||
case Roles::Title:
|
||||
return m_favouriteSongs.at(index.row()).title;
|
||||
case Roles::ArtistsDisplayString:
|
||||
return m_favouriteSongs.at(index.row()).artist;
|
||||
case Roles::Artists:
|
||||
return QVariant::fromValue(std::vector<meta::Artist> {
|
||||
{
|
||||
m_favouriteSongs.at(index.row()).artist.toStdString(),
|
||||
{}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
FavouriteWatcher::FavouriteWatcher(Library *library, const QString &videoId)
|
||||
: QObject(library), m_videoId(videoId), m_library(library)
|
||||
{
|
||||
auto update = [this] {
|
||||
connectFuture(m_library->database().getResult<SingleValue<bool>>("select count(*) > 0 from favourites where video_id = ?", m_videoId), this, [this](auto count) {
|
||||
if (count) {
|
||||
m_isFavourite = count->value;
|
||||
Q_EMIT isFavouriteChanged();
|
||||
}
|
||||
});
|
||||
};
|
||||
update();
|
||||
connect(library, &Library::favouritesChanged, this, update);
|
||||
}
|
||||
|
||||
bool FavouriteWatcher::isFavourite() const {
|
||||
return m_isFavourite;
|
||||
}
|
||||
|
||||
SearchHistoryModel::SearchHistoryModel(QFuture<std::vector<SingleValue<QString>>> &&historyFuture, QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
connectFuture(historyFuture, this, [this](const auto history) {
|
||||
beginResetModel();
|
||||
m_history = history;
|
||||
endResetModel();
|
||||
});
|
||||
}
|
||||
|
||||
int SearchHistoryModel::rowCount(const QModelIndex &parent) const {
|
||||
return parent.isValid() ? 0 : m_history.size();
|
||||
}
|
||||
|
||||
QVariant SearchHistoryModel::data(const QModelIndex &index, int role) const {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return m_history[index.row()].value;
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
WasPlayedWatcher::WasPlayedWatcher(Library* library, const QString& videoId)
|
||||
: QObject(library), m_videoId(videoId), m_library(library)
|
||||
{
|
||||
connect(m_library, &Library::playbackHistoryChanged, this, &WasPlayedWatcher::query);
|
||||
query();
|
||||
}
|
||||
|
||||
void WasPlayedWatcher::query()
|
||||
{
|
||||
connectFuture(m_library->database().getResult<SingleValue<bool>>("select count(*) > 0 from played_songs where video_id = ?", m_videoId), this, &WasPlayedWatcher::update);
|
||||
}
|
||||
|
||||
|
||||
bool WasPlayedWatcher::wasPlayed() const
|
||||
{
|
||||
return m_wasPlayed;
|
||||
}
|
||||
|
||||
|
||||
void WasPlayedWatcher::update(std::optional<SingleValue<bool>> result)
|
||||
{
|
||||
if(result.has_value())
|
||||
{
|
||||
m_wasPlayed = result->value;
|
||||
Q_EMIT wasPlayedChanged();
|
||||
}
|
||||
}
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QQuickAsyncImageProvider>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "asyncytmusic.h"
|
||||
#include "asyncdatabase.h"
|
||||
|
||||
class FavouriteWatcher;
|
||||
class WasPlayedWatcher;
|
||||
|
||||
struct Song {
|
||||
using ColumnTypes = std::tuple<QString, QString, QString, QString>;
|
||||
|
||||
static Song fromSql(ColumnTypes tuple) {
|
||||
auto [videoId, title, artist, album] = tuple;
|
||||
return Song {videoId, title, artist, album};
|
||||
}
|
||||
|
||||
QString videoId;
|
||||
QString title;
|
||||
QString artist;
|
||||
QString album;
|
||||
};
|
||||
|
||||
class FavouritesModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
enum Roles {
|
||||
VideoId = Qt::UserRole + 1,
|
||||
Title,
|
||||
Artists,
|
||||
ArtistsDisplayString
|
||||
};
|
||||
|
||||
public:
|
||||
FavouritesModel(QFuture<std::vector<Song>> &&songs, QObject *parent = nullptr);
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private:
|
||||
std::vector<Song> m_favouriteSongs;
|
||||
};
|
||||
|
||||
struct PlayedSong {
|
||||
using ColumnTypes = std::tuple<QString, int, QString, QString, QString>;
|
||||
|
||||
static PlayedSong fromSql(ColumnTypes tuple) {
|
||||
auto [videoId, plays, title, artist, album] = tuple;
|
||||
return PlayedSong {videoId, title, artist, album, plays};
|
||||
}
|
||||
|
||||
QString videoId;
|
||||
QString title;
|
||||
QString artist;
|
||||
QString album;
|
||||
int plays;
|
||||
};
|
||||
|
||||
class PlaybackHistoryModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
VideoId = Qt::UserRole + 1,
|
||||
Title,
|
||||
Artists,
|
||||
ArtistsDisplayString,
|
||||
Plays
|
||||
};
|
||||
Q_ENUM(Roles);
|
||||
|
||||
PlaybackHistoryModel(QFuture<std::vector<PlayedSong>> &&songs, QObject *parent = nullptr);
|
||||
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private:
|
||||
std::vector<PlayedSong> m_playedSongs;
|
||||
};
|
||||
|
||||
class SearchHistoryModel : public QAbstractListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SearchHistoryModel(QFuture<std::vector<SingleValue<QString>>> &&historyFuture, QObject *parent = nullptr);
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private:
|
||||
std::vector<SingleValue<QString>> m_history;
|
||||
};
|
||||
|
||||
class Library : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QAbstractListModel *favourites READ favourites NOTIFY favouritesChanged)
|
||||
Q_PROPERTY(QAbstractListModel *searches READ searches NOTIFY searchesChanged)
|
||||
Q_PROPERTY(QAbstractListModel *playbackHistory READ playbackHistory NOTIFY playbackHistoryChanged)
|
||||
Q_PROPERTY(QAbstractListModel *mostPlayed READ mostPlayed NOTIFY playbackHistoryChanged)
|
||||
|
||||
public:
|
||||
explicit Library(QObject *parent = nullptr);
|
||||
~Library();
|
||||
|
||||
static Library &instance();
|
||||
|
||||
FavouritesModel *favourites();
|
||||
Q_SIGNAL void favouritesChanged();
|
||||
Q_INVOKABLE void addFavourite(const QString &videoId, const QString &title, const QString &artist, const QString &album);
|
||||
Q_INVOKABLE void removeFavourite(const QString &videoId);
|
||||
Q_INVOKABLE FavouriteWatcher *favouriteWatcher(const QString &videoId);
|
||||
|
||||
SearchHistoryModel *searches();
|
||||
Q_SIGNAL void searchesChanged();
|
||||
Q_INVOKABLE void addSearch(const QString &text);
|
||||
Q_INVOKABLE void removeSearch(const QString &text);
|
||||
|
||||
PlaybackHistoryModel *playbackHistory();
|
||||
Q_SIGNAL void playbackHistoryChanged();
|
||||
Q_INVOKABLE void addPlaybackHistoryItem(const QString &videoId, const QString &title, const QString &artist, const QString &album);
|
||||
Q_INVOKABLE void removePlaybackHistoryItem(const QString &videoId);
|
||||
Q_INVOKABLE WasPlayedWatcher *wasPlayedWatcher(const QString &videoId);
|
||||
|
||||
PlaybackHistoryModel *mostPlayed();
|
||||
|
||||
QNetworkAccessManager &nam();
|
||||
ThreadedDatabase &database() {
|
||||
return *m_database;
|
||||
}
|
||||
|
||||
private:
|
||||
QFuture<void> addSong(const QString &videoId, const QString &title, const QString &artist, const QString &album);
|
||||
|
||||
QNetworkAccessManager m_networkImageCacher;
|
||||
std::unique_ptr<ThreadedDatabase> m_database;
|
||||
};
|
||||
|
||||
|
||||
class ThumbnailSource : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString videoId READ videoId WRITE setVideoId NOTIFY videoIdChanged)
|
||||
Q_PROPERTY(QUrl cachedPath READ cachedPath NOTIFY cachedPathChanged)
|
||||
|
||||
QString videoId() const {
|
||||
return m_videoId;
|
||||
}
|
||||
void setVideoId(const QString &id);
|
||||
Q_SIGNAL void videoIdChanged();
|
||||
|
||||
QUrl cachedPath() const {
|
||||
return m_cachedPath;
|
||||
}
|
||||
void setCachedPath(const QUrl &path) {
|
||||
m_cachedPath = path;
|
||||
cachedPathChanged();
|
||||
}
|
||||
Q_SIGNAL void cachedPathChanged();
|
||||
|
||||
private:
|
||||
QString m_videoId;
|
||||
QUrl m_cachedPath;
|
||||
};
|
||||
|
||||
class FavouriteWatcher : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool isFavourite READ isFavourite NOTIFY isFavouriteChanged)
|
||||
|
||||
public:
|
||||
FavouriteWatcher(Library *library, const QString &videoId);
|
||||
|
||||
bool isFavourite() const;
|
||||
Q_SIGNAL void isFavouriteChanged();
|
||||
|
||||
Q_SIGNAL void videoIdChanged();
|
||||
|
||||
private:
|
||||
QString m_videoId;
|
||||
Library *m_library;
|
||||
bool m_isFavourite = false;
|
||||
};
|
||||
|
||||
class WasPlayedWatcher : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool wasPlayed READ wasPlayed NOTIFY wasPlayedChanged)
|
||||
|
||||
public:
|
||||
WasPlayedWatcher(Library *Library, const QString &VideoId);
|
||||
|
||||
bool wasPlayed() const;
|
||||
|
||||
Q_SIGNAL void wasPlayedChanged();
|
||||
|
||||
private:
|
||||
bool m_wasPlayed = false;
|
||||
QString m_videoId;
|
||||
Library *m_library;
|
||||
Q_SLOT void update(std::optional<SingleValue<bool>> result);
|
||||
Q_SLOT void query();
|
||||
};
|
||||
@@ -5,8 +5,13 @@
|
||||
#include <QApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QtQml>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QUrl>
|
||||
#include <KLocalizedContext>
|
||||
#include <KLocalizedString>
|
||||
#include <KCrash>
|
||||
#include <KAboutData>
|
||||
#include <QQuickWindow>
|
||||
|
||||
#include "searchmodel.h"
|
||||
#include "albummodel.h"
|
||||
@@ -15,6 +20,11 @@
|
||||
#include "userplaylistmodel.h"
|
||||
#include "errorhandler.h"
|
||||
#include "playlistmodel.h"
|
||||
#include "playerutils.h"
|
||||
#include "library.h"
|
||||
#include "blur.h"
|
||||
|
||||
#include "asyncdatabase.h"
|
||||
|
||||
constexpr auto URI = "org.kde.ytmusic";
|
||||
|
||||
@@ -26,6 +36,11 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||
QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
|
||||
QCoreApplication::setApplicationName(QStringLiteral("audiotube"));
|
||||
|
||||
KLocalizedString::setApplicationDomain("audiotube");
|
||||
|
||||
KAboutData::setApplicationData(KAboutData(QStringLiteral("audiotube"), QStringLiteral("AudioTube")));
|
||||
KCrash::initialize();
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
qmlRegisterType<SearchModel>(URI, 1, 0, "SearchModel");
|
||||
@@ -33,6 +48,10 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||
qmlRegisterType<VideoInfoExtractor>(URI, 1, 0, "VideoInfoExtractor");
|
||||
qmlRegisterType<ArtistModel>(URI, 1, 0, "ArtistModel");
|
||||
qmlRegisterType<PlaylistModel>(URI, 1, 0, "PlaylistModel");
|
||||
qmlRegisterUncreatableType<PlaybackHistoryModel>(URI, 1, 0, "PlaybackHistoryModel","");
|
||||
qmlRegisterType<QSortFilterProxyModel>(URI, 1, 0, "SortFilterModel");
|
||||
qmlRegisterType<Blur>(URI, 1, 0, "Blur");
|
||||
|
||||
qmlRegisterSingletonType<UserPlaylistModel>(URI, 1, 0, "UserPlaylistModel", [](QQmlEngine *, QJSEngine *) {
|
||||
return new UserPlaylistModel();
|
||||
});
|
||||
@@ -40,6 +59,15 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||
return new ErrorHandler();
|
||||
});
|
||||
|
||||
qmlRegisterSingletonType<PlayerUtils>(URI, 1, 0, "PlayerUtils", [](QQmlEngine *, QJSEngine *) {
|
||||
return new PlayerUtils();
|
||||
});
|
||||
|
||||
qmlRegisterSingletonInstance<Library>(URI, 1, 0, "Library", &Library::instance());
|
||||
qmlRegisterType<ThumbnailSource>(URI, 1, 0, "ThumbnailSource");
|
||||
qmlRegisterAnonymousType<FavouriteWatcher>(URI, 1);
|
||||
qmlRegisterAnonymousType<WasPlayedWatcher>(URI, 1);
|
||||
|
||||
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
|
||||
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
||||
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,8 @@
|
||||
-- SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
--
|
||||
-- SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
drop table songs;
|
||||
drop table played_songs;
|
||||
drop table favourites;
|
||||
drop table searches;
|
||||
@@ -0,0 +1,26 @@
|
||||
-- SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
|
||||
--
|
||||
-- SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
create table songs (
|
||||
video_id Text primary key not null,
|
||||
title Text not null,
|
||||
artist Text,
|
||||
album Text
|
||||
);
|
||||
|
||||
create table played_songs (
|
||||
video_id Text primary key not null,
|
||||
plays Int not null,
|
||||
foreign key (video_id) references songs(video_id)
|
||||
);
|
||||
|
||||
create table favourites (
|
||||
video_id Text primary key not null,
|
||||
foreign key (video_id) references songs(video_id)
|
||||
);
|
||||
|
||||
create table searches (
|
||||
search_id integer primary key autoincrement not null,
|
||||
search_query Text not null
|
||||
);
|
||||
@@ -1,10 +0,0 @@
|
||||
qt5_add_dbus_adaptor(DBUS_SRCS
|
||||
dbus/org.mpris.MediaPlayer2.xml
|
||||
mprisapplication.h MprisApplication)
|
||||
|
||||
qt5_add_dbus_adaptor(DBUS_SRCS
|
||||
dbus/org.mpris.MediaPlayer2.Player.xml
|
||||
mprisplayer.h MprisPlayer)
|
||||
|
||||
add_library(mpris2 STATIC mprisapplication.cpp mprisplayer.cpp ${DBUS_SRCS})
|
||||
target_link_libraries(mpris2 PUBLIC Qt5::Core Qt5::DBus)
|
||||
@@ -1,672 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<node name="/Player_Interface" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
|
||||
<interface name="org.mpris.MediaPlayer2.Player">
|
||||
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
This interface implements the methods for querying and providing basic
|
||||
control over what is currently playing.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
|
||||
<tp:enum name="Playback_Status" tp:name-for-bindings="Playback_Status" type="s">
|
||||
<tp:enumvalue suffix="Playing" value="Playing">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A track is currently playing.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="Paused" value="Paused">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A track is currently paused.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="Stopped" value="Stopped">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>There is no track currently playing.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A playback state.</p>
|
||||
</tp:docstring>
|
||||
</tp:enum>
|
||||
|
||||
<tp:enum name="Loop_Status" tp:name-for-bindings="Loop_Status" type="s">
|
||||
<tp:enumvalue suffix="None" value="None">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The playback will stop when there are no more tracks to play</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="Track" value="Track">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The current track will start again from the begining once it has finished playing</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="Playlist" value="Playlist">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The playback loops through a list of tracks</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A repeat / loop status</p>
|
||||
</tp:docstring>
|
||||
</tp:enum>
|
||||
|
||||
<tp:simple-type name="Track_Id" type="o" array-name="Track_Id_List">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Unique track identifier.</p>
|
||||
<p>
|
||||
If the media player implements the TrackList interface and allows
|
||||
the same track to appear multiple times in the tracklist,
|
||||
this must be unique within the scope of the tracklist.
|
||||
</p>
|
||||
<p>
|
||||
Note that this should be a valid D-Bus object id, although clients
|
||||
should not assume that any object is actually exported with any
|
||||
interfaces at that path.
|
||||
</p>
|
||||
<p>
|
||||
Media players may not use any paths starting with
|
||||
<literal>/org/mpris</literal> unless explicitly allowed by this specification.
|
||||
Such paths are intended to have special meaning, such as
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
to indicate "no track".
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This is a D-Bus object id as that is the definitive way to have
|
||||
unique identifiers on D-Bus. It also allows for future optional
|
||||
expansions to the specification where tracks are exported to D-Bus
|
||||
with an interface similar to org.gnome.UPnP.MediaItem2.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<tp:simple-type name="Playback_Rate" type="d">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A playback rate</p>
|
||||
<p>
|
||||
This is a multiplier, so a value of 0.5 indicates that playback is
|
||||
happening at half speed, while 1.5 means that 1.5 seconds of "track time"
|
||||
is consumed every second.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<tp:simple-type name="Volume" type="d">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Audio volume level</p>
|
||||
<ul>
|
||||
<li>0.0 means mute.</li>
|
||||
<li>1.0 is a sensible maximum volume level (ex: 0dB).</li>
|
||||
</ul>
|
||||
<p>
|
||||
Note that the volume may be higher than 1.0, although generally
|
||||
clients should not attempt to set it above 1.0.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<tp:simple-type name="Time_In_Us" type="x">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Time in microseconds.</p>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<method name="Next" tp:name-for-bindings="Next">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Skips to the next track in the tracklist.</p>
|
||||
<p>
|
||||
If there is no next track (and endless playback and track
|
||||
repeat are both off), stop playback.
|
||||
</p>
|
||||
<p>If playback is paused or stopped, it remains that way.</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanGoNext</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to call this method should have
|
||||
no effect.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="Previous" tp:name-for-bindings="Previous">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Skips to the previous track in the tracklist.</p>
|
||||
<p>
|
||||
If there is no previous track (and endless playback and track
|
||||
repeat are both off), stop playback.
|
||||
</p>
|
||||
<p>If playback is paused or stopped, it remains that way.</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanGoPrevious</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to call this method should have
|
||||
no effect.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="Pause" tp:name-for-bindings="Pause">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Pauses playback.</p>
|
||||
<p>If playback is already paused, this has no effect.</p>
|
||||
<p>
|
||||
Calling Play after this should cause playback to start again
|
||||
from the same position.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanPause</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to call this method should have
|
||||
no effect.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="PlayPause" tp:name-for-bindings="PlayPause">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Pauses playback.</p>
|
||||
<p>If playback is already paused, resumes playback.</p>
|
||||
<p>If playback is stopped, starts playback.</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanPause</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to call this method should have
|
||||
no effect and raise an error.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="Stop" tp:name-for-bindings="Stop">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Stops playback.</p>
|
||||
<p>If playback is already stopped, this has no effect.</p>
|
||||
<p>
|
||||
Calling Play after this should cause playback to
|
||||
start again from the beginning of the track.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to call this method should have
|
||||
no effect and raise an error.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="Play" tp:name-for-bindings="Play">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Starts or resumes playback.</p>
|
||||
<p>If already playing, this has no effect.</p>
|
||||
<p>If paused, playback resumes from the current position.</p>
|
||||
<p>If there is no track to play, this has no effect.</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanPlay</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to call this method should have
|
||||
no effect.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="Seek" tp:name-for-bindings="Seek">
|
||||
<arg direction="in" type="x" name="Offset" tp:type="Time_In_Us">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The number of microseconds to seek forward.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Seeks forward in the current track by the specified number
|
||||
of microseconds.
|
||||
</p>
|
||||
<p>
|
||||
A negative value seeks back. If this would mean seeking
|
||||
back further than the start of the track, the position
|
||||
is set to 0.
|
||||
</p>
|
||||
<p>
|
||||
If the value passed in would mean seeking beyond the end
|
||||
of the track, acts like a call to Next.
|
||||
</p>
|
||||
<p>
|
||||
If the <tp:member-ref>CanSeek</tp:member-ref> property is false,
|
||||
this has no effect.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="SetPosition" tp:name-for-bindings="Set_Position">
|
||||
<arg direction="in" type="o" tp:type="Track_Id" name="TrackId">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The currently playing track's identifier.</p>
|
||||
<p>
|
||||
If this does not match the id of the currently-playing track,
|
||||
the call is ignored as "stale".
|
||||
</p>
|
||||
<p>
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
is <em>not</em> a valid value for this argument.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg direction="in" type="x" tp:type="Time_In_Us" name="Position">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Track position in microseconds.</p>
|
||||
<p>This must be between 0 and <track_length>.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Sets the current track position in microseconds.</p>
|
||||
<p>If the Position argument is less than 0, do nothing.</p>
|
||||
<p>
|
||||
If the Position argument is greater than the track length,
|
||||
do nothing.
|
||||
</p>
|
||||
<p>
|
||||
If the <tp:member-ref>CanSeek</tp:member-ref> property is false,
|
||||
this has no effect.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
The reason for having this method, rather than making
|
||||
<tp:member-ref>Position</tp:member-ref> writable, is to include
|
||||
the TrackId argument to avoid race conditions where a client tries
|
||||
to seek to a position when the track has already changed.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="OpenUri" tp:name-for-bindings="Open_Uri">
|
||||
<arg direction="in" type="s" tp:type="Uri" name="Uri">
|
||||
<tp:docstring>
|
||||
<p>
|
||||
Uri of the track to load. Its uri scheme should be an element of the
|
||||
<literal>org.mpris.MediaPlayer2.SupportedUriSchemes</literal>
|
||||
property and the mime-type should match one of the elements of the
|
||||
<literal>org.mpris.MediaPlayer2.SupportedMimeTypes</literal>.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Opens the Uri given as an argument</p>
|
||||
<p>If the playback is stopped, starts playing</p>
|
||||
<p>
|
||||
If the uri scheme or the mime-type of the uri to open is not supported,
|
||||
this method does nothing and may raise an error. In particular, if the
|
||||
list of available uri schemes is empty, this method may not be
|
||||
implemented.
|
||||
</p>
|
||||
<p>Clients should not assume that the Uri has been opened as soon as this
|
||||
method returns. They should wait until the mpris:trackid field in the
|
||||
<tp:member-ref>Metadata</tp:member-ref> property changes.
|
||||
</p>
|
||||
<p>
|
||||
If the media player implements the TrackList interface, then the
|
||||
opened track should be made part of the tracklist, the
|
||||
<literal>org.mpris.MediaPlayer2.TrackList.TrackAdded</literal> or
|
||||
<literal>org.mpris.MediaPlayer2.TrackList.TrackListReplaced</literal>
|
||||
signal should be fired, as well as the
|
||||
<literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
|
||||
signal on the tracklist interface.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<property name="PlaybackStatus" tp:name-for-bindings="Playback_Status" type="s" tp:type="Playback_Status" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The current playback status.</p>
|
||||
<p>
|
||||
May be "Playing", "Paused" or "Stopped".
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="LoopStatus" type="s" access="readwrite"
|
||||
tp:name-for-bindings="Loop_Status" tp:type="Loop_Status">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<annotation name="org.mpris.MediaPlayer2.property.optional" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The current loop / repeat status</p>
|
||||
<p>May be:
|
||||
<ul>
|
||||
<li>"None" if the playback will stop when there are no more tracks to play</li>
|
||||
<li>"Track" if the current track will start again from the begining once it has finished playing</li>
|
||||
<li>"Playlist" if the playback loops through a list of tracks</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to set this property should have
|
||||
no effect and raise an error.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Rate" tp:name-for-bindings="Rate" type="d" tp:type="Playback_Rate" access="readwrite">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The current playback rate.</p>
|
||||
<p>
|
||||
The value must fall in the range described by
|
||||
<tp:member-ref>MinimumRate</tp:member-ref> and
|
||||
<tp:member-ref>MaximumRate</tp:member-ref>, and must not be 0.0. If
|
||||
playback is paused, the <tp:member-ref>PlaybackStatus</tp:member-ref>
|
||||
property should be used to indicate this. A value of 0.0 should not
|
||||
be set by the client. If it is, the media player should act as
|
||||
though <tp:member-ref>Pause</tp:member-ref> was called.
|
||||
</p>
|
||||
<p>
|
||||
If the media player has no ability to play at speeds other than the
|
||||
normal playback rate, this must still be implemented, and must
|
||||
return 1.0. The <tp:member-ref>MinimumRate</tp:member-ref> and
|
||||
<tp:member-ref>MaximumRate</tp:member-ref> properties must also be
|
||||
set to 1.0.
|
||||
</p>
|
||||
<p>
|
||||
Not all values may be accepted by the media player. It is left to
|
||||
media player implementations to decide how to deal with values they
|
||||
cannot use; they may either ignore them or pick a "best fit" value.
|
||||
Clients are recommended to only use sensible fractions or multiples
|
||||
of 1 (eg: 0.5, 0.25, 1.5, 2.0, etc).
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This allows clients to display (reasonably) accurate progress bars
|
||||
without having to regularly query the media player for the current
|
||||
position.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Shuffle" tp:name-for-bindings="Shuffle" type="b" access="readwrite">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<annotation name="org.mpris.MediaPlayer2.property.optional" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
A value of <strong>false</strong> indicates that playback is
|
||||
progressing linearly through a playlist, while <strong>true</strong>
|
||||
means playback is progressing through a playlist in some other order.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to set this property should have
|
||||
no effect and raise an error.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Metadata" tp:name-for-bindings="Metadata" type="a{sv}" tp:type="Metadata_Map" access="read">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName" value="QMap<QString, QString>"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The metadata of the current element.</p>
|
||||
<p>
|
||||
If there is a current track, this must have a "mpris:trackid" entry
|
||||
(of D-Bus type "o") at the very least, which contains a D-Bus path that
|
||||
uniquely identifies this track.
|
||||
</p>
|
||||
<p>
|
||||
See the type documentation for more details.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Volume" type="d" tp:type="Volume" tp:name-for-bindings="Volume" access="readwrite">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true" />
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The volume level.</p>
|
||||
<p>
|
||||
When setting, if a negative value is passed, the volume
|
||||
should be set to 0.0.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, attempting to set this property should have
|
||||
no effect and raise an error.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Position" type="x" tp:type="Time_In_Us" tp:name-for-bindings="Position" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The current track position in microseconds, between 0 and
|
||||
the 'mpris:length' metadata entry (see Metadata).
|
||||
</p>
|
||||
<p>
|
||||
Note: If the media player allows it, the current playback position
|
||||
can be changed either the SetPosition method or the Seek method on
|
||||
this interface. If this is not the case, the
|
||||
<tp:member-ref>CanSeek</tp:member-ref> property is false, and
|
||||
setting this property has no effect and can raise an error.
|
||||
</p>
|
||||
<p>
|
||||
If the playback progresses in a way that is inconstistant with the
|
||||
<tp:member-ref>Rate</tp:member-ref> property, the
|
||||
<tp:member-ref>Seeked</tp:member-ref> signal is emited.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="MinimumRate" tp:name-for-bindings="Minimum_Rate" type="d" tp:type="Playback_Rate" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The minimum value which the <tp:member-ref>Rate</tp:member-ref>
|
||||
property can take.
|
||||
Clients should not attempt to set the
|
||||
<tp:member-ref>Rate</tp:member-ref> property below this value.
|
||||
</p>
|
||||
<p>
|
||||
Note that even if this value is 0.0 or negative, clients should
|
||||
not attempt to set the <tp:member-ref>Rate</tp:member-ref> property
|
||||
to 0.0.
|
||||
</p>
|
||||
<p>This value should always be 1.0 or less.</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="MaximumRate" tp:name-for-bindings="Maximum_Rate" type="d" tp:type="Playback_Rate" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The maximum value which the <tp:member-ref>Rate</tp:member-ref>
|
||||
property can take.
|
||||
Clients should not attempt to set the
|
||||
<tp:member-ref>Rate</tp:member-ref> property above this value.
|
||||
</p>
|
||||
<p>
|
||||
This value should always be 1.0 or greater.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanGoNext" tp:name-for-bindings="Can_Go_Next" type="b" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Whether the client can call the <tp:member-ref>Next</tp:member-ref>
|
||||
method on this interface and expect the current track to change.
|
||||
</p>
|
||||
<p>
|
||||
If it is unknown whether a call to <tp:member-ref>Next</tp:member-ref> will
|
||||
be successful (for example, when streaming tracks), this property should
|
||||
be set to <strong>true</strong>.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, this property should also be
|
||||
<strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Even when playback can generally be controlled, there may not
|
||||
always be a next track to move to.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanGoPrevious" tp:name-for-bindings="Can_Go_Previous" type="b" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Whether the client can call the
|
||||
<tp:member-ref>Previous</tp:member-ref> method on this interface and
|
||||
expect the current track to change.
|
||||
</p>
|
||||
<p>
|
||||
If it is unknown whether a call to <tp:member-ref>Previous</tp:member-ref>
|
||||
will be successful (for example, when streaming tracks), this property
|
||||
should be set to <strong>true</strong>.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, this property should also be
|
||||
<strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Even when playback can generally be controlled, there may not
|
||||
always be a next previous to move to.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanPlay" tp:name-for-bindings="Can_Play" type="b" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Whether playback can be started using
|
||||
<tp:member-ref>Play</tp:member-ref> or
|
||||
<tp:member-ref>PlayPause</tp:member-ref>.
|
||||
</p>
|
||||
<p>
|
||||
Note that this is related to whether there is a "current track": the
|
||||
value should not depend on whether the track is currently paused or
|
||||
playing. In fact, if a track is currently playing (and
|
||||
<tp:member-ref>CanControl</tp:member-ref> is <strong>true</strong>),
|
||||
this should be <strong>true</strong>.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, this property should also be
|
||||
<strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Even when playback can generally be controlled, it may not be
|
||||
possible to enter a "playing" state, for example if there is no
|
||||
"current track".
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanPause" tp:name-for-bindings="Can_Pause" type="b" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Whether playback can be paused using
|
||||
<tp:member-ref>Pause</tp:member-ref> or
|
||||
<tp:member-ref>PlayPause</tp:member-ref>.
|
||||
</p>
|
||||
<p>
|
||||
Note that this is an intrinsic property of the current track: its
|
||||
value should not depend on whether the track is currently paused or
|
||||
playing. In fact, if playback is currently paused (and
|
||||
<tp:member-ref>CanControl</tp:member-ref> is <strong>true</strong>),
|
||||
this should be <strong>true</strong>.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, this property should also be
|
||||
<strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Not all media is pausable: it may not be possible to pause some
|
||||
streamed media, for example.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanSeek" tp:name-for-bindings="Can_Seek" type="b" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Whether the client can control the playback position using
|
||||
<tp:member-ref>Seek</tp:member-ref> and
|
||||
<tp:member-ref>SetPosition</tp:member-ref>. This may be different for
|
||||
different tracks.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanControl</tp:member-ref> is
|
||||
<strong>false</strong>, this property should also be
|
||||
<strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Not all media is seekable: it may not be possible to seek when
|
||||
playing some streamed media, for example.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanControl" tp:name-for-bindings="Can_Control" type="b" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="false"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Whether the media player may be controlled over this interface.</p>
|
||||
<p>
|
||||
This property is not expected to change, as it describes an intrinsic
|
||||
capability of the implementation.
|
||||
</p>
|
||||
<p>
|
||||
If this is <strong>false</strong>, clients should assume that all
|
||||
properties on this interface are read-only (and will raise errors
|
||||
if writing to them is attempted), no methods are implemented
|
||||
and all other properties starting with "Can" are also
|
||||
<strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This allows clients to determine whether to present and enable
|
||||
controls to the user in advance of attempting to call methods
|
||||
and write to properties.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<signal name="Seeked" tp:name-for-bindings="Seeked">
|
||||
<arg name="Position" type="x" tp:type="Time_In_Us">
|
||||
<tp:docstring>
|
||||
<p>The new position, in microseconds.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Indicates that the track position has changed in a way that is
|
||||
inconsistant with the current playing state.
|
||||
</p>
|
||||
<p>When this signal is not received, clients should assume that:</p>
|
||||
<ul>
|
||||
<li>
|
||||
When playing, the position progresses according to the rate property.
|
||||
</li>
|
||||
<li>When paused, it remains constant.</li>
|
||||
</ul>
|
||||
<p>
|
||||
This signal does not need to be emitted when playback starts
|
||||
or when the track changes, unless the track is starting at an
|
||||
unexpected position. An expected position would be the last
|
||||
known one when going from Paused to Playing, and 0 when going from
|
||||
Stopped to Playing.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
<!-- vim:set sw=2 sts=2 et ft=xml: -->
|
||||
@@ -1,253 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<node name="/Playlists_Interface" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
|
||||
<interface name="org.mpris.MediaPlayer2.Playlists">
|
||||
<tp:added version="2.1" />
|
||||
<tp:docstring>
|
||||
<p>Provides access to the media player's playlists.</p>
|
||||
<p>
|
||||
Since D-Bus does not provide an easy way to check for what interfaces
|
||||
are exported on an object, clients should attempt to get one of the
|
||||
properties on this interface to see if it is implemented.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
|
||||
<tp:simple-type name="Playlist_Id" type="o" array-name="Playlist_Id_List">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Unique playlist identifier.</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Multiple playlists may have the same name.
|
||||
</p>
|
||||
<p>
|
||||
This is a D-Bus object id as that is the definitive way to have
|
||||
unique identifiers on D-Bus. It also allows for future optional
|
||||
expansions to the specification where tracks are exported to D-Bus
|
||||
with an interface similar to org.gnome.UPnP.MediaItem2.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<tp:simple-type name="Uri" type="s" array-name="Uri_List">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A URI.</p>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<tp:struct name="Playlist" array-name="Playlist_List">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A data structure describing a playlist.</p>
|
||||
</tp:docstring>
|
||||
<tp:member type="o" tp:type="Playlist_Id" name="Id">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A unique identifier for the playlist.</p>
|
||||
<p>This should remain the same if the playlist is renamed.</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
<tp:member type="s" name="Name">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The name of the playlist, typically given by the user.</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
<tp:member type="s" tp:type="Uri" name="Icon">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The URI of an (optional) icon.</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
</tp:struct>
|
||||
|
||||
<tp:struct name="Maybe_Playlist">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A data structure describing a playlist, or nothing.</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
D-Bus does not (at the time of writing) support a MAYBE type,
|
||||
so we are forced to invent our own.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
<tp:member type="b" name="Valid">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Whether this structure refers to a valid playlist.</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
<tp:member type="(oss)" tp:type="Playlist" name="Playlist">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The playlist, providing Valid is true, otherwise undefined.</p>
|
||||
<p>
|
||||
When constructing this type, it should be noted that the playlist
|
||||
ID must be a valid object path, or D-Bus implementations may reject
|
||||
it. This is true even when Valid is false. It is suggested that
|
||||
"/" is used as the playlist ID in this case.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
</tp:struct>
|
||||
|
||||
<tp:enum name="Playlist_Ordering" array-name="Playlist_Ordering_List" type="s">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Specifies the ordering of returned playlists.</p>
|
||||
</tp:docstring>
|
||||
<tp:enumvalue suffix="Alphabetical" value="Alphabetical">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Alphabetical ordering by name, ascending.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="CreationDate" value="Created">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Ordering by creation date, oldest first.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="ModifiedDate" value="Modified">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Ordering by last modified date, oldest first.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="LastPlayDate" value="Played">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Ordering by date of last playback, oldest first.</p>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="UserDefined" value="User">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A user-defined ordering.</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Some media players may allow users to order playlists as they
|
||||
wish. This ordering allows playlists to be retreived in that
|
||||
order.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
</tp:enum>
|
||||
|
||||
<method name="ActivatePlaylist" tp:name-for-bindings="Activate_Playlist">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Starts playing the given playlist.
|
||||
</p>
|
||||
<p>
|
||||
Note that this must be implemented. If the media player does not
|
||||
allow clients to change the playlist, it should not implement this
|
||||
interface at all.
|
||||
</p>
|
||||
<p>
|
||||
It is up to the media player whether this completely replaces the
|
||||
current tracklist, or whether it is merely inserted into the
|
||||
tracklist and the first track starts. For example, if the media
|
||||
player is operating in a "jukebox" mode, it may just append the
|
||||
playlist to the list of upcoming tracks, and skip to the first
|
||||
track in the playlist.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
<arg direction="in" name="PlaylistId" type="o">
|
||||
<tp:docstring>
|
||||
<p>The id of the playlist to activate.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="GetPlaylists" tp:name-for-bindings="Get_Playlists">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Gets a set of playlists.</p>
|
||||
</tp:docstring>
|
||||
<arg direction="in" name="Index" type="u">
|
||||
<tp:docstring>
|
||||
<p>The index of the first playlist to be fetched (according to the ordering).</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg direction="in" name="MaxCount" type="u">
|
||||
<tp:docstring>
|
||||
<p>The maximum number of playlists to fetch.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg direction="in" name="Order" type="s" tp:type="Playlist_Ordering">
|
||||
<tp:docstring>
|
||||
<p>The ordering that should be used.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg direction="in" name="ReverseOrder" type="b">
|
||||
<tp:docstring>
|
||||
<p>Whether the order should be reversed.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="PlaylistList"/>
|
||||
<arg direction="out" name="Playlists" type="a(oss)" tp:type="Playlist[]">
|
||||
<tp:docstring>
|
||||
<p>A list of (at most MaxCount) playlists.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<property name="PlaylistCount" type="u" tp:name-for-bindings="Playlist_Count" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The number of playlists available.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Orderings" tp:name-for-bindings="Orderings" type="as" tp:type="Playlist_Ordering[]" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The available orderings. At least one must be offered.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
Media players may not have access to all the data required for some
|
||||
orderings. For example, creation times are not available on UNIX
|
||||
filesystems (don't let the ctime fool you!). On the other hand,
|
||||
clients should have some way to get the "most recent" playlists.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="ActivePlaylist" type="(b(oss))" tp:name-for-bindings="Active_Playlist" tp:type="Maybe_Playlist" access="read">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName" value="PlaylistType"/>
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The currently-active playlist.
|
||||
</p>
|
||||
<p>
|
||||
If there is no currently-active playlist, the structure's Valid field
|
||||
will be false, and the Playlist details are undefined.
|
||||
</p>
|
||||
<p>
|
||||
Note that this may not have a value even after ActivatePlaylist is
|
||||
called with a valid playlist id as ActivatePlaylist implementations
|
||||
have the option of simply inserting the contents of the playlist into
|
||||
the current tracklist.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<signal name="PlaylistChanged" tp:name-for-bindings="Playlist_Changed">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="Playlist"/>
|
||||
<arg name="Playlist" type="(oss)" tp:type="Playlist">
|
||||
<tp:docstring>
|
||||
The playlist which details have changed.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Indicates that either the Name or Icon attribute of a
|
||||
playlist has changed.
|
||||
</p>
|
||||
<p>Client implementations should be aware that this signal
|
||||
may not be implemented.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
Without this signal, media players have no way to notify clients
|
||||
of a change in the attributes of a playlist other than the active one
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
<!-- vim:set sw=2 sts=2 et ft=xml: -->
|
||||
|
||||
@@ -1,352 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<node name="/Track_List_Interface" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
|
||||
<interface name="org.mpris.MediaPlayer2.TrackList">
|
||||
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Provides access to a short list of tracks which were recently played or
|
||||
will be played shortly. This is intended to provide context to the
|
||||
currently-playing track, rather than giving complete access to the
|
||||
media player's playlist.
|
||||
</p>
|
||||
<p>
|
||||
Example use cases are the list of tracks from the same album as the
|
||||
currently playing song or the
|
||||
<a href="http://projects.gnome.org/rhythmbox/">Rhythmbox</a> play queue.
|
||||
</p>
|
||||
<p>
|
||||
Each track in the tracklist has a unique identifier.
|
||||
The intention is that this uniquely identifies the track within
|
||||
the scope of the tracklist. In particular, if a media item
|
||||
(a particular music file, say) occurs twice in the track list, each
|
||||
occurrence should have a different identifier. If a track is removed
|
||||
from the middle of the playlist, it should not affect the track ids
|
||||
of any other tracks in the tracklist.
|
||||
</p>
|
||||
<p>
|
||||
As a result, the traditional track identifiers of URLs and position
|
||||
in the playlist cannot be used. Any scheme which satisfies the
|
||||
uniqueness requirements is valid, as clients should not make any
|
||||
assumptions about the value of the track id beyond the fact
|
||||
that it is a unique identifier.
|
||||
</p>
|
||||
<p>
|
||||
Note that the (memory and processing) burden of implementing the
|
||||
TrackList interface and maintaining unique track ids for the
|
||||
playlist can be mitigated by only exposing a subset of the playlist when
|
||||
it is very long (the 20 or so tracks around the currently playing
|
||||
track, for example). This is a recommended practice as the tracklist
|
||||
interface is not designed to enable browsing through a large list of tracks,
|
||||
but rather to provide clients with context about the currently playing track.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
|
||||
<tp:mapping name="Metadata_Map" array-name="Metadata_Map_List">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A mapping from metadata attribute names to values.</p>
|
||||
<p>
|
||||
The <b>mpris:trackid</b> attribute must always be present, and must be
|
||||
of D-Bus type "o". This contains a D-Bus path that uniquely identifies
|
||||
the track within the scope of the playlist. There may or may not be
|
||||
an actual D-Bus object at that path; this specification says nothing
|
||||
about what interfaces such an object may implement.
|
||||
</p>
|
||||
<p>
|
||||
If the length of the track is known, it should be provided in the
|
||||
metadata property with the "mpris:length" key. The length must be
|
||||
given in microseconds, and be represented as a signed 64-bit integer.
|
||||
</p>
|
||||
<p>
|
||||
If there is an image associated with the track, a URL for it may be
|
||||
provided using the "mpris:artUrl" key. For other metadata, fields
|
||||
defined by the
|
||||
<a href="http://xesam.org/main/XesamOntology">Xesam ontology</a>
|
||||
should be used, prefixed by "xesam:". See the
|
||||
<a href="http://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata">metadata page on the freedesktop.org wiki</a>
|
||||
for a list of common fields.
|
||||
</p>
|
||||
<p>
|
||||
Lists of strings should be passed using the array-of-string ("as")
|
||||
D-Bus type. Dates should be passed as strings using the ISO 8601
|
||||
extended format (eg: 2007-04-29T14:35:51). If the timezone is
|
||||
known, RFC 3339's internet profile should be used (eg:
|
||||
2007-04-29T14:35:51+02:00).
|
||||
</p>
|
||||
</tp:docstring>
|
||||
<tp:member type="s" name="Attribute">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The name of the attribute; see the
|
||||
<a href="http://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata">metadata page</a>
|
||||
for guidelines on names to use.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
<tp:member type="v" name="Value">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The value of the attribute, in the most appropriate format.</p>
|
||||
</tp:docstring>
|
||||
</tp:member>
|
||||
</tp:mapping>
|
||||
|
||||
<tp:simple-type name="Uri" type="s">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A unique resource identifier.</p>
|
||||
</tp:docstring>
|
||||
</tp:simple-type>
|
||||
|
||||
<method name="GetTracksMetadata" tp:name-for-bindings="Get_Tracks_Metadata">
|
||||
<arg direction="in" name="TrackIds" type="ao" tp:type="Track_Id[]">
|
||||
<tp:docstring>
|
||||
<p>The list of track ids for which metadata is requested.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MetadataMap"/>
|
||||
<arg direction="out" type="aa{sv}" tp:type="Metadata_Map[]" name="Metadata">
|
||||
<tp:docstring>
|
||||
<p>Metadata of the set of tracks given as input.</p>
|
||||
<p>See the type documentation for more details.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Gets all the metadata available for a set of tracks.</p>
|
||||
<p>
|
||||
Each set of metadata must have a "mpris:trackid" entry at the very least,
|
||||
which contains a string that uniquely identifies this track within
|
||||
the scope of the tracklist.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="AddTrack" tp:name-for-bindings="Add_Track">
|
||||
<arg direction="in" type="s" tp:type="Uri" name="Uri">
|
||||
<tp:docstring>
|
||||
<p>
|
||||
The uri of the item to add. Its uri scheme should be an element of the
|
||||
<strong>org.mpris.MediaPlayer2.SupportedUriSchemes</strong>
|
||||
property and the mime-type should match one of the elements of the
|
||||
<strong>org.mpris.MediaPlayer2.SupportedMimeTypes</strong>
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg direction="in" type="o" tp:type="Track_Id" name="AfterTrack">
|
||||
<tp:docstring>
|
||||
<p>
|
||||
The identifier of the track after which
|
||||
the new item should be inserted. The path
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
indicates that the track should be inserted at the
|
||||
start of the track list.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg direction="in" type="b" name="SetAsCurrent">
|
||||
<tp:docstring>
|
||||
<p>
|
||||
Whether the newly inserted track should be considered as
|
||||
the current track. Setting this to true has the same effect as
|
||||
calling GoTo afterwards.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Adds a URI in the TrackList.</p>
|
||||
<p>
|
||||
If the <tp:member-ref>CanEditTracks</tp:member-ref> property is false,
|
||||
this has no effect.
|
||||
</p>
|
||||
<p>
|
||||
Note: Clients should not assume that the track has been added at the
|
||||
time when this method returns. They should wait for a TrackAdded (or
|
||||
TrackListReplaced) signal.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="RemoveTrack" tp:name-for-bindings="Remove__Track">
|
||||
<arg direction="in" type="o" tp:type="Track_Id" name="TrackId">
|
||||
<tp:docstring>
|
||||
<p>Identifier of the track to be removed.</p>
|
||||
<p>
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
is <em>not</em> a valid value for this argument.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Removes an item from the TrackList.</p>
|
||||
<p>If the track is not part of this tracklist, this has no effect.</p>
|
||||
<p>
|
||||
If the <tp:member-ref>CanEditTracks</tp:member-ref> property is false,
|
||||
this has no effect.
|
||||
</p>
|
||||
<p>
|
||||
Note: Clients should not assume that the track has been removed at the
|
||||
time when this method returns. They should wait for a TrackRemoved (or
|
||||
TrackListReplaced) signal.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="GoTo" tp:name-for-bindings="Go_To">
|
||||
<arg direction="in" type="o" tp:type="Track_Id" name="TrackId">
|
||||
<tp:docstring>
|
||||
<p>Identifier of the track to skip to.</p>
|
||||
<p>
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
is <em>not</em> a valid value for this argument.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Skip to the specified TrackId.</p>
|
||||
<p>If the track is not part of this tracklist, this has no effect.</p>
|
||||
<p>
|
||||
If this object is not <strong>/org/mpris/MediaPlayer2</strong>,
|
||||
the current TrackList's tracks should be replaced with the contents of
|
||||
this TrackList, and the TrackListReplaced signal should be fired from
|
||||
<strong>/org/mpris/MediaPlayer2</strong>.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<property name="Tracks" type="ao" tp:type="Track_Id[]" tp:name-for-bindings="Tracks" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/>
|
||||
<tp:docstring>
|
||||
<p>
|
||||
An array which contains the identifier of each track
|
||||
in the tracklist, in order.
|
||||
</p>
|
||||
<p>
|
||||
The <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
|
||||
signal is emited every time this property changes, but the signal
|
||||
message does not contain the new value.
|
||||
|
||||
Client implementations should rather rely on the
|
||||
<tp:member-ref>TrackAdded</tp:member-ref>,
|
||||
<tp:member-ref>TrackRemoved</tp:member-ref> and
|
||||
<tp:member-ref>TrackListReplaced</tp:member-ref> signals to keep their
|
||||
representation of the tracklist up to date.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanEditTracks" type="b" tp:name-for-bindings="Can_Edit_Tracks" access="read">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
If <strong>false</strong>, calling
|
||||
<tp:member-ref>AddTrack</tp:member-ref> or
|
||||
<tp:member-ref>RemoveTrack</tp:member-ref> will have no effect,
|
||||
and may raise a NotSupported error.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<signal name="TrackListReplaced" tp:name-for-bindings="Track_List_Replaced">
|
||||
<arg name="Tracks" type="ao" tp:type="Track_Id[]">
|
||||
<tp:docstring>
|
||||
<p>The new content of the tracklist.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg name="CurrentTrack" type="o" tp:type="Track_Id">
|
||||
<tp:docstring>
|
||||
<p>The identifier of the track to be considered as current.</p>
|
||||
<p>
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
indicates that there is no current track.
|
||||
</p>
|
||||
<p>
|
||||
This should correspond to the <literal>mpris:trackid</literal> field of the
|
||||
Metadata property of the <literal>org.mpris.MediaPlayer2.Player</literal>
|
||||
interface.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Indicates that the entire tracklist has been replaced.</p>
|
||||
<p>
|
||||
It is left up to the implementation to decide when
|
||||
a change to the track list is invasive enough that
|
||||
this signal should be emitted instead of a series of
|
||||
TrackAdded and TrackRemoved signals.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
<signal name="TrackAdded" tp:name-for-bindings="Track_Added">
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MetadataMap"/>
|
||||
<arg type="a{sv}" tp:type="Metadata_Map" name="Metadata">
|
||||
<tp:docstring>
|
||||
<p>The metadata of the newly added item.</p>
|
||||
<p>This must include a mpris:trackid entry.</p>
|
||||
<p>See the type documentation for more details.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="o" tp:type="Track_Id" name="AfterTrack">
|
||||
<tp:docstring>
|
||||
<p>
|
||||
The identifier of the track after which the new track
|
||||
was inserted. The path
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
indicates that the track was inserted at the
|
||||
start of the track list.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Indicates that a track has been added to the track list.</p>
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
<signal name="TrackRemoved" tp:name-for-bindings="Track_Removed">
|
||||
<arg type="o" tp:type="Track_Id" name="TrackId">
|
||||
<tp:docstring>
|
||||
<p>The identifier of the track being removed.</p>
|
||||
<p>
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
is <em>not</em> a valid value for this argument.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Indicates that a track has been removed from the track list.</p>
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
<signal name="TrackMetadataChanged" tp:name-for-bindings="Track_Metadata_Changed">
|
||||
<arg type="o" tp:type="Track_Id" name="TrackId">
|
||||
<tp:docstring>
|
||||
<p>The id of the track which metadata has changed.</p>
|
||||
<p>If the track id has changed, this will be the old value.</p>
|
||||
<p>
|
||||
<literal>/org/mpris/MediaPlayer2/TrackList/NoTrack</literal>
|
||||
is <em>not</em> a valid value for this argument.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="MetadataMap"/>
|
||||
<arg type="a{sv}" tp:type="Metadata_Map" name="Metadata">
|
||||
<tp:docstring>
|
||||
<p>The new track metadata.</p>
|
||||
<p>
|
||||
This must include a mpris:trackid entry. If the track id has
|
||||
changed, this will be the new value.
|
||||
</p>
|
||||
<p>See the type documentation for more details.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Indicates that the metadata of a track in the tracklist has changed.
|
||||
</p>
|
||||
<p>
|
||||
This may indicate that a track has been replaced, in which case the
|
||||
mpris:trackid metadata entry is different from the TrackId argument.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
<!-- vim:set sw=2 sts=2 et ft=xml: -->
|
||||
@@ -1,198 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<node name="/Media_Player" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
|
||||
<interface name="org.mpris.MediaPlayer2">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
|
||||
|
||||
<method name="Raise" tp:name-for-bindings="Raise">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Brings the media player's user interface to the front using any
|
||||
appropriate mechanism available.
|
||||
</p>
|
||||
<p>
|
||||
The media player may be unable to control how its user interface
|
||||
is displayed, or it may not have a graphical user interface at all.
|
||||
In this case, the <tp:member-ref>CanRaise</tp:member-ref> property is
|
||||
<strong>false</strong> and this method does nothing.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<method name="Quit" tp:name-for-bindings="Quit">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Causes the media player to stop running.</p>
|
||||
<p>
|
||||
The media player may refuse to allow clients to shut it down.
|
||||
In this case, the <tp:member-ref>CanQuit</tp:member-ref> property is
|
||||
<strong>false</strong> and this method does nothing.
|
||||
</p>
|
||||
<p>
|
||||
Note: Media players which can be D-Bus activated, or for which there is
|
||||
no sensibly easy way to terminate a running instance (via the main
|
||||
interface or a notification area icon for example) should allow clients
|
||||
to use this method. Otherwise, it should not be needed.
|
||||
</p>
|
||||
<p>If the media player does not have a UI, this should be implemented.</p>
|
||||
</tp:docstring>
|
||||
</method>
|
||||
|
||||
<property name="CanQuit" type="b" tp:name-for-bindings="Can_Quit" access="read">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
If <strong>false</strong>, calling
|
||||
<tp:member-ref>Quit</tp:member-ref> will have no effect, and may
|
||||
raise a NotSupported error. If <strong>true</strong>, calling
|
||||
<tp:member-ref>Quit</tp:member-ref> will cause the media application
|
||||
to attempt to quit (although it may still be prevented from quitting
|
||||
by the user, for example).
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Fullscreen" type="b" tp:name-for-bindings="Fullscreen" access="readwrite">
|
||||
<tp:added version="2.2" />
|
||||
<annotation name="org.mpris.MediaPlayer2.property.optional" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>Whether the media player is occupying the fullscreen.</p>
|
||||
<p>
|
||||
This is typically used for videos. A value of <strong>true</strong>
|
||||
indicates that the media player is taking up the full screen.
|
||||
</p>
|
||||
<p>
|
||||
Media centre software may well have this value fixed to <strong>true</strong>
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanSetFullscreen</tp:member-ref> is <strong>true</strong>,
|
||||
clients may set this property to <strong>true</strong> to tell the media player
|
||||
to enter fullscreen mode, or to <strong>false</strong> to return to windowed
|
||||
mode.
|
||||
</p>
|
||||
<p>
|
||||
If <tp:member-ref>CanSetFullscreen</tp:member-ref> is <strong>false</strong>,
|
||||
then attempting to set this property should have no effect, and may raise
|
||||
an error. However, even if it is <strong>true</strong>, the media player
|
||||
may still be unable to fulfil the request, in which case attempting to set
|
||||
this property will have no effect (but should not raise an error).
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This allows remote control interfaces, such as LIRC or mobile devices like
|
||||
phones, to control whether a video is shown in fullscreen.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanSetFullscreen" type="b" tp:name-for-bindings="Can_Set_Fullscreen" access="read">
|
||||
<tp:added version="2.2" />
|
||||
<annotation name="org.mpris.MediaPlayer2.property.optional" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
If <strong>false</strong>, attempting to set
|
||||
<tp:member-ref>Fullscreen</tp:member-ref> will have no effect, and may
|
||||
raise an error. If <strong>true</strong>, attempting to set
|
||||
<tp:member-ref>Fullscreen</tp:member-ref> will not raise an error, and (if it
|
||||
is different from the current value) will cause the media player to attempt to
|
||||
enter or exit fullscreen mode.
|
||||
</p>
|
||||
<p>
|
||||
Note that the media player may be unable to fulfil the request.
|
||||
In this case, the value will not change. If the media player knows in
|
||||
advance that it will not be able to fulfil the request, however, this
|
||||
property should be <strong>false</strong>.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This allows clients to choose whether to display controls for entering
|
||||
or exiting fullscreen mode.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="CanRaise" type="b" tp:name-for-bindings="Can_Raise" access="read">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
If <strong>false</strong>, calling
|
||||
<tp:member-ref>Raise</tp:member-ref> will have no effect, and may
|
||||
raise a NotSupported error. If <strong>true</strong>, calling
|
||||
<tp:member-ref>Raise</tp:member-ref> will cause the media application
|
||||
to attempt to bring its user interface to the front, although it may
|
||||
be prevented from doing so (by the window manager, for example).
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="HasTrackList" type="b" tp:name-for-bindings="Has_TrackList" access="read">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
Indicates whether the <strong>/org/mpris/MediaPlayer2</strong>
|
||||
object implements the <strong>org.mpris.MediaPlayer2.TrackList</strong>
|
||||
interface.
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Identity" type="s" tp:name-for-bindings="Identity" access="read">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>A friendly name to identify the media player to users.</p>
|
||||
<p>This should usually match the name found in .desktop files</p>
|
||||
<p>(eg: "VLC media player").</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="DesktopEntry" type="s" tp:name-for-bindings="Desktop_Entry" access="read">
|
||||
<annotation name="org.mpris.MediaPlayer2.property.optional" value="true"/>
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>The basename of an installed .desktop file which complies with the <a href="http://standards.freedesktop.org/desktop-entry-spec/latest/">Desktop entry specification</a>,
|
||||
with the ".desktop" extension stripped.</p>
|
||||
<p>
|
||||
Example: The desktop entry file is "/usr/share/applications/vlc.desktop",
|
||||
and this property contains "vlc"
|
||||
</p>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="SupportedUriSchemes" type="as" tp:name-for-bindings="Supported_Uri_Schemes" access="read">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The URI schemes supported by the media player.
|
||||
</p>
|
||||
<p>
|
||||
This can be viewed as protocols supported by the player in almost
|
||||
all cases. Almost every media player will include support for the
|
||||
"file" scheme. Other common schemes are "http" and "rtsp".
|
||||
</p>
|
||||
<p>
|
||||
Note that URI schemes should be lower-case.
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This is important for clients to know when using the editing
|
||||
capabilities of the Playlist interface, for example.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="SupportedMimeTypes" type="as" tp:name-for-bindings="Supported_Mime_Types" access="read">
|
||||
<tp:docstring xmlns="http://www.w3.org/1999/xhtml">
|
||||
<p>
|
||||
The mime-types supported by the media player.
|
||||
</p>
|
||||
<p>
|
||||
Mime-types should be in the standard format (eg: audio/mpeg or
|
||||
application/ogg).
|
||||
</p>
|
||||
<tp:rationale>
|
||||
<p>
|
||||
This is important for clients to know when using the editing
|
||||
capabilities of the Playlist interface, for example.
|
||||
</p>
|
||||
</tp:rationale>
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
<!-- vim:set sw=2 sts=2 et ft=xml: -->
|
||||
@@ -1,176 +0,0 @@
|
||||
#include "mprisapplication.h"
|
||||
|
||||
#include <QDBusConnection>
|
||||
|
||||
#include "mediaplayer2adaptor.h"
|
||||
#include "playeradaptor.h"
|
||||
|
||||
struct MprisApplicationPrivate {
|
||||
std::unique_ptr<MediaPlayer2Adaptor> adaptor;
|
||||
bool canQuit = false;
|
||||
bool canRaise = false;
|
||||
bool canSetFullscreen = false;
|
||||
QString desktopEntry;
|
||||
bool fullscreen = false;
|
||||
bool hasTrackList = false;
|
||||
QString identity;
|
||||
QStringList supportedMimeTypes;
|
||||
QStringList supportedUriSchemes;
|
||||
};
|
||||
|
||||
MprisApplication::MprisApplication(const QString &appId, QObject *parent)
|
||||
: QObject(parent)
|
||||
, d(std::make_unique<MprisApplicationPrivate>())
|
||||
{
|
||||
d->adaptor = std::make_unique<MediaPlayer2Adaptor>(this);
|
||||
QDBusConnection::sessionBus().registerService(QStringLiteral("org.mpris.MediaPlayer2.") + appId);
|
||||
if (!QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/mpris/MediaPlayer2"), this)) {
|
||||
qWarning() << "Failed to register MPRIS interface";
|
||||
}
|
||||
}
|
||||
|
||||
MprisApplication::~MprisApplication() = default;
|
||||
|
||||
bool MprisApplication::canQuit() const
|
||||
{
|
||||
return d->canQuit;
|
||||
}
|
||||
|
||||
void MprisApplication::setCanQuit(bool canQuit)
|
||||
{
|
||||
if (d->canQuit == canQuit) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->canQuit = canQuit;
|
||||
Q_EMIT canQuitChanged();
|
||||
}
|
||||
|
||||
bool MprisApplication::canRaise() const
|
||||
{
|
||||
return d->canRaise;
|
||||
}
|
||||
|
||||
void MprisApplication::setCanRaise(bool canRaise)
|
||||
{
|
||||
if (d->canRaise == canRaise) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->canRaise = canRaise;
|
||||
Q_EMIT canRaiseChanged();
|
||||
}
|
||||
|
||||
bool MprisApplication::canSetFullscreen() const
|
||||
{
|
||||
return d->canSetFullscreen;
|
||||
}
|
||||
|
||||
void MprisApplication::setCanSetFullscreen(bool can)
|
||||
{
|
||||
if (d->canSetFullscreen == can) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->canSetFullscreen = can;
|
||||
Q_EMIT canSetFullscreenChanged();
|
||||
}
|
||||
|
||||
QString MprisApplication::desktopEntry() const
|
||||
{
|
||||
return d->desktopEntry;
|
||||
}
|
||||
|
||||
void MprisApplication::setDesktopEntry(const QString &entry)
|
||||
{
|
||||
if (d->desktopEntry == entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->desktopEntry = entry;
|
||||
Q_EMIT desktopEntryChanged();
|
||||
}
|
||||
|
||||
bool MprisApplication::fullscreen() const
|
||||
{
|
||||
return d->fullscreen;
|
||||
}
|
||||
|
||||
void MprisApplication::setFullscreen(bool value)
|
||||
{
|
||||
if (d->fullscreen == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->fullscreen = value;
|
||||
Q_EMIT fullscreenChanged();
|
||||
}
|
||||
|
||||
bool MprisApplication::hasTrackList() const
|
||||
{
|
||||
return d->hasTrackList;
|
||||
}
|
||||
|
||||
void MprisApplication::setHasTrackList(bool has)
|
||||
{
|
||||
if (d->hasTrackList == has) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->hasTrackList = has;
|
||||
Q_EMIT hasTrackListChanged();
|
||||
}
|
||||
|
||||
QString MprisApplication::identity() const
|
||||
{
|
||||
return d->identity;
|
||||
}
|
||||
|
||||
void MprisApplication::setIdentity(const QString &appName)
|
||||
{
|
||||
if (d->identity == appName) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->identity = appName;
|
||||
Q_EMIT identityChanged();
|
||||
}
|
||||
|
||||
QStringList MprisApplication::supportedMimeTypes() const
|
||||
{
|
||||
return d->supportedMimeTypes;
|
||||
}
|
||||
|
||||
void MprisApplication::setSupportedMimeTypes(const QStringList &types) {
|
||||
if (d->supportedMimeTypes == types) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->supportedMimeTypes = types;
|
||||
Q_EMIT supportedMimeTypesChanged();
|
||||
}
|
||||
|
||||
QStringList MprisApplication::supportedUriSchemes() const
|
||||
{
|
||||
return d->supportedUriSchemes;
|
||||
}
|
||||
|
||||
void MprisApplication::setSupportedUriSchemes(const QStringList &schemes)
|
||||
{
|
||||
if (d->supportedUriSchemes == schemes) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->supportedMimeTypes = schemes;
|
||||
Q_EMIT supportedUriSchemesChanged();
|
||||
}
|
||||
|
||||
void MprisApplication::Quit()
|
||||
{
|
||||
Q_EMIT quitRequested();
|
||||
}
|
||||
|
||||
void MprisApplication::Raise()
|
||||
{
|
||||
Q_EMIT raiseRequested();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
#ifndef MPRISAPPLICATION_H
|
||||
#define MPRISAPPLICATION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct MprisApplicationPrivate;
|
||||
|
||||
class MprisApplication : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
// DBus property names
|
||||
Q_PROPERTY(bool CanQuit READ canQuit NOTIFY canQuitChanged)
|
||||
Q_PROPERTY(bool CanRaise READ canRaise NOTIFY canRaiseChanged)
|
||||
Q_PROPERTY(bool CanSetFullscreen READ canSetFullscreen NOTIFY canSetFullscreenChanged)
|
||||
Q_PROPERTY(QString DesktopEntry READ desktopEntry NOTIFY desktopEntryChanged)
|
||||
Q_PROPERTY(bool Fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
|
||||
Q_PROPERTY(bool HasTrackList READ hasTrackList NOTIFY hasTrackListChanged)
|
||||
Q_PROPERTY(QString Identity READ identity NOTIFY identityChanged)
|
||||
Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes NOTIFY supportedMimeTypesChanged)
|
||||
Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes NOTIFY supportedUriSchemes)
|
||||
|
||||
// QML property names
|
||||
Q_PROPERTY(bool canQuit READ canQuit WRITE setCanQuit NOTIFY canQuitChanged)
|
||||
Q_PROPERTY(bool canRaise READ canRaise WRITE setCanRaise NOTIFY canRaiseChanged)
|
||||
Q_PROPERTY(bool canSetFullscreen READ canSetFullscreen NOTIFY canSetFullscreenChanged)
|
||||
Q_PROPERTY(QString desktopEntry READ desktopEntry NOTIFY desktopEntryChanged)
|
||||
Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
|
||||
Q_PROPERTY(bool hasTrackList READ hasTrackList NOTIFY hasTrackListChanged)
|
||||
Q_PROPERTY(QString identity READ identity NOTIFY identityChanged)
|
||||
Q_PROPERTY(QStringList supportedMimeTypes READ supportedMimeTypes NOTIFY supportedMimeTypesChanged)
|
||||
Q_PROPERTY(QStringList supportedUriSchemes READ supportedUriSchemes NOTIFY supportedUriSchemes)
|
||||
|
||||
friend class MediaPlayer2Adaptor;
|
||||
|
||||
public:
|
||||
explicit MprisApplication(const QString &appId, QObject *parent = nullptr);
|
||||
~MprisApplication();
|
||||
|
||||
bool canQuit() const;
|
||||
void setCanQuit(bool canQuit);
|
||||
Q_SIGNAL void canQuitChanged();
|
||||
|
||||
bool canRaise() const;
|
||||
void setCanRaise(bool canRaise);
|
||||
Q_SIGNAL void canRaiseChanged();
|
||||
|
||||
bool canSetFullscreen() const;
|
||||
void setCanSetFullscreen(bool can);
|
||||
Q_SIGNAL void canSetFullscreenChanged();
|
||||
|
||||
QString desktopEntry() const;
|
||||
void setDesktopEntry(const QString &entry);
|
||||
Q_SIGNAL void desktopEntryChanged();
|
||||
|
||||
bool fullscreen() const;
|
||||
void setFullscreen(bool value);
|
||||
Q_SIGNAL void fullscreenChanged();
|
||||
|
||||
bool hasTrackList() const;
|
||||
void setHasTrackList(bool has);
|
||||
Q_SIGNAL void hasTrackListChanged();
|
||||
|
||||
QString identity() const;
|
||||
void setIdentity(const QString &appName);
|
||||
Q_SIGNAL void identityChanged();
|
||||
|
||||
QStringList supportedMimeTypes() const;
|
||||
void setSupportedMimeTypes(const QStringList &types);
|
||||
Q_SIGNAL void supportedMimeTypesChanged();
|
||||
|
||||
QStringList supportedUriSchemes() const;
|
||||
void setSupportedUriSchemes(const QStringList &schemes);
|
||||
Q_SIGNAL void supportedUriSchemesChanged();
|
||||
|
||||
protected:
|
||||
void Quit();
|
||||
void Raise();
|
||||
|
||||
Q_SIGNALS:
|
||||
void quitRequested();
|
||||
void raiseRequested();
|
||||
|
||||
private:
|
||||
std::unique_ptr<MprisApplicationPrivate> d;
|
||||
};
|
||||
|
||||
#endif // MPRISAPPLICATION_H
|
||||
@@ -1,60 +0,0 @@
|
||||
#include "mprisplayer.h"
|
||||
|
||||
#include <playeradaptor.h>
|
||||
|
||||
MprisPlayer::MprisPlayer(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_adaptor(std::make_unique<PlayerAdaptor>(this))
|
||||
{
|
||||
QDBusConnection::sessionBus().registerService(QStringLiteral("org.mpris.MediaPlayer2.") + "audiotube");
|
||||
if (!QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/mpris/MediaPlayer2"), this)) {
|
||||
qWarning() << "Failed to register MPRIS interface";
|
||||
}
|
||||
}
|
||||
|
||||
void MprisPlayer::Next()
|
||||
{
|
||||
Q_EMIT nextRequested();
|
||||
}
|
||||
|
||||
void MprisPlayer::OpenUri(const QString &uri)
|
||||
{
|
||||
Q_EMIT openUriRequested(uri);
|
||||
}
|
||||
|
||||
void MprisPlayer::Pause()
|
||||
{
|
||||
Q_EMIT pauseRequested();
|
||||
}
|
||||
|
||||
void MprisPlayer::Play()
|
||||
{
|
||||
Q_EMIT playRequested();
|
||||
}
|
||||
|
||||
void MprisPlayer::PlayPause()
|
||||
{
|
||||
Q_EMIT playPauseRequested();
|
||||
}
|
||||
|
||||
void MprisPlayer::Previous()
|
||||
{
|
||||
Q_EMIT previousRequested();
|
||||
}
|
||||
|
||||
void MprisPlayer::Seek(qlonglong offset)
|
||||
{
|
||||
Q_EMIT seekRequested(offset);
|
||||
}
|
||||
|
||||
void MprisPlayer::SetPosition(const QDBusObjectPath &trackId, qlonglong position)
|
||||
{
|
||||
Q_EMIT setPositionRequested(MprisTrack {}, position); // TODO write MprisTrack class
|
||||
}
|
||||
|
||||
void MprisPlayer::Stop()
|
||||
{
|
||||
Q_EMIT stopRequested();
|
||||
}
|
||||
|
||||
MprisPlayer::~MprisPlayer() = default;
|
||||
Loaded 100 of 117 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user