├── .editorconfig ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── lint-and-format.yml ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── assets ├── dbus │ ├── mprisNode.xml │ └── watchNode.xml ├── images │ ├── ego.png │ ├── popup.png │ ├── prefs_general.png │ ├── prefs_other.png │ ├── prefs_panel.png │ ├── prefs_positions.png │ └── prefs_shortcuts.png ├── locale │ ├── be.po │ ├── ca.po │ ├── cs.po │ ├── de.po │ ├── es.po │ ├── mediacontrols@cliffniff.github.com.pot │ ├── pt_BR.po │ └── ru.po ├── org.gnome.shell.extensions.mediacontrols.gresource.xml ├── org.gnome.shell.extensions.mediacontrols.gschema.xml └── ui │ ├── app-chooser.blp │ ├── blacklisted-players.blp │ ├── element-list.blp │ ├── label-list.blp │ └── prefs.blp ├── mediacontrols.sh ├── package.json ├── pnpm-lock.yaml ├── src ├── extension.ts ├── helpers │ ├── prefs │ │ ├── AppChooser.ts │ │ ├── BlacklistedPlayers.ts │ │ ├── ElementList.ts │ │ └── LabelList.ts │ └── shell │ │ ├── MenuSlider.ts │ │ ├── PanelButton.ts │ │ ├── PlayerProxy.ts │ │ └── ScrollingLabel.ts ├── index.d.ts ├── metadata.json ├── prefs.ts ├── stylesheet.css ├── types │ ├── dbus.ts │ ├── enums │ │ ├── common.ts │ │ └── shell_only.ts │ └── misc.ts └── utils │ ├── common.ts │ ├── prefs_only.ts │ └── shell_only.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | indent_style = space 10 | indent_size = 2 11 | 12 | [*.{js,ts,css}] 13 | indent_size = 4 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:import/recommended", "plugin:import/typescript"], 4 | "plugins": ["@typescript-eslint", "only-warn"], 5 | "parser": "@typescript-eslint/parser", 6 | "env": { 7 | "es2021": true 8 | }, 9 | "parserOptions": { 10 | "ecmaVersion": 2022, 11 | "sourceType": "module" 12 | }, 13 | "globals": { 14 | "ARGV": "readonly", 15 | "Debugger": "readonly", 16 | "GIRepositoryGType": "readonly", 17 | "globalThis": "readonly", 18 | "imports": "readonly", 19 | "Intl": "readonly", 20 | "log": "readonly", 21 | "logError": "readonly", 22 | "pkg": "readonly", 23 | "print": "readonly", 24 | "printerr": "readonly", 25 | "window": "readonly", 26 | "TextEncoder": "readonly", 27 | "TextDecoder": "readonly", 28 | "console": "readonly", 29 | "setTimeout": "readonly", 30 | "setInterval": "readonly", 31 | "clearTimeout": "readonly", 32 | "clearInterval": "readonly" 33 | }, 34 | "rules": { 35 | "import/extensions": ["error", "ignorePackages"], 36 | "import/no-unresolved": "off", 37 | "max-len": [ 38 | "warn", 39 | { 40 | "code": 140, 41 | "ignoreComments": true, 42 | "ignoreStrings": true, 43 | "ignoreTemplateLiterals": true, 44 | "ignoreRegExpLiterals": true 45 | } 46 | ], 47 | "no-use-before-define": [ 48 | "error", 49 | { 50 | "functions": false, 51 | "classes": true, 52 | "variables": true, 53 | "allowNamedExports": true 54 | } 55 | ], 56 | "no-restricted-globals": [ 57 | "error", 58 | { 59 | "name": "Debugger", 60 | "message": "Internal use only" 61 | }, 62 | { 63 | "name": "GIRepositoryGType", 64 | "message": "Internal use only" 65 | }, 66 | { 67 | "name": "log", 68 | "message": "Use debugLog()" 69 | }, 70 | { 71 | "name": "logError", 72 | "message": "Use errorLog()" 73 | } 74 | ], 75 | "no-restricted-properties": [ 76 | "error", 77 | { 78 | "object": "imports", 79 | "property": "format", 80 | "message": "Use template strings" 81 | }, 82 | { 83 | "object": "pkg", 84 | "property": "initFormat", 85 | "message": "Use template strings" 86 | }, 87 | { 88 | "object": "Lang", 89 | "property": "copyProperties", 90 | "message": "Use Object.assign()" 91 | }, 92 | { 93 | "object": "Lang", 94 | "property": "bind", 95 | "message": "Use arrow notation or Function.prototype.bind()" 96 | }, 97 | { 98 | "object": "Lang", 99 | "property": "Class", 100 | "message": "Use ES6 classes" 101 | } 102 | ], 103 | "no-restricted-syntax": [ 104 | "error", 105 | { 106 | "selector": "MethodDefinition[key.name=\"_init\"] CallExpression[arguments.length<=1][callee.object.type=\"Super\"][callee.property.name=\"_init\"]", 107 | "message": "Use constructor() and super()" 108 | } 109 | ], 110 | "no-constant-condition": [ 111 | "warn", 112 | { 113 | "checkLoops": false 114 | } 115 | ] 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Environment:** 27 | - Distro: [e.g. Ubuntu 23.10] 28 | - GNOME version [e.g. 43, 45] 29 | - Extension Version [e.g. 2.0.0] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/lint-and-format.yml: -------------------------------------------------------------------------------- 1 | name: Lint and format 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | lint: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: Install packages 18 | uses: pnpm/action-setup@v2 19 | with: 20 | version: 8 21 | run_install: true 22 | 23 | - name: Lint 24 | run: ./mediacontrols.sh lint 25 | format: 26 | runs-on: ubuntu-latest 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v3 31 | 32 | - name: Install packages 33 | uses: pnpm/action-setup@v2 34 | with: 35 | version: 8 36 | run_install: true 37 | 38 | - name: Format 39 | run: ./mediacontrols.sh format 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .vscode 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "bracketSameLine": true, 4 | "quoteProps": "consistent", 5 | "singleQuote": false 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Marcus Heine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## What does this extension do? 2 | 3 | Show controls and information of the currently playing media in the panel. 4 | 5 | ## Features 6 | 7 | - Customize the extension the way you want it 8 | - Basic media controls (play/pause/next/previous/loop/shuffle/seek) 9 | - Mouse actions lets you run different actions via left/middle/right/scroll. 10 | - Popup with album art and a slider to control the playback 11 | - Scrolling animations 12 | - Blacklist players 13 | 14 | --- 15 | 16 | ## How to install 17 | 18 | #### Install from extensions.gnome.org (Recommended) 19 | 20 | [](https://extensions.gnome.org/extension/4470/media-controls/) 21 | 22 | #### Manual installation 23 | 24 | Install from source 25 | 26 | - Download archive file from the releases tab 27 | - Open a terminal in the directory containing the downloaded file 28 | - Install and enable the extension by executing `gnome-extensions install extension.zip --force` in the terminal 29 | 30 | --- 31 | 32 | ## Reporting issues 33 | 34 | - Make sure your issue isn't a duplicate 35 | - Include the following information when creating the issue, 36 | - Extension version 37 | - Gnome version 38 | - Your distribution 39 | - A screenshot if it is possible 40 | 41 | --- 42 | 43 | ## Get involved 44 | 45 | Any type of contribution is appreciated! If you have any suggestions for new features feel free to open a new issue. 46 | 47 | If you are interested in translating, download the [po file](https://github.com/sakithb/media-controls/blob/main/assets/locale/mediacontrols%40cliffniff.github.com.pot) and translate it. Then open a pull request with the translated file. You can use [Gtranslator](https://flathub.org/apps/org.gnome.Gtranslator) or [Poedit](https://flathub.org/apps/net.poedit.Poedit) to translate. 48 | 49 | If you are interested in contributing code. There are no specific guidelines for contributing. Just make sure you follow the coding style of the project. To update the translation files run `./mediacontrols.sh translations` in the extensions directory after your changes are done. This will update the files in the locale folder. 50 | 51 | 52 | 53 | 54 | 55 | Made with [contrib.rocks](https://contrib.rocks). 56 | 57 | ## Screenshots 58 | 59 | #### Popup menu 60 | 61 | []() 62 | 63 | #### General settings 64 | 65 | []() 66 | 67 | #### Panel settings 68 | 69 | []() 70 | 71 | #### Position settings 72 | 73 | []() 74 | 75 | #### Shortcut settings 76 | 77 | []() 78 | 79 | #### Other settings 80 | 81 | []() 82 | -------------------------------------------------------------------------------- /assets/dbus/mprisNode.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /assets/dbus/watchNode.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /assets/images/ego.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/ego.png -------------------------------------------------------------------------------- /assets/images/popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/popup.png -------------------------------------------------------------------------------- /assets/images/prefs_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/prefs_general.png -------------------------------------------------------------------------------- /assets/images/prefs_other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/prefs_other.png -------------------------------------------------------------------------------- /assets/images/prefs_panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/prefs_panel.png -------------------------------------------------------------------------------- /assets/images/prefs_positions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/prefs_positions.png -------------------------------------------------------------------------------- /assets/images/prefs_shortcuts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakithb/media-controls/c42949c378de1e238f148d72d06da8c5ae8c5b27/assets/images/prefs_shortcuts.png -------------------------------------------------------------------------------- /assets/locale/be.po: -------------------------------------------------------------------------------- 1 | # Belaruasian translation for Media Controls. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR Aliaksei Piatrouski , 2025. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: \n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 11 | "PO-Revision-Date: 2025-05-15 17:58+0200\n" 12 | "Last-Translator: Aliaksei Piatrouski \n" 13 | "Language-Team: Belarusian\n" 14 | "Language: be\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || " 19 | "n%100>=20) ? 1 : 2);\n" 20 | "X-Generator: Poedit 3.6\n" 21 | 22 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 src/prefs.ts:203 src/prefs.ts:205 23 | #: src/prefs.ts:202 24 | msgid "Are you sure you want to clear the cache?" 25 | msgstr "Упэўнены, што хочаце ачысціць кэш?" 26 | 27 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 src/prefs.ts:196 src/prefs.ts:195 28 | #: src/prefs.ts:204 src/prefs.ts:206 src/prefs.ts:203 assets/ui/app-chooser.blp:21 29 | msgid "Cancel" 30 | msgstr "Скасаваць" 31 | 32 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 src/prefs.ts:196 33 | #: src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 assets/ui/prefs.blp:255 34 | msgid "Clear cache" 35 | msgstr "Ачысціць кэш" 36 | 37 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 src/prefs.ts:204 src/prefs.ts:213 38 | #: src/prefs.ts:203 src/prefs.ts:212 src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 39 | #: src/prefs.ts:220 40 | #, javascript-format 41 | msgid "Cache size: %s" 42 | msgstr "Памер кэша: %s" 43 | 44 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 src/prefs.ts:304 src/prefs.ts:306 45 | #: src/prefs.ts:303 46 | msgid "Cache cleared successfully!" 47 | msgstr "Кэш паспяхова ачышчаны!" 48 | 49 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 src/prefs.ts:306 src/prefs.ts:308 50 | #: src/prefs.ts:305 51 | msgid "Failed to clear cache!" 52 | msgstr "Не ўдалося ачысціць кэш!" 53 | 54 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 55 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 src/helpers/prefs/BlacklistedPlayers.ts:50 56 | msgid "No players are blacklisted" 57 | msgstr "Няма прайгравальнікаў у чорным спісе" 58 | 59 | #: src/helpers/LabelList.ts:9 60 | msgid "Artist" 61 | msgstr "Выканаўца" 62 | 63 | #: src/helpers/LabelList.ts:10 64 | msgid "Title" 65 | msgstr "Назва" 66 | 67 | #: src/helpers/LabelList.ts:11 68 | msgid "Album" 69 | msgstr "Альбом" 70 | 71 | #: src/helpers/LabelList.ts:12 72 | msgid "Disc Number" 73 | msgstr "Нумар дыска" 74 | 75 | #: src/helpers/LabelList.ts:13 76 | msgid "Track Number" 77 | msgstr "Нумар трэка" 78 | 79 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 80 | msgid "Select app to blacklist" 81 | msgstr "Выберыце праграму для дадання ў чорны спіс" 82 | 83 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 84 | msgid "Select" 85 | msgstr "Выбраць" 86 | 87 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 88 | msgid "Blacklist players" 89 | msgstr "Чорны спіс прайгравальнікаў" 90 | 91 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 92 | msgid "Blacklisted players will be ignored by the extension." 93 | msgstr "Прайгравальнікі з чорнага спісу будуць ігнаравацца пашырэннем." 94 | 95 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 96 | msgid "Add" 97 | msgstr "Дадаць" 98 | 99 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 100 | msgid "Elements" 101 | msgstr "Элементы" 102 | 103 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 assets/ui/element-list.blp:14 104 | #: assets/ui/prefs.blp:136 105 | msgid "Player icon" 106 | msgstr "Значок прайгравальніка" 107 | 108 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 assets/ui/element-list.blp:24 109 | #: assets/ui/label-list.blp:7 110 | msgid "Label" 111 | msgstr "Метка" 112 | 113 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 assets/ui/element-list.blp:34 114 | #: assets/ui/prefs.blp:102 115 | msgid "Player controls" 116 | msgstr "Кіраванне прайгравальнікам" 117 | 118 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 119 | msgid "Add item" 120 | msgstr "Дадаць элемент" 121 | 122 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 123 | msgid "Add custom text" 124 | msgstr "Дадаць уласны тэкст" 125 | 126 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 127 | msgid "General" 128 | msgstr "Агульныя" 129 | 130 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 131 | msgid "Common" 132 | msgstr "Асноўныя" 133 | 134 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 135 | msgid "Labels" 136 | msgstr "Меткі" 137 | 138 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 139 | msgid "Customize the labels in the panel and the popup menu" 140 | msgstr "Наладзіць меткі на панэлі і ва ўсплываючым меню" 141 | 142 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 143 | msgid "Fixed width" 144 | msgstr "Фіксаваная шырыня" 145 | 146 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 147 | msgid "Use the specified width even when they are smaller than the width" 148 | msgstr "Выкарыстоўваць зададзеную шырыню, нават калі яна меншая за патрэбную" 149 | 150 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 151 | msgid "Scroll labels" 152 | msgstr "Пракручваць меткі" 153 | 154 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 155 | msgid "Scroll the labels when they are wider than the width" 156 | msgstr "Пракручваць меткі, калі яны шырэйшыя за зададзеную шырыню" 157 | 158 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 159 | msgid "Hide the media notification" 160 | msgstr "Схаваць апавяшчэнне аб медыя" 161 | 162 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 163 | msgid "Hide the media notifications in the notification list" 164 | msgstr "Схаваць апавяшчэнні аб медыя ў спісе апавяшчэнняў" 165 | 166 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 167 | msgid "Information" 168 | msgstr "Інфармацыя" 169 | 170 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 171 | msgid "Homepage" 172 | msgstr "Хатняя старонка" 173 | 174 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 175 | msgid "Release notes" 176 | msgstr "Заўвагі да выпуску" 177 | 178 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 assets/ui/prefs.blp:82 179 | msgid "Report an issue" 180 | msgstr "Паведаміць аб праблеме" 181 | 182 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 183 | msgid "Panel" 184 | msgstr "Панэль" 185 | 186 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 187 | msgid "Show label" 188 | msgstr "Паказваць метку" 189 | 190 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 191 | msgid "Show player controls" 192 | msgstr "Паказваць элементы кіравання прайгравальнікам" 193 | 194 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 195 | msgid "Show play/pause button" 196 | msgstr "Паказваць кнопку прайгравання/паўзы" 197 | 198 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 199 | msgid "Show next track button" 200 | msgstr "Паказваць кнопку наступнага трэка" 201 | 202 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 203 | msgid "Show previous track button" 204 | msgstr "Паказваць кнопку папярэдняга трэка" 205 | 206 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 207 | msgid "Show seek forward button" 208 | msgstr "Паказваць кнопку перамоткі наперад" 209 | 210 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 211 | msgid "Show seek back button" 212 | msgstr "Паказваць кнопку перамоткі назад" 213 | 214 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 215 | msgid "Show player icon" 216 | msgstr "Паказваць значок прайгравальніка" 217 | 218 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 219 | msgid "Colored player icon" 220 | msgstr "Каляровы значок прайгравальніка" 221 | 222 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 223 | msgid "Positions" 224 | msgstr "Пазіцыі" 225 | 226 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 227 | msgid "Extension" 228 | msgstr "Пашырэнне" 229 | 230 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 231 | msgid "Position" 232 | msgstr "Пазіцыя" 233 | 234 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 235 | msgid "Position of the extension in the panel" 236 | msgstr "Пазіцыя пашырэння на панэлі" 237 | 238 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 239 | msgid "Left" 240 | msgstr "Злева" 241 | 242 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 243 | msgid "Center" 244 | msgstr "Па цэнтры" 245 | 246 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 247 | msgid "Right" 248 | msgstr "Справа" 249 | 250 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 251 | msgid "Index" 252 | msgstr "Індэкс" 253 | 254 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 255 | msgid "Index of the extension" 256 | msgstr "Індэкс пашырэння" 257 | 258 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 259 | msgid "Shortcuts" 260 | msgstr "Скароты" 261 | 262 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 assets/ui/prefs.blp:320 263 | msgid "Show popup menu" 264 | msgstr "Паказаць меню" 265 | 266 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 267 | msgid "Shortcut to toggle the popup menu" 268 | msgstr "Скарот для пераключэння ўсплываючага меню" 269 | 270 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 assets/ui/prefs.blp:277 271 | msgid "Set shortcut" 272 | msgstr "Усталяваць скарот" 273 | 274 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 275 | msgid "Mouse actions" 276 | msgstr "Дзеянні мышы" 277 | 278 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 279 | msgid "Left click / Tap" 280 | msgstr "Левы клік / Націск" 281 | 282 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 283 | msgid "Middle click" 284 | msgstr "Сярэдні клік" 285 | 286 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 287 | msgid "Right click" 288 | msgstr "Правы клік" 289 | 290 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 291 | msgid "Double click / Double tap" 292 | msgstr "Двайны клік / Двайны націск" 293 | 294 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 295 | msgid "Scroll up / Swipe right" 296 | msgstr "Пракрутка ўверх / Правядзенне направа" 297 | 298 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 299 | msgid "Scroll down / Swipe left" 300 | msgstr "Пракрутка ўніз / Правядзенне налева" 301 | 302 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 303 | msgid "Other" 304 | msgstr "Іншае" 305 | 306 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 307 | msgid "Cache" 308 | msgstr "Кэш" 309 | 310 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 311 | msgid "This extension cache album art to improve performance. You can clear the cache here." 312 | msgstr "Гэтае пашырэнне кэшуе вокладкі альбомаў для паляпшэння прадукцыйнасці. Вы можаце ачысціць кэш тут." 313 | 314 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 315 | msgid "Cache album art" 316 | msgstr "Кэшаваць вокладкі альбомаў" 317 | 318 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 319 | msgid "Clear" 320 | msgstr "Ачысціць" 321 | 322 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 323 | msgid "" 324 | "Press escape to cancel.\n" 325 | "Press enter to set the shortcut.\n" 326 | "Press backspace to reset." 327 | msgstr "" 328 | "Націсніце escape, каб скасаваць.\n" 329 | "Націсніце enter, каб усталяваць скарот.\n" 330 | "Націсніце backspace, каб скінуць." 331 | 332 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 333 | msgid "Press shortcut" 334 | msgstr "Націсніце скарот" 335 | 336 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 337 | msgid "None" 338 | msgstr "Няма" 339 | 340 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 341 | msgid "Play/Pause" 342 | msgstr "Прайграць/Паўза" 343 | 344 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 345 | msgid "Play" 346 | msgstr "Прайграць" 347 | 348 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 349 | msgid "Pause" 350 | msgstr "Паўза" 351 | 352 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 353 | msgid "Next track" 354 | msgstr "Наступны трэк" 355 | 356 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 357 | msgid "Previous track" 358 | msgstr "Папярэдні трэк" 359 | 360 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 361 | msgid "Volume up" 362 | msgstr "Павелічэнне гучнасці" 363 | 364 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 365 | msgid "Volume down" 366 | msgstr "Памяншэнне гучнасці" 367 | 368 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 369 | msgid "Toggle loop" 370 | msgstr "Пераключыць паўтор" 371 | 372 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 373 | msgid "Toggle shuffle" 374 | msgstr "Пераключыць перамешванне" 375 | 376 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 377 | msgid "Raise player" 378 | msgstr "Узняць прайгравальнік на першы план" 379 | 380 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 381 | msgid "Quit player" 382 | msgstr "Выйсці з прайгравальніка" 383 | 384 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 385 | msgid "Open preferences" 386 | msgstr "Адкрыць налады" 387 | 388 | #: src/helpers/prefs/LabelList.ts:97 389 | msgid "Custom text" 390 | msgstr "Уласны тэкст" 391 | 392 | #: assets/ui/prefs.blp:20 393 | msgid "Width" 394 | msgstr "Шырыня" 395 | 396 | #: assets/ui/prefs.blp:21 397 | msgid "0 to take all available space" 398 | msgstr "0, каб заняць усю даступную прастору" 399 | 400 | #: src/helpers/shell/PanelButton.ts:258 401 | msgid "Unknown player" 402 | msgstr "Невядомы прайгравальнік" 403 | 404 | #: src/helpers/shell/PanelButton.ts:434 405 | msgid "Unknown artist" 406 | msgstr "Невядомы выканаўца" 407 | 408 | #: src/helpers/shell/PanelButton.ts:745 409 | msgid "Unknown album" 410 | msgstr "Невядомы альбом" 411 | -------------------------------------------------------------------------------- /assets/locale/ca.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 12 | "PO-Revision-Date: 2024-04-30 00:34-0600\n" 13 | "Last-Translator: \n" 14 | "Language-Team: \n" 15 | "Language: ca\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "X-Generator: Poedit 3.4.2\n" 20 | 21 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 22 | #: src/prefs.ts:203 src/prefs.ts:205 src/prefs.ts:202 23 | msgid "Are you sure you want to clear the cache?" 24 | msgstr "Segur que voleu netejar la memòria cau?" 25 | 26 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 27 | #: src/prefs.ts:196 src/prefs.ts:195 src/prefs.ts:204 src/prefs.ts:206 28 | #: src/prefs.ts:203 assets/ui/app-chooser.blp:21 29 | msgid "Cancel" 30 | msgstr "Cancel·la" 31 | 32 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 33 | #: src/prefs.ts:196 src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 34 | #: assets/ui/prefs.blp:255 35 | msgid "Clear cache" 36 | msgstr "Neteja la memòria cau" 37 | 38 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 39 | #: src/prefs.ts:204 src/prefs.ts:213 src/prefs.ts:203 src/prefs.ts:212 40 | #: src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 41 | #: src/prefs.ts:220 42 | #, javascript-format 43 | msgid "Cache size: %s" 44 | msgstr "Mida de la memòria cau: %s" 45 | 46 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 47 | #: src/prefs.ts:304 src/prefs.ts:306 src/prefs.ts:303 48 | msgid "Cache cleared successfully!" 49 | msgstr "S’ha netejat la memòria cau correctament." 50 | 51 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 52 | #: src/prefs.ts:306 src/prefs.ts:308 src/prefs.ts:305 53 | msgid "Failed to clear cache!" 54 | msgstr "No s’ha pogut netejar la memòria cau." 55 | 56 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 57 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 58 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 59 | msgid "" 60 | "No players are blacklisted" 62 | msgstr "" 63 | "No s’ha vetat cap " 64 | "reproductor" 65 | 66 | #: src/helpers/LabelList.ts:9 67 | msgid "Artist" 68 | msgstr "Artista" 69 | 70 | #: src/helpers/LabelList.ts:10 71 | msgid "Title" 72 | msgstr "Títol" 73 | 74 | #: src/helpers/LabelList.ts:11 75 | msgid "Album" 76 | msgstr "Àlbum" 77 | 78 | #: src/helpers/LabelList.ts:12 79 | msgid "Disc Number" 80 | msgstr "Número de disc" 81 | 82 | #: src/helpers/LabelList.ts:13 83 | msgid "Track Number" 84 | msgstr "Número de peça" 85 | 86 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 87 | msgid "Select app to blacklist" 88 | msgstr "Seleccioneu l’aplicació a vetar" 89 | 90 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 91 | msgid "Select" 92 | msgstr "Selecciona" 93 | 94 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 95 | msgid "Blacklist players" 96 | msgstr "Veta reproductors" 97 | 98 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 99 | msgid "Blacklisted players will be ignored by the extension." 100 | msgstr "L’extensió ignorarà els reproductors vetats." 101 | 102 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 103 | msgid "Add" 104 | msgstr "Afegeix" 105 | 106 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 107 | msgid "Elements" 108 | msgstr "Elements" 109 | 110 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 111 | #: assets/ui/element-list.blp:14 assets/ui/prefs.blp:136 112 | msgid "Player icon" 113 | msgstr "Icona del reproductor" 114 | 115 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 116 | #: assets/ui/element-list.blp:24 assets/ui/label-list.blp:7 117 | msgid "Label" 118 | msgstr "Etiqueta" 119 | 120 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 121 | #: assets/ui/element-list.blp:34 assets/ui/prefs.blp:102 122 | msgid "Player controls" 123 | msgstr "Controls del reproductor" 124 | 125 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 126 | msgid "Add item" 127 | msgstr "Afegeix un element" 128 | 129 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 130 | msgid "Add custom text" 131 | msgstr "Afegeix text personalitzat" 132 | 133 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 134 | msgid "General" 135 | msgstr "Generals" 136 | 137 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 138 | msgid "Common" 139 | msgstr "Comuns" 140 | 141 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 142 | msgid "Labels" 143 | msgstr "Etiquetes" 144 | 145 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 146 | msgid "Customize the labels in the panel and the popup menu" 147 | msgstr "Personalitzeu les etiquetes al plafó i al menú emergent" 148 | 149 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 150 | msgid "Fixed width" 151 | msgstr "Amplada fixa" 152 | 153 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 154 | msgid "Use the specified width even when they are smaller than the width" 155 | msgstr "Usa l’amplada especificada encara que siguin més petites que aquesta" 156 | 157 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 158 | msgid "Scroll labels" 159 | msgstr "Desplaça les etiquetes" 160 | 161 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 162 | msgid "Scroll the labels when they are wider than the width" 163 | msgstr "Desplaça les etiquetes quan són més amples que el valor fix" 164 | 165 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 166 | msgid "Hide the media notification" 167 | msgstr "Amaga la notificació multimèdia" 168 | 169 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 170 | msgid "Hide the media notifications in the notification list" 171 | msgstr "Amaga les notificacions multimèdia a la llista de notificacions" 172 | 173 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 174 | msgid "Information" 175 | msgstr "Informació" 176 | 177 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 178 | msgid "Homepage" 179 | msgstr "Lloc web" 180 | 181 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 182 | msgid "Release notes" 183 | msgstr "Novetats de la versió" 184 | 185 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 186 | #: assets/ui/prefs.blp:82 187 | msgid "Report an issue" 188 | msgstr "Informa d’un problema" 189 | 190 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 191 | msgid "Panel" 192 | msgstr "Plafó" 193 | 194 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 195 | msgid "Show label" 196 | msgstr "Mostra l’etiqueta" 197 | 198 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 199 | msgid "Show player controls" 200 | msgstr "Mostra els controls de reproducció" 201 | 202 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 203 | msgid "Show play/pause button" 204 | msgstr "Mostra el botó Reprodueix/pausa" 205 | 206 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 207 | msgid "Show next track button" 208 | msgstr "Mostra el botó Peça següent" 209 | 210 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 211 | msgid "Show previous track button" 212 | msgstr "Mostra el botó Peça anterior" 213 | 214 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 215 | msgid "Show seek forward button" 216 | msgstr "Mostra el botó Cerca endavant" 217 | 218 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 219 | msgid "Show seek back button" 220 | msgstr "Mostra el botó Cerca enrere" 221 | 222 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 223 | msgid "Show player icon" 224 | msgstr "Mostra la icona del reproductor" 225 | 226 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 227 | msgid "Colored player icon" 228 | msgstr "Icona de reproductor colorida" 229 | 230 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 231 | msgid "Positions" 232 | msgstr "Posicions" 233 | 234 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 235 | msgid "Extension" 236 | msgstr "Extensió" 237 | 238 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 239 | msgid "Position" 240 | msgstr "Posició" 241 | 242 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 243 | msgid "Position of the extension in the panel" 244 | msgstr "Posició de l’extensió al plafó" 245 | 246 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 247 | msgid "Left" 248 | msgstr "Esquerra" 249 | 250 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 251 | msgid "Center" 252 | msgstr "Centre" 253 | 254 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 255 | msgid "Right" 256 | msgstr "Dreta" 257 | 258 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 259 | msgid "Index" 260 | msgstr "Índex" 261 | 262 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 263 | msgid "Index of the extension" 264 | msgstr "Índex de l’extensió" 265 | 266 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 267 | msgid "Shortcuts" 268 | msgstr "Dreceres" 269 | 270 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 271 | #: assets/ui/prefs.blp:320 272 | msgid "Show popup menu" 273 | msgstr "Mostra el menú emergent" 274 | 275 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 276 | msgid "Shortcut to toggle the popup menu" 277 | msgstr "Drecera per a activar o desactivar el menú emergent" 278 | 279 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 280 | #: assets/ui/prefs.blp:277 281 | msgid "Set shortcut" 282 | msgstr "Defineix la drecera" 283 | 284 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 285 | msgid "Mouse actions" 286 | msgstr "Accions del ratolí" 287 | 288 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 289 | msgid "Left click / Tap" 290 | msgstr "Clic esquerre/toc" 291 | 292 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 293 | msgid "Middle click" 294 | msgstr "Clic del mig" 295 | 296 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 297 | msgid "Right click" 298 | msgstr "Clic dret" 299 | 300 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 301 | msgid "Double click / Double tap" 302 | msgstr "Doble clic/doble toc" 303 | 304 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 305 | msgid "Scroll up / Swipe right" 306 | msgstr "Desplaçament amunt/lliscada a la dreta" 307 | 308 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 309 | msgid "Scroll down / Swipe left" 310 | msgstr "Desplaçament avall/lliscada a l’esquerra" 311 | 312 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 313 | msgid "Other" 314 | msgstr "Altres" 315 | 316 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 317 | msgid "Cache" 318 | msgstr "Memòria cau" 319 | 320 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 321 | msgid "" 322 | "This extension cache album art to improve performance. You can clear the " 323 | "cache here." 324 | msgstr "" 325 | "Aquesta extensió emmagatzema les portades a la memòria cau per a millorar " 326 | "el rendiment. Podeu netejar-la ací." 327 | 328 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 329 | msgid "Cache album art" 330 | msgstr "Emmagatzema en memòria cau les portades" 331 | 332 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 333 | msgid "Clear" 334 | msgstr "Neteja" 335 | 336 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 337 | msgid "" 338 | "Press escape to cancel.\n" 339 | "Press enter to set the shortcut.\n" 340 | "Press backspace to reset." 341 | msgstr "" 342 | "Premeu Escapada per a cancel·lar.\n" 343 | "Premeu Retorn per a definir la drecera.\n" 344 | "Premeu Retrocès per a reinicialitzar." 345 | 346 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 347 | msgid "Press shortcut" 348 | msgstr "Premeu la drecera" 349 | 350 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 351 | msgid "None" 352 | msgstr "Cap" 353 | 354 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 355 | msgid "Play/Pause" 356 | msgstr "Reprodueix/pausa" 357 | 358 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 359 | msgid "Play" 360 | msgstr "Reprodueix" 361 | 362 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 363 | msgid "Pause" 364 | msgstr "Posa en pausa" 365 | 366 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 367 | msgid "Next track" 368 | msgstr "Peça següent" 369 | 370 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 371 | msgid "Previous track" 372 | msgstr "Peça anterior" 373 | 374 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 375 | msgid "Volume up" 376 | msgstr "Apuja el volum" 377 | 378 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 379 | msgid "Volume down" 380 | msgstr "Abaixa el volum" 381 | 382 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 383 | msgid "Toggle loop" 384 | msgstr "Activa o desactiva el bucle" 385 | 386 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 387 | msgid "Toggle shuffle" 388 | msgstr "Activa o desactiva el mode aleatori" 389 | 390 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 391 | msgid "Raise player" 392 | msgstr "Eleva el reproductor" 393 | 394 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 395 | msgid "Quit player" 396 | msgstr "Surt del reproductor" 397 | 398 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 399 | msgid "Open preferences" 400 | msgstr "Obre les preferències" 401 | 402 | #: src/helpers/prefs/LabelList.ts:97 403 | msgid "Custom text" 404 | msgstr "Text personalitzat" 405 | 406 | #: assets/ui/prefs.blp:20 407 | msgid "Width" 408 | msgstr "Amplada" 409 | 410 | #: assets/ui/prefs.blp:21 411 | msgid "0 to take all available space" 412 | msgstr "0 per a usar tot l’espai disponible" 413 | 414 | #: src/helpers/shell/PanelButton.ts:258 415 | msgid "Unknown player" 416 | msgstr "Reproductor desconegut" 417 | 418 | #: src/helpers/shell/PanelButton.ts:434 419 | msgid "Unknown artist" 420 | msgstr "Artista desconegut" 421 | 422 | #: src/helpers/shell/PanelButton.ts:745 423 | msgid "Unknown album" 424 | msgstr "Àlbum desconegut" 425 | -------------------------------------------------------------------------------- /assets/locale/cs.po: -------------------------------------------------------------------------------- 1 | # Czech translation for Media Controls 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR Amerey.eu , 2023. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: \n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 11 | "PO-Revision-Date: 2024-01-13 11:21+0100\n" 12 | "Last-Translator: Christian Lauinger \n" 13 | "Language-Team: \n" 14 | "Language: cs\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "X-Generator: Poedit 3.4.2\n" 19 | 20 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 21 | #: src/prefs.ts:203 src/prefs.ts:205 src/prefs.ts:202 22 | msgid "Are you sure you want to clear the cache?" 23 | msgstr "" 24 | 25 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 26 | #: src/prefs.ts:196 src/prefs.ts:195 src/prefs.ts:204 src/prefs.ts:206 27 | #: src/prefs.ts:203 assets/ui/app-chooser.blp:21 28 | msgid "Cancel" 29 | msgstr "" 30 | 31 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 32 | #: src/prefs.ts:196 src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 33 | #: assets/ui/prefs.blp:255 34 | msgid "Clear cache" 35 | msgstr "Vyčistit mezipaměť" 36 | 37 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 38 | #: src/prefs.ts:204 src/prefs.ts:213 src/prefs.ts:203 src/prefs.ts:212 39 | #: src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 40 | #: src/prefs.ts:220 41 | #, javascript-format 42 | msgid "Cache size: %s" 43 | msgstr "" 44 | 45 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 46 | #: src/prefs.ts:304 src/prefs.ts:306 src/prefs.ts:303 47 | msgid "Cache cleared successfully!" 48 | msgstr "" 49 | 50 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 51 | #: src/prefs.ts:306 src/prefs.ts:308 src/prefs.ts:305 52 | msgid "Failed to clear cache!" 53 | msgstr "" 54 | 55 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 56 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 57 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 58 | msgid "" 59 | "No players are blacklisted" 61 | msgstr "" 62 | 63 | #: src/helpers/LabelList.ts:9 64 | msgid "Artist" 65 | msgstr "Interpret" 66 | 67 | #: src/helpers/LabelList.ts:10 68 | msgid "Title" 69 | msgstr "" 70 | 71 | #: src/helpers/LabelList.ts:11 72 | msgid "Album" 73 | msgstr "Album" 74 | 75 | #: src/helpers/LabelList.ts:12 76 | msgid "Disc Number" 77 | msgstr "" 78 | 79 | #: src/helpers/LabelList.ts:13 80 | msgid "Track Number" 81 | msgstr "" 82 | 83 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 84 | msgid "Select app to blacklist" 85 | msgstr "" 86 | 87 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 88 | msgid "Select" 89 | msgstr "" 90 | 91 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 92 | msgid "Blacklist players" 93 | msgstr "Přehrávače na blacklistu" 94 | 95 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 96 | msgid "Blacklisted players will be ignored by the extension." 97 | msgstr "" 98 | 99 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 100 | msgid "Add" 101 | msgstr "" 102 | 103 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 104 | msgid "Elements" 105 | msgstr "" 106 | 107 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 108 | #: assets/ui/element-list.blp:14 assets/ui/prefs.blp:136 109 | msgid "Player icon" 110 | msgstr "Ikona přehrávače" 111 | 112 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 113 | #: assets/ui/element-list.blp:24 assets/ui/label-list.blp:7 114 | msgid "Label" 115 | msgstr "" 116 | 117 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 118 | #: assets/ui/element-list.blp:34 assets/ui/prefs.blp:102 119 | msgid "Player controls" 120 | msgstr "Ovládání přehrávače" 121 | 122 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 123 | msgid "Add item" 124 | msgstr "" 125 | 126 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 127 | msgid "Add custom text" 128 | msgstr "" 129 | 130 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 131 | msgid "General" 132 | msgstr "Obecné" 133 | 134 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 135 | msgid "Common" 136 | msgstr "" 137 | 138 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 139 | msgid "Labels" 140 | msgstr "" 141 | 142 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 143 | msgid "Customize the labels in the panel and the popup menu" 144 | msgstr "" 145 | 146 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 147 | msgid "Fixed width" 148 | msgstr "" 149 | 150 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 151 | msgid "Use the specified width even when they are smaller than the width" 152 | msgstr "" 153 | 154 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 155 | msgid "Scroll labels" 156 | msgstr "" 157 | 158 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 159 | msgid "Scroll the labels when they are wider than the width" 160 | msgstr "" 161 | 162 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 163 | msgid "Hide the media notification" 164 | msgstr "Skrýt oznámení o médiích" 165 | 166 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 167 | msgid "Hide the media notifications in the notification list" 168 | msgstr "" 169 | 170 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 171 | msgid "Information" 172 | msgstr "" 173 | 174 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 175 | msgid "Homepage" 176 | msgstr "Domovská stránka" 177 | 178 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 179 | msgid "Release notes" 180 | msgstr "" 181 | 182 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 183 | #: assets/ui/prefs.blp:82 184 | msgid "Report an issue" 185 | msgstr "" 186 | 187 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 188 | msgid "Panel" 189 | msgstr "" 190 | 191 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 192 | msgid "Show label" 193 | msgstr "" 194 | 195 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 196 | msgid "Show player controls" 197 | msgstr "" 198 | 199 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 200 | msgid "Show play/pause button" 201 | msgstr "" 202 | 203 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 204 | msgid "Show next track button" 205 | msgstr "" 206 | 207 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 208 | msgid "Show previous track button" 209 | msgstr "" 210 | 211 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 212 | msgid "Show seek forward button" 213 | msgstr "" 214 | 215 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 216 | msgid "Show seek back button" 217 | msgstr "" 218 | 219 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 220 | msgid "Show player icon" 221 | msgstr "" 222 | 223 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 224 | msgid "Colored player icon" 225 | msgstr "Barevná ikona přehrávače" 226 | 227 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 228 | msgid "Positions" 229 | msgstr "" 230 | 231 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 232 | msgid "Extension" 233 | msgstr "" 234 | 235 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 236 | msgid "Position" 237 | msgstr "Pozice" 238 | 239 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 240 | msgid "Position of the extension in the panel" 241 | msgstr "" 242 | 243 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 244 | msgid "Left" 245 | msgstr "Vlevo" 246 | 247 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 248 | msgid "Center" 249 | msgstr "Uprostřed" 250 | 251 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 252 | msgid "Right" 253 | msgstr "Vpravo" 254 | 255 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 256 | msgid "Index" 257 | msgstr "" 258 | 259 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 260 | msgid "Index of the extension" 261 | msgstr "" 262 | 263 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 264 | msgid "Shortcuts" 265 | msgstr "Klávesové zkratky" 266 | 267 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 268 | #: assets/ui/prefs.blp:320 269 | msgid "Show popup menu" 270 | msgstr "" 271 | 272 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 273 | msgid "Shortcut to toggle the popup menu" 274 | msgstr "" 275 | 276 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 277 | #: assets/ui/prefs.blp:277 278 | msgid "Set shortcut" 279 | msgstr "" 280 | 281 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 282 | msgid "Mouse actions" 283 | msgstr "Akce myši" 284 | 285 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 286 | msgid "Left click / Tap" 287 | msgstr "" 288 | 289 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 290 | msgid "Middle click" 291 | msgstr "Prostřední klik" 292 | 293 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 294 | msgid "Right click" 295 | msgstr "Pravý klik" 296 | 297 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 298 | msgid "Double click / Double tap" 299 | msgstr "" 300 | 301 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 302 | msgid "Scroll up / Swipe right" 303 | msgstr "" 304 | 305 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 306 | msgid "Scroll down / Swipe left" 307 | msgstr "" 308 | 309 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 310 | msgid "Other" 311 | msgstr "Ostatní" 312 | 313 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 314 | msgid "Cache" 315 | msgstr "Mezipaměť" 316 | 317 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 318 | msgid "" 319 | "This extension cache album art to improve performance. You can clear the " 320 | "cache here." 321 | msgstr "" 322 | 323 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 324 | msgid "Cache album art" 325 | msgstr "" 326 | 327 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 328 | msgid "Clear" 329 | msgstr "" 330 | 331 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 332 | msgid "" 333 | "Press escape to cancel.\n" 334 | "Press enter to set the shortcut.\n" 335 | "Press backspace to reset." 336 | msgstr "" 337 | 338 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 339 | msgid "Press shortcut" 340 | msgstr "" 341 | 342 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 343 | msgid "None" 344 | msgstr "---" 345 | 346 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 347 | msgid "Play/Pause" 348 | msgstr "" 349 | 350 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 351 | msgid "Play" 352 | msgstr "Přehrát" 353 | 354 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 355 | msgid "Pause" 356 | msgstr "Pozastavit" 357 | 358 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 359 | msgid "Next track" 360 | msgstr "" 361 | 362 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 363 | msgid "Previous track" 364 | msgstr "" 365 | 366 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 367 | msgid "Volume up" 368 | msgstr "Zvýšit hlasitost" 369 | 370 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 371 | msgid "Volume down" 372 | msgstr "Snížit hlasitost" 373 | 374 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 375 | msgid "Toggle loop" 376 | msgstr "" 377 | 378 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 379 | msgid "Toggle shuffle" 380 | msgstr "Přepnout náhodné přehrávání" 381 | 382 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 383 | msgid "Raise player" 384 | msgstr "Přepnout další skladbu" 385 | 386 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 387 | msgid "Quit player" 388 | msgstr "Ukončit" 389 | 390 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 391 | msgid "Open preferences" 392 | msgstr "" 393 | 394 | #: src/helpers/prefs/LabelList.ts:97 395 | msgid "Custom text" 396 | msgstr "" 397 | 398 | #: assets/ui/prefs.blp:20 399 | msgid "Width" 400 | msgstr "" 401 | 402 | #: assets/ui/prefs.blp:21 403 | msgid "0 to take all available space" 404 | msgstr "" 405 | 406 | #: src/helpers/shell/PanelButton.ts:258 407 | msgid "Unknown player" 408 | msgstr "" 409 | 410 | #: src/helpers/shell/PanelButton.ts:434 411 | msgid "Unknown artist" 412 | msgstr "Neznámý umělec" 413 | 414 | #: src/helpers/shell/PanelButton.ts:745 415 | msgid "Unknown album" 416 | msgstr "Neznámé album" 417 | 418 | #~ msgid "[MediaControls] Enabling" 419 | #~ msgstr "[MediaControls] Aktivace" 420 | 421 | #~ msgid "[MediaControls] Disabling" 422 | #~ msgstr "[MediaControls] Deaktivace" 423 | 424 | #~ msgid "[MediaControls] Reloading" 425 | #~ msgstr "[MediaControls] Opětovné načítání" 426 | 427 | #~ msgid "Track" 428 | #~ msgstr "Skladba" 429 | 430 | #~ msgid "Track + Album" 431 | #~ msgstr "Skladba + Album" 432 | 433 | #~ msgid "Artist + Album" 434 | #~ msgstr "Interpret + Album" 435 | 436 | #~ msgid "Album + Artist" 437 | #~ msgstr "Album + Interpret" 438 | 439 | #~ msgid "Album + Track" 440 | #~ msgstr "Album + Skladba" 441 | 442 | #~ msgid "URL" 443 | #~ msgstr "URL" 444 | 445 | #~ msgid "Player name" 446 | #~ msgstr "Název přehrávače" 447 | 448 | #~ msgid "Playback status" 449 | #~ msgstr "Stav přehrávání" 450 | 451 | #~ msgid "Filename" 452 | #~ msgstr "Název souboru" 453 | 454 | #~ msgid "Control icons" 455 | #~ msgstr "Ikony ovládání" 456 | 457 | #~ msgid "Sources menu" 458 | #~ msgstr "Nabídka zdrojů" 459 | 460 | #~ msgid "Left double click" 461 | #~ msgstr "Levý dvojklik" 462 | 463 | #~ msgid "Right double click" 464 | #~ msgstr "Pravý dvojklik" 465 | 466 | #~ msgid "Hover" 467 | #~ msgstr "Najetí myší" 468 | 469 | #~ msgid "unstable" 470 | #~ msgstr "nestabilní" 471 | 472 | #~ msgid "Next" 473 | #~ msgstr "Další" 474 | 475 | #~ msgid "Previous" 476 | #~ msgstr "Předchozí" 477 | 478 | #~ msgid "Cycle loop options" 479 | #~ msgstr "Volby cyklické smyčky" 480 | 481 | #~ msgid "Toggle sources menu" 482 | #~ msgstr "Přepnout nabídku zdrojů" 483 | 484 | #~ msgid "Toggle track information menu" 485 | #~ msgstr "Přepnout nabídku informací o skladbě" 486 | 487 | #~ msgid "Settings" 488 | #~ msgstr "Nastavení" 489 | 490 | #~ msgid "Maximum widget width" 491 | #~ msgstr "Maximální šířka doplňku" 492 | 493 | #~ msgid "0 to disable" 494 | #~ msgstr "0 pro deaktivaci" 495 | 496 | #~ msgid "No. of seconds to seek by" 497 | #~ msgstr "Počet sekund k vyhledání" 498 | 499 | #~ msgid "Use native seek" 500 | #~ msgstr "Použít nativní hledání" 501 | 502 | #~ msgid "Disable this if seeking is not working" 503 | #~ msgstr "Pokud vyhledávání nefunguje, deaktivujte tuto možnost" 504 | 505 | #~ msgid "Clip title and artist in track information menu" 506 | #~ msgstr "Ořezat název a interpreta v nabídce informací o skladbě" 507 | 508 | #~ msgid "Disable this to use wrapping instead" 509 | #~ msgstr "Chcete-li místo toho použít zalamování, deaktivujte tuto možnost" 510 | 511 | #~ msgid "Scroll the track label in the panel" 512 | #~ msgstr "Posouvat štítek stopy na panelu" 513 | 514 | #~ msgid "Enable this to scroll the panel label instead of clipping" 515 | #~ msgstr "Povolte tuto možnost, chcete-li posouvat štítek namísto ořezávání" 516 | 517 | #~ msgid "Starting label" 518 | #~ msgstr "Počáteční štítek" 519 | 520 | #~ msgid "Separating label" 521 | #~ msgstr "Oddělovací štítek" 522 | 523 | #~ msgid "Ending label" 524 | #~ msgstr "Koncový štítek" 525 | 526 | #~ msgid "Github" 527 | #~ msgstr "Github" 528 | 529 | #~ msgid "Visibility" 530 | #~ msgstr "Zobrazení" 531 | 532 | #~ msgid "show/hide elements" 533 | #~ msgstr "zobrazit/skrýt prvky" 534 | 535 | #~ msgid "Title/Track name" 536 | #~ msgstr "Jméno/Název skladby" 537 | 538 | #~ msgid "Separators" 539 | #~ msgstr "Oddělovače" 540 | 541 | #~ msgid "Colors" 542 | #~ msgstr "Barvy" 543 | 544 | #~ msgid "Separator characters" 545 | #~ msgstr "Oddělovací znaky" 546 | 547 | #~ msgid "Preset" 548 | #~ msgstr "Předvolba" 549 | 550 | #~ msgid "To use it choose 'Custom' under 'Preset' selection" 551 | #~ msgstr "Chcete-li jej použít, vyberte „Vlastní“ pod výběrem „Předvolba“" 552 | 553 | #~ msgid "Appearance" 554 | #~ msgstr "Vzhled" 555 | 556 | #~ msgid "Extension position" 557 | #~ msgstr "Pozice doplňku" 558 | 559 | #~ msgid "Element order" 560 | #~ msgstr "Pořadí" 561 | 562 | #~ msgid "Hotkey" 563 | #~ msgstr "Klávesová zkratka" 564 | 565 | #~ msgid "Hot key" 566 | #~ msgstr "Klávesová zkratka" 567 | 568 | #~ msgid "Hot key to toggle the track information menu" 569 | #~ msgstr "Klávesová zkratka pro přepínání nabídky informací o skladbě" 570 | 571 | #~ msgid "Select a hotkey" 572 | #~ msgstr "Vyberte klávesovou zkratku" 573 | 574 | #~ msgid "New hotkey" 575 | #~ msgstr "Nová klávesová zkratka" 576 | 577 | #~ msgid "Add player" 578 | #~ msgstr "Přidat přehrávač" 579 | 580 | #~ msgid "Determine player automatically" 581 | #~ msgstr "Automaticky vybrat přehrávač" 582 | -------------------------------------------------------------------------------- /assets/locale/es.po: -------------------------------------------------------------------------------- 1 | # Spanish translation (ノ^ヮ^)ノ*:・゚✧. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Nosis , 2024. 5 | # Adolfo Jayme Barrientos , 2024. 6 | # 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: unnamed project\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 12 | "PO-Revision-Date: 2024-04-29 23:48-0600\n" 13 | "Last-Translator: Adolfo Jayme Barrientos \n" 14 | "Language-Team: Spanish\n" 15 | "Language: es\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "X-Generator: Gtranslator 46.1\n" 20 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 21 | 22 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 23 | #: src/prefs.ts:203 src/prefs.ts:205 src/prefs.ts:202 24 | msgid "Are you sure you want to clear the cache?" 25 | msgstr "¿Confirma que quiere variar la antememoria?" 26 | 27 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 28 | #: src/prefs.ts:196 src/prefs.ts:195 src/prefs.ts:204 src/prefs.ts:206 29 | #: src/prefs.ts:203 assets/ui/app-chooser.blp:21 30 | msgid "Cancel" 31 | msgstr "Cancelar" 32 | 33 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 34 | #: src/prefs.ts:196 src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 35 | #: assets/ui/prefs.blp:255 36 | msgid "Clear cache" 37 | msgstr "Vaciar antememoria" 38 | 39 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 40 | #: src/prefs.ts:204 src/prefs.ts:213 src/prefs.ts:203 src/prefs.ts:212 41 | #: src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 42 | #: src/prefs.ts:220 43 | #, javascript-format 44 | msgid "Cache size: %s" 45 | msgstr "Tamaño de antememoria: %s" 46 | 47 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 48 | #: src/prefs.ts:304 src/prefs.ts:306 src/prefs.ts:303 49 | msgid "Cache cleared successfully!" 50 | msgstr "Se vació la antememoria correctamente." 51 | 52 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 53 | #: src/prefs.ts:306 src/prefs.ts:308 src/prefs.ts:305 54 | msgid "Failed to clear cache!" 55 | msgstr "No se pudo vaciar la antememoria." 56 | 57 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 58 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 59 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 60 | msgid "" 61 | "No players are blacklisted" 63 | msgstr "" 64 | "No hay reproductores vetados" 65 | 66 | #: src/helpers/LabelList.ts:9 67 | msgid "Artist" 68 | msgstr "Artista" 69 | 70 | #: src/helpers/LabelList.ts:10 71 | msgid "Title" 72 | msgstr "Título" 73 | 74 | #: src/helpers/LabelList.ts:11 75 | msgid "Album" 76 | msgstr "Álbum" 77 | 78 | #: src/helpers/LabelList.ts:12 79 | msgid "Disc Number" 80 | msgstr "Número del disco" 81 | 82 | #: src/helpers/LabelList.ts:13 83 | msgid "Track Number" 84 | msgstr "Número de canción" 85 | 86 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 87 | msgid "Select app to blacklist" 88 | msgstr "Seleccione la aplicación que desea vetar" 89 | 90 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 91 | msgid "Select" 92 | msgstr "Seleccionar" 93 | 94 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 95 | msgid "Blacklist players" 96 | msgstr "Vetar reproductores" 97 | 98 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 99 | msgid "Blacklisted players will be ignored by the extension." 100 | msgstr "La extensión ignorará los reproductores vetados." 101 | 102 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 103 | msgid "Add" 104 | msgstr "Añadir" 105 | 106 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 107 | msgid "Elements" 108 | msgstr "Elementos" 109 | 110 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 111 | #: assets/ui/element-list.blp:14 assets/ui/prefs.blp:136 112 | msgid "Player icon" 113 | msgstr "Icono del reproductor" 114 | 115 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 116 | #: assets/ui/element-list.blp:24 assets/ui/label-list.blp:7 117 | msgid "Label" 118 | msgstr "Etiqueta" 119 | 120 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 121 | #: assets/ui/element-list.blp:34 assets/ui/prefs.blp:102 122 | msgid "Player controls" 123 | msgstr "Controles del reproductor" 124 | 125 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 126 | msgid "Add item" 127 | msgstr "Añadir elemento" 128 | 129 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 130 | msgid "Add custom text" 131 | msgstr "Añadir un texto personalizado" 132 | 133 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 134 | msgid "General" 135 | msgstr "Generales" 136 | 137 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 138 | msgid "Common" 139 | msgstr "Común" 140 | 141 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 142 | msgid "Labels" 143 | msgstr "Etiquetas" 144 | 145 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 146 | msgid "Customize the labels in the panel and the popup menu" 147 | msgstr "Personalizar las etiquetas del panel y del menú emergente" 148 | 149 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 150 | msgid "Fixed width" 151 | msgstr "Anchura fija" 152 | 153 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 154 | msgid "Use the specified width even when they are smaller than the width" 155 | msgstr "Utilizar anchura especificada aun cuando sean más pequeños que esta" 156 | 157 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 158 | msgid "Scroll labels" 159 | msgstr "Desplazar etiquetas" 160 | 161 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 162 | msgid "Scroll the labels when they are wider than the width" 163 | msgstr "Desplazar etiquetas cuando superen la anchura fijada" 164 | 165 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 166 | msgid "Hide the media notification" 167 | msgstr "Ocultar notificaciones multimedia" 168 | 169 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 170 | msgid "Hide the media notifications in the notification list" 171 | msgstr "Ocultar las notificaciones multimedia en la lista de notificaciones" 172 | 173 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 174 | msgid "Information" 175 | msgstr "Información" 176 | 177 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 178 | msgid "Homepage" 179 | msgstr "Sitio web" 180 | 181 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 182 | msgid "Release notes" 183 | msgstr "Novedades de la versión" 184 | 185 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 186 | #: assets/ui/prefs.blp:82 187 | msgid "Report an issue" 188 | msgstr "Informar de un problema" 189 | 190 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 191 | msgid "Panel" 192 | msgstr "Panel" 193 | 194 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 195 | msgid "Show label" 196 | msgstr "Mostrar etiqueta" 197 | 198 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 199 | msgid "Show player controls" 200 | msgstr "Mostrar controles del reproductor" 201 | 202 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 203 | msgid "Show play/pause button" 204 | msgstr "Mostrar botón de reproducción/pausa" 205 | 206 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 207 | msgid "Show next track button" 208 | msgstr "Mostrar el botón de pista siguiente" 209 | 210 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 211 | msgid "Show previous track button" 212 | msgstr "Botón el botón de pista anterior" 213 | 214 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 215 | msgid "Show seek forward button" 216 | msgstr "Mostrar botón de adelantar" 217 | 218 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 219 | msgid "Show seek back button" 220 | msgstr "Mostrar el botón de atrasar" 221 | 222 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 223 | msgid "Show player icon" 224 | msgstr "Mostrar el icono del reproductor" 225 | 226 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 227 | msgid "Colored player icon" 228 | msgstr "Colorear el icono del reproductor" 229 | 230 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 231 | msgid "Positions" 232 | msgstr "Posiciones" 233 | 234 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 235 | msgid "Extension" 236 | msgstr "Extensión" 237 | 238 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 239 | msgid "Position" 240 | msgstr "Posición" 241 | 242 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 243 | msgid "Position of the extension in the panel" 244 | msgstr "Posición de la extensión en el panel" 245 | 246 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 247 | msgid "Left" 248 | msgstr "Izquierda" 249 | 250 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 251 | msgid "Center" 252 | msgstr "Centro" 253 | 254 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 255 | msgid "Right" 256 | msgstr "Derecha" 257 | 258 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 259 | msgid "Index" 260 | msgstr "Índice" 261 | 262 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 263 | msgid "Index of the extension" 264 | msgstr "Índice de la extensión" 265 | 266 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 267 | msgid "Shortcuts" 268 | msgstr "Atajos" 269 | 270 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 271 | #: assets/ui/prefs.blp:320 272 | msgid "Show popup menu" 273 | msgstr "Mostrar menú emergente" 274 | 275 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 276 | msgid "Shortcut to toggle the popup menu" 277 | msgstr "Atajo para activar el menú emergente" 278 | 279 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 280 | #: assets/ui/prefs.blp:277 281 | msgid "Set shortcut" 282 | msgstr "Establecer atajo" 283 | 284 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 285 | msgid "Mouse actions" 286 | msgstr "Acciones con el ratón" 287 | 288 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 289 | msgid "Left click / Tap" 290 | msgstr "Pulsación izquierda/toque" 291 | 292 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 293 | msgid "Middle click" 294 | msgstr "Pulsación central" 295 | 296 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 297 | msgid "Right click" 298 | msgstr "Pulsación derecha" 299 | 300 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 301 | msgid "Double click / Double tap" 302 | msgstr "Pulsación/toque doble" 303 | 304 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 305 | msgid "Scroll up / Swipe right" 306 | msgstr "Desplazarse hacia arriba/deslizar a la derecha" 307 | 308 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 309 | msgid "Scroll down / Swipe left" 310 | msgstr "Desplazarse hacia abajo/deslizar a la izquierda" 311 | 312 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 313 | msgid "Other" 314 | msgstr "Otro" 315 | 316 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 317 | msgid "Cache" 318 | msgstr "Antememoria" 319 | 320 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 321 | msgid "" 322 | "This extension cache album art to improve performance. You can clear the " 323 | "cache here." 324 | msgstr "" 325 | "Esta extensión almacena en antememoria la portada del álbum para mejorar el " 326 | "rendimiento. Puede vaciar la antememoria aquí." 327 | 328 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 329 | msgid "Cache album art" 330 | msgstr "Prealmacenar portadas de álbumes" 331 | 332 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 333 | msgid "Clear" 334 | msgstr "Vaciar" 335 | 336 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 337 | msgid "" 338 | "Press escape to cancel.\n" 339 | "Press enter to set the shortcut.\n" 340 | "Press backspace to reset." 341 | msgstr "" 342 | "Presione Escape para cancelar.\n" 343 | "Presione Intro para definir el atajo.\n" 344 | "Presione Retroceso para restablecer." 345 | 346 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 347 | msgid "Press shortcut" 348 | msgstr "Pulse el atajo" 349 | 350 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 351 | msgid "None" 352 | msgstr "Ninguno" 353 | 354 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 355 | msgid "Play/Pause" 356 | msgstr "Reproducir/pausar" 357 | 358 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 359 | msgid "Play" 360 | msgstr "Reproducir" 361 | 362 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 363 | msgid "Pause" 364 | msgstr "Pausar" 365 | 366 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 367 | msgid "Next track" 368 | msgstr "Pista siguiente" 369 | 370 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 371 | msgid "Previous track" 372 | msgstr "Pista anterior" 373 | 374 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 375 | msgid "Volume up" 376 | msgstr "Subir volumen" 377 | 378 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 379 | msgid "Volume down" 380 | msgstr "Bajar volumen" 381 | 382 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 383 | msgid "Toggle loop" 384 | msgstr "Alternar reproducción en bucle" 385 | 386 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 387 | msgid "Toggle shuffle" 388 | msgstr "Alternar reproducción aleatoria" 389 | 390 | # Duda de la palabra Raise 391 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 392 | msgid "Raise player" 393 | msgstr "Elevar reproductor" 394 | 395 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 396 | msgid "Quit player" 397 | msgstr "Salir del reproductor" 398 | 399 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 400 | msgid "Open preferences" 401 | msgstr "Abrir preferencias" 402 | 403 | #: src/helpers/prefs/LabelList.ts:97 404 | msgid "Custom text" 405 | msgstr "Texto personalizado" 406 | 407 | #: assets/ui/prefs.blp:20 408 | msgid "Width" 409 | msgstr "Anchura" 410 | 411 | #: assets/ui/prefs.blp:21 412 | msgid "0 to take all available space" 413 | msgstr "0 para ocupar todo el espacio disponible" 414 | 415 | #: src/helpers/shell/PanelButton.ts:258 416 | msgid "Unknown player" 417 | msgstr "Reproductor desconocido" 418 | 419 | #: src/helpers/shell/PanelButton.ts:434 420 | msgid "Unknown artist" 421 | msgstr "Artista desconocido" 422 | 423 | #: src/helpers/shell/PanelButton.ts:745 424 | msgid "Unknown album" 425 | msgstr "Álbum desconocido" 426 | -------------------------------------------------------------------------------- /assets/locale/mediacontrols@cliffniff.github.com.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 21 | #: src/prefs.ts:203 src/prefs.ts:205 src/prefs.ts:202 src/prefs.ts:203 22 | msgid "Are you sure you want to clear the cache?" 23 | msgstr "" 24 | 25 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 26 | #: src/prefs.ts:196 src/prefs.ts:195 src/prefs.ts:204 src/prefs.ts:206 27 | #: src/prefs.ts:203 assets/ui/app-chooser.blp:21 src/prefs.ts:204 28 | #: assets/ui/app-chooser.blp:21 29 | msgid "Cancel" 30 | msgstr "" 31 | 32 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 33 | #: src/prefs.ts:196 src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 34 | #: assets/ui/prefs.blp:255 src/prefs.ts:205 assets/ui/prefs.blp:255 35 | msgid "Clear cache" 36 | msgstr "" 37 | 38 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 39 | #: src/prefs.ts:204 src/prefs.ts:213 src/prefs.ts:203 src/prefs.ts:212 40 | #: src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 41 | #: src/prefs.ts:220 src/prefs.ts:212 src/prefs.ts:221 42 | #, javascript-format 43 | msgid "Cache size: %s" 44 | msgstr "" 45 | 46 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 47 | #: src/prefs.ts:304 src/prefs.ts:306 src/prefs.ts:303 src/prefs.ts:304 48 | msgid "Cache cleared successfully!" 49 | msgstr "" 50 | 51 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 52 | #: src/prefs.ts:306 src/prefs.ts:308 src/prefs.ts:305 src/prefs.ts:306 53 | msgid "Failed to clear cache!" 54 | msgstr "" 55 | 56 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 57 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 58 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 59 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 60 | msgid "" 61 | "No players are blacklisted" 63 | msgstr "" 64 | 65 | #: src/helpers/LabelList.ts:9 66 | msgid "Artist" 67 | msgstr "" 68 | 69 | #: src/helpers/LabelList.ts:10 70 | msgid "Title" 71 | msgstr "" 72 | 73 | #: src/helpers/LabelList.ts:11 74 | msgid "Album" 75 | msgstr "" 76 | 77 | #: src/helpers/LabelList.ts:12 78 | msgid "Disc Number" 79 | msgstr "" 80 | 81 | #: src/helpers/LabelList.ts:13 82 | msgid "Track Number" 83 | msgstr "" 84 | 85 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 86 | #: assets/ui/app-chooser.blp:7 87 | msgid "Select app to blacklist" 88 | msgstr "" 89 | 90 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 91 | #: assets/ui/app-chooser.blp:26 92 | msgid "Select" 93 | msgstr "" 94 | 95 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 96 | #: assets/ui/blacklisted-players.blp:7 97 | msgid "Blacklist players" 98 | msgstr "" 99 | 100 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 101 | #: assets/ui/blacklisted-players.blp:8 102 | msgid "Blacklisted players will be ignored by the extension." 103 | msgstr "" 104 | 105 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 106 | #: assets/ui/blacklisted-players.blp:19 107 | msgid "Add" 108 | msgstr "" 109 | 110 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 111 | #: assets/ui/element-list.blp:7 112 | msgid "Elements" 113 | msgstr "" 114 | 115 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 116 | #: assets/ui/element-list.blp:14 assets/ui/prefs.blp:136 117 | #: assets/ui/prefs.blp:136 assets/ui/element-list.blp:14 118 | msgid "Player icon" 119 | msgstr "" 120 | 121 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 122 | #: assets/ui/element-list.blp:24 assets/ui/label-list.blp:7 123 | #: assets/ui/label-list.blp:7 assets/ui/element-list.blp:24 124 | msgid "Label" 125 | msgstr "" 126 | 127 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 128 | #: assets/ui/element-list.blp:34 assets/ui/prefs.blp:102 129 | #: assets/ui/prefs.blp:102 assets/ui/element-list.blp:34 130 | msgid "Player controls" 131 | msgstr "" 132 | 133 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 134 | #: assets/ui/label-list.blp:20 135 | msgid "Add item" 136 | msgstr "" 137 | 138 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 139 | #: assets/ui/label-list.blp:26 140 | msgid "Add custom text" 141 | msgstr "" 142 | 143 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 assets/ui/prefs.blp:8 144 | msgid "General" 145 | msgstr "" 146 | 147 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 assets/ui/prefs.blp:12 148 | msgid "Common" 149 | msgstr "" 150 | 151 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 assets/ui/prefs.blp:15 152 | msgid "Labels" 153 | msgstr "" 154 | 155 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 assets/ui/prefs.blp:16 156 | msgid "Customize the labels in the panel and the popup menu" 157 | msgstr "" 158 | 159 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 assets/ui/prefs.blp:32 160 | msgid "Fixed width" 161 | msgstr "" 162 | 163 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 assets/ui/prefs.blp:33 164 | msgid "Use the specified width even when they are smaller than the width" 165 | msgstr "" 166 | 167 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 assets/ui/prefs.blp:37 168 | msgid "Scroll labels" 169 | msgstr "" 170 | 171 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 assets/ui/prefs.blp:38 172 | msgid "Scroll the labels when they are wider than the width" 173 | msgstr "" 174 | 175 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 assets/ui/prefs.blp:44 176 | msgid "Hide the media notification" 177 | msgstr "" 178 | 179 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 assets/ui/prefs.blp:45 180 | msgid "Hide the media notifications in the notification list" 181 | msgstr "" 182 | 183 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 assets/ui/prefs.blp:51 184 | msgid "Information" 185 | msgstr "" 186 | 187 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 assets/ui/prefs.blp:54 188 | msgid "Homepage" 189 | msgstr "" 190 | 191 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 assets/ui/prefs.blp:66 192 | msgid "Release notes" 193 | msgstr "" 194 | 195 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 196 | #: assets/ui/prefs.blp:82 assets/ui/prefs.blp:78 assets/ui/prefs.blp:82 197 | msgid "Report an issue" 198 | msgstr "" 199 | 200 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 assets/ui/prefs.blp:93 201 | msgid "Panel" 202 | msgstr "" 203 | 204 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 assets/ui/prefs.blp:98 205 | msgid "Show label" 206 | msgstr "" 207 | 208 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 assets/ui/prefs.blp:106 209 | msgid "Show player controls" 210 | msgstr "" 211 | 212 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 assets/ui/prefs.blp:110 213 | msgid "Show play/pause button" 214 | msgstr "" 215 | 216 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 assets/ui/prefs.blp:115 217 | msgid "Show next track button" 218 | msgstr "" 219 | 220 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 assets/ui/prefs.blp:120 221 | msgid "Show previous track button" 222 | msgstr "" 223 | 224 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 assets/ui/prefs.blp:125 225 | msgid "Show seek forward button" 226 | msgstr "" 227 | 228 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 assets/ui/prefs.blp:130 229 | msgid "Show seek back button" 230 | msgstr "" 231 | 232 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 assets/ui/prefs.blp:140 233 | msgid "Show player icon" 234 | msgstr "" 235 | 236 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 assets/ui/prefs.blp:144 237 | msgid "Colored player icon" 238 | msgstr "" 239 | 240 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 assets/ui/prefs.blp:152 241 | msgid "Positions" 242 | msgstr "" 243 | 244 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 assets/ui/prefs.blp:156 245 | msgid "Extension" 246 | msgstr "" 247 | 248 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 assets/ui/prefs.blp:159 249 | msgid "Position" 250 | msgstr "" 251 | 252 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 assets/ui/prefs.blp:160 253 | msgid "Position of the extension in the panel" 254 | msgstr "" 255 | 256 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 assets/ui/prefs.blp:164 257 | msgid "Left" 258 | msgstr "" 259 | 260 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 assets/ui/prefs.blp:165 261 | msgid "Center" 262 | msgstr "" 263 | 264 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 assets/ui/prefs.blp:166 265 | msgid "Right" 266 | msgstr "" 267 | 268 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 assets/ui/prefs.blp:172 269 | msgid "Index" 270 | msgstr "" 271 | 272 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 assets/ui/prefs.blp:173 273 | msgid "Index of the extension" 274 | msgstr "" 275 | 276 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 assets/ui/prefs.blp:190 277 | msgid "Shortcuts" 278 | msgstr "" 279 | 280 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 281 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:195 assets/ui/prefs.blp:320 282 | msgid "Show popup menu" 283 | msgstr "" 284 | 285 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 assets/ui/prefs.blp:196 286 | msgid "Shortcut to toggle the popup menu" 287 | msgstr "" 288 | 289 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 290 | #: assets/ui/prefs.blp:277 assets/ui/prefs.blp:200 assets/ui/prefs.blp:277 291 | msgid "Set shortcut" 292 | msgstr "" 293 | 294 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 assets/ui/prefs.blp:208 295 | msgid "Mouse actions" 296 | msgstr "" 297 | 298 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 assets/ui/prefs.blp:211 299 | msgid "Left click / Tap" 300 | msgstr "" 301 | 302 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 assets/ui/prefs.blp:216 303 | msgid "Middle click" 304 | msgstr "" 305 | 306 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 assets/ui/prefs.blp:221 307 | msgid "Right click" 308 | msgstr "" 309 | 310 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 assets/ui/prefs.blp:226 311 | msgid "Double click / Double tap" 312 | msgstr "" 313 | 314 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 assets/ui/prefs.blp:231 315 | msgid "Scroll up / Swipe right" 316 | msgstr "" 317 | 318 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 assets/ui/prefs.blp:236 319 | msgid "Scroll down / Swipe left" 320 | msgstr "" 321 | 322 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 assets/ui/prefs.blp:243 323 | msgid "Other" 324 | msgstr "" 325 | 326 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 assets/ui/prefs.blp:247 327 | msgid "Cache" 328 | msgstr "" 329 | 330 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 assets/ui/prefs.blp:248 331 | msgid "" 332 | "This extension cache album art to improve performance. You can clear the " 333 | "cache here." 334 | msgstr "" 335 | 336 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 assets/ui/prefs.blp:251 337 | msgid "Cache album art" 338 | msgstr "" 339 | 340 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 assets/ui/prefs.blp:266 341 | msgid "Clear" 342 | msgstr "" 343 | 344 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 assets/ui/prefs.blp:293 345 | msgid "" 346 | "Press escape to cancel.\n" 347 | "Press enter to set the shortcut.\n" 348 | "Press backspace to reset." 349 | msgstr "" 350 | 351 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 assets/ui/prefs.blp:299 352 | msgid "Press shortcut" 353 | msgstr "" 354 | 355 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 assets/ui/prefs.blp:310 356 | msgid "None" 357 | msgstr "" 358 | 359 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 assets/ui/prefs.blp:311 360 | msgid "Play/Pause" 361 | msgstr "" 362 | 363 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 assets/ui/prefs.blp:312 364 | msgid "Play" 365 | msgstr "" 366 | 367 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 assets/ui/prefs.blp:313 368 | msgid "Pause" 369 | msgstr "" 370 | 371 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 assets/ui/prefs.blp:314 372 | msgid "Next track" 373 | msgstr "" 374 | 375 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 assets/ui/prefs.blp:315 376 | msgid "Previous track" 377 | msgstr "" 378 | 379 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 assets/ui/prefs.blp:316 380 | msgid "Volume up" 381 | msgstr "" 382 | 383 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 assets/ui/prefs.blp:317 384 | msgid "Volume down" 385 | msgstr "" 386 | 387 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 assets/ui/prefs.blp:318 388 | msgid "Toggle loop" 389 | msgstr "" 390 | 391 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 assets/ui/prefs.blp:319 392 | msgid "Toggle shuffle" 393 | msgstr "" 394 | 395 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 assets/ui/prefs.blp:321 396 | msgid "Raise player" 397 | msgstr "" 398 | 399 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 assets/ui/prefs.blp:322 400 | msgid "Quit player" 401 | msgstr "" 402 | 403 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 assets/ui/prefs.blp:323 404 | msgid "Open preferences" 405 | msgstr "" 406 | 407 | #: src/helpers/prefs/LabelList.ts:97 src/helpers/prefs/LabelList.ts:97 408 | msgid "Custom text" 409 | msgstr "" 410 | 411 | #: assets/ui/prefs.blp:20 assets/ui/prefs.blp:20 412 | msgid "Width" 413 | msgstr "" 414 | 415 | #: assets/ui/prefs.blp:21 assets/ui/prefs.blp:21 416 | msgid "0 to take all available space" 417 | msgstr "" 418 | 419 | #: src/helpers/shell/PanelButton.ts:258 420 | msgid "Unknown player" 421 | msgstr "" 422 | 423 | #: src/helpers/shell/PanelButton.ts:434 424 | msgid "Unknown artist" 425 | msgstr "" 426 | 427 | #: src/helpers/shell/PanelButton.ts:745 428 | msgid "Unknown album" 429 | msgstr "" 430 | -------------------------------------------------------------------------------- /assets/locale/pt_BR.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 12 | "PO-Revision-Date: 2024-05-21 11:37-0300\n" 13 | "Last-Translator: Andrey R. Visniewski\n" 14 | "Language-Team: portugues brasil\n" 15 | "Language: pt_BR\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "X-Generator: Poedit 3.4.3\n" 20 | 21 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 22 | #: src/prefs.ts:203 src/prefs.ts:205 src/prefs.ts:202 23 | msgid "Are you sure you want to clear the cache?" 24 | msgstr "Tem certeza de que deseja limpar o cache?" 25 | 26 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 27 | #: src/prefs.ts:196 src/prefs.ts:195 src/prefs.ts:204 src/prefs.ts:206 28 | #: src/prefs.ts:203 assets/ui/app-chooser.blp:21 29 | msgid "Cancel" 30 | msgstr "Cancelar" 31 | 32 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 33 | #: src/prefs.ts:196 src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 34 | #: assets/ui/prefs.blp:255 35 | msgid "Clear cache" 36 | msgstr "Limpar cache" 37 | 38 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 39 | #: src/prefs.ts:204 src/prefs.ts:213 src/prefs.ts:203 src/prefs.ts:212 40 | #: src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 41 | #: src/prefs.ts:220 42 | #, javascript-format 43 | msgid "Cache size: %s" 44 | msgstr "Tamanho do cache: %s" 45 | 46 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 47 | #: src/prefs.ts:304 src/prefs.ts:306 src/prefs.ts:303 48 | msgid "Cache cleared successfully!" 49 | msgstr "Cache limpo com sucesso!" 50 | 51 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 52 | #: src/prefs.ts:306 src/prefs.ts:308 src/prefs.ts:305 53 | msgid "Failed to clear cache!" 54 | msgstr "Falha ao limpar o cache!" 55 | 56 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 57 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 58 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 59 | msgid "" 60 | "No players are blacklisted" 62 | msgstr "" 63 | "Nenhum Reprodutor de mídia " 64 | "é colocada na lista negra" 65 | 66 | #: src/helpers/LabelList.ts:9 67 | msgid "Artist" 68 | msgstr "Artista" 69 | 70 | #: src/helpers/LabelList.ts:10 71 | msgid "Title" 72 | msgstr "Título" 73 | 74 | #: src/helpers/LabelList.ts:11 75 | msgid "Album" 76 | msgstr "Álbum" 77 | 78 | #: src/helpers/LabelList.ts:12 79 | msgid "Disc Number" 80 | msgstr "Número do disco" 81 | 82 | #: src/helpers/LabelList.ts:13 83 | msgid "Track Number" 84 | msgstr "Número da Faixa" 85 | 86 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 87 | msgid "Select app to blacklist" 88 | msgstr "Selecione o aplicativo para colocar na lista negra" 89 | 90 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 91 | msgid "Select" 92 | msgstr "Selecionar" 93 | 94 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 95 | msgid "Blacklist players" 96 | msgstr "Lista negra dos Reprodutores de mídia" 97 | 98 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 99 | msgid "Blacklisted players will be ignored by the extension." 100 | msgstr "" 101 | "Os Reprodutores de mídia na lista negra serão ignorados pela extensão." 102 | 103 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 104 | msgid "Add" 105 | msgstr "Adicionar" 106 | 107 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 108 | msgid "Elements" 109 | msgstr "Elementos" 110 | 111 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 112 | #: assets/ui/element-list.blp:14 assets/ui/prefs.blp:136 113 | msgid "Player icon" 114 | msgstr "Ícone do Reprodutor de mídia" 115 | 116 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 117 | #: assets/ui/element-list.blp:24 assets/ui/label-list.blp:7 118 | msgid "Label" 119 | msgstr "Legenda" 120 | 121 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 122 | #: assets/ui/element-list.blp:34 assets/ui/prefs.blp:102 123 | msgid "Player controls" 124 | msgstr "Controles do Reprodutor de mídia" 125 | 126 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 127 | msgid "Add item" 128 | msgstr "Adicionar item" 129 | 130 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 131 | msgid "Add custom text" 132 | msgstr "Adicionar texto customizado" 133 | 134 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 135 | msgid "General" 136 | msgstr "Geral" 137 | 138 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 139 | msgid "Common" 140 | msgstr "Comum" 141 | 142 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 143 | msgid "Labels" 144 | msgstr "Legendas" 145 | 146 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 147 | msgid "Customize the labels in the panel and the popup menu" 148 | msgstr "Personalize as legendas no painel e no menu pop-up" 149 | 150 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 151 | msgid "Fixed width" 152 | msgstr "Largura fixa" 153 | 154 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 155 | msgid "Use the specified width even when they are smaller than the width" 156 | msgstr "Use a largura especificada mesmo quando forem menores que a largura" 157 | 158 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 159 | msgid "Scroll labels" 160 | msgstr "Rolar legendas" 161 | 162 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 163 | msgid "Scroll the labels when they are wider than the width" 164 | msgstr "Role as legendas quando elas forem mais largas que a largura" 165 | 166 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 167 | msgid "Hide the media notification" 168 | msgstr "Ocultar a notificação de mídia" 169 | 170 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 171 | msgid "Hide the media notifications in the notification list" 172 | msgstr "Oculte as notificações de mídia na lista de notificações" 173 | 174 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 175 | msgid "Information" 176 | msgstr "Informação" 177 | 178 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 179 | msgid "Homepage" 180 | msgstr "Pagina inicial" 181 | 182 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 183 | msgid "Release notes" 184 | msgstr "Notas de lançamento" 185 | 186 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 187 | #: assets/ui/prefs.blp:82 188 | msgid "Report an issue" 189 | msgstr "Informar um problema" 190 | 191 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 192 | msgid "Panel" 193 | msgstr "Painel" 194 | 195 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 196 | msgid "Show label" 197 | msgstr "Mostrar legenda" 198 | 199 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 200 | msgid "Show player controls" 201 | msgstr "Mostrar controles do reprodutor de mídia" 202 | 203 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 204 | msgid "Show play/pause button" 205 | msgstr "Mostrar botão play/pause" 206 | 207 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 208 | msgid "Show next track button" 209 | msgstr "Mostrar botão da próxima musica" 210 | 211 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 212 | msgid "Show previous track button" 213 | msgstr "Mostrar botão da musica anterior" 214 | 215 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 216 | msgid "Show seek forward button" 217 | msgstr "Mostrar botão de busca para frente" 218 | 219 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 220 | msgid "Show seek back button" 221 | msgstr "Mostrar botão de busca de retorno" 222 | 223 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 224 | msgid "Show player icon" 225 | msgstr "Mostrar ícone do reprodutor de mídia" 226 | 227 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 228 | msgid "Colored player icon" 229 | msgstr "Colorir ícone do reprodutor de mídia" 230 | 231 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 232 | msgid "Positions" 233 | msgstr "Posições" 234 | 235 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 236 | msgid "Extension" 237 | msgstr "Extensão" 238 | 239 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 240 | msgid "Position" 241 | msgstr "Posição" 242 | 243 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 244 | msgid "Position of the extension in the panel" 245 | msgstr "Posição da extensão no painel" 246 | 247 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 248 | msgid "Left" 249 | msgstr "Esquerda" 250 | 251 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 252 | msgid "Center" 253 | msgstr "Centro" 254 | 255 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 256 | msgid "Right" 257 | msgstr "Direita" 258 | 259 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 260 | msgid "Index" 261 | msgstr "Índice" 262 | 263 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 264 | msgid "Index of the extension" 265 | msgstr "Índice da extensão" 266 | 267 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 268 | msgid "Shortcuts" 269 | msgstr "Atalhos" 270 | 271 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 272 | #: assets/ui/prefs.blp:320 273 | msgid "Show popup menu" 274 | msgstr "Mostrar menu pop-up" 275 | 276 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 277 | msgid "Shortcut to toggle the popup menu" 278 | msgstr "Atalho para alternar o menu pop-up" 279 | 280 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 281 | #: assets/ui/prefs.blp:277 282 | msgid "Set shortcut" 283 | msgstr "Definir atalho" 284 | 285 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 286 | msgid "Mouse actions" 287 | msgstr "Ações do mouse" 288 | 289 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 290 | msgid "Left click / Tap" 291 | msgstr "Clique esquerdo/ toque" 292 | 293 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 294 | msgid "Middle click" 295 | msgstr "Clique com a rodinha do mouse" 296 | 297 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 298 | msgid "Right click" 299 | msgstr "Clique com o botão direito" 300 | 301 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 302 | msgid "Double click / Double tap" 303 | msgstr "Clique duplo / toque duplo" 304 | 305 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 306 | msgid "Scroll up / Swipe right" 307 | msgstr "Rolar para cima / deslizar para a direita" 308 | 309 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 310 | msgid "Scroll down / Swipe left" 311 | msgstr "Role para baixo / deslize para a esquerda" 312 | 313 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 314 | msgid "Other" 315 | msgstr "Outro" 316 | 317 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 318 | msgid "Cache" 319 | msgstr "Cache" 320 | 321 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 322 | msgid "" 323 | "This extension cache album art to improve performance. You can clear the " 324 | "cache here." 325 | msgstr "" 326 | "Esta extensão armazena em cache a arte do álbum para melhorar o desempenho. " 327 | "Você pode limpar o cache aqui." 328 | 329 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 330 | msgid "Cache album art" 331 | msgstr "Arte do álbum em cache" 332 | 333 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 334 | msgid "Clear" 335 | msgstr "Limpar" 336 | 337 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 338 | msgid "" 339 | "Press escape to cancel.\n" 340 | "Press enter to set the shortcut.\n" 341 | "Press backspace to reset." 342 | msgstr "" 343 | "Pressione espaço para cancelar.\n" 344 | "Pressione Enter para definir o atalho.\n" 345 | "Pressione backspace para redefinir." 346 | 347 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 348 | msgid "Press shortcut" 349 | msgstr "Pressione o atalho" 350 | 351 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 352 | msgid "None" 353 | msgstr "Nenhum" 354 | 355 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 356 | msgid "Play/Pause" 357 | msgstr "Reproduzir/Pausar" 358 | 359 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 360 | msgid "Play" 361 | msgstr "Play" 362 | 363 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 364 | msgid "Pause" 365 | msgstr "Pausar" 366 | 367 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 368 | msgid "Next track" 369 | msgstr "Próxima música" 370 | 371 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 372 | msgid "Previous track" 373 | msgstr "Música anterior" 374 | 375 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 376 | msgid "Volume up" 377 | msgstr "Aumentar o volume" 378 | 379 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 380 | msgid "Volume down" 381 | msgstr "Diminuir volume" 382 | 383 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 384 | msgid "Toggle loop" 385 | msgstr "Alternar loop" 386 | 387 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 388 | msgid "Toggle shuffle" 389 | msgstr "Alternar ordem aleatória" 390 | 391 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 392 | msgid "Raise player" 393 | msgstr "Aumentar o reprodutor de mídia" 394 | 395 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 396 | msgid "Quit player" 397 | msgstr "Sair do reprodutor de mídia" 398 | 399 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 400 | msgid "Open preferences" 401 | msgstr "Abrir preferências" 402 | 403 | #: src/helpers/prefs/LabelList.ts:97 404 | msgid "Custom text" 405 | msgstr "Texto personalizado" 406 | 407 | #: assets/ui/prefs.blp:20 408 | msgid "Width" 409 | msgstr "Largura" 410 | 411 | #: assets/ui/prefs.blp:21 412 | msgid "0 to take all available space" 413 | msgstr "0 para ocupar todo o espaço disponível" 414 | 415 | #: src/helpers/shell/PanelButton.ts:258 416 | msgid "Unknown player" 417 | msgstr "Reprodutor de mídia desconhecido" 418 | 419 | #: src/helpers/shell/PanelButton.ts:434 420 | msgid "Unknown artist" 421 | msgstr "Artista desconhecido" 422 | 423 | #: src/helpers/shell/PanelButton.ts:745 424 | msgid "Unknown album" 425 | msgstr "Álbum desconhecido" 426 | -------------------------------------------------------------------------------- /assets/locale/ru.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2024-01-13 11:19+0100\n" 12 | "PO-Revision-Date: 2024-10-27 11:10+1100\n" 13 | "Last-Translator: Aleksandr Shamaraev \n" 14 | "Language-Team: \n" 15 | "Language: ru\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "X-Generator: Poedit 3.5\n" 20 | 21 | #: src/prefs.ts:125 src/prefs.ts:192 src/prefs.ts:195 src/prefs.ts:194 22 | #: src/prefs.ts:203 src/prefs.ts:205 src/prefs.ts:202 23 | msgid "Are you sure you want to clear the cache?" 24 | msgstr "Вы уверены, что хотите очистить кэш?" 25 | 26 | #: src/prefs.ts:126 assets/ui/app-chooser.blp:19 src/prefs.ts:193 27 | #: src/prefs.ts:196 src/prefs.ts:195 src/prefs.ts:204 src/prefs.ts:206 28 | #: src/prefs.ts:203 assets/ui/app-chooser.blp:21 29 | msgid "Cancel" 30 | msgstr "Отмена" 31 | 32 | #: src/prefs.ts:127 assets/ui/prefs.blp:253 src/prefs.ts:194 src/prefs.ts:197 33 | #: src/prefs.ts:196 src/prefs.ts:205 src/prefs.ts:207 src/prefs.ts:204 34 | #: assets/ui/prefs.blp:255 35 | msgid "Clear cache" 36 | msgstr "Очистить кэш" 37 | 38 | #: src/prefs.ts:134 src/prefs.ts:143 src/prefs.ts:201 src/prefs.ts:210 39 | #: src/prefs.ts:204 src/prefs.ts:213 src/prefs.ts:203 src/prefs.ts:212 40 | #: src/prefs.ts:221 src/prefs.ts:214 src/prefs.ts:223 src/prefs.ts:211 41 | #: src/prefs.ts:220 42 | #, javascript-format 43 | msgid "Cache size: %s" 44 | msgstr "Размер кэша: %s" 45 | 46 | #: src/prefs.ts:226 src/prefs.ts:293 src/prefs.ts:296 src/prefs.ts:295 47 | #: src/prefs.ts:304 src/prefs.ts:306 src/prefs.ts:303 48 | msgid "Cache cleared successfully!" 49 | msgstr "Кэш успешно очищен!" 50 | 51 | #: src/prefs.ts:228 src/prefs.ts:295 src/prefs.ts:298 src/prefs.ts:297 52 | #: src/prefs.ts:306 src/prefs.ts:308 src/prefs.ts:305 53 | msgid "Failed to clear cache!" 54 | msgstr "Не удалось очистить кэш!" 55 | 56 | #: src/helpers/BlacklistedPlayers.ts:50 src/helpers/BlacklistedPlayers.ts:47 57 | #: src/helpers/prefs/BlacklistedPlayers.ts:47 58 | #: src/helpers/prefs/BlacklistedPlayers.ts:50 59 | msgid "" 60 | "No players are blacklisted" 62 | msgstr "" 63 | "Нет плееров в черном " 64 | "списке" 65 | 66 | #: src/helpers/LabelList.ts:9 67 | msgid "Artist" 68 | msgstr "Артист" 69 | 70 | #: src/helpers/LabelList.ts:10 71 | msgid "Title" 72 | msgstr "Название" 73 | 74 | #: src/helpers/LabelList.ts:11 75 | msgid "Album" 76 | msgstr "Альбом" 77 | 78 | #: src/helpers/LabelList.ts:12 79 | msgid "Disc Number" 80 | msgstr "Номер диска" 81 | 82 | #: src/helpers/LabelList.ts:13 83 | msgid "Track Number" 84 | msgstr "Номер трека" 85 | 86 | #: assets/ui/app-chooser.blp:5 assets/ui/app-chooser.blp:7 87 | msgid "Select app to blacklist" 88 | msgstr "Выберите приложение для добавления в черный список" 89 | 90 | #: assets/ui/app-chooser.blp:24 assets/ui/app-chooser.blp:26 91 | msgid "Select" 92 | msgstr "Выбрать" 93 | 94 | #: assets/ui/blacklisted-players.blp:5 assets/ui/blacklisted-players.blp:7 95 | msgid "Blacklist players" 96 | msgstr "Черный список плееров" 97 | 98 | #: assets/ui/blacklisted-players.blp:6 assets/ui/blacklisted-players.blp:8 99 | msgid "Blacklisted players will be ignored by the extension." 100 | msgstr "Расширение будет игнорировать плееры, занесенные в черный список." 101 | 102 | #: assets/ui/blacklisted-players.blp:17 assets/ui/blacklisted-players.blp:19 103 | msgid "Add" 104 | msgstr "Добавить" 105 | 106 | #: assets/ui/element-list.blp:5 assets/ui/element-list.blp:7 107 | msgid "Elements" 108 | msgstr "Элементы" 109 | 110 | #: assets/ui/element-list.blp:12 assets/ui/prefs.blp:134 111 | #: assets/ui/element-list.blp:14 assets/ui/prefs.blp:136 112 | msgid "Player icon" 113 | msgstr "Иконка плеера" 114 | 115 | #: assets/ui/element-list.blp:22 assets/ui/label-list.blp:5 116 | #: assets/ui/element-list.blp:24 assets/ui/label-list.blp:7 117 | msgid "Label" 118 | msgstr "Заголовок" 119 | 120 | #: assets/ui/element-list.blp:32 assets/ui/prefs.blp:100 121 | #: assets/ui/element-list.blp:34 assets/ui/prefs.blp:102 122 | msgid "Player controls" 123 | msgstr "Управление плеером" 124 | 125 | #: assets/ui/label-list.blp:18 assets/ui/label-list.blp:20 126 | msgid "Add item" 127 | msgstr "Добавить элемент" 128 | 129 | #: assets/ui/label-list.blp:24 assets/ui/label-list.blp:26 130 | msgid "Add custom text" 131 | msgstr "Добавить собственный текст" 132 | 133 | #: assets/ui/prefs.blp:6 assets/ui/prefs.blp:8 134 | msgid "General" 135 | msgstr "Главные" 136 | 137 | #: assets/ui/prefs.blp:10 assets/ui/prefs.blp:12 138 | msgid "Common" 139 | msgstr "Общие" 140 | 141 | #: assets/ui/prefs.blp:13 assets/ui/prefs.blp:15 142 | msgid "Labels" 143 | msgstr "Заголовки" 144 | 145 | #: assets/ui/prefs.blp:14 assets/ui/prefs.blp:16 146 | msgid "Customize the labels in the panel and the popup menu" 147 | msgstr "Настройка заголовка на панели и во всплывающем меню" 148 | 149 | #: assets/ui/prefs.blp:30 assets/ui/prefs.blp:32 150 | msgid "Fixed width" 151 | msgstr "Фиксированная ширина" 152 | 153 | #: assets/ui/prefs.blp:31 assets/ui/prefs.blp:33 154 | msgid "Use the specified width even when they are smaller than the width" 155 | msgstr "Использовать указанную ширину, даже если она меньше ширины заголовков" 156 | 157 | #: assets/ui/prefs.blp:35 assets/ui/prefs.blp:37 158 | msgid "Scroll labels" 159 | msgstr "Прокручивать заголовок" 160 | 161 | #: assets/ui/prefs.blp:36 assets/ui/prefs.blp:38 162 | msgid "Scroll the labels when they are wider than the width" 163 | msgstr "Прокручивать заголовки, если они шире ширины" 164 | 165 | #: assets/ui/prefs.blp:42 assets/ui/prefs.blp:44 166 | msgid "Hide the media notification" 167 | msgstr "Скрывать медиа уведомления" 168 | 169 | #: assets/ui/prefs.blp:43 assets/ui/prefs.blp:45 170 | msgid "Hide the media notifications in the notification list" 171 | msgstr "Скрыть уведомления мультимедиа в списке уведомлений" 172 | 173 | #: assets/ui/prefs.blp:49 assets/ui/prefs.blp:51 174 | msgid "Information" 175 | msgstr "Информация" 176 | 177 | #: assets/ui/prefs.blp:52 assets/ui/prefs.blp:54 178 | msgid "Homepage" 179 | msgstr "Домашняя страница" 180 | 181 | #: assets/ui/prefs.blp:64 assets/ui/prefs.blp:66 182 | msgid "Release notes" 183 | msgstr "Страница релизов" 184 | 185 | #: assets/ui/prefs.blp:76 assets/ui/prefs.blp:80 assets/ui/prefs.blp:78 186 | #: assets/ui/prefs.blp:82 187 | msgid "Report an issue" 188 | msgstr "Сообщить о проблеме" 189 | 190 | #: assets/ui/prefs.blp:91 assets/ui/prefs.blp:93 191 | msgid "Panel" 192 | msgstr "Панель" 193 | 194 | #: assets/ui/prefs.blp:96 assets/ui/prefs.blp:98 195 | msgid "Show label" 196 | msgstr "Показать заголовок" 197 | 198 | #: assets/ui/prefs.blp:104 assets/ui/prefs.blp:106 199 | msgid "Show player controls" 200 | msgstr "Показать элементы управления плеером" 201 | 202 | #: assets/ui/prefs.blp:108 assets/ui/prefs.blp:110 203 | msgid "Show play/pause button" 204 | msgstr "Показать кнопку воспроизведения/паузы" 205 | 206 | #: assets/ui/prefs.blp:113 assets/ui/prefs.blp:115 207 | msgid "Show next track button" 208 | msgstr "Показать кнопку следующий трек" 209 | 210 | #: assets/ui/prefs.blp:118 assets/ui/prefs.blp:120 211 | msgid "Show previous track button" 212 | msgstr "Показать кнопку предыдущий трек" 213 | 214 | #: assets/ui/prefs.blp:123 assets/ui/prefs.blp:125 215 | msgid "Show seek forward button" 216 | msgstr "Показать кнопку поиск вперед" 217 | 218 | #: assets/ui/prefs.blp:128 assets/ui/prefs.blp:130 219 | msgid "Show seek back button" 220 | msgstr "Показать кнопку поиск назад" 221 | 222 | #: assets/ui/prefs.blp:138 assets/ui/prefs.blp:140 223 | msgid "Show player icon" 224 | msgstr "Показать значок плеера" 225 | 226 | #: assets/ui/prefs.blp:142 assets/ui/prefs.blp:144 227 | msgid "Colored player icon" 228 | msgstr "Цветной значок плеера" 229 | 230 | #: assets/ui/prefs.blp:150 assets/ui/prefs.blp:152 231 | msgid "Positions" 232 | msgstr "Позиции" 233 | 234 | #: assets/ui/prefs.blp:154 assets/ui/prefs.blp:156 235 | msgid "Extension" 236 | msgstr "Расширение" 237 | 238 | #: assets/ui/prefs.blp:157 assets/ui/prefs.blp:159 239 | msgid "Position" 240 | msgstr "Позиция" 241 | 242 | #: assets/ui/prefs.blp:158 assets/ui/prefs.blp:160 243 | msgid "Position of the extension in the panel" 244 | msgstr "Расположение расширения на панели" 245 | 246 | #: assets/ui/prefs.blp:162 assets/ui/prefs.blp:164 247 | msgid "Left" 248 | msgstr "Слева" 249 | 250 | #: assets/ui/prefs.blp:163 assets/ui/prefs.blp:165 251 | msgid "Center" 252 | msgstr "Центр" 253 | 254 | #: assets/ui/prefs.blp:164 assets/ui/prefs.blp:166 255 | msgid "Right" 256 | msgstr "Справа" 257 | 258 | #: assets/ui/prefs.blp:170 assets/ui/prefs.blp:172 259 | msgid "Index" 260 | msgstr "Индекс" 261 | 262 | #: assets/ui/prefs.blp:171 assets/ui/prefs.blp:173 263 | msgid "Index of the extension" 264 | msgstr "Индекс расширения" 265 | 266 | #: assets/ui/prefs.blp:188 assets/ui/prefs.blp:190 267 | msgid "Shortcuts" 268 | msgstr "Ярлыки" 269 | 270 | #: assets/ui/prefs.blp:193 assets/ui/prefs.blp:318 assets/ui/prefs.blp:195 271 | #: assets/ui/prefs.blp:320 272 | msgid "Show popup menu" 273 | msgstr "Всплывающее окно" 274 | 275 | #: assets/ui/prefs.blp:194 assets/ui/prefs.blp:196 276 | msgid "Shortcut to toggle the popup menu" 277 | msgstr "Сочетание клавиш для переключения всплывающего меню" 278 | 279 | #: assets/ui/prefs.blp:198 assets/ui/prefs.blp:275 assets/ui/prefs.blp:200 280 | #: assets/ui/prefs.blp:277 281 | msgid "Set shortcut" 282 | msgstr "Установить сочетание клавиш" 283 | 284 | #: assets/ui/prefs.blp:206 assets/ui/prefs.blp:208 285 | msgid "Mouse actions" 286 | msgstr "Действия мыши" 287 | 288 | #: assets/ui/prefs.blp:209 assets/ui/prefs.blp:211 289 | msgid "Left click / Tap" 290 | msgstr "Левый щелчок / Касание" 291 | 292 | #: assets/ui/prefs.blp:214 assets/ui/prefs.blp:216 293 | msgid "Middle click" 294 | msgstr "Средний щелчок" 295 | 296 | #: assets/ui/prefs.blp:219 assets/ui/prefs.blp:221 297 | msgid "Right click" 298 | msgstr "Правый щелчок" 299 | 300 | #: assets/ui/prefs.blp:224 assets/ui/prefs.blp:226 301 | msgid "Double click / Double tap" 302 | msgstr "Двойной щелчок / Двойное нажатие" 303 | 304 | #: assets/ui/prefs.blp:229 assets/ui/prefs.blp:231 305 | msgid "Scroll up / Swipe right" 306 | msgstr "Прокрутите вверх / Пролистнуть вправо" 307 | 308 | #: assets/ui/prefs.blp:234 assets/ui/prefs.blp:236 309 | msgid "Scroll down / Swipe left" 310 | msgstr "Прокрутите вниз / Пролистнуть влево" 311 | 312 | #: assets/ui/prefs.blp:241 assets/ui/prefs.blp:243 313 | msgid "Other" 314 | msgstr "Другое" 315 | 316 | #: assets/ui/prefs.blp:245 assets/ui/prefs.blp:247 317 | msgid "Cache" 318 | msgstr "Кэш" 319 | 320 | #: assets/ui/prefs.blp:246 assets/ui/prefs.blp:248 321 | msgid "" 322 | "This extension cache album art to improve performance. You can clear the " 323 | "cache here." 324 | msgstr "" 325 | "Это расширение кэширует обложки альбомов для повышения производительности. " 326 | "Вы можете очистить кэш здесь." 327 | 328 | #: assets/ui/prefs.blp:249 assets/ui/prefs.blp:251 329 | msgid "Cache album art" 330 | msgstr "Кэшировать обложку альбома" 331 | 332 | #: assets/ui/prefs.blp:264 assets/ui/prefs.blp:266 333 | msgid "Clear" 334 | msgstr "Очистить" 335 | 336 | #: assets/ui/prefs.blp:291 assets/ui/prefs.blp:293 337 | msgid "" 338 | "Press escape to cancel.\n" 339 | "Press enter to set the shortcut.\n" 340 | "Press backspace to reset." 341 | msgstr "" 342 | "Для отмены нажмите Escape.\n" 343 | "Нажмите Enter, чтобы установить.\n" 344 | "Для сброса нажмите клавишу Backspace." 345 | 346 | #: assets/ui/prefs.blp:297 assets/ui/prefs.blp:299 347 | msgid "Press shortcut" 348 | msgstr "Нажмите сочетание клавиш" 349 | 350 | #: assets/ui/prefs.blp:308 assets/ui/prefs.blp:310 351 | msgid "None" 352 | msgstr "Нет" 353 | 354 | #: assets/ui/prefs.blp:309 assets/ui/prefs.blp:311 355 | msgid "Play/Pause" 356 | msgstr "Воспроизведение/Пауза" 357 | 358 | #: assets/ui/prefs.blp:310 assets/ui/prefs.blp:312 359 | msgid "Play" 360 | msgstr "Играть" 361 | 362 | #: assets/ui/prefs.blp:311 assets/ui/prefs.blp:313 363 | msgid "Pause" 364 | msgstr "Пауза" 365 | 366 | #: assets/ui/prefs.blp:312 assets/ui/prefs.blp:314 367 | msgid "Next track" 368 | msgstr "Следующий трек" 369 | 370 | #: assets/ui/prefs.blp:313 assets/ui/prefs.blp:315 371 | msgid "Previous track" 372 | msgstr "Предыдущий трек" 373 | 374 | #: assets/ui/prefs.blp:314 assets/ui/prefs.blp:316 375 | msgid "Volume up" 376 | msgstr "Увеличить громкость" 377 | 378 | #: assets/ui/prefs.blp:315 assets/ui/prefs.blp:317 379 | msgid "Volume down" 380 | msgstr "Уменьшить громкость" 381 | 382 | #: assets/ui/prefs.blp:316 assets/ui/prefs.blp:318 383 | msgid "Toggle loop" 384 | msgstr "Зацикливание" 385 | 386 | #: assets/ui/prefs.blp:317 assets/ui/prefs.blp:319 387 | msgid "Toggle shuffle" 388 | msgstr "Перемешивание" 389 | 390 | #: assets/ui/prefs.blp:319 assets/ui/prefs.blp:321 391 | msgid "Raise player" 392 | msgstr "Вызвать плеер" 393 | 394 | #: assets/ui/prefs.blp:320 assets/ui/prefs.blp:322 395 | msgid "Quit player" 396 | msgstr "Выйти из плеера" 397 | 398 | #: assets/ui/prefs.blp:321 assets/ui/prefs.blp:323 399 | msgid "Open preferences" 400 | msgstr "Открыть настройки" 401 | 402 | #: src/helpers/prefs/LabelList.ts:97 403 | msgid "Custom text" 404 | msgstr "Пользовательский текст" 405 | 406 | #: assets/ui/prefs.blp:20 407 | msgid "Width" 408 | msgstr "Ширина" 409 | 410 | #: assets/ui/prefs.blp:21 411 | msgid "0 to take all available space" 412 | msgstr "0, чтобы занять все доступное пространство" 413 | 414 | #: src/helpers/shell/PanelButton.ts:258 415 | msgid "Unknown player" 416 | msgstr "Неизвестный плеер" 417 | 418 | #: src/helpers/shell/PanelButton.ts:434 419 | msgid "Unknown artist" 420 | msgstr "Неизвестный артист" 421 | 422 | #: src/helpers/shell/PanelButton.ts:745 423 | msgid "Unknown album" 424 | msgstr "Неизвестный альбом" 425 | -------------------------------------------------------------------------------- /assets/org.gnome.shell.extensions.mediacontrols.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ui/prefs.ui 5 | ui/blacklisted-players.ui 6 | ui/element-list.ui 7 | ui/label-list.ui 8 | ui/app-chooser.ui 9 | 10 | 11 | -------------------------------------------------------------------------------- /assets/org.gnome.shell.extensions.mediacontrols.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 200 27 | 28 | 29 | false 30 | 31 | 32 | true 33 | 34 | 35 | true 36 | 37 | 38 | true 39 | 40 | 41 | true 42 | 43 | 44 | true 45 | 46 | 47 | true 48 | 49 | 50 | true 51 | 52 | 53 | true 54 | 55 | 56 | true 57 | 58 | 59 | true 60 | 61 | 62 | true 63 | 64 | 65 | 'Center' 66 | 67 | 68 | 0 69 | 70 | 71 | ['ICON', 'LABEL', 'CONTROLS'] 72 | 73 | 74 | ['TITLE', '-', 'ARTIST'] 75 | 76 | 77 | 'SHOW_POPUP_MENU' 78 | 79 | 80 | 'OPEN_PREFERENCES' 81 | 82 | 83 | 'RAISE_PLAYER' 84 | 85 | 86 | 'NONE' 87 | 88 | 89 | 'VOLUME_UP' 90 | 91 | 92 | 'VOLUME_DOWN' 93 | 94 | 95 | true 96 | 97 | 98 | [] 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /assets/ui/app-chooser.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | translation-domain "mediacontrols@cliffniff.github.com"; 5 | 6 | template $AppChooser: Adw.Window { 7 | title: _("Select app to blacklist"); 8 | modal: true; 9 | resizable: false; 10 | default-width: 300; 11 | default-height: 600; 12 | hide-on-close: true; 13 | 14 | Adw.ToolbarView { 15 | [top] 16 | Adw.HeaderBar { 17 | decoration-layout: ""; 18 | 19 | [start] 20 | Button cancel-btn { 21 | label: _("Cancel"); 22 | } 23 | 24 | [end] 25 | Button select-btn { 26 | label: _("Select"); 27 | 28 | styles [ 29 | "suggested-action" 30 | ] 31 | } 32 | } 33 | 34 | ScrolledWindow { 35 | ListBox list-box { 36 | selection-mode: single; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /assets/ui/blacklisted-players.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | translation-domain "mediacontrols@cliffniff.github.com"; 5 | 6 | template $BlacklistedPlayers: Adw.PreferencesGroup { 7 | title: _("Blacklist players"); 8 | description: _("Blacklisted players will be ignored by the extension."); 9 | 10 | header-suffix: Button add-btn { 11 | halign: end; 12 | valign: center; 13 | 14 | styles [ 15 | "suggested-action" 16 | ] 17 | 18 | Adw.ButtonContent { 19 | label: _("Add"); 20 | icon-name: "list-add-symbolic"; 21 | } 22 | }; 23 | 24 | ListBox list-box { 25 | selection-mode: none; 26 | styles ["boxed-list"] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /assets/ui/element-list.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | translation-domain "mediacontrols@cliffniff.github.com"; 5 | 6 | template $ElementList: Adw.PreferencesGroup { 7 | title: _("Elements"); 8 | 9 | ListBox list-box { 10 | styles ["boxed-list"] 11 | selection-mode: multiple; 12 | 13 | Adw.ActionRow icon-row { 14 | title: _("Player icon"); 15 | activatable: true; 16 | 17 | [suffix] 18 | Image { 19 | icon-name: "list-drag-handle-symbolic"; 20 | } 21 | } 22 | 23 | Adw.ActionRow label-row { 24 | title: _("Label"); 25 | activatable: true; 26 | 27 | [suffix] 28 | Image { 29 | icon-name: "list-drag-handle-symbolic"; 30 | } 31 | } 32 | 33 | Adw.ActionRow controls-row { 34 | title: _("Player controls"); 35 | activatable: true; 36 | 37 | [suffix] 38 | Image { 39 | icon-name: "list-drag-handle-symbolic"; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /assets/ui/label-list.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | translation-domain "mediacontrols@cliffniff.github.com"; 5 | 6 | template $LabelList: Adw.PreferencesGroup { 7 | title: _("Label"); 8 | 9 | header-suffix: Box { 10 | halign: end; 11 | valign: center; 12 | margin-top: 10; 13 | margin-bottom: 10; 14 | 15 | styles [ 16 | "linked" 17 | ] 18 | 19 | Button add-item-btn { 20 | label: _("Add item"); 21 | halign: end; 22 | valign: center; 23 | } 24 | 25 | Button add-text-btn { 26 | label: _("Add custom text"); 27 | halign: end; 28 | valign: center; 29 | } 30 | }; 31 | 32 | ListBox list-box { 33 | selection-mode: none; 34 | styles [ "boxed-list" ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /assets/ui/prefs.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Gio 2.0; 3 | using Adw 1; 4 | 5 | translation-domain "mediacontrols@cliffniff.github.com"; 6 | 7 | Adw.PreferencesPage page-general { 8 | title: _("General"); 9 | icon-name: "preferences-system-symbolic"; 10 | 11 | Adw.PreferencesGroup { 12 | title: _("Common"); 13 | 14 | Adw.ExpanderRow { 15 | title: _("Labels"); 16 | subtitle: _("Customize the labels in the panel and the popup menu"); 17 | expanded: true; 18 | 19 | Adw.SpinRow sr-general-label-width { 20 | title: _("Width"); 21 | subtitle: _("0 to take all available space"); 22 | 23 | adjustment: Adjustment { 24 | lower: 0; 25 | upper: 1000; 26 | step-increment: 10; 27 | value: 200; 28 | }; 29 | } 30 | 31 | Adw.SwitchRow sr-general-label-fixed { 32 | title: _("Fixed width"); 33 | subtitle: _("Use the specified width even when they are smaller than the width"); 34 | } 35 | 36 | Adw.SwitchRow sr-general-scroll-labels { 37 | title: _("Scroll labels"); 38 | subtitle: _("Scroll the labels when they are wider than the width"); 39 | } 40 | 41 | } 42 | 43 | Adw.SwitchRow sr-general-hide-media-notification { 44 | title: _("Hide the media notification"); 45 | subtitle: _("Hide the media notifications in the notification list"); 46 | } 47 | 48 | } 49 | 50 | Adw.PreferencesGroup { 51 | title: _("Information"); 52 | 53 | Adw.ActionRow { 54 | title: _("Homepage"); 55 | activatable-widget: lb-general-homepage; 56 | 57 | LinkButton lb-general-homepage { 58 | icon-name: "go-next-symbolic"; 59 | uri: "https://github.com/sakithb/media-controls/blob/main/README.md"; 60 | margin-top: 10; 61 | margin-bottom: 10; 62 | } 63 | } 64 | 65 | Adw.ActionRow { 66 | title: _("Release notes"); 67 | activatable-widget: lb-general-notes; 68 | 69 | LinkButton lb-general-notes { 70 | icon-name: "go-next-symbolic"; 71 | uri: "https://github.com/sakithb/media-controls/releases/latest"; 72 | margin-top: 10; 73 | margin-bottom: 10; 74 | } 75 | } 76 | 77 | Adw.ActionRow { 78 | title: _("Report an issue"); 79 | activatable-widget: lb-general-issues; 80 | 81 | LinkButton lb-general-issues { 82 | label: _("Report an issue"); 83 | icon-name: "go-next-symbolic"; 84 | uri: "https://github.com/sakithb/media-controls/issues"; 85 | margin-top: 10; 86 | margin-bottom: 10; 87 | } 88 | } 89 | } 90 | } 91 | 92 | Adw.PreferencesPage page-panel { 93 | title: _("Panel"); 94 | icon-name: "user-desktop-symbolic"; 95 | 96 | Adw.PreferencesGroup { 97 | Adw.SwitchRow sr-panel-show-label { 98 | title: _("Show label"); 99 | } 100 | 101 | Adw.ExpanderRow { 102 | title: _("Player controls"); 103 | expanded: true; 104 | 105 | Adw.SwitchRow sr-panel-show-controls { 106 | title: _("Show player controls"); 107 | } 108 | 109 | Adw.SwitchRow sr-panel-show-play { 110 | title: _("Show play/pause button"); 111 | sensitive: bind sr-panel-show-controls.active; 112 | } 113 | 114 | Adw.SwitchRow sr-panel-show-next { 115 | title: _("Show next track button"); 116 | sensitive: bind sr-panel-show-controls.active; 117 | } 118 | 119 | Adw.SwitchRow sr-panel-show-prev { 120 | title: _("Show previous track button"); 121 | sensitive: bind sr-panel-show-controls.active; 122 | } 123 | 124 | Adw.SwitchRow sr-panel-show-seek-forward { 125 | title: _("Show seek forward button"); 126 | sensitive: bind sr-panel-show-controls.active; 127 | } 128 | 129 | Adw.SwitchRow sr-panel-show-seek-backward { 130 | title: _("Show seek back button"); 131 | sensitive: bind sr-panel-show-controls.active; 132 | } 133 | } 134 | 135 | Adw.ExpanderRow { 136 | title: _("Player icon"); 137 | expanded: true; 138 | 139 | Adw.SwitchRow sr-panel-show-player { 140 | title: _("Show player icon"); 141 | } 142 | 143 | Adw.SwitchRow sr-panel-colored-player { 144 | title: _("Colored player icon"); 145 | sensitive: bind sr-panel-show-player.active; 146 | } 147 | } 148 | } 149 | } 150 | 151 | Adw.PreferencesPage page-positions { 152 | title: _("Positions"); 153 | icon-name: "view-list-symbolic"; 154 | 155 | Adw.PreferencesGroup { 156 | title: _("Extension"); 157 | 158 | Adw.ComboRow cr-positions-extension-position { 159 | title: _("Position"); 160 | subtitle: _("Position of the extension in the panel"); 161 | 162 | model: StringList { 163 | strings [ 164 | _("Left"), 165 | _("Center"), 166 | _("Right"), 167 | ] 168 | }; 169 | } 170 | 171 | Adw.SpinRow sr-positions-extension-index { 172 | title: _("Index"); 173 | subtitle: _("Index of the extension"); 174 | 175 | adjustment: Adjustment { 176 | lower: 0; 177 | upper: 100; 178 | value: 0; 179 | step-increment: 1; 180 | }; 181 | } 182 | } 183 | 184 | $ElementList gp-positions-elements {} 185 | 186 | $LabelList gp-positions-labels {} 187 | } 188 | 189 | Adw.PreferencesPage page-shortcuts { 190 | title: _("Shortcuts"); 191 | icon-name: "input-keyboard-symbolic"; 192 | 193 | Adw.PreferencesGroup { 194 | Adw.ActionRow row-shortcuts-popup { 195 | title: _("Show popup menu"); 196 | subtitle: _("Shortcut to toggle the popup menu"); 197 | activatable-widget: sl-shortcuts-popup; 198 | 199 | ShortcutLabel sl-shortcuts-popup { 200 | disabled-text: _("Set shortcut"); 201 | halign: center; 202 | valign: center; 203 | } 204 | } 205 | } 206 | 207 | Adw.PreferencesGroup { 208 | title: _("Mouse actions"); 209 | 210 | Adw.ComboRow cr-shortcuts-mouse-left { 211 | title: _("Left click / Tap"); 212 | model: mouse-actions; 213 | } 214 | 215 | Adw.ComboRow cr-shortcuts-mouse-middle { 216 | title: _("Middle click"); 217 | model: mouse-actions; 218 | } 219 | 220 | Adw.ComboRow cr-shortcuts-mouse-right { 221 | title: _("Right click"); 222 | model: mouse-actions; 223 | } 224 | 225 | Adw.ComboRow cr-shortcuts-mouse-double { 226 | title: _("Double click / Double tap"); 227 | model: mouse-actions; 228 | } 229 | 230 | Adw.ComboRow cr-shortcuts-mouse-scroll-up { 231 | title: _("Scroll up / Swipe right"); 232 | model: mouse-actions; 233 | } 234 | 235 | Adw.ComboRow cr-shortcuts-mouse-scroll-down { 236 | title: _("Scroll down / Swipe left"); 237 | model: mouse-actions; 238 | } 239 | } 240 | } 241 | 242 | Adw.PreferencesPage page-other { 243 | title: _("Other"); 244 | icon-name: "preferences-other-symbolic"; 245 | 246 | Adw.PreferencesGroup { 247 | title: _("Cache"); 248 | description: _("This extension cache album art to improve performance. You can clear the cache here."); 249 | 250 | Adw.SwitchRow sr-other-cache { 251 | title: _("Cache album art"); 252 | } 253 | 254 | Adw.ActionRow row-other-cache-clear { 255 | title: _("Clear cache"); 256 | 257 | Button btn-other-cache-clear { 258 | halign: end; 259 | valign: center; 260 | 261 | styles [ 262 | "destructive-action" 263 | ] 264 | 265 | Adw.ButtonContent { 266 | label: _("Clear"); 267 | icon-name: "user-trash-symbolic"; 268 | } 269 | } 270 | } 271 | } 272 | 273 | $BlacklistedPlayers gp-other-blacklist {} 274 | } 275 | 276 | Adw.Window win-shortcut-editor { 277 | title: _("Set shortcut"); 278 | modal: true; 279 | resizable: false; 280 | default-width: 300; 281 | default-height: 200; 282 | hide-on-close: true; 283 | 284 | Adw.ToolbarView { 285 | Box { 286 | orientation: vertical; 287 | margin-start: 20; 288 | margin-end: 20; 289 | margin-top: 20; 290 | margin-bottom: 20; 291 | 292 | Label { 293 | label: _("Press escape to cancel.\nPress enter to set the shortcut.\nPress backspace to reset."); 294 | use-markup: true; 295 | wrap: true; 296 | } 297 | 298 | ShortcutLabel sl-shortcut-editor { 299 | disabled-text: _("Press shortcut"); 300 | halign: center; 301 | valign: center; 302 | vexpand: true; 303 | } 304 | } 305 | } 306 | } 307 | 308 | StringList mouse-actions { 309 | strings [ 310 | _("None"), 311 | _("Play/Pause"), 312 | _("Play"), 313 | _("Pause"), 314 | _("Next track"), 315 | _("Previous track"), 316 | _("Volume up"), 317 | _("Volume down"), 318 | _("Toggle loop"), 319 | _("Toggle shuffle"), 320 | _("Show popup menu"), 321 | _("Raise player"), 322 | _("Quit player"), 323 | _("Open preferences") 324 | ] 325 | } 326 | -------------------------------------------------------------------------------- /mediacontrols.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | nested() { 5 | export MUTTER_DEBUG_DUMMY_MODE_SPECS=1366x768 6 | dbus-run-session -- gnome-shell --unsafe-mode --nested --wayland --no-x11 7 | } 8 | 9 | build() { 10 | echo "Compiling..." 11 | npm run compile 12 | 13 | if [ "$1" = "release" ]; then 14 | echo "Prettifying..." 15 | npm run compile:padding 16 | 17 | echo "Stripping debug values..." 18 | sed 's/const DEBUG = true;/const DEBUG = false;/g' ./dist/compiled/utils/common.js >./dist/compiled/utils/common.js.tmp 19 | mv ./dist/compiled/utils/common.js.tmp ./dist/compiled/utils/common.js 20 | fi 21 | 22 | cp src/metadata.json dist/compiled/metadata.json 23 | cp src/stylesheet.css dist/compiled/stylesheet.css 24 | 25 | echo "Packing..." 26 | 27 | EXCLUDEFILES=("metadata.json" "extension.js" "prefs.js" "stylesheet.css") 28 | EXCLUDEDIRS=("compiled") 29 | JSSRCDIR="$PWD/dist/compiled" 30 | BUILDDIR="$PWD/dist/builds" 31 | 32 | FINDFARGS=() 33 | 34 | for F in "${EXCLUDEFILES[@]}"; do 35 | FINDFARGS+=("!" "-name" "$F") 36 | done 37 | 38 | FINDDARGS=() 39 | 40 | for D in "${EXCLUDEDIRS[@]}"; do 41 | FINDDARGS+=("!" "-name" "$D") 42 | done 43 | 44 | EXTRAFILES=$(find "$JSSRCDIR" -maxdepth 1 -type f "${FINDFARGS[@]}") 45 | EXTRADIRS=$(find "$JSSRCDIR" -maxdepth 1 -type d "${FINDDARGS[@]}") 46 | ESFLAGS=() 47 | 48 | for F in $EXTRAFILES; do 49 | ESFLAGS+=("--extra-source=$F") 50 | done 51 | 52 | for D in $EXTRADIRS; do 53 | ESFLAGS+=("--extra-source=$D") 54 | done 55 | 56 | SCHEMA="$PWD/assets/org.gnome.shell.extensions.mediacontrols.gschema.xml" 57 | PODIR="$PWD/assets/locale" 58 | 59 | mkdir -p "$BUILDDIR" 60 | gnome-extensions pack -f -o "$BUILDDIR" --schema="$SCHEMA" --podir="$PODIR" "${ESFLAGS[@]}" "$JSSRCDIR" 61 | } 62 | 63 | debug() { 64 | echo "Debugging..." 65 | build 66 | install 67 | nested 68 | } 69 | 70 | reload() { 71 | echo "Reloading..." 72 | build 73 | install 74 | 75 | if [ "$XDG_SESSION_TYPE" = "x11" ]; then 76 | pkill -HUP gnome-shell 77 | else 78 | echo "Reloading Wayland session is not supported yet." 79 | fi 80 | } 81 | 82 | translations() { 83 | echo "Updating translations..." 84 | 85 | touch assets/locale/mediacontrols@cliffniff.github.com.pot 86 | 87 | find . -type f -iname "*.blp" -o -iname "*.ts" -not -path "./node_modules/*" | xargs xgettext --from-code=UTF-8 \ 88 | --add-comments \ 89 | --join-existing \ 90 | --keyword=_ \ 91 | --keyword=C_:1c,2 \ 92 | --language=Javascript \ 93 | --output=assets/locale/mediacontrols@cliffniff.github.com.pot 94 | 95 | for pofile in assets/locale/*.po; do 96 | echo "Updating: $pofile" 97 | msgmerge -U "$pofile" "assets/locale/mediacontrols@cliffniff.github.com.pot" 98 | done 99 | 100 | rm assets/locale/*.po~ 2>/dev/null 101 | echo "Done" 102 | } 103 | 104 | lint() { 105 | echo "Linting..." 106 | npm run lint 107 | } 108 | 109 | format() { 110 | echo "Formatting..." 111 | npm run format 112 | } 113 | 114 | install() { 115 | echo "Installing..." 116 | gnome-extensions install --force ./dist/builds/mediacontrols@cliffniff.github.com.shell-extension.zip 117 | } 118 | 119 | uninstall() { 120 | echo "Uninstalling..." 121 | gnome-extensions uninstall mediacontrols@cliffniff.github.com 122 | } 123 | 124 | enable() { 125 | echo "Enabling..." 126 | gnome-extensions enable mediacontrols@cliffniff.github.com 127 | } 128 | 129 | disable() { 130 | echo "Disabling..." 131 | gnome-extensions disable mediacontrols@cliffniff.github.com 132 | } 133 | 134 | prefs() { 135 | echo "Opening prefs..." 136 | gnome-extensions prefs mediacontrols@cliffniff.github.com 137 | } 138 | 139 | watch() { 140 | echo "Watching for setting changes..." 141 | dconf watch /org/gnome/shell/extensions/mediacontrols/ 142 | } 143 | 144 | case "$1" in 145 | release) 146 | build "release" 147 | ;; 148 | build) 149 | build 150 | ;; 151 | debug) 152 | debug 153 | ;; 154 | reload) 155 | reload 156 | ;; 157 | translations) 158 | translations 159 | ;; 160 | lint) 161 | lint 162 | ;; 163 | format) 164 | format 165 | ;; 166 | install) 167 | install 168 | ;; 169 | uninstall) 170 | uninstall 171 | ;; 172 | enable) 173 | enable 174 | ;; 175 | disable) 176 | disable 177 | ;; 178 | prefs) 179 | prefs 180 | ;; 181 | watch) 182 | watch 183 | ;; 184 | *) 185 | echo "Usage: $0 {release|build|reload|debug|translations|lint|format|install|uninstall|enable|disable|prefs|watch}" 186 | exit 1 187 | ;; 188 | esac 189 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "scripts": { 4 | "compile": "npm run compile:clean && npm run compile:tsc && npm run compile:ui && npm run compile:assets && npm run compile:gresource && npm run compile:post", 5 | "compile:tsc": "tsc", 6 | "compile:ui": "mkdir -p dist/compiled/ui;for i in assets/ui/*.blp;do BASENAME=$(basename $i);/usr/bin/env blueprint-compiler compile --output ./dist/compiled/ui/${BASENAME%.*}.ui $i;done", 7 | "compile:padding": "eslint --fix --rule \"{padding-line-between-statements: ['error', { 'blankLine': 'always', 'prev': '*', 'next': 'block-like' }, { 'blankLine': 'always', 'prev': 'block-like', 'next': '*' }, { 'blankLine': 'always', 'prev': 'multiline-expression', 'next': '*' }, { 'blankLine': 'always', 'prev': '*', 'next': 'multiline-expression' }, { 'blankLine': 'always', 'prev': 'import', 'next': 'expression' }, { 'blankLine': 'always', 'prev': 'expression', 'next': 'export' }, { 'blankLine': 'always', 'prev': 'expression', 'next': 'class' }]}\" dist/compiled/", 8 | "compile:assets": "find assets -type f -not -path '*/images/*' -not -path '*/locale/*' -not -path '*/schemas/*' -not -path '*/ui/*' -exec sh -c 'f=\"{}\"; p=${f#*/}; d=$(dirname $p); mkdir -p dist/compiled/$d; cp $f dist/compiled/$p' ';'", 9 | "compile:gresource": "glib-compile-resources assets/org.gnome.shell.extensions.mediacontrols.gresource.xml --target=dist/compiled/org.gnome.shell.extensions.mediacontrols.gresource --sourcedir=dist/compiled/", 10 | "compile:post": "rm -rf dist/compiled/*.xml dist/compiled/ui/; ls dist/compiled/types/ | grep -xv \"enums\" | xargs -I \"$\" rm \"dist/compiled/types/$\"", 11 | "compile:clean": "rm -rf dist", 12 | "lint": "eslint src --ext .ts", 13 | "format": "prettier --write src" 14 | }, 15 | "devDependencies": { 16 | "@girs/adw-1": "1.8.0-4.0.0-beta.23", 17 | "@girs/clutter-13": "13.0.0-4.0.0-beta.23", 18 | "@girs/cogl-13": "13.0.0-4.0.0-beta.23", 19 | "@girs/gdk-4.0": "4.0.0-4.0.0-beta.23", 20 | "@girs/gdkpixbuf-2.0": "2.0.0-4.0.0-beta.23", 21 | "@girs/gio-2.0": "2.84.0-4.0.0-beta.23", 22 | "@girs/gjs": "4.0.0-beta.23", 23 | "@girs/glib-2.0": "2.84.0-4.0.0-beta.23", 24 | "@girs/gnome-shell": "48.0.2", 25 | "@girs/gobject-2.0": "2.84.0-4.0.0-beta.23", 26 | "@girs/graphene-1.0": "1.0.0-4.0.0-beta.23", 27 | "@girs/gsk-4.0": "4.0.0-4.0.0-beta.23", 28 | "@girs/gtk-4.0": "4.18.3-4.0.0-beta.23", 29 | "@girs/meta-13": "13.0.0-4.0.0-beta.23", 30 | "@girs/pango-1.0": "1.56.4-4.0.0-beta.23", 31 | "@girs/shell-13": "13.0.0-4.0.0-beta.23", 32 | "@girs/soup-3.0": "3.6.4-4.0.0-beta.23", 33 | "@girs/st-13": "13.0.0-4.0.0-beta.23", 34 | "@typescript-eslint/eslint-plugin": "^6.12.0", 35 | "@typescript-eslint/parser": "^6.12.0", 36 | "eslint": "^8.54.0", 37 | "eslint-plugin-import": "^2.29.1", 38 | "eslint-plugin-only-warn": "^1.1.0", 39 | "prettier": "^3.1.1", 40 | "typescript": "^5.3.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/helpers/prefs/AppChooser.ts: -------------------------------------------------------------------------------- 1 | import Adw from "gi://Adw"; 2 | import Gio from "gi://Gio"; 3 | import Gtk from "gi://Gtk"; 4 | 5 | class AppChooser extends Adw.Window { 6 | private listBox: Gtk.ListBox; 7 | private selectBtn: Gtk.Button; 8 | private cancelBtn: Gtk.Button; 9 | 10 | constructor(params = {}) { 11 | super(params); 12 | 13 | // @ts-expect-error Typescript doesn't know about the internal children 14 | this.listBox = this._list_box; 15 | // @ts-expect-error Typescript doesn't know about the internal children 16 | this.selectBtn = this._select_btn; 17 | // @ts-expect-error Typescript doesn't know about the internal children 18 | this.cancelBtn = this._cancel_btn; 19 | 20 | const apps = Gio.AppInfo.get_all(); 21 | 22 | for (const app of apps) { 23 | if (app.should_show() === false) continue; 24 | 25 | const row = new Adw.ActionRow(); 26 | row.title = app.get_display_name(); 27 | row.subtitle = app.get_id(); 28 | row.subtitleLines = 1; 29 | 30 | const icon = new Gtk.Image({ gicon: app.get_icon() }); 31 | row.add_prefix(icon); 32 | 33 | this.listBox.append(row); 34 | } 35 | 36 | this.cancelBtn.connect("clicked", () => { 37 | this.close(); 38 | }); 39 | } 40 | 41 | public showChooser() { 42 | return new Promise((resolve) => { 43 | const signalId = this.selectBtn.connect("clicked", () => { 44 | this.close(); 45 | this.selectBtn.disconnect(signalId); 46 | 47 | const row = this.listBox.get_selected_row() as Adw.ActionRow; 48 | resolve(row.subtitle); 49 | }); 50 | 51 | this.present(); 52 | }); 53 | } 54 | } 55 | 56 | export default AppChooser; 57 | -------------------------------------------------------------------------------- /src/helpers/prefs/BlacklistedPlayers.ts: -------------------------------------------------------------------------------- 1 | import Adw from "gi://Adw"; 2 | import Gio from "gi://Gio"; 3 | import Gtk from "gi://Gtk"; 4 | import { gettext as _ } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js"; 5 | 6 | import { AppChooser } from "../../prefs.js"; 7 | import { handleError } from "../../utils/common.js"; 8 | 9 | class BlacklistedPlayers extends Adw.PreferencesGroup { 10 | public players: string[]; 11 | 12 | private appChooser: InstanceType; 13 | private listBox: Gtk.ListBox; 14 | private addBtn: Gtk.Button; 15 | 16 | constructor(params = {}) { 17 | super(params); 18 | 19 | // @ts-expect-error Typescript doesn't know about the internal children 20 | this.listBox = this._list_box; 21 | // @ts-expect-error Typescript doesn't know about the internal children 22 | this.addBtn = this._add_btn; 23 | // @ts-expect-error Typescript doesn't know about the internal children 24 | this.appChooser = this._app_chooser; 25 | 26 | this.appChooser = new AppChooser(); 27 | 28 | this.addBtn.connect("clicked", async () => { 29 | const appId = await this.appChooser.showChooser().catch(handleError); 30 | if (appId == null) return; 31 | 32 | this.players.unshift(appId); 33 | this.notify("players"); 34 | this.addElements(); 35 | }); 36 | } 37 | 38 | public initPlayers(players: string[]) { 39 | this.players = players; 40 | this.addElements(); 41 | } 42 | 43 | private addElements() { 44 | this.listBox.remove_all(); 45 | 46 | if (this.players.length === 0) { 47 | const row = new Adw.ActionRow(); 48 | 49 | const label = new Gtk.Label(); 50 | label.label = _("No players are blacklisted"); 51 | label.useMarkup = true; 52 | label.halign = Gtk.Align.CENTER; 53 | label.marginTop = 20; 54 | label.marginBottom = 20; 55 | 56 | row.set_child(label); 57 | this.listBox.append(row); 58 | return; 59 | } 60 | 61 | const apps = Gio.AppInfo.get_all(); 62 | 63 | for (const player of this.players) { 64 | const row = new Adw.ActionRow(); 65 | 66 | const app = apps.find((app) => app.get_id() === player); 67 | row.title = app.get_display_name(); 68 | 69 | const icon = new Gtk.Image({ gicon: app.get_icon(), iconSize: Gtk.IconSize.LARGE }); 70 | row.add_prefix(icon); 71 | 72 | const deleteBtn = new Gtk.Button({ icon_name: "user-trash-symbolic" }); 73 | deleteBtn.marginTop = 10; 74 | deleteBtn.marginBottom = 10; 75 | deleteBtn.add_css_class("flat"); 76 | deleteBtn.add_css_class("circular"); 77 | row.add_suffix(deleteBtn); 78 | 79 | deleteBtn.connect("clicked", () => { 80 | const index = this.players.indexOf(player); 81 | this.players.splice(index, 1); 82 | this.notify("players"); 83 | this.addElements(); 84 | }); 85 | 86 | this.listBox.append(row); 87 | } 88 | } 89 | } 90 | 91 | export default BlacklistedPlayers; 92 | -------------------------------------------------------------------------------- /src/helpers/prefs/ElementList.ts: -------------------------------------------------------------------------------- 1 | import Adw from "gi://Adw"; 2 | import GObject from "gi://GObject"; 3 | import Gdk from "gi://Gdk"; 4 | import Graphene from "gi://Graphene"; 5 | import Gtk from "gi://Gtk"; 6 | import { PanelElements } from "../../types/enums/common.js"; 7 | 8 | interface PanelElementRow extends Adw.ActionRow { 9 | elementKey: string; 10 | } 11 | 12 | class ElementList extends Adw.PreferencesGroup { 13 | public elements: string[]; 14 | 15 | private listBox: Gtk.ListBox; 16 | private iconRow: PanelElementRow; 17 | private labelRow: PanelElementRow; 18 | private controlsRow: PanelElementRow; 19 | 20 | constructor(params = {}) { 21 | super(params); 22 | 23 | // @ts-expect-error Typescript doesn't know about the internal children 24 | this.listBox = this._list_box; 25 | // @ts-expect-error Typescript doesn't know about the internal children 26 | this.iconRow = this._icon_row; 27 | this.iconRow.elementKey = "ICON"; 28 | // @ts-expect-error Typescript doesn't know about the internal children 29 | this.labelRow = this._label_row; 30 | this.labelRow.elementKey = "LABEL"; 31 | // @ts-expect-error Typescript doesn't know about the internal children 32 | this.controlsRow = this._controls_row; 33 | this.controlsRow.elementKey = "CONTROLS"; 34 | 35 | this.elements = []; 36 | 37 | const dropTarget = Gtk.DropTarget.new(GObject.TYPE_UINT, Gdk.DragAction.MOVE); 38 | dropTarget.connect("drop", (_, sourceIndex, x, y) => { 39 | const targetRow = this.listBox.get_row_at_y(y); 40 | if (targetRow == null || sourceIndex == null) return; 41 | 42 | const index = sourceIndex.get_uint(); 43 | const sourceValue = this.elements[index]; 44 | const targetIndex = targetRow.get_index(); 45 | 46 | this.elements.splice(targetIndex > index ? targetIndex + 1 : targetIndex, 0, sourceValue); 47 | this.elements.splice(index > targetIndex ? index + 1 : index, 1); 48 | 49 | this.notify("elements"); 50 | this.listBox.drag_unhighlight_row(); 51 | this.listBox.invalidate_sort(); 52 | }); 53 | 54 | this.listBox.add_controller(dropTarget); 55 | this.listBox.set_sort_func((firstRow: PanelElementRow, secondRow: PanelElementRow) => { 56 | const firstIndex = this.elements.indexOf(firstRow.elementKey); 57 | const secondIndex = this.elements.indexOf(secondRow.elementKey); 58 | 59 | return firstIndex - secondIndex; 60 | }); 61 | } 62 | 63 | public initElements(elements: string[]) { 64 | for (let i = 0; i < elements.length; i++) { 65 | let dragX = 0; 66 | let dragY = 0; 67 | 68 | const dragSource = new Gtk.DragSource({ actions: Gdk.DragAction.MOVE }); 69 | const dropController = new Gtk.DropControllerMotion(); 70 | 71 | dragSource.connect("prepare", (dragSource, x, y) => { 72 | dragX = x; 73 | dragY = y; 74 | 75 | const row = dragSource.widget as Adw.ActionRow; 76 | const index = row.get_index(); 77 | 78 | const value = new GObject.Value(); 79 | value.init(GObject.TYPE_UINT); 80 | value.set_uint(index); 81 | 82 | const content = Gdk.ContentProvider.new_for_value(value); 83 | return content; 84 | }); 85 | 86 | dragSource.connect("drag-begin", (dragSource) => { 87 | const row = dragSource.widget as Adw.ActionRow; 88 | const icon = this.snapshotRow(row); 89 | dragSource.set_icon(icon, dragX, dragY); 90 | }); 91 | 92 | dropController.connect("enter", (dropController) => { 93 | const row = dropController.widget as Adw.ActionRow; 94 | this.listBox.drag_highlight_row(row); 95 | }); 96 | 97 | dropController.connect("leave", () => { 98 | this.listBox.drag_unhighlight_row(); 99 | }); 100 | 101 | const element = PanelElements[elements[i]]; 102 | 103 | if (element === PanelElements.ICON) { 104 | this.iconRow.add_controller(dragSource); 105 | this.iconRow.add_controller(dropController); 106 | } else if (element === PanelElements.LABEL) { 107 | this.labelRow.add_controller(dragSource); 108 | this.labelRow.add_controller(dropController); 109 | } else if (element === PanelElements.CONTROLS) { 110 | this.controlsRow.add_controller(dragSource); 111 | this.controlsRow.add_controller(dropController); 112 | } 113 | } 114 | 115 | this.elements = elements; 116 | this.listBox.invalidate_sort(); 117 | } 118 | 119 | private snapshotRow(row: Adw.PreferencesRow) { 120 | const paintable = new Gtk.WidgetPaintable({ widget: row }); 121 | const width = row.get_allocated_width(); 122 | const height = row.get_allocated_height(); 123 | 124 | const snapshot = new Gtk.Snapshot(); 125 | paintable.snapshot(snapshot, width, height); 126 | 127 | const node = snapshot.to_node(); 128 | const renderer = row.get_native().get_renderer(); 129 | 130 | const rect = new Graphene.Rect(); 131 | rect.init(0, 0, width, height); 132 | 133 | const texture = renderer.render_texture(node, rect); 134 | return texture; 135 | } 136 | } 137 | 138 | export default ElementList; 139 | -------------------------------------------------------------------------------- /src/helpers/prefs/LabelList.ts: -------------------------------------------------------------------------------- 1 | import Adw from "gi://Adw"; 2 | import GObject from "gi://GObject"; 3 | import Gdk from "gi://Gdk"; 4 | import Graphene from "gi://Graphene"; 5 | import Gtk from "gi://Gtk"; 6 | import { gettext as _ } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js"; 7 | import { LabelTypes } from "../../types/enums/common.js"; 8 | 9 | class LabelList extends Adw.PreferencesGroup { 10 | public labels: string[]; 11 | 12 | private labelsList: Gtk.StringList; 13 | private listBox: Gtk.ListBox; 14 | private addItemBtn: Gtk.Button; 15 | private addTextBtn: Gtk.Button; 16 | 17 | constructor(params = {}) { 18 | super(params); 19 | 20 | // @ts-expect-error Typescript doesn't know about internal children 21 | this.listBox = this._list_box; 22 | // @ts-expect-error Typescript doesn't know about internal children 23 | this.addItemBtn = this._add_item_btn; 24 | // @ts-expect-error Typescript doesn't know about internal children 25 | this.addTextBtn = this._add_text_btn; 26 | 27 | this.labelsList = new Gtk.StringList({ 28 | strings: Object.values(LabelTypes).map(_), 29 | }); 30 | 31 | const dropTarget = Gtk.DropTarget.new(GObject.TYPE_UINT, Gdk.DragAction.MOVE); 32 | dropTarget.connect("drop", (_, sourceIndex, x, y) => { 33 | const targetRow = this.listBox.get_row_at_y(y); 34 | if (targetRow == null || sourceIndex == null) return; 35 | 36 | const index = sourceIndex.get_uint(); 37 | const sourceValue = this.labels[index]; 38 | const targetIndex = targetRow.get_index(); 39 | 40 | this.labels.splice(targetIndex > index ? targetIndex + 1 : targetIndex, 0, sourceValue); 41 | this.labels.splice(index > targetIndex ? index + 1 : index, 1); 42 | 43 | this.notify("labels"); 44 | this.listBox.drag_unhighlight_row(); 45 | this.addElements(); 46 | }); 47 | 48 | this.addItemBtn.connect("clicked", () => { 49 | this.labels.push("ALBUM"); 50 | this.notify("labels"); 51 | this.addElements(); 52 | }); 53 | 54 | this.addTextBtn.connect("clicked", () => { 55 | this.labels.push(""); 56 | this.notify("labels"); 57 | this.addElements(); 58 | }); 59 | 60 | this.listBox.add_controller(dropTarget); 61 | } 62 | 63 | public initLabels(labels: string[]) { 64 | this.labels = labels; 65 | this.addElements(); 66 | } 67 | 68 | private addElements() { 69 | this.listBox.remove_all(); 70 | 71 | if (this.labels.length === 0) { 72 | const row = new Adw.ActionRow(); 73 | 74 | const label = new Gtk.Label(); 75 | label.label = "No labels added"; 76 | label.useMarkup = true; 77 | label.halign = Gtk.Align.CENTER; 78 | label.marginTop = 20; 79 | label.marginBottom = 20; 80 | 81 | row.set_child(label); 82 | this.listBox.append(row); 83 | return; 84 | } 85 | 86 | for (let i = 0; i < this.labels.length; i++) { 87 | const element = this.labels[i]; 88 | if (Object.keys(LabelTypes).includes(element)) { 89 | const row = new Adw.ComboRow(); 90 | row.title = _(LabelTypes[element]); 91 | row.model = this.labelsList; 92 | row.selected = Object.keys(LabelTypes).indexOf(element); 93 | 94 | this.handleComboBoxChange(row); 95 | this.completeRowCreation(row, i); 96 | } else { 97 | const row = new Adw.EntryRow(); 98 | row.title = _("Custom text"); 99 | row.text = element; 100 | 101 | this.handleEntryChange(row); 102 | this.completeRowCreation(row, i); 103 | } 104 | } 105 | } 106 | 107 | private completeRowCreation(row: Adw.ComboRow | Adw.EntryRow, index: number) { 108 | const dragIcon = new Gtk.Image({ icon_name: "list-drag-handle-symbolic" }); 109 | row.add_prefix(dragIcon); 110 | 111 | const deleteBtn = new Gtk.Button({ icon_name: "user-trash-symbolic" }); 112 | deleteBtn.marginTop = 10; 113 | deleteBtn.marginBottom = 10; 114 | deleteBtn.add_css_class("flat"); 115 | deleteBtn.add_css_class("circular"); 116 | row.add_suffix(deleteBtn); 117 | 118 | deleteBtn.connect("clicked", () => { 119 | this.labels.splice(index, 1); 120 | this.notify("labels"); 121 | this.addElements(); 122 | }); 123 | 124 | const value = new GObject.Value(); 125 | value.init(GObject.TYPE_UINT); 126 | value.set_uint(index); 127 | 128 | const content = Gdk.ContentProvider.new_for_value(value); 129 | 130 | const dragSource = new Gtk.DragSource({ actions: Gdk.DragAction.MOVE, content }); 131 | const dropController = new Gtk.DropControllerMotion(); 132 | 133 | dragSource.connect("prepare", (dragSource, x, y) => { 134 | const row = dragSource.widget as Adw.ComboRow | Adw.EntryRow; 135 | const snapshot = this.snapshotRow(row); 136 | 137 | dragSource.set_icon(snapshot, x, y); 138 | return dragSource.content; 139 | }); 140 | 141 | dropController.connect("enter", (dropController) => { 142 | const row = dropController.widget as Adw.ComboRow | Adw.EntryRow; 143 | this.listBox.drag_highlight_row(row); 144 | }); 145 | 146 | dropController.connect("leave", () => { 147 | this.listBox.drag_unhighlight_row(); 148 | }); 149 | 150 | row.add_controller(dragSource); 151 | row.add_controller(dropController); 152 | 153 | this.listBox.append(row); 154 | } 155 | 156 | private handleComboBoxChange(row: Adw.ComboRow) { 157 | row.connect("notify::selected", () => { 158 | const rowIndex = row.get_index(); 159 | const labelListKeys = Object.keys(LabelTypes); 160 | const labelKey = labelListKeys[row.selected]; 161 | 162 | this.labels.splice(rowIndex, 1, labelKey); 163 | this.notify("labels"); 164 | this.addElements(); 165 | }); 166 | } 167 | 168 | private handleEntryChange(row: Adw.EntryRow) { 169 | row.connect("notify::text", () => { 170 | const rowIndex = row.get_index(); 171 | this.labels.splice(rowIndex, 1, row.text); 172 | this.notify("labels"); 173 | }); 174 | } 175 | 176 | private snapshotRow(row: Adw.PreferencesRow) { 177 | const paintable = new Gtk.WidgetPaintable({ widget: row }); 178 | const width = row.get_allocated_width(); 179 | const height = row.get_allocated_height(); 180 | 181 | const snapshot = new Gtk.Snapshot(); 182 | paintable.snapshot(snapshot, width, height); 183 | 184 | const node = snapshot.to_node(); 185 | 186 | const renderer = row.get_native().get_renderer(); 187 | const rect = new Graphene.Rect(); 188 | rect.init(0, 0, width, height); 189 | 190 | const texture = renderer.render_texture(node, rect); 191 | return texture; 192 | } 193 | } 194 | 195 | export default LabelList; 196 | -------------------------------------------------------------------------------- /src/helpers/shell/MenuSlider.ts: -------------------------------------------------------------------------------- 1 | import Clutter from "gi://Clutter"; 2 | import GObject from "gi://GObject"; 3 | import St from "gi://St"; 4 | 5 | import * as Slider from "resource:///org/gnome/shell/ui/slider.js"; 6 | import { msToHHMMSS } from "../../utils/common.js"; 7 | 8 | class MenuSlider extends St.BoxLayout { 9 | private transition: Clutter.PropertyTransition; 10 | 11 | private slider: Slider.Slider; 12 | private textBox: St.BoxLayout; 13 | private elapsedLabel: St.Label; 14 | private durationLabel: St.Label; 15 | 16 | private dragPaused: boolean; 17 | private disabled: boolean; 18 | 19 | private rate: number; 20 | 21 | constructor() { 22 | super({ orientation: Clutter.Orientation.VERTICAL }); 23 | 24 | this.rate = 1.0; 25 | this.slider = new Slider.Slider(0); 26 | this.textBox = new St.BoxLayout(); 27 | 28 | this.elapsedLabel = new St.Label({ 29 | text: "00:00", 30 | xExpand: true, 31 | xAlign: Clutter.ActorAlign.START, 32 | }); 33 | 34 | this.durationLabel = new St.Label({ 35 | text: "00:00", 36 | xExpand: true, 37 | xAlign: Clutter.ActorAlign.END, 38 | }); 39 | 40 | this.slider.connect("drag-begin", () => { 41 | if (this.transition.is_playing() && this.disabled === false) { 42 | this.transition.pause(); 43 | this.dragPaused = true; 44 | } 45 | 46 | return Clutter.EVENT_PROPAGATE; 47 | }); 48 | 49 | this.slider.connect("drag-end", () => { 50 | const ms = this.slider.value * this.transition.duration; 51 | this.emit("seeked", Math.floor(ms * 1000)); 52 | 53 | if (this.dragPaused) { 54 | this.transition.advance(ms); 55 | this.transition.start(); 56 | this.dragPaused = false; 57 | } 58 | 59 | return Clutter.EVENT_PROPAGATE; 60 | }); 61 | 62 | this.slider.connect("scroll-event", () => { 63 | return Clutter.EVENT_STOP; 64 | }); 65 | 66 | const initial = new GObject.Value(); 67 | initial.init(GObject.TYPE_INT); 68 | initial.set_int(0); 69 | 70 | const final = new GObject.Value(); 71 | final.init(GObject.TYPE_INT); 72 | final.set_int(1); 73 | 74 | this.transition = new Clutter.PropertyTransition({ 75 | propertyName: "value", 76 | progressMode: Clutter.AnimationMode.LINEAR, 77 | repeatCount: 1, 78 | interval: new Clutter.Interval({ 79 | valueType: GObject.TYPE_DOUBLE, 80 | initial: initial, 81 | final: final, 82 | }), 83 | }); 84 | 85 | this.transition.connect("marker-reached", (_, name: string) => { 86 | this.elapsedLabel.text = name; 87 | }); 88 | 89 | this.textBox.add_child(this.elapsedLabel); 90 | this.textBox.add_child(this.durationLabel); 91 | this.add_child(this.textBox); 92 | this.add_child(this.slider); 93 | 94 | this.slider.add_transition("progress", this.transition); 95 | this.connect("destroy", this.onDestroy.bind(this)); 96 | this.setDisabled(true); 97 | } 98 | 99 | public updateSlider(position: number, length: number, rate: number) { 100 | this.rate = rate || 1.0; 101 | this.setLength(length); 102 | this.setPosition(position); 103 | } 104 | 105 | public setRate(rate: number) { 106 | const oldRate = this.rate; 107 | this.rate = rate || 1.0; 108 | 109 | this.setPosition(this.transition.get_elapsed_time() * oldRate * 1000); 110 | this.setLength(this.transition.duration * oldRate * 1000); 111 | } 112 | 113 | public setPosition(position: number) { 114 | position = position / 1000; 115 | 116 | this.elapsedLabel.text = msToHHMMSS(position); 117 | this.slider.value = position / this.rate / this.transition.duration; 118 | this.transition.advance(position / this.rate); 119 | } 120 | 121 | public setLength(length: number) { 122 | length = length / 1000; 123 | 124 | this.durationLabel.text = msToHHMMSS(length); 125 | this.slider.value = 0; 126 | this.transition.set_duration(length / this.rate); 127 | this.transition.rewind(); 128 | 129 | this.updateMarkers(); 130 | } 131 | 132 | public pauseTransition() { 133 | if (this.disabled === false) { 134 | this.transition.pause(); 135 | } 136 | } 137 | 138 | public resumeTransition() { 139 | if (this.disabled === false) { 140 | this.transition.start(); 141 | } 142 | } 143 | 144 | public setDisabled(disabled: boolean) { 145 | this.disabled = disabled; 146 | this.slider.reactive = !disabled; 147 | this.opacity = disabled ? 127 : 255; 148 | 149 | if (disabled) { 150 | this.durationLabel.text = "00:00"; 151 | this.elapsedLabel.text = "00:00"; 152 | 153 | this.transition.set_duration(1); 154 | this.transition.stop(); 155 | this.slider.value = 0; 156 | } else { 157 | this.updateMarkers(); 158 | } 159 | } 160 | 161 | private updateMarkers() { 162 | const noOfSecs = Math.floor(this.transition.duration / (1000 / this.rate)); 163 | const markers = this.transition.list_markers(-1); 164 | 165 | for (const marker of markers) { 166 | this.transition.remove_marker(marker); 167 | } 168 | 169 | for (let i = 0; i <= noOfSecs; i++) { 170 | const ms = i * 1000; 171 | const elapsedText = msToHHMMSS(ms); 172 | this.transition.add_marker_at_time(elapsedText, ms / this.rate); 173 | } 174 | } 175 | 176 | private onDestroy() { 177 | this.slider.remove_transition("progress"); 178 | this.slider.destroy(); 179 | this.textBox.destroy(); 180 | } 181 | } 182 | 183 | const GMenuSlider = GObject.registerClass( 184 | { 185 | GTypeName: "MenuSlider", 186 | Signals: { 187 | seeked: { 188 | param_types: [GObject.TYPE_INT], 189 | }, 190 | }, 191 | }, 192 | MenuSlider, 193 | ); 194 | 195 | export default GMenuSlider; 196 | -------------------------------------------------------------------------------- /src/helpers/shell/PlayerProxy.ts: -------------------------------------------------------------------------------- 1 | import Gio from "gi://Gio"; 2 | 3 | import { MPRIS_PLAYER_IFACE_NAME, MPRIS_OBJECT_PATH, PlaybackStatus, LoopStatus } from "../../types/enums/common.js"; 4 | import { errorLog, handleError } from "../../utils/common.js"; 5 | import { createDbusProxy } from "../../utils/shell_only.js"; 6 | import { KeysOf } from "../../types/misc.js"; 7 | import { 8 | MprisInterface, 9 | MprisPlayerInterface, 10 | MprisPlayerInterfaceMetadata, 11 | MprisPlayerInterfaceMetadataUnpacked, 12 | PlayerProxyDBusProperties, 13 | PlayerProxyProperties, 14 | PropertiesInterface, 15 | } from "../../types/dbus.js"; 16 | import GLib from "gi://GLib"; 17 | 18 | type PlayerProxyChangeListeners = Map< 19 | KeysOf, 20 | ((value: PlayerProxyProperties[KeysOf]) => void)[] 21 | >; 22 | 23 | export default class PlayerProxy { 24 | private isPinned: boolean; 25 | private mprisProxy: MprisInterface; 26 | private mprisPlayerProxy: MprisPlayerInterface; 27 | private propertiesProxy: PropertiesInterface; 28 | private changeListeners: PlayerProxyChangeListeners; 29 | private pollSourceId: number; 30 | 31 | public busName: string; 32 | public isInvalid: boolean; 33 | 34 | constructor(busName: string) { 35 | this.busName = busName; 36 | this.isPinned = false; 37 | this.isInvalid = true; 38 | this.changeListeners = new Map(); 39 | } 40 | 41 | public async initPlayer( 42 | mprisIface: Gio.DBusInterfaceInfo, 43 | mprisPlayerIface: Gio.DBusInterfaceInfo, 44 | propertiesIface: Gio.DBusInterfaceInfo, 45 | ) { 46 | const mprisProxy = createDbusProxy(mprisIface, this.busName, MPRIS_OBJECT_PATH).catch( 47 | handleError, 48 | ); 49 | const mprisPlayerProxy = createDbusProxy( 50 | mprisPlayerIface, 51 | this.busName, 52 | MPRIS_OBJECT_PATH, 53 | ).catch(handleError); 54 | 55 | const propertiesProxy = createDbusProxy( 56 | propertiesIface, 57 | this.busName, 58 | MPRIS_OBJECT_PATH, 59 | ).catch(handleError); 60 | 61 | const proxies = await Promise.all([mprisProxy, mprisPlayerProxy, propertiesProxy]).catch(handleError); 62 | 63 | if (proxies == null) { 64 | errorLog("Failed to create proxies"); 65 | return false; 66 | } 67 | 68 | this.mprisProxy = proxies[0]; 69 | this.mprisPlayerProxy = proxies[1]; 70 | this.propertiesProxy = proxies[2]; 71 | 72 | this.propertiesProxy.connectSignal( 73 | "PropertiesChanged", 74 | (proxy: unknown, senderName: string, [, changedProperties]) => { 75 | for (const [property, value] of Object.entries(changedProperties)) { 76 | this.callOnChangedListeners(property as KeysOf, value.recursiveUnpack()); 77 | } 78 | }, 79 | ); 80 | 81 | this.onChanged("Metadata", this.validatePlayer.bind(this)); 82 | this.onChanged("Identity", this.validatePlayer.bind(this)); 83 | this.onChanged("DesktopEntry", this.validatePlayer.bind(this)); 84 | this.validatePlayer(); 85 | this.pollTillInitialized(); 86 | 87 | return true; 88 | } 89 | 90 | public pinPlayer() { 91 | this.isPinned = true; 92 | this.callOnChangedListeners("IsPinned", this.isPinned); 93 | } 94 | 95 | public unpinPlayer() { 96 | this.isPinned = false; 97 | this.callOnChangedListeners("IsPinned", this.isPinned); 98 | } 99 | 100 | public isPlayerPinned() { 101 | return this.isPinned; 102 | } 103 | 104 | /** 105 | * Some players don't set the initial position and metadata immediately on startup 106 | */ 107 | private pollTillInitialized() { 108 | const timeout = 5000; 109 | const interval = 250; 110 | 111 | let count = Math.ceil(timeout / interval); 112 | 113 | this.pollSourceId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, interval, () => { 114 | count--; 115 | 116 | const positionPromise = this.propertiesProxy.GetAsync(MPRIS_PLAYER_IFACE_NAME, "Position"); 117 | const metadataPromise = this.propertiesProxy.GetAsync(MPRIS_PLAYER_IFACE_NAME, "Metadata"); 118 | 119 | Promise.all([positionPromise, metadataPromise]) 120 | .then(([positionVariant, metadataVariant]) => { 121 | const unpackedPosition = positionVariant[0].recursiveUnpack() as number; 122 | const unpackedMetadata = 123 | metadataVariant[0].recursiveUnpack() as MprisPlayerInterfaceMetadataUnpacked; 124 | 125 | if (unpackedPosition > 0 && unpackedMetadata["mpris:length"] > 0) { 126 | this.mprisPlayerProxy.set_cached_property("Position", positionVariant[0]); 127 | this.mprisPlayerProxy.set_cached_property("Metadata", metadataVariant[0]); 128 | this.callOnChangedListeners("Metadata", unpackedMetadata); 129 | GLib.source_remove(this.pollSourceId); 130 | } else if (count <= 0) { 131 | GLib.source_remove(this.pollSourceId); 132 | } 133 | }) 134 | .catch(() => { 135 | GLib.source_remove(this.pollSourceId); 136 | }); 137 | 138 | return GLib.SOURCE_CONTINUE; 139 | }); 140 | } 141 | 142 | private validatePlayer() { 143 | const isValidName = this.mprisProxy.Identity || this.mprisProxy.DesktopEntry; 144 | const isValidMetadata = this.metadata && this.metadata["xesam:title"]; 145 | 146 | this.isInvalid = !isValidName || !isValidMetadata; 147 | this.callOnChangedListeners("IsInvalid", this.isInvalid); 148 | } 149 | 150 | private unpackMetadata(metadata: MprisPlayerInterfaceMetadata) { 151 | const unpackedMetadata = {}; 152 | 153 | for (const [key, value] of Object.entries(metadata)) { 154 | unpackedMetadata[key] = value.recursiveUnpack(); 155 | } 156 | 157 | return unpackedMetadata as MprisPlayerInterfaceMetadataUnpacked; 158 | } 159 | 160 | private callOnChangedListeners>( 161 | property: T, 162 | value: PlayerProxyProperties[T], 163 | ) { 164 | const listeners = this.changeListeners.get(property); 165 | 166 | if (listeners == null) { 167 | return; 168 | } 169 | 170 | for (const listener of listeners) { 171 | try { 172 | listener(value); 173 | } catch (error) { 174 | errorLog(`Failed to call listener for property ${property}:`, error); 175 | } 176 | } 177 | } 178 | 179 | get playbackStatus(): PlaybackStatus { 180 | return this.mprisPlayerProxy.PlaybackStatus; 181 | } 182 | 183 | get loopStatus(): LoopStatus { 184 | return this.mprisPlayerProxy.LoopStatus; 185 | } 186 | 187 | get rate(): number { 188 | return this.mprisPlayerProxy.Rate; 189 | } 190 | 191 | get shuffle(): boolean { 192 | return this.mprisPlayerProxy.Shuffle; 193 | } 194 | 195 | get metadata(): MprisPlayerInterfaceMetadataUnpacked { 196 | return this.unpackMetadata(this.mprisPlayerProxy.Metadata); 197 | } 198 | 199 | get volume(): number { 200 | return this.mprisPlayerProxy.Volume; 201 | } 202 | 203 | get position(): Promise { 204 | return this.propertiesProxy 205 | .GetAsync(MPRIS_PLAYER_IFACE_NAME, "Position") 206 | .then((result) => { 207 | return result[0].get_int64(); 208 | }) 209 | .catch(() => { 210 | return null; 211 | }); 212 | } 213 | 214 | get minimumRate(): number { 215 | return this.mprisPlayerProxy.MinimumRate; 216 | } 217 | 218 | get maximumRate(): number { 219 | return this.mprisPlayerProxy.MaximumRate; 220 | } 221 | 222 | get canGoNext(): boolean { 223 | return this.mprisPlayerProxy.CanGoNext; 224 | } 225 | 226 | get canGoPrevious(): boolean { 227 | return this.mprisPlayerProxy.CanGoPrevious; 228 | } 229 | 230 | get canPlay(): boolean { 231 | return this.mprisPlayerProxy.CanPlay; 232 | } 233 | 234 | get canPause(): boolean { 235 | return this.mprisPlayerProxy.CanPause; 236 | } 237 | 238 | get canSeek(): boolean { 239 | return this.mprisPlayerProxy.CanSeek; 240 | } 241 | 242 | get canControl(): boolean { 243 | return this.mprisPlayerProxy.CanControl; 244 | } 245 | 246 | get canQuit(): boolean { 247 | return this.mprisProxy.CanQuit; 248 | } 249 | 250 | get canRaise(): boolean { 251 | return this.mprisProxy.CanRaise; 252 | } 253 | 254 | get canSetFullscreen(): boolean { 255 | return this.mprisProxy.CanSetFullscreen; 256 | } 257 | 258 | get desktopEntry(): string { 259 | return this.mprisProxy.DesktopEntry; 260 | } 261 | 262 | get hasTrackList(): boolean { 263 | return this.mprisProxy.HasTrackList; 264 | } 265 | 266 | get identity(): string { 267 | return this.mprisProxy.Identity; 268 | } 269 | 270 | get supportedMimeTypes(): string[] { 271 | return this.mprisProxy.SupportedMimeTypes; 272 | } 273 | 274 | get supportedUriSchemes(): string[] { 275 | return this.mprisProxy.SupportedUriSchemes; 276 | } 277 | 278 | set loopStatus(loopStatus: LoopStatus) { 279 | this.mprisPlayerProxy.LoopStatus = loopStatus; 280 | } 281 | 282 | set rate(rate: number) { 283 | this.mprisPlayerProxy.Rate = rate; 284 | } 285 | 286 | set shuffle(shuffle: boolean) { 287 | this.mprisPlayerProxy.Shuffle = shuffle; 288 | } 289 | 290 | set volume(volume: number) { 291 | this.mprisPlayerProxy.Volume = volume; 292 | } 293 | 294 | set fullscreen(fullscreen: boolean) { 295 | this.mprisProxy.Fullscreen = fullscreen; 296 | } 297 | 298 | public async next() { 299 | await this.mprisPlayerProxy.NextAsync().catch(handleError); 300 | } 301 | 302 | public async previous() { 303 | await this.mprisPlayerProxy.PreviousAsync().catch(handleError); 304 | } 305 | 306 | public async pause() { 307 | await this.mprisPlayerProxy.PauseAsync().catch(handleError); 308 | } 309 | 310 | public async playPause() { 311 | await this.mprisPlayerProxy.PlayPauseAsync().catch(handleError); 312 | } 313 | 314 | public async stop() { 315 | await this.mprisPlayerProxy.StopAsync().catch(handleError); 316 | } 317 | 318 | public async play() { 319 | await this.mprisPlayerProxy.PlayAsync().catch(handleError); 320 | } 321 | 322 | public async seek(offset: number) { 323 | await this.mprisPlayerProxy.SeekAsync(offset).catch(handleError); 324 | } 325 | 326 | public async setPosition(trackId: string, position: number) { 327 | await this.mprisPlayerProxy.SetPositionAsync(trackId, position).catch(handleError); 328 | } 329 | 330 | public async openUri(uri: string) { 331 | await this.mprisPlayerProxy.OpenUriAsync(uri).catch(handleError); 332 | } 333 | 334 | public async raise() { 335 | await this.mprisProxy.RaiseAsync().catch(handleError); 336 | } 337 | 338 | public async quit() { 339 | await this.mprisProxy.QuitAsync().catch(handleError); 340 | } 341 | 342 | public toggleLoop() { 343 | const loopStatuses = Object.values(LoopStatus); 344 | const currentIndex = loopStatuses.findIndex((loop) => loop === this.loopStatus); 345 | const nextIndex = (currentIndex + 1 + loopStatuses.length) % loopStatuses.length; 346 | 347 | this.loopStatus = loopStatuses[nextIndex]; 348 | } 349 | 350 | public toggleShuffle() { 351 | this.shuffle = !this.shuffle; 352 | } 353 | 354 | public onSeeked(callback: (position: number) => void) { 355 | const signalId = this.mprisPlayerProxy.connectSignal("Seeked", () => { 356 | this.position.then(callback); 357 | }); 358 | 359 | return this.mprisPlayerProxy.disconnectSignal.bind(this.mprisPlayerProxy, signalId); 360 | } 361 | 362 | public onChanged>( 363 | property: T, 364 | callback: (value: PlayerProxyProperties[T]) => void, 365 | ) { 366 | const listeners = this.changeListeners.get(property); 367 | let id: number; 368 | 369 | if (listeners == null) { 370 | id = 0; 371 | this.changeListeners.set(property, [callback]); 372 | } else { 373 | id = listeners.push(callback); 374 | } 375 | 376 | return id; 377 | } 378 | 379 | public removeListener>(property: T, id: number) { 380 | const listeners = this.changeListeners.get(property); 381 | 382 | if (listeners == null) { 383 | return; 384 | } 385 | 386 | listeners.splice(id, 1); 387 | } 388 | 389 | public onDestroy() { 390 | if (this.pollSourceId != null) { 391 | GLib.source_remove(this.pollSourceId); 392 | } 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /src/helpers/shell/ScrollingLabel.ts: -------------------------------------------------------------------------------- 1 | import Clutter from "gi://Clutter"; 2 | import GObject from "gi://GObject"; 3 | import Pango from "gi://Pango"; 4 | import St from "gi://St"; 5 | 6 | export interface ScrollingLabelParams { 7 | text: string; 8 | width: number; 9 | direction?: Clutter.TimelineDirection; 10 | isFixedWidth?: boolean; 11 | isScrolling: boolean; 12 | initPaused: boolean; 13 | } 14 | 15 | const SCROLL_ANIMATION_SPEED = 0.04; 16 | 17 | class ScrollingLabel extends St.ScrollView { 18 | public label: St.Label; 19 | public box: St.BoxLayout; 20 | 21 | private onAdjustmentChangedId: number; 22 | private onShowChangedId: number; 23 | 24 | private isScrolling: boolean; 25 | private isFixedWidth: boolean; 26 | private initPaused: boolean; 27 | private labelWidth: number; 28 | private direction: Clutter.TimelineDirection; 29 | 30 | private transition: Clutter.PropertyTransition; 31 | 32 | constructor(params: ScrollingLabelParams) { 33 | super({ 34 | hscrollbarPolicy: St.PolicyType.NEVER, 35 | vscrollbarPolicy: St.PolicyType.NEVER, 36 | }); 37 | 38 | const defaultParams = { 39 | direction: Clutter.TimelineDirection.FORWARD, 40 | isFixedWidth: true, 41 | }; 42 | 43 | const { text, width, direction, isFixedWidth, isScrolling, initPaused } = { 44 | ...defaultParams, 45 | ...params, 46 | }; 47 | 48 | this.isScrolling = isScrolling; 49 | this.isFixedWidth = isFixedWidth; 50 | this.initPaused = initPaused; 51 | this.labelWidth = width; 52 | this.direction = direction; 53 | 54 | this.box = new St.BoxLayout({ 55 | xExpand: true, 56 | yExpand: true, 57 | }); 58 | 59 | this.label = new St.Label({ 60 | text, 61 | yAlign: Clutter.ActorAlign.CENTER, 62 | xAlign: Clutter.ActorAlign.START, 63 | }); 64 | 65 | this.onShowChangedId = this.label.connect("show", this.onShowChanged.bind(this)); 66 | this.box.add_child(this.label); 67 | 68 | this.add_child(this.box); 69 | } 70 | 71 | public pauseScrolling() { 72 | this.transition?.pause(); 73 | this.initPaused = true; 74 | } 75 | 76 | public resumeScrolling() { 77 | this.transition?.start(); 78 | this.initPaused = false; 79 | } 80 | 81 | private initScrolling() { 82 | const adjustment = this.get_hadjustment(); 83 | const origText = this.label.text + " "; 84 | 85 | this.onAdjustmentChangedId = adjustment.connect( 86 | "changed", 87 | this.onAdjustmentChanged.bind(this, adjustment, origText), 88 | ); 89 | 90 | this.label.text = `${origText} `; 91 | this.label.clutterText.ellipsize = Pango.EllipsizeMode.NONE; 92 | } 93 | 94 | private onAdjustmentChanged(adjustment: St.Adjustment, origText: string) { 95 | if (adjustment.upper <= adjustment.pageSize) { 96 | return; 97 | } 98 | 99 | const initial = new GObject.Value(); 100 | initial.init(GObject.TYPE_INT); 101 | initial.set_int(adjustment.value); 102 | 103 | const final = new GObject.Value(); 104 | final.init(GObject.TYPE_INT); 105 | final.set_int(adjustment.upper); 106 | 107 | const duration = adjustment.upper / SCROLL_ANIMATION_SPEED; 108 | 109 | const pspec = adjustment.find_property("value"); 110 | const interval = new Clutter.Interval({ 111 | valueType: pspec.value_type, 112 | initial, 113 | final, 114 | }); 115 | 116 | this.transition = new Clutter.PropertyTransition({ 117 | propertyName: "value", 118 | progressMode: Clutter.AnimationMode.LINEAR, 119 | direction: this.direction, 120 | repeatCount: -1, 121 | duration, 122 | interval, 123 | }); 124 | 125 | this.label.text = `${origText} ${origText}`; 126 | adjustment.add_transition("scroll", this.transition); 127 | adjustment.disconnect(this.onAdjustmentChangedId); 128 | 129 | if (this.initPaused) { 130 | this.transition.pause(); 131 | } 132 | } 133 | 134 | private onShowChanged() { 135 | if (this.label.visible === false) { 136 | return; 137 | } 138 | 139 | const isLabelWider = this.label.width > this.labelWidth && this.labelWidth > 0; 140 | 141 | if (isLabelWider && this.isScrolling) { 142 | this.initScrolling(); 143 | } 144 | 145 | if (this.isFixedWidth && this.labelWidth > 0) { 146 | this.box.width = this.labelWidth; 147 | this.label.xAlign = Clutter.ActorAlign.CENTER; 148 | this.label.xExpand = true; 149 | } else if (isLabelWider) { 150 | this.box.width = Math.min(this.label.width, this.labelWidth); 151 | } 152 | 153 | this.label.disconnect(this.onShowChangedId); 154 | } 155 | 156 | vfunc_scroll_event(): boolean { 157 | return Clutter.EVENT_PROPAGATE; 158 | } 159 | } 160 | 161 | const GScrollingLabel = GObject.registerClass( 162 | { 163 | GTypeName: "ScrollingLabel", 164 | }, 165 | ScrollingLabel, 166 | ); 167 | 168 | export default GScrollingLabel; 169 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | import "@girs/adw-1/ambient"; 2 | import "@girs/gdk-4.0/ambient"; 3 | import "@girs/gjs/ambient"; 4 | import "@girs/gjs/dom"; 5 | import "@girs/gjs"; 6 | import "@girs/glib-2.0/ambient"; 7 | import "@girs/gnome-shell/ambient"; 8 | import "@girs/gobject-2.0/ambient"; 9 | import "@girs/gtk-4.0/ambient"; 10 | import "@girs/st-13/ambient"; 11 | import "@girs/shell-13/ambient"; 12 | import "@girs/clutter-13/ambient"; 13 | import "@girs/pango-1.0/ambient"; 14 | import "@girs/soup-3.0/ambient"; 15 | import "@girs/meta-13/ambient"; 16 | import "@girs/cogl-13/ambient"; 17 | import "@girs/gdkpixbuf-2.0/ambient"; 18 | 19 | declare global { 20 | var global: any; 21 | 22 | interface ImportMeta { 23 | url: string; 24 | } 25 | 26 | interface String { 27 | format(...args: unknown[]): string; 28 | } 29 | } 30 | 31 | declare module "@girs/gobject-2.0" { 32 | namespace GObject { 33 | function type_from_name(name: string | null): GType | 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "uuid": "mediacontrols@cliffniff.github.com", 3 | "name": "Media Controls", 4 | "description": "Show controls and information of the currently playing media in the panel.", 5 | "url": "https://github.com/cliffniff/media-controls", 6 | "settings-schema": "org.gnome.shell.extensions.mediacontrols", 7 | "gettext-domain": "mediacontrols@cliffniff.github.com", 8 | "version-name": "2.1.0", 9 | "shell-version": [ 10 | "48" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/stylesheet.css: -------------------------------------------------------------------------------- 1 | .colored-icon { 2 | -st-icon-style: requested; 3 | } 4 | 5 | .symbolic-icon { 6 | -st-icon-style: symbolic; 7 | } 8 | 9 | .no-margin { 10 | margin: 0; 11 | } 12 | 13 | .no-padding { 14 | padding: 0; 15 | } 16 | 17 | .panel-button { 18 | padding-left: 6px; 19 | padding-right: 6px; 20 | } 21 | 22 | .panel-button-box > * { 23 | padding-left: 6px; 24 | padding-right: 6px; 25 | } 26 | 27 | .panel-button-box > *:last-child:not(.controls-box) { 28 | padding-left: 6px; 29 | padding-right: 6px; 30 | } 31 | 32 | .panel-controls-box { 33 | padding-left: 0px; 34 | padding-right: 0px; 35 | } 36 | 37 | .panel-controls-box > * { 38 | padding-left: 6px; 39 | padding-right: 6px; 40 | } 41 | 42 | .popup-menu-container { 43 | padding: 12px; 44 | } 45 | 46 | .popup-menu-box { 47 | border-width: 0px; 48 | } 49 | 50 | .popup-menu-box > * { 51 | margin-top: 6px; 52 | margin-bottom: 6px; 53 | } 54 | 55 | .popup-menu-player-icons { 56 | margin-top: 6px; 57 | border-radius: 6px; 58 | } 59 | 60 | .popup-menu-player-icons-icon { 61 | padding: 6px; 62 | background-color: rgba(0, 0, 0, 0.125); 63 | transition-property: background-color; 64 | transition-duration: 200ms; 65 | } 66 | 67 | .popup-menu-player-icons-icon-last { 68 | border-radius: 0px 6px 6px 0px; 69 | } 70 | 71 | .popup-menu-player-icons-icon-first { 72 | border-radius: 6px 0px 0px 6px; 73 | } 74 | 75 | .popup-menu-player-icons-icon:hover { 76 | background-color: rgba(160, 160, 160, 0.25); 77 | } 78 | 79 | .popup-menu-player-icons-icon-active { 80 | background-color: rgba(160, 160, 160, 0.25); 81 | } 82 | 83 | .popup-menu-player-label { 84 | font-size: small; 85 | margin-right: 6px; 86 | margin-left: 6px; 87 | } 88 | 89 | .popup-menu-label-title { 90 | font-size: large; 91 | } 92 | 93 | .popup-menu-control-icon { 94 | padding: 6px; 95 | border-radius: 99px; 96 | } 97 | 98 | .popup-menu-control-icon:hover { 99 | background-color: rgba(160, 160, 160, 0.25); 100 | } 101 | -------------------------------------------------------------------------------- /src/types/dbus.ts: -------------------------------------------------------------------------------- 1 | import Gio from "gi://Gio"; 2 | import GLib from "gi://GLib"; 3 | 4 | import { KeysOf } from "./misc.js"; 5 | import { LoopStatus, PlaybackStatus } from "./enums/common.js"; 6 | 7 | type MethodResult = [T]; 8 | 9 | export interface MprisPlayerInterfaceMetadataUnpacked { 10 | "mpris:trackid": string; 11 | "mpris:length": number; 12 | "mpris:artUrl": string; 13 | "xesam:album": string; 14 | "xesam:albumArtist": string[]; 15 | "xesam:artist": string[]; 16 | "xesam:asText": string; 17 | "xesam:audioBPM": number; 18 | "xesam:autoRating": number; 19 | "xesam:comment": string[]; 20 | "xesam:composer": string[]; 21 | "xesam:contentCreated": string; 22 | "xesam:discNumber": number; 23 | "xesam:firstUsed": string; 24 | "xesam:genre": string[]; 25 | "xesam:lastUsed": string; 26 | "xesam:lyricist": string[]; 27 | "xesam:title": string; 28 | "xesam:trackNumber": number; 29 | "xesam:url": string; 30 | "xesam:useCount": number; 31 | "xesam:userRating": number; 32 | } 33 | 34 | export interface MprisPlayerInterfaceMetadata { 35 | "mpris:trackid": GLib.Variant; 36 | "mpris:length": GLib.Variant; 37 | "mpris:artUrl": GLib.Variant; 38 | "xesam:album": GLib.Variant; 39 | "xesam:albumArtist": GLib.Variant; 40 | "xesam:artist": GLib.Variant; 41 | "xesam:asText": GLib.Variant; 42 | "xesam:audioBPM": GLib.Variant; 43 | "xesam:autoRating": GLib.Variant; 44 | "xesam:comment": GLib.Variant; 45 | "xesam:composer": GLib.Variant; 46 | "xesam:contentCreated": GLib.Variant; 47 | "xesam:discNumber": GLib.Variant; 48 | "xesam:firstUsed": GLib.Variant; 49 | "xesam:genre": GLib.Variant; 50 | "xesam:lastUsed": GLib.Variant; 51 | "xesam:lyricist": GLib.Variant; 52 | "xesam:title": GLib.Variant; 53 | "xesam:trackNumber": GLib.Variant; 54 | "xesam:url": GLib.Variant; 55 | "xesam:useCount": GLib.Variant; 56 | "xesam:userRating": GLib.Variant; 57 | } 58 | 59 | export interface PlayerProxyDBusProperties { 60 | PlaybackStatus: PlaybackStatus; 61 | LoopStatus: LoopStatus; 62 | Rate: number; 63 | Shuffle: boolean; 64 | Metadata: MprisPlayerInterfaceMetadata | MprisPlayerInterfaceMetadataUnpacked; 65 | Volume: number; 66 | Position: number; 67 | MinimumRate: number; 68 | MaximumRate: number; 69 | CanGoNext: boolean; 70 | CanGoPrevious: boolean; 71 | CanPlay: boolean; 72 | CanPause: boolean; 73 | CanSeek: boolean; 74 | CanControl: boolean; 75 | CanQuit: boolean; 76 | Fullscreen: boolean; 77 | CanSetFullscreen: boolean; 78 | CanRaise: boolean; 79 | HasTrackList: boolean; 80 | Identity: string; 81 | DesktopEntry: string; 82 | SupportedUriSchemes: string[]; 83 | SupportedMimeTypes: string[]; 84 | } 85 | 86 | export interface PlayerProxyProperties extends PlayerProxyDBusProperties { 87 | IsInvalid: boolean; 88 | IsPinned: boolean; 89 | } 90 | 91 | export interface PropertiesSignalArgs { 92 | PropertiesChanged: [ 93 | interfaceName: string, 94 | changedProperties: { [k in KeysOf]: GLib.Variant }, 95 | invalidatedProperties: string[], 96 | ]; 97 | } 98 | 99 | export interface MprisPlayerSignalArgs { 100 | Seeked: number; 101 | } 102 | 103 | export interface StdPropertiesSignalArgs { 104 | NameOwnerChanged: [busName: string, oldOwner: string, newOwner: string]; 105 | NameLost: string; 106 | NameAcquired: string; 107 | } 108 | 109 | export interface BaseInterface extends Omit { 110 | connectSignal( 111 | name: N, 112 | callback: (proxy: Gio.DBusProxy, senderName: string, args: T[N]) => void, 113 | ): number; 114 | } 115 | 116 | export interface PropertiesInterface extends BaseInterface { 117 | GetAsync(interfaceName: string, propertyName: string): Promise>; 118 | GetAllAsync(interfaceName: string): Promise>; 119 | SetAsync(interfaceName: string, propertyName: string, value: GLib.Variant): Promise; 120 | GetSync(interfaceName: string, propertyName: string): MethodResult; 121 | GetAllSync(interfaceName: string): MethodResult; 122 | SetSync(interfaceName: string, propertyName: string, value: GLib.Variant): void; 123 | GetRemote( 124 | interfaceName: string, 125 | propertyName: string, 126 | callback: (returnValue: MethodResult, errorObj: unknown, fdList: unknown[]) => void, 127 | ): void; 128 | GetAllRemote( 129 | interfaceName: string, 130 | callback: (returnValue: MethodResult, errorObj: unknown, fdList: unknown[]) => void, 131 | ): void; 132 | SetRemote( 133 | interfaceName: string, 134 | propertyName: string, 135 | value: GLib.Variant, 136 | callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void, 137 | ): void; 138 | } 139 | 140 | export interface MprisInterface extends BaseInterface { 141 | CanQuit: boolean; 142 | Fullscreen?: boolean; 143 | CanSetFullscreen?: boolean; 144 | CanRaise: boolean; 145 | HasTrackList: boolean; 146 | Identity: string; 147 | DesktopEntry?: string; 148 | SupportedUriSchemes: string[]; 149 | SupportedMimeTypes: string[]; 150 | RaiseRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 151 | QuitRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 152 | RaiseAsync(): Promise; 153 | QuitAsync(): Promise; 154 | RaiseSync(): void; 155 | QuitSync(): void; 156 | } 157 | 158 | export interface MprisPlayerInterface extends BaseInterface { 159 | PlaybackStatus: PlaybackStatus; 160 | LoopStatus?: LoopStatus; 161 | Rate: number; 162 | Shuffle?: boolean; 163 | Metadata: MprisPlayerInterfaceMetadata; 164 | Volume: number; 165 | Position: number; 166 | MinimumRate: number; 167 | MaximumRate: number; 168 | CanGoNext: boolean; 169 | CanGoPrevious: boolean; 170 | CanPlay: boolean; 171 | CanPause: boolean; 172 | CanSeek: boolean; 173 | CanControl: boolean; 174 | NextRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 175 | PreviousRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 176 | PauseRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 177 | PlayPauseRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 178 | StopRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 179 | PlayRemote(callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 180 | SeekRemote(Offset: number, callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 181 | SetPositionRemote( 182 | TrackId: string, 183 | Position: number, 184 | callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void, 185 | ): void; 186 | OpenUriRemote(Uri: string, callback: (returnValue: void, errorObj: unknown, fdList: unknown[]) => void): void; 187 | NextAsync(): Promise; 188 | PreviousAsync(): Promise; 189 | PauseAsync(): Promise; 190 | PlayPauseAsync(): Promise; 191 | StopAsync(): Promise; 192 | PlayAsync(): Promise; 193 | SeekAsync(Offset: number): Promise; 194 | SetPositionAsync(TrackId: string, Position: number): Promise; 195 | OpenUriAsync(Uri: string): Promise; 196 | NextSync(): void; 197 | PreviousSync(): void; 198 | PauseSync(): void; 199 | PlayPauseSync(): void; 200 | StopSync(): void; 201 | PlaySync(): void; 202 | SeekSync(position: number): void; 203 | SetPositionSync(trackId: string, position: number): void; 204 | OpenUriSync(uri: string): void; 205 | } 206 | 207 | export interface StdInterface extends BaseInterface { 208 | ListNamesAsync(): Promise>; 209 | ListNamesSync(): MethodResult; 210 | ListNamesRemote( 211 | callback: (returnValue: MethodResult, errorObj: unknown, fdList: unknown[]) => void, 212 | ): void; 213 | } 214 | -------------------------------------------------------------------------------- /src/types/enums/common.ts: -------------------------------------------------------------------------------- 1 | import { Enum } from "../misc.js"; 2 | 3 | export const DBUS_IFACE_NAME = "org.freedesktop.DBus"; 4 | export const MPRIS_OBJECT_PATH = "/org/mpris/MediaPlayer2"; 5 | export const DBUS_OBJECT_PATH = "/org/freedesktop/DBus"; 6 | export const MPRIS_IFACE_NAME = "org.mpris.MediaPlayer2"; 7 | export const DBUS_PROPERTIES_IFACE_NAME = "org.freedesktop.DBus.Properties"; 8 | export const MPRIS_PLAYER_IFACE_NAME = "org.mpris.MediaPlayer2.Player"; 9 | 10 | export const PlaybackStatus = { 11 | PLAYING: "Playing", 12 | PAUSED: "Paused", 13 | STOPPED: "Stopped", 14 | } as const; 15 | 16 | export const LoopStatus = { 17 | NONE: "None", 18 | TRACK: "Track", 19 | PLAYLIST: "Playlist", 20 | } as const; 21 | 22 | export const ExtensionPositions = { 23 | LEFT: "left", 24 | CENTER: "center", 25 | RIGHT: "right", 26 | } as const; 27 | 28 | export const LabelTypes = { 29 | ARTIST: "Artist", 30 | TITLE: "Title", 31 | ALBUM: "Album", 32 | DISC_NUMBER: "Disc Number", 33 | TRACK_NUMBER: "Track Number", 34 | } as const; 35 | 36 | export const PanelElements = { 37 | ICON: 0, 38 | LABEL: 1, 39 | CONTROLS: 2, 40 | } as const; 41 | 42 | export const MouseActions = { 43 | NONE: 0, 44 | PLAY_PAUSE: 1, 45 | PLAY: 2, 46 | PAUSE: 3, 47 | NEXT_TRACK: 4, 48 | PREVIOUS_TRACK: 5, 49 | VOLUME_UP: 6, 50 | VOLUME_DOWN: 7, 51 | TOGGLE_LOOP: 8, 52 | TOGGLE_SHUFFLE: 9, 53 | SHOW_POPUP_MENU: 10, 54 | RAISE_PLAYER: 11, 55 | QUIT_PLAYER: 12, 56 | OPEN_PREFERENCES: 13, 57 | } as const; 58 | 59 | export const WidgetFlags = { 60 | PANEL_ICON: 1 << 0, 61 | PANEL_LABEL: 1 << 1, 62 | PANEL_CONTROLS_SEEK_BACKWARD: 1 << 2, 63 | PANEL_CONTROLS_PREVIOUS: 1 << 3, 64 | PANEL_CONTROLS_PLAYPAUSE: 1 << 4, 65 | PANEL_CONTROLS_NEXT: 1 << 5, 66 | PANEL_CONTROLS_SEEK_FORWARD: 1 << 6, 67 | PANEL_CONTROLS: (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6), 68 | PANEL: (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6), 69 | PANEL_NO_REPLACE: 1 << 7, 70 | MENU_PLAYERS: 1 << 8, 71 | MENU_IMAGE: 1 << 9, 72 | MENU_LABELS: 1 << 10, 73 | MENU_SLIDER: 1 << 11, 74 | MENU_CONTROLS_LOOP: 1 << 12, 75 | MENU_CONTROLS_PREV: 1 << 13, 76 | MENU_CONTROLS_PLAYPAUSE: 1 << 14, 77 | MENU_CONTROLS_NEXT: 1 << 15, 78 | MENU_CONTROLS_SHUFFLE: 1 << 16, 79 | MENU_CONTROLS: (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) | (1 << 16), 80 | MENU: (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) | (1 << 16), 81 | ALL: ~(-1 << 17), 82 | } as const; 83 | 84 | export type PanelElements = Enum; 85 | export type LabelTypes = Enum; 86 | export type ExtensionPositions = Enum; 87 | export type MouseActions = Enum; 88 | export type LoopStatus = Enum; 89 | export type PlaybackStatus = Enum; 90 | export type WidgetFlags = Enum; 91 | -------------------------------------------------------------------------------- /src/types/enums/shell_only.ts: -------------------------------------------------------------------------------- 1 | import Clutter from "gi://Clutter"; 2 | import { Enum } from "../misc.js"; 3 | 4 | export const ControlIconOptions = { 5 | LOOP_NONE: { 6 | name: "loop", 7 | iconName: "media-playlist-repeat-symbolic", 8 | menuProps: { 9 | index: 0, 10 | options: { 11 | xExpand: false, 12 | xAlign: Clutter.ActorAlign.START, 13 | opacity: 160, 14 | }, 15 | }, 16 | }, 17 | LOOP_TRACK: { 18 | name: "loop", 19 | iconName: "media-playlist-repeat-song-symbolic", 20 | menuProps: { 21 | index: 0, 22 | options: { 23 | xExpand: false, 24 | xAlign: Clutter.ActorAlign.START, 25 | }, 26 | }, 27 | }, 28 | LOOP_PLAYLIST: { 29 | name: "loop", 30 | iconName: "media-playlist-repeat-symbolic", 31 | menuProps: { 32 | index: 0, 33 | options: { 34 | xExpand: false, 35 | xAlign: Clutter.ActorAlign.START, 36 | }, 37 | }, 38 | }, 39 | SEEK_BACKWARD: { 40 | name: "seekbackward", 41 | iconName: "media-seek-backward-symbolic", 42 | panelProps: { 43 | index: 0, 44 | }, 45 | }, 46 | PREVIOUS: { 47 | name: "previous", 48 | iconName: "media-skip-backward-symbolic", 49 | menuProps: { 50 | index: 1, 51 | options: { 52 | xExpand: true, 53 | xAlign: Clutter.ActorAlign.END, 54 | marginRight: 5, 55 | }, 56 | }, 57 | panelProps: { 58 | index: 1, 59 | }, 60 | }, 61 | PLAY: { 62 | name: "playpause", 63 | iconName: "media-playback-start-symbolic", 64 | menuProps: { 65 | index: 2, 66 | options: { 67 | xExpand: false, 68 | xAlign: Clutter.ActorAlign.CENTER, 69 | }, 70 | }, 71 | panelProps: { 72 | index: 2, 73 | }, 74 | }, 75 | PAUSE: { 76 | name: "playpause", 77 | iconName: "media-playback-pause-symbolic", 78 | menuProps: { 79 | index: 2, 80 | options: { 81 | xExpand: false, 82 | xAlign: Clutter.ActorAlign.CENTER, 83 | }, 84 | }, 85 | panelProps: { 86 | index: 2, 87 | }, 88 | }, 89 | NEXT: { 90 | name: "next", 91 | iconName: "media-skip-forward-symbolic", 92 | menuProps: { 93 | index: 3, 94 | options: { 95 | xExpand: true, 96 | xAlign: Clutter.ActorAlign.START, 97 | marginLeft: 5, 98 | }, 99 | }, 100 | panelProps: { 101 | index: 3, 102 | }, 103 | }, 104 | SEEK_FORWARD: { 105 | name: "seekforward", 106 | iconName: "media-seek-forward-symbolic", 107 | panelProps: { 108 | index: 4, 109 | }, 110 | }, 111 | SHUFFLE_ON: { 112 | name: "shuffle", 113 | iconName: "media-playlist-shuffle-symbolic", 114 | menuProps: { 115 | index: 4, 116 | options: { 117 | xExpand: false, 118 | xAlign: Clutter.ActorAlign.END, 119 | }, 120 | }, 121 | }, 122 | SHUFFLE_OFF: { 123 | name: "shuffle", 124 | iconName: "media-playlist-consecutive-symbolic", 125 | menuProps: { 126 | index: 4, 127 | options: { 128 | xExpand: false, 129 | xAlign: Clutter.ActorAlign.END, 130 | }, 131 | }, 132 | }, 133 | } as const; 134 | 135 | export type ControlIconOptions = Enum; 136 | export type MenuControlIconOptions = (typeof ControlIconOptions)[ 137 | | "LOOP_NONE" 138 | | "LOOP_TRACK" 139 | | "LOOP_PLAYLIST" 140 | | "PREVIOUS" 141 | | "PLAY" 142 | | "PAUSE" 143 | | "NEXT" 144 | | "SHUFFLE_ON" 145 | | "SHUFFLE_OFF"]; 146 | export type PanelControlIconOptions = (typeof ControlIconOptions)[ 147 | | "SEEK_BACKWARD" 148 | | "PREVIOUS" 149 | | "PLAY" 150 | | "PAUSE" 151 | | "NEXT" 152 | | "SEEK_FORWARD"]; 153 | -------------------------------------------------------------------------------- /src/types/misc.ts: -------------------------------------------------------------------------------- 1 | export type Enum = X[keyof X]; 2 | export type KeysOf = keyof X; 3 | export type ValuesOf = X[keyof X]; 4 | -------------------------------------------------------------------------------- /src/utils/common.ts: -------------------------------------------------------------------------------- 1 | const DEBUG = true; 2 | 3 | export const enumValueByIndex = (enumObject: T, index: number) => { 4 | return Object.values(enumObject)[index]; 5 | }; 6 | 7 | export const enumKeyByValue = (enumObject: T, value: unknown) => { 8 | return Object.keys(enumObject).find((key) => enumObject[key] === value); 9 | }; 10 | 11 | export const debugLog = (...args: unknown[]) => { 12 | if (DEBUG) { 13 | console.log("[Media Controls]", ...args); 14 | } 15 | }; 16 | 17 | export const errorLog = (...args: unknown[]) => { 18 | console.error("[Media Controls]", "Error:", ...args); 19 | }; 20 | 21 | export const handleError = (error: unknown): null => { 22 | errorLog(error); 23 | return null; 24 | }; 25 | 26 | export const msToHHMMSS = (ms: number): string => { 27 | const seconds = Math.floor(ms / 1000); 28 | const minutes = Math.floor(ms / 60000); 29 | const hours = Math.floor(ms / 3600000); 30 | 31 | const secondsString = String(seconds % 60).padStart(2, "0"); 32 | const minutesString = String(minutes % 60).padStart(2, "0"); 33 | const hoursString = String(hours).padStart(2, "0"); 34 | 35 | if (hours > 0) { 36 | return `${hoursString}:${minutesString}:${secondsString}`; 37 | } else { 38 | return `${minutesString}:${secondsString}`; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /src/utils/prefs_only.ts: -------------------------------------------------------------------------------- 1 | import Gdk from "gi://Gdk"; 2 | import Gtk from "gi://Gtk"; 3 | 4 | export const FORBIDDEN_KEYVALS = [ 5 | Gdk.KEY_Home, 6 | Gdk.KEY_Left, 7 | Gdk.KEY_Up, 8 | Gdk.KEY_Right, 9 | Gdk.KEY_Down, 10 | Gdk.KEY_Page_Up, 11 | Gdk.KEY_Page_Down, 12 | Gdk.KEY_End, 13 | Gdk.KEY_Tab, 14 | Gdk.KEY_KP_Enter, 15 | Gdk.KEY_Return, 16 | Gdk.KEY_Mode_switch, 17 | ]; 18 | 19 | export const isValidAccelerator = (mask: number, keyval: number) => { 20 | return Gtk.accelerator_valid(keyval, mask) || (keyval === Gdk.KEY_Tab && mask !== 0); 21 | }; 22 | 23 | export const isValidBinding = (mask: number, keycode: number, keyval: number) => { 24 | if (mask === 0) { 25 | return false; 26 | } 27 | 28 | if (mask === Gdk.ModifierType.SHIFT_MASK && keycode !== 0) { 29 | if (keyval >= Gdk.KEY_a && keyval <= Gdk.KEY_z) { 30 | return false; 31 | } else if (keyval >= Gdk.KEY_A && keyval <= Gdk.KEY_Z) { 32 | return false; 33 | } else if (keyval >= Gdk.KEY_0 && keyval <= Gdk.KEY_9) { 34 | return false; 35 | } else if (keyval >= Gdk.KEY_kana_fullstop && keyval <= Gdk.KEY_semivoicedsound) { 36 | return false; 37 | } else if (keyval >= Gdk.KEY_Arabic_comma && keyval <= Gdk.KEY_Arabic_sukun) { 38 | return false; 39 | } else if (keyval >= Gdk.KEY_Serbian_dje && keyval <= Gdk.KEY_Cyrillic_HARDSIGN) { 40 | return false; 41 | } else if (keyval >= Gdk.KEY_Greek_ALPHAaccent && keyval <= Gdk.KEY_Greek_omega) { 42 | return false; 43 | } else if (keyval >= Gdk.KEY_hebrew_doublelowline && keyval <= Gdk.KEY_hebrew_taf) { 44 | return false; 45 | } else if (keyval >= Gdk.KEY_Thai_kokai && keyval <= Gdk.KEY_Thai_lekkao) { 46 | return false; 47 | } else if (keyval >= Gdk.KEY_Hangul_Kiyeog && keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) { 48 | return false; 49 | } else if (FORBIDDEN_KEYVALS.includes(keyval)) { 50 | return false; 51 | } 52 | } 53 | 54 | return true; 55 | }; 56 | -------------------------------------------------------------------------------- /src/utils/shell_only.ts: -------------------------------------------------------------------------------- 1 | // Utils only used in the extension. Do not import this file in the preferences window because Shell is not available there. 2 | 3 | import GLib from "gi://GLib"; 4 | import Soup from "gi://Soup"; 5 | import Shell from "gi://Shell"; 6 | import Gio from "gi://Gio"; 7 | import { errorLog, handleError } from "./common.js"; 8 | 9 | Gio._promisify(Gio.DBusProxy, "new", "new_finish"); 10 | Gio._promisify(Gio.File.prototype, "replace_contents_bytes_async", "replace_contents_finish"); 11 | Gio._promisify(Gio.File.prototype, "read_async", "read_finish"); 12 | Gio._promisify(Soup.Session.prototype, "send_and_read_async", "send_and_read_finish"); 13 | 14 | export const getAppByIdAndEntry = (id: string, entry: string): Shell.App => { 15 | const appSystem = Shell.AppSystem.get_default(); 16 | const runningApps = appSystem.get_running(); 17 | 18 | const idResults = Shell.AppSystem.search(id ?? ""); 19 | const entryResults = Shell.AppSystem.search(entry ?? ""); 20 | 21 | if (entryResults?.length > 0) { 22 | const app = runningApps.find((app) => entryResults[0].includes(app.get_id())); 23 | if (app != null) { 24 | return app; 25 | } 26 | } 27 | 28 | if (idResults?.length > 0) { 29 | const app = runningApps.find((app) => idResults[0].includes(app.get_id())); 30 | if (app != null) { 31 | return app; 32 | } 33 | } 34 | 35 | return null; 36 | }; 37 | 38 | export const getImage = async (url: string): Promise => { 39 | if (url == null || url == "") { 40 | return null; 41 | } 42 | 43 | const encoder = new TextEncoder(); 44 | const urlBytes = encoder.encode(url); 45 | 46 | const encodedUrl = GLib.base64_encode(urlBytes); 47 | const path = GLib.build_filenamev([GLib.get_user_cache_dir(), "mediacontrols@cliffniff.github.com", encodedUrl]); 48 | 49 | const exitCode = GLib.mkdir_with_parents(GLib.path_get_dirname(path), 493); 50 | if (exitCode === -1) { 51 | errorLog(`Failed to create cache directory: ${path}`); 52 | return null; 53 | } 54 | 55 | const file = Gio.File.new_for_path(path); 56 | 57 | if (file.query_exists(null)) { 58 | const stream = await file.read_async(null, null).catch(handleError); 59 | 60 | if (stream == null) { 61 | errorLog(`Failed to load image from cache: ${encodedUrl}`); 62 | return null; 63 | } 64 | 65 | return stream; 66 | } else { 67 | const uri = GLib.Uri.parse(url, GLib.UriFlags.NONE); 68 | 69 | if (uri == null) { 70 | return null; 71 | } 72 | 73 | const scheme = uri.get_scheme(); 74 | 75 | if (scheme === "file") { 76 | const file = Gio.File.new_for_uri(uri.to_string()); 77 | 78 | if (file.query_exists(null) === false) { 79 | return null; 80 | } 81 | 82 | const stream = await file.read_async(null, null).catch(handleError); 83 | 84 | if (stream == null) { 85 | errorLog(`Failed to load local image: ${encodedUrl}`); 86 | return null; 87 | } 88 | 89 | return stream; 90 | } else if (scheme === "http" || scheme === "https") { 91 | const session = new Soup.Session(); 92 | const message = new Soup.Message({ method: "GET", uri }); 93 | 94 | const bytes = await session.send_and_read_async(message, null, null).catch(handleError); 95 | 96 | if (bytes == null) { 97 | errorLog(`Failed to load image: ${url}`); 98 | return null; 99 | } 100 | 101 | // @ts-expect-error Types are wrong 102 | const resultPromise = file.replace_contents_bytes_async( 103 | bytes, 104 | null, 105 | false, 106 | Gio.FileCreateFlags.NONE, 107 | null, 108 | ) as Promise<[boolean]>; 109 | 110 | const result = await resultPromise.catch(handleError); 111 | 112 | if (result?.[0] === false) { 113 | errorLog(`Failed to cache image: ${url}`); 114 | return null; 115 | } 116 | 117 | const stream = await file.read_async(null, null).catch(handleError); 118 | 119 | if (stream == null) { 120 | errorLog(`Failed to load cached image: ${url}`); 121 | return null; 122 | } 123 | 124 | return stream; 125 | } else { 126 | errorLog(`Invalid scheme: ${scheme}`); 127 | return null; 128 | } 129 | } 130 | }; 131 | 132 | export const createDbusProxy = async ( 133 | ifaceInfo: Gio.DBusInterfaceInfo, 134 | name: string, 135 | object: string, 136 | ): Promise => { 137 | // @ts-expect-error Types have not been promisified yet 138 | const proxy = Gio.DBusProxy.new( 139 | Gio.DBus.session, 140 | Gio.DBusProxyFlags.NONE, 141 | ifaceInfo, 142 | name, 143 | object, 144 | ifaceInfo.name, 145 | null, 146 | ) as Promise; 147 | 148 | return proxy; 149 | }; 150 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "Bundler", 4 | "outDir": "dist/compiled", 5 | "target": "ESNext", 6 | "module": "ESNext", 7 | "removeComments": false, 8 | "skipLibCheck": true, 9 | "lib": ["ESNext"] 10 | }, 11 | "include": ["./src/**/*.ts"], 12 | "exclude": ["./src/types/dev.ts"] 13 | } 14 | --------------------------------------------------------------------------------