1412 Commits

Author SHA1 Message Date
Rafał Dzięgiel
4a34fb3484 clapper: discoverer: Skip items that already have tags
When tags are populated elsewhere, do not run discovery on them again.
It is possible they were discovered in more efficient maner
(e.g. from playlist data itself).

This avoid us downloading each media item separately after all
playlist items are queued.
2025-07-26 15:37:33 +02:00
Rafał Dzięgiel
d8ea220aad clapper-app: Remove claps handling code
It is now handled inside playlist demuxer, with the other playlist formats
2025-07-26 15:37:31 +02:00
Rafał Dzięgiel
dc56cb201a clapper: Support demuxing uri-list and claps files 2025-07-26 15:37:28 +02:00
Rafał Dzięgiel
07f944fb31 clapper: Update harvest common formats description 2025-07-26 15:37:26 +02:00
Rafał Dzięgiel
b2e6533c30 clapper: Store full caps in harvest
Make it possible to know which enhancer harvested this cached data
2025-07-26 15:37:24 +02:00
Rafał Dzięgiel
7a56fbfff8 clapper: Rename "uri-list-demux" element
Move as harvest URI demuxer since it is supposed to work only with
harvest data from extractable src. Also change caps media type
to "text/x-uri" which is non-standard, but we have to differentiate
single URI from harvest and URI list (one or more URIs).
2025-07-26 15:37:22 +02:00
Rafał Dzięgiel
7457ffda13 clapper: Handle parsed playlists
Handle "ClapperPlaylistParsed" messages on playbin bus by updating current media
item (playlist) to redirect to the first item in that playlist (with changed tags)
and appending remaining items to the queue after that playlist position.

This basically means that playlist gets resolved into simply adding more
items to the queue. This should also work with nested playlists within playlist.
2025-07-26 15:37:18 +02:00
Rafał Dzięgiel
bee2e08fb1 clapper: Add playlist demuxer element
Uses "Playlistable" enhancers to parse playlist and demux first URI in it
2025-07-26 15:32:32 +02:00
Rafał Dzięgiel
0c1d291006 clapper: Split URI list demux code into subclass 2025-07-19 15:43:36 +02:00
Rafał Dzięgiel
4002a63e3a clapper: Add "Playlistable" interface
An interface for creating enhancers that parse data
into individual media items
2025-07-19 15:43:30 +02:00
Rafał Dzięgiel
ff054743e6 flatpak: Sync with Flathub 2025-07-19 15:39:42 +02:00
Rafał Dzięgiel
9432156aec flatpak: Sync with Flathub 2025-07-19 14:54:02 +02:00
Rafał Dzięgiel
47d3ebe693 Revert "flatpak: Skip libmpeg2 build for now"
This reverts commit f63e13ed39.

This workaround does not work, since GStreamer build manifest we use
as shared module from Flathub has explicitly enabled libmpeg2 support.
2025-07-19 12:56:13 +02:00
Rafał Dzięgiel
5f8270f0e8 clapper-app: Retain compatibility with older graphviz 2025-07-19 12:49:01 +02:00
Rafał Dzięgiel
54f059aaa3 clapper-app: Correct pipeline SVG size variable type 2025-07-19 12:03:52 +02:00
Rafał Dzięgiel
f63e13ed39 flatpak: Skip libmpeg2 build for now
Source URI is dead. Build Flatpak without it until
fixed or mirror is found, so our CI works again.
2025-07-19 11:59:22 +02:00
Rafał Dzięgiel
daadabba8d Merge pull request #567 from Rafostar/mpris-compat
MPRIS compat changes
2025-06-26 19:44:07 +02:00
Rafał Dzięgiel
225e665aff clapper: Deprecate MPRIS feature
It was ported to Clapper Enhancers repo as a plugin and applications
using old one should slowy move towards using new plugin instead
2025-06-26 19:37:23 +02:00
Rafał Dzięgiel
31564b568b clapper-app: Prefer MPRIS enhancer over feature object
First try to find and use new MPRIS enhancer plugin, then old MPRIS feature as fallback
2025-06-26 19:09:34 +02:00
Rafał Dzięgiel
1c376612b8 clapper: Do not skip on loading ported enhancers
With some workarounds, we can make enhancers that were ported from
features still be loaded and used within single process without
requirement for building Clapper with their old implementations disabled.

Since MPRIS enhancer already has workarounds in place, lets just remove
all code that was skipping its loading.
2025-06-26 19:06:02 +02:00
Rafał Dzięgiel
c4afd8bea1 Merge pull request #565 from Rafostar/timeline-improvements
Timeline improvements
2025-06-24 19:22:12 +02:00
Rafał Dzięgiel
266c588db9 clapper-gtk: seek-bar: Make custom markers colorful 2025-06-24 18:53:52 +02:00
Rafał Dzięgiel
1c0049ec2b clapper: Make timeline insert/remove work from any thread
Detect and auto switch thread to main if done from a different one.
With this, apps can still continue to implement thread switch and doing
multiple insertions/deletions within single main thread invoke or simply
call this function from a different thread for convenience.
2025-06-24 18:53:43 +02:00
Rafał Dzięgiel
7f326e6875 Merge pull request #564 from Rafostar/disallow-enhancers
clapper: Ability to allow/disallow enhancers
2025-06-24 18:51:52 +02:00
Rafał Dzięgiel
16430c4c66 clapper-app: Allow usage of all reactable enhancers
Enable and use all found enhancer plugins on the system
2025-06-22 13:36:09 +02:00
Rafał Dzięgiel
9f1102bafd clapper: Add ability to enable/disable creation of given enhancer
Allow apps to enable or disable given enhancer instances from being created.
Also as a safely measure, by default only enable enhancers that work
on-demand (extractables) and disable others (reactables).
2025-06-22 13:35:57 +02:00
Rafał Dzięgiel
7b4a19659b Merge pull request #561 from musicinmybrain/remote-only-fsf
Update LGPL-2.1-or-later notices and text for remote-only FSF
2025-06-19 12:43:50 +02:00
Benjamin A. Beasley
8fe46d315c Update LGPL-2.1-or-later license text for remote-only FSF
The Free Software Foundation is now remote-only, and no longer has a
street address. Updated license text is from
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt.
2025-06-14 11:35:04 -04:00
Benjamin A. Beasley
b5cc171803 Update LGPL-2.1-or-later license notices for remote-only FSF
The Free Software Foundation is now remote-only, and no longer has a
street address. Updated license notice text is from
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html#SEC4.
2025-06-14 11:35:02 -04:00
Rafał Dzięgiel
0f929014d5 clapper: reactable: Fix invalid assert check
Fix a copy-paste bug. There is no item to check in this function.
2025-06-09 20:57:45 +02:00
Rafał Dzięgiel
f3b120f451 Merge pull request #559 from Rafostar/reactable
clapper: Add "Reactable" interface
2025-06-09 20:52:15 +02:00
Rafał Dzięgiel
c354d31436 clapper: reactable: Inform which properties were updated 2025-06-09 20:21:39 +02:00
Rafał Dzięgiel
c0b360dc0f clapper-app: Add support for MPRIS enhancer 2025-06-09 18:37:40 +02:00
Rafał Dzięgiel
a6ca0b726c clapper: Implement reactables manager
An object for managing instances of reactable type of enhancers.

Based on/similar to features manager which along with Clapper
features objects gets deprecated in favour of reactables.
2025-06-09 18:36:06 +02:00
Rafał Dzięgiel
976bcc338f clapper: Add "Reactable" interface
An interface for creating enhancers that react to the
playback and/or events that should influence it.
2025-06-08 17:46:35 +02:00
Rafał Dzięgiel
6273446817 Merge pull request #558 from Rafostar/tagged
clapper: Add taglist to media items
2025-06-08 17:43:12 +02:00
Rafał Dzięgiel
72ab32d4ef shared: Do not print deprecations when compiling own code
We keep and use old functions in code for the compatibility reasons with
older API versions. Do not print warnings about them being deprecated when
compiling Clapper library that has and uses such function internally.
2025-06-08 17:17:23 +02:00
Rafał Dzięgiel
e9d0d8f345 clapper: Add taglist to media items
Allow apps to read and/or populate initial taglist within media item.
Apps might care about other tags that Clapper application does not,
so this single property allows them to read whatever tag they might need.
2025-06-08 17:17:13 +02:00
Rafał Dzięgiel
0b8d359844 meson: Improve GIR init section
Init with disabled registry and remove it only for clapper-gtk where its not needed.
2025-06-08 16:57:04 +02:00
Rafał Dzięgiel
4a93bea203 Revert "meson: Remove GIR init section"
This reverts commit b05f0f2b30.
2025-06-08 16:56:57 +02:00
Rafał Dzięgiel
5e2c1a8e30 flatpak: Sync with Flathub 2025-06-08 16:40:47 +02:00
Rafał Dzięgiel
72c8e4ab84 clapper: Fix missing pspec ref when copying proxy
Newly created enhancer proxies hold param specs with a reference
on each and unref them when finalized. For this reason, copied
proxy objects needs to ref pspecs from source, otherwise it would
do an unref without holding a reference on object during destruction.
2025-06-02 20:10:53 +02:00
Rafał Dzięgiel
db61b9c773 gst-plugin: Avoid main thread invoke when used with "ClapperGtkVideo"
This thread invoke is done mainly to support testing with gst-launch-1.0,
otherwise no need when used with "ClapperGtkVideo". We can avoid doing this,
by checking whether this type was already registered in which case it means
that "ClapperGtkVideo" widget is used within GTK application and registered
before sink starts processing data.

In case of "ClapperGtkVideo" we might run into situation where these two threads
are stuck waiting for each other to be idle. This change works around this issue.

Fixes #555
2025-05-25 15:06:32 +02:00
Rafał Dzięgiel
682ad6c3c8 clapper: Allow peeking in Vala
Vala does better job at handling objects without increased reference than
interpreted languages, so its safe to expose list "peek" functions to it.
2025-05-23 16:15:11 +02:00
Rafał Dzięgiel
749796a12f clapper: doc: Update enhancer proxy docs 2025-05-23 16:11:46 +02:00
Rafał Dzięgiel
c557c11e86 clapper: Check enhancer config existence before applying it
Fixes crash due to trying to apply config for an enhancer while
there are no settings in this enhancer to be applied
2025-05-23 08:12:09 +02:00
Rafał Dzięgiel
a2f67a9bc0 Merge pull request #553 from Rafostar/harvest-caching
clapper: Implement harvest caching
2025-05-21 19:49:26 +02:00
Rafał Dzięgiel
ddc0a4d8f9 clapper: doc: Fix missing transfer annotation 2025-05-21 19:42:27 +02:00
Rafał Dzięgiel
92e3e686db clapper: doc: Fix adaptive-start-bitrate description 2025-05-21 18:36:19 +02:00
Rafał Dzięgiel
9fd87dbbb9 clapper: Rename enhancersrc -> extractablesrc
Since this element only uses enhancers of "extractable" type
2025-05-21 17:42:15 +02:00
Rafał Dzięgiel
ca15f4760a clapper: Cleanup cached harvests periodically 2025-05-21 17:42:08 +02:00
Rafał Dzięgiel
6ddb53252a clapper: Implement harvest caching
Using recently added local cache functionality, store harvests
that have expiration date. With this, next time the same URI is
selected for playback we can read it from cache, skipping loading
of any enhancer plugins and doing network requests.

This also works nicely with Clapper discoverer feature.
Making queued items be fetched and cached ahead of playback.
2025-05-20 18:56:28 +02:00
Rafał Dzięgiel
b30d53d8ce clapper: Add ability to set harvest expiration date 2025-05-20 17:18:20 +02:00
Rafał Dzięgiel
1527873bcc clapper: Fix missing unref of mapped file
In case where enhancer plugin version did not match
an unref was missing of read file.
2025-05-19 20:42:32 +02:00
Rafał Dzięgiel
e23f2acb3e meson: Remove unused "config.h" variable 2025-05-18 13:24:51 +02:00
Rafał Dzięgiel
1dfcb218ac meson: Bump min required libadwaita version
Since URI dialog was ported to use AdwAlertDialog,
a minimal Adw version has to be changed to 1.5.
2025-05-17 18:55:31 +02:00
Rafał Dzięgiel
b05f0f2b30 meson: Remove GIR init section
Clapper GStreamer plugin is not part of GObject Introspection,
so no need to init GStreamer when compiling bindings.
2025-05-17 18:20:33 +02:00
Rafał Dzięgiel
dad0d46196 Merge pull request #546 from Rafostar/configurable-enhancers
Make Clapper Enhancers configurable
2025-05-16 18:30:05 +02:00
Rafał Dzięgiel
e34f729f62 clapper: Move basic functions into separate files
Avoid including whole "clapper.h" internally.
Faster recompilation when changes are done.
2025-05-16 17:02:29 +02:00
Rafał Dzięgiel
a97e7d1a96 clapper: Avoid using hardcoded API name in enhancers loader on win32 2025-05-16 17:02:10 +02:00
Rafał Dzięgiel
c6c4fe309b clapper: Implement data cache
Add data cache functions and use them to store enhancer data into local cache file.
This way we can restore all properties and interfaces used in enhancer without
creating its instance. This avoids loading interpreters like Python at init time
making startup a lot faster.
2025-05-16 17:02:07 +02:00
Rafał Dzięgiel
3ef6e9694a clapper-app: Add enhancers to preferences window
Browse, read info and configure Clapper enhancer plugins from preferences window
2025-05-16 17:02:03 +02:00
Rafał Dzięgiel
d951be7a56 clapper: Remove usage of "X-Interfaces" in enhancer data
At this point its sole remaining place where its used is one debug message.
For this reason remove it. With this, enhancer plugin files no longer need to
have this in them unless they want to keep Clapper 0.8 compat (otherwise unused).
2025-05-16 17:01:59 +02:00
Rafał Dzięgiel
98fdd7c58b clapper: Introduce "ClapperEnhancerProxy" objects
Add support for configuring Clapper Enhancers. In order to do that,
introduce enhancer proxy object that act as intermediary between
player and enhancer plugin.

We cannot give direct access to enhancer instances from code, since
they are managed (created and destroyed) by player as/when needed.
Also due to some interpreted languages not working with multiple
threads. Instead, give proxy objects that will store each enhancer
configuration to be applied when an enhancer instance is created.

With this, implementations also gain ability to browse available
enhancers, see what they support and change their properties.

Enhancers are now also assigned to player, instead of being only global.
This allows to configure them separately on a per player instance basis.

Writing configurable enhancers is super easy too, as all plugin has
to do is install standard GParamSpec properties to its class with a
corresponding gschema file (for global props only) and its done.
2025-05-16 17:01:51 +02:00
Rafał Dzięgiel
147d94088c Merge pull request #548 from ximion/master
Use modern appstream, instead of appstream-util for validation
2025-05-03 15:42:28 +02:00
Matthias Klumpp
c7790d9f7b Use modern appstream, instead of appstream-util for validation 2025-05-03 01:56:53 +02:00
Rafał Dzięgiel
f5731957dc New Crowdin updates (#524)
* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-app.pot (Romanian)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Spanish)

* New translations clapper-app.pot (Afrikaans)

* New translations clapper-app.pot (Arabic)

* New translations clapper-app.pot (Catalan)

* New translations clapper-app.pot (Czech)

* New translations clapper-app.pot (Danish)

* New translations clapper-app.pot (German)

* New translations clapper-app.pot (Greek)

* New translations clapper-app.pot (Basque)

* New translations clapper-app.pot (Finnish)

* New translations clapper-app.pot (Hebrew)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-app.pot (Italian)

* New translations clapper-app.pot (Japanese)

* New translations clapper-app.pot (Korean)

* New translations clapper-app.pot (Lithuanian)

* New translations clapper-app.pot (Dutch)

* New translations clapper-app.pot (Norwegian)

* New translations clapper-app.pot (Polish)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Russian)

* New translations clapper-app.pot (Slovak)

* New translations clapper-app.pot (Serbian (Cyrillic))

* New translations clapper-app.pot (Swedish)

* New translations clapper-app.pot (Turkish)

* New translations clapper-app.pot (Ukrainian)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-app.pot (Chinese Traditional)

* New translations clapper-app.pot (Vietnamese)

* New translations clapper-app.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Persian)

* New translations clapper-app.pot (Croatian)

* New translations clapper-app.pot (Hindi)

* New translations clapper-app.pot (Asturian)

* New translations clapper-app.pot (Occitan)

* New translations clapper-app.pot (Persian)

* New translations clapper-app.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Finnish)

* New translations clapper-app.pot (Russian)

* New translations clapper-gtk.pot (Russian)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (German)
2025-04-27 15:20:33 +02:00
Rafał Dzięgiel
2e3c98d9b4 Merge pull request #530 from Rafostar/pipeline-preview-launcher
Ability to show GStreamer pipeline
2025-04-27 13:04:04 +02:00
Rafał Dzięgiel
d09824fb1a clapper-app: Show error dialog on pipeline preview failure 2025-04-26 21:25:13 +02:00
Rafał Dzięgiel
366315077e clapper-app: Use user data dir for storing pipeline exports
System tmp directory does not work within containers such as Flatpak
for our usage with file launcher, so make our own temp in app data dir
2025-04-26 18:33:02 +02:00
Rafał Dzięgiel
a75184a471 flatpak: Build graphviz
Needed for pipeline preview app functionality
2025-04-26 18:32:59 +02:00
Rafał Dzięgiel
5bd6ba8948 meson: Add "pipeline-preview" to printed summary 2025-04-26 18:32:57 +02:00
Rafał Dzięgiel
160dbce265 clapper-app: Add "show pipeline" key shortcut to help overlay 2025-04-26 18:32:55 +02:00
Rafał Dzięgiel
224326857b clapper-app: Create pipeline preview file async 2025-04-26 18:32:42 +02:00
Rafał Dzięgiel
f9b31c51a7 Merge pull request #538 from fritteli/fix-typo-in-german-translation
chore: Fix typo in german translation
2025-04-11 20:11:27 +02:00
Manuel Friedli
be1de8bc77 chore: Fix typo in german translation 2025-04-04 23:06:42 +02:00
Rafał Dzięgiel
b8a4a90b6c clapper-app: Delete temp dir on exit
Pipeline preview creates temp files, so delete whole directory
recursively on app exit. Since these files are used through
launcher/portal with another app, we do not know when user finished
using them, thus we cannot detect and remove them earlier.
2025-02-18 18:30:09 +01:00
Rafał Dzięgiel
d73f33785d clapper-app: Fix a file path in POTFILES
Since #479 "window" was renamed to "dialog".
We also need to update POTFILES accordingly.
2025-02-16 17:49:11 +01:00
Rafał Dzięgiel
dca8fbd336 clapper-app: Add GStreamer pipeline preview
Allow to preview GStreamer pipeline while playing content.
This makes it easier to check what is used underneath.
2025-02-16 17:36:05 +01:00
Rafał Dzięgiel
681d5b8699 clapper: Add a function to get pipeline graph data 2025-02-16 17:23:34 +01:00
Rafał Dzięgiel
009f272f64 Merge pull request #479 from geopjr-forks/fix/adw-1-6-deprecations
clapper-app: Fix libadwaita 1.6 deprecations
2025-02-16 13:22:54 +01:00
Evan Paterakis
a5bc1b5578 clapper-app: set uri-dialog's content width to 420
Co-authored-by: Rafał Dzięgiel <40623528+Rafostar@users.noreply.github.com>
2025-02-15 19:17:04 +02:00
Rafał Dzięgiel
49471882c1 clapper-app: Update POT file 2025-02-15 12:48:42 +01:00
Evan Paterakis
069be30225 clapper-app: fix adw 1.6 deprecations 2025-02-12 17:49:22 +02:00
Rafał Dzięgiel
5f83d93374 Merge pull request #525 from abhijeeth-babu/patch-1
Remove "Music" from Clapper's keywords to lower its priority as a music player
2025-02-10 19:59:51 +01:00
Rafał Dzięgiel
d0a9122833 Merge pull request #528 from Rafostar/ci-arm64
workflows: Build natively on arm64
2025-02-10 19:26:16 +01:00
Rafał Dzięgiel
c29b8871a3 workflows: Build natively on arm64
Replace QEMU with native arm64 runners, now that they are available
2025-02-10 18:21:37 +01:00
Rafał Dzięgiel
d4d0f9e95e flatpak: Sync with Flathub 2025-02-08 12:48:37 +01:00
Rafał Dzięgiel
291c6e35f2 Back to development 2025-02-08 11:48:12 +01:00
Abhijeeth Babu
69bace7150 Remove other unneeded keywords (Album, GNOME, Clapper) from desktop file 2025-01-27 22:57:01 +05:30
Abhijeeth Babu
401e33b1c0 Remove "Music" from Clapper's keywords to lower its priority as a music player
This PR removes the keyword "Music" from Clapper's `.desktop` file to lower its priority as a music player in desktop search results. This ensures that Clapper is not prominently suggested when searching for music-related applications, while retaining its functionality as a video player.

### Changes:
- Removed "Music" from the `Keywords` field in the `.desktop` file.

This change does not affect Clapper's ability to play audio files but adjusts its visibility in application search results.
2025-01-25 22:10:10 +05:30
Rafał Dzięgiel
a449b6b3f5 0.8.0 2025-01-20 21:29:59 +01:00
Rafał Dzięgiel
2d12c8980d clapper-app: Update LINGUAS file 2025-01-20 21:17:53 +01:00
Rafał Dzięgiel
ea102ed870 clapper-gtk: Update LINGUAS file 2025-01-20 21:17:13 +01:00
Rafał Dzięgiel
ee6f3cccdb New Crowdin updates (#517)
* New translations clapper-gtk.pot (German)

* New translations clapper-app.pot (German)

* New translations clapper-app.pot (German)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-gtk.pot (Portuguese)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Russian)

* New translations clapper-app.pot (French)

* New translations clapper-gtk.pot (French)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-gtk.pot (Polish)

* New translations clapper-app.pot (Polish)

* New translations clapper-gtk.pot (Romanian)

* New translations clapper-app.pot (Romanian)

* New translations clapper-app.pot (Romanian)
2025-01-20 21:13:13 +01:00
Rafał Dzięgiel
63d393662e metainfo: Update version history 2025-01-20 20:46:59 +01:00
Rafał Dzięgiel
80285fb50b clapper: Fix importing enhancers with extra path
We cannot use "goto" here, like it was before, as we would fall into an endless loop.
2025-01-20 17:43:48 +01:00
Rafał Dzięgiel
e9377f0c6a Merge pull request #519 from Rafostar/misc-fixes
Miscellaneous fixes
2025-01-19 18:02:10 +01:00
Rafał Dzięgiel
ce102b9c76 workflows: Use flatpak-builder action master version
Since "flatpak-builder" action uses deprecated "upload-artifact"
version, that can stop working soon, disable it and upload ourselves.
This is supported in master, but not in any tagged version,
so for now switch to using action from master branch.

Also bump used runtime to GNOME 47 when building.
2025-01-19 17:42:08 +01:00
Rafał Dzięgiel
4df812066f clapper: enhancers-loader: Support loading extra enhancers
Allow setting an additional dir(s) with "CLAPPER_ENHANCERS_EXTRA_PATH" env.

This should allow to add other enhancers without removing default ones.
If app/user needs to remove default ones, "CLAPPER_ENHANCERS_PATH" env
can be set to empty.
2025-01-19 15:48:45 +01:00
Rafał Dzięgiel
8752d08113 clapper: enhancers-loader: Fix default enhancers dir on Win32 2025-01-19 15:48:34 +01:00
Rafał Dzięgiel
fe30ba24fa clapper-gtk: extra-menu-button: Drop popover focus on unmap
Fixes #496
2025-01-18 18:31:03 +01:00
Rafał Dzięgiel
4472d87f8b clapper-app: Show sink bin child name in info window
Sinks that are bin types often take another configurable sink through a property.
We want to show what was set there in info window too.
2025-01-18 17:27:39 +01:00
Rafał Dzięgiel
e35d04a742 clapper-app: Fix internal functions visibility
We have to export functions that are used from UI files, otherwise they are
not accessible. For this reason add a special internal visibility header.
2025-01-18 15:59:12 +01:00
Rafał Dzięgiel
f017b23798 Merge pull request #518 from Rafostar/win-installer
Provide Windows installer
2025-01-18 11:50:42 +01:00
Rafał Dzięgiel
3513c37f97 clapper-app: Fix declaration-after-statement warning 2025-01-17 21:57:34 +01:00
Rafał Dzięgiel
2225cc68c4 workflows: windows: Add cleanup step
Removal of things that will not be used in an installed app
2025-01-17 21:57:11 +01:00
Rafał Dzięgiel
228ef3e556 workflows: windows: Create installer instead of portable
It makes things much easier for the user, such as automatically associating
video files with Clapper, makes menu entries, optional desktop icon and takes
care of eventual uninstall and/or update later.
2025-01-17 21:53:36 +01:00
Rafał Dzięgiel
21417a1ae7 pkgs: Generate Inno Setup based Windows installer 2025-01-17 21:53:20 +01:00
Rafał Dzięgiel
5906d1b78e clapper-app: Add Windows icon 2025-01-17 21:51:16 +01:00
Rafał Dzięgiel
b7b33172fe New Crowdin updates (#514)
* New translations clapper-gtk.pot (Romanian)

* New translations clapper-app.pot (Romanian)

* New translations clapper-gtk.pot (French)

* New translations clapper-app.pot (French)

* New translations clapper-gtk.pot (Spanish)

* New translations clapper-app.pot (Spanish)

* New translations clapper-gtk.pot (Afrikaans)

* New translations clapper-app.pot (Afrikaans)

* New translations clapper-gtk.pot (Arabic)

* New translations clapper-app.pot (Arabic)

* New translations clapper-gtk.pot (Catalan)

* New translations clapper-app.pot (Catalan)

* New translations clapper-gtk.pot (Czech)

* New translations clapper-app.pot (Czech)

* New translations clapper-gtk.pot (Danish)

* New translations clapper-app.pot (Danish)

* New translations clapper-gtk.pot (German)

* New translations clapper-app.pot (German)

* New translations clapper-gtk.pot (Greek)

* New translations clapper-app.pot (Greek)

* New translations clapper-gtk.pot (Basque)

* New translations clapper-app.pot (Basque)

* New translations clapper-gtk.pot (Finnish)

* New translations clapper-app.pot (Finnish)

* New translations clapper-gtk.pot (Hebrew)

* New translations clapper-app.pot (Hebrew)

* New translations clapper-gtk.pot (Hungarian)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-gtk.pot (Italian)

* New translations clapper-app.pot (Italian)

* New translations clapper-gtk.pot (Japanese)

* New translations clapper-app.pot (Japanese)

* New translations clapper-gtk.pot (Korean)

* New translations clapper-app.pot (Korean)

* New translations clapper-gtk.pot (Lithuanian)

* New translations clapper-app.pot (Lithuanian)

* New translations clapper-gtk.pot (Dutch)

* New translations clapper-app.pot (Dutch)

* New translations clapper-gtk.pot (Norwegian)

* New translations clapper-app.pot (Norwegian)

* New translations clapper-gtk.pot (Polish)

* New translations clapper-app.pot (Polish)

* New translations clapper-gtk.pot (Portuguese)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-gtk.pot (Russian)

* New translations clapper-app.pot (Russian)

* New translations clapper-gtk.pot (Slovak)

* New translations clapper-app.pot (Slovak)

* New translations clapper-gtk.pot (Serbian (Cyrillic))

* New translations clapper-app.pot (Serbian (Cyrillic))

* New translations clapper-gtk.pot (Swedish)

* New translations clapper-app.pot (Swedish)

* New translations clapper-gtk.pot (Turkish)

* New translations clapper-app.pot (Turkish)

* New translations clapper-gtk.pot (Ukrainian)

* New translations clapper-app.pot (Ukrainian)

* New translations clapper-gtk.pot (Chinese Simplified)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-gtk.pot (Chinese Traditional)

* New translations clapper-app.pot (Chinese Traditional)

* New translations clapper-gtk.pot (Vietnamese)

* New translations clapper-app.pot (Vietnamese)

* New translations clapper-gtk.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Portuguese, Brazilian)

* New translations clapper-gtk.pot (Persian)

* New translations clapper-app.pot (Persian)

* New translations clapper-gtk.pot (Croatian)

* New translations clapper-app.pot (Croatian)

* New translations clapper-gtk.pot (Hindi)

* New translations clapper-app.pot (Hindi)

* New translations clapper-gtk.pot (Asturian)

* New translations clapper-app.pot (Asturian)

* New translations clapper-gtk.pot (Occitan)

* New translations clapper-app.pot (Occitan)
2025-01-13 18:32:37 +01:00
Rafał Dzięgiel
d4d82034a4 Merge pull request #515 from Rafostar/win-hi-clock
clapper-app: Support high resolution clock on MS Windows
2025-01-12 20:47:59 +01:00
Rafał Dzięgiel
09b3ef8f39 clapper-app: Do not enforce GSK renderer on Windows 2025-01-12 17:12:33 +01:00
Rafał Dzięgiel
d9b20dcc18 clapper-app: Support Windows high resolution clock
Windows high resolution clock improves accuracy of various Windows
timer APIs and precision of GstSystemClock during playback
2025-01-12 17:12:24 +01:00
Rafał Dzięgiel
60e7d56611 clapper-app: Update POT file 2025-01-11 15:24:07 +01:00
Rafał Dzięgiel
e3bc87ba11 clapper-app: Add "Clear Queue" menu option
An option to clear playback queue from UI. This is quckier
and easier than manually dragging every item to bin.

Closes #434
2025-01-11 15:17:50 +01:00
Rafał Dzięgiel
b542aa1e76 clapper: Wait with flush after streams are selected
Instead flushing right after select streams request, wait until
they are selected before doing a flush.

This fixes a hang when changing audio language with hlsdemux2.
2025-01-10 23:54:29 +01:00
Rafał Dzięgiel
6534fb1e22 clapper-app: Update LINGUAS file 2025-01-07 19:22:15 +01:00
Rafał Dzięgiel
c8b3e28299 clapper-gtk: Update LINGUAS file 2025-01-07 19:21:58 +01:00
Rafał Dzięgiel
35424bf8cf clapper-app: Update POT file 2025-01-07 19:06:11 +01:00
Rafał Dzięgiel
6989b86249 clapper-gtk: Update POT file 2025-01-07 19:05:57 +01:00
Rafał Dzięgiel
fed0c0a972 clapper-app: Add do not translate desktop app name comment 2025-01-07 19:03:10 +01:00
Rafał Dzięgiel
496cc60272 Merge pull request #512 from Rafostar/video-placeholder
clapper-gtk: Add video placeholder widget
2025-01-02 14:18:52 +01:00
Rafał Dzięgiel
a91ce5b0ab clapper-gtk: Add video placeholder widget
A simple placeholder to be shown when "ClapperGtkVideo" is used with a video
sink that cannot be embedded in it (with a text explaining that).
2025-01-02 13:34:36 +01:00
Rafał Dzięgiel
93b1be3147 New Crowdin updates (#503)
* New translations clapper-app.pot (Turkish)

* New translations clapper-gtk.pot (Spanish)

* New translations clapper-app.pot (Spanish)
2024-11-22 22:41:54 +01:00
Rafał Dzięgiel
cca4b002b6 Merge pull request #492 from danialbehzadi/i18n
Make dektop file i18n.
2024-11-22 22:40:50 +01:00
Rafał Dzięgiel
8e6599ae81 Merge pull request #508 from Rafostar/nightly-fix
Update Flatpak Nightly
2024-11-16 22:33:31 +01:00
Rafał Dzięgiel
77ee519f8c flatpak-nightly: Update manifest
Use 24.08 for ffmpeg and switch to Rust stable with added recommended env vars
2024-11-16 17:25:49 +01:00
Rafał Dzięgiel
c42e12d2be workflows: Update nightly extensions to 24.08
Also change to Rust stable to fix build failing
2024-11-16 17:25:03 +01:00
Rafał Dzięgiel
2b916ef856 Merge pull request #506 from Rafostar/adaptive
Add adaptive streaming bitrate control to Clapper API
2024-11-16 16:15:19 +01:00
Rafał Dzięgiel
303bda4d65 clapper: Do not reset "adaptive-bandwidth" to zero
When new instance of adaptive demuxer is created (different video is played)
this prop value would become zero. We want to avoid that and instead report
only bandwidth after fragment is downloaded, so when video will be unplayable,
next one will not start from lowest quality.
2024-11-16 15:26:24 +01:00
Rafał Dzięgiel
22430620a8 clapper-app: Apply "adaptive-start-bitrate" on startup
Watch for "adaptive-bandwidth" changes during adaptive streaming, use these to
set "adaptive-start-bitrate" player property, so we do not always start streaming
from some constant bitrate value which might not be the best for everyone.

Additionally, store last value in GSettings on app exit and also add a command
line arg to set this too.
2024-11-15 23:39:00 +01:00
Rafał Dzięgiel
e4045b98b3 clapper: Add "adaptive-bandwidth" readable property
Apps can use it to determine and set an optimal value for
start bitrate instead of starting at some constant value.
2024-11-15 23:38:50 +01:00
Rafał Dzięgiel
aa819cf2d3 flatpak: Update runtime to 47 2024-11-14 23:19:38 +01:00
Rafał Dzięgiel
a065b81846 flatpak: Add GStreamer 1.24 for testing
We do not yet have GStreamer 1.24 in Flathub repo, so for testing purposes add it here temporarily
2024-11-14 23:18:16 +01:00
Rafał Dzięgiel
9fbba4d66a meson: Bump min required GStreamer version
Setting "start-bitrate" property requires at least GStreamer 1.24.

We do not want to introduce APIs that work only if user has a certain
dependency version, thus this bump instead of version check.

Related work on GStreamer side:
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3894
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3895

Since these were contributed to GStreamer almost 2 years ago with the intention
of using them in Clapper, I think its about time to start do so.
2024-11-14 22:28:21 +01:00
Rafał Dzięgiel
ab659d0951 clapper: Use playbin3 by default
New GStreamer adaptive demuxers work only within playbin3. In order to not
introduce new APIs (setting adaptive bitrate) that do not work by default
and to have the whole "clapper-enhancers" concept working correctly, its
about time to move on to playbin3.
2024-11-13 20:06:34 +01:00
Rafał Dzięgiel
bd3ce28716 clapper: Ability to request adaptive bitrates
Add APIs to allow apps to select start, min and max bitrates for adaptive streaming.

Combining min+max values can allow to implement a video quality selector,
although possible bitrates/qualities are not communicated with an app yet.
2024-11-13 20:00:59 +01:00
Rafał Dzięgiel
0a15e70d02 Merge pull request #501 from Rafostar/libpeas
Support libpeas based plugin system
2024-11-11 13:22:10 +01:00
Rafał Dzięgiel
d42b17a749 workflows: Add libpeas to windows build
Required for enhancers loader
2024-11-11 12:49:23 +01:00
Rafał Dzięgiel
719a4043b5 workflows: Disable "enhancers-loader" for docs build
Not needed to build the docs, so disable it
2024-11-11 12:49:19 +01:00
Rafał Dzięgiel
ee3d07b158 flatpak: Replace gtuber with Clapper enhancers
Also add all required dependencies
2024-11-11 12:49:17 +01:00
Rafał Dzięgiel
c8ef0f891d clapper: Support libpeas based plugin system
Allow loading external plugins called "Enhancers" that as the name suggests,
enhance Clapper library capabilities.

Currently implemented is a "ClapperExtractable" interface meant to extract
an actual media that GStreamer can later play from an initial input URI.
Additionally, an internal GStreamer elements that work with it are ported/moved
here from "gtuber" library that this functionality replaces.
2024-11-11 12:49:07 +01:00
Rafał Dzięgiel
220913de14 Merge pull request #499 from Rafostar/esc-unfullscreen
clapper-app: Add unfullscreen keyboard shortcut
2024-10-15 19:53:32 +02:00
Rafał Dzięgiel
2d1f6f471b clapper-app: Add unfullscreen keyboard shortcut
Unfullscreen with Escape key

Closes #494
2024-10-15 19:32:48 +02:00
Rafał Dzięgiel
af4a876edc New Crowdin updates (#473)
* New translations clapper-gtk.pot (Hindi)

* New translations clapper-app.pot (Russian)

* New translations clapper-gtk.pot (Czech)

* New translations clapper-gtk.pot (Persian)

* New translations clapper-gtk.pot (Norwegian)
2024-10-10 20:23:28 +02:00
Danial Behzadi
e81bcb2f9a Update src/bin/clapper-app/data/meson.build
Co-authored-by: Rafał Dzięgiel <40623528+Rafostar@users.noreply.github.com>
2024-09-28 13:02:29 +03:30
Danial Behzadi
ba64ff224e Make dektop file i18n. 2024-09-28 03:37:21 +03:30
Rafał Dzięgiel
14cdbef81c clapper-gtk: Fix metadata ignore for different languages
Since missing plugin string is translated, word describing its type
(e.g. Decoder) might come before plugin name itself, so we need to
check whole text to find substring instead of checking only prefix.

Fixes #477
2024-08-02 17:22:27 +02:00
Rafał Dzięgiel
931dc255c1 clapper-gtk: Fix some video props not being writable
They should have been writable as we even have setters for them
2024-07-23 17:55:11 +02:00
Rafał Dzięgiel
2f39fef47b readme: Update screenshots 2024-06-30 21:38:29 +02:00
Rafał Dzięgiel
c05a6361b7 clapper-app: metainfo: Add captions to screenshots 2024-06-30 21:29:26 +02:00
Rafał Dzięgiel
c152f3d791 clapper-app: Update LINGUAS file 2024-06-29 18:24:40 +02:00
Rafał Dzięgiel
f967e169b5 clapper-gtk: Update LINGUAS file 2024-06-29 18:24:26 +02:00
Rafał Dzięgiel
04a5bc8523 New Crowdin updates (#431)
* New translations clapper-gtk.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Catalan)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-gtk.pot (Chinese Simplified)

* New translations clapper-gtk.pot (Occitan)

* New translations clapper-app.pot (Occitan)
2024-06-29 18:18:06 +02:00
Rafał Dzięgiel
135be60497 clapper-gtk: billboard: Make transition a tad faster 2024-06-29 17:49:41 +02:00
Rafał Dzięgiel
736fddbe46 meson: Do not list Clapper API features when not building it
No need to list API features if API is not being built.

This avoids an issue with meson script error when Clapper API
build is skipped, since these are not declared then.

Fixes #468
2024-06-29 17:35:47 +02:00
Rafał Dzięgiel
63f2fa1946 examples: Start playback after assembling app window
This is the correct order of how things should be done, so teach what is right
2024-06-29 15:07:59 +02:00
Rafał Dzięgiel
99708e1267 clapper-gtk: status: Apply ".osd" style class
Otherwise text is invisible on light themed apps,
since it renders as black letters on a black background
2024-06-29 15:05:12 +02:00
Rafał Dzięgiel
636e61ead1 clapper-gtk: video: Use "scaletempo" by default
Do not require applications to import GStreamer and their devs to learn its
basics just to set this single element. Similarly as ClapperGtkVideo sets
"clappersink" during construction, it can also set "scaletempo" as this is
the most common choice for an audio filter.

Elements can still be changed like before if desired by setting corresponding
player properties.
2024-06-29 14:52:25 +02:00
Rafał Dzięgiel
147399afd8 clapper: media-item: Fix construct with NULL as "cache-location" 2024-06-28 19:47:07 +02:00
Rafał Dzięgiel
2843a17879 Merge pull request #467 from Rafostar/cached-items
clapper: Add media item creation with cached file
2024-06-27 22:13:36 +02:00
Rafał Dzięgiel
bf0a8b68db clapper: Add media item creation with cached file
Allow creating item with a previously downloaded cache file.
When set, file at location will be tried to be loaded first.
If this fails, URI will be used as normal.
2024-06-27 20:57:59 +02:00
Rafał Dzięgiel
af4ae2c942 clapper: Fix missing "download-complete" signal on short videos
Short video might be fully downloaded before playback starts.
This prevents us from emitting "download-complete" signal with
corresponding media item when download cache is enabled.

Check if we have pending item, as this will be the item downloaded
in such case (before it becomes playing item).
2024-06-22 11:20:57 +02:00
Rafał Dzięgiel
c0221dedc8 examples: Fix typo 2024-06-22 11:12:10 +02:00
Rafał Dzięgiel
9f54c1058c Merge pull request #463 from Rafostar/ms-win
Support MS Windows
2024-06-21 20:32:50 +02:00
Rafał Dzięgiel
07f850d58a workflows: Add windows build job 2024-06-21 18:50:24 +02:00
Rafał Dzięgiel
650b568319 clapper-app: meson: Do not install mimes on Windows
They are unsupported. We use file extensions instead.
2024-06-21 18:50:21 +02:00
Rafał Dzięgiel
abff579b70 clapper-app: Fix missing media in file dialog on Windows
Windows does not support mime-types file filters, so use file extensions instead
2024-06-21 18:50:13 +02:00
Rafał Dzięgiel
0b253b41f6 clapper-app: meson: Binaries with/without console on Windows 2024-06-20 18:32:50 +02:00
Rafał Dzięgiel
d5832bd2db gst-plugin: Improve importers lookup on Win32 2024-06-19 22:44:27 +02:00
Rafał Dzięgiel
98371e822e gst-plugin: Allow overriding importers path with env variable 2024-06-17 21:41:11 +02:00
Rafał Dzięgiel
3f2e5d569d clapper-gtk: video: Fix signals disconnection after dispose
A possibility exists that something else keeps a reference to the player
even after video is disposed. In this case signals from the player would
not be disconnected.

We have to disconnect them manually here to ensure their callbacks will
not be used after disposal.
2024-06-17 19:26:18 +02:00
Rafał Dzięgiel
f58e722002 clapper-app: Fix unused variable warning when no MPRIS
When compiling without MPRIS feature "instance_count" is left unused,
so skip it with preprocessor in order to avoid warning.
2024-06-16 17:35:06 +02:00
Rafał Dzięgiel
262983e857 clapper-app: Ensure private types for GtkBuilder
We need to ensure types that are not part of public API, otherwise GtkBuilder will fail to use them
(e81aad25a1/gtk/glade/README.glade (L15)).
2024-06-16 15:21:23 +02:00
Rafał Dzięgiel
6ca1bccd1a clapper-gtk: Ensure private types before template init
We need to ensure types that are not part of public API, otherwise GtkBuilder will fail to use them
(e81aad25a1/gtk/glade/README.glade (L15)).
2024-06-16 14:51:56 +02:00
Rafał Dzięgiel
c25cfd9598 clapper-app: meson: Do not skip whole data install on non-linux
We cannot run app without schemas, thus we need to compile and install them on any OS
2024-06-16 13:50:54 +02:00
Rafał Dzięgiel
3ce937c2b9 gst-plugin: Properly export external API symbols
We do not install headers from gst-plugin, but still need to export
symbols to compile modules that use plugin provided shared libraries.
2024-06-16 13:50:49 +02:00
Rafał Dzięgiel
521a83bad0 clapper: meson: Add additional check for gdbus-codegen
Check at meson level if "gdbus-codegen" is available and otherwise
exit cleanly, possibly building without MPRIS feature instead of failing.
2024-06-16 13:50:41 +02:00
Rafał Dzięgiel
d4598846d3 clapper-gtk: Properly export external API symbols 2024-06-16 13:48:27 +02:00
Rafał Dzięgiel
50d4fbe43b clapper: Properly export external API symbols 2024-06-16 13:48:17 +02:00
Rafał Dzięgiel
df371c698a clapper-app: Fix opened file content type detection
Fixes issues with detecting whether file has one of supported subtitles mime types
2024-06-14 17:32:03 +02:00
Rafał Dzięgiel
2eaf5032cd Merge pull request #451 from Rafostar/resize-me
Resize app window to match aspect ratio with middle click
2024-05-26 17:06:58 +02:00
Rafał Dzięgiel
28de283a98 clapper-app: Add auto window resize keyboard shortcut
In addition to middle click, also add "Super+r" keyboard shortcut to perform window resize to fit video action
2024-05-25 21:30:26 +02:00
Rafał Dzięgiel
ae6512b233 clapper-app: Resize window to match aspect ratio with middle click 2024-05-25 21:16:59 +02:00
Rafał Dzięgiel
5049f620eb Merge pull request #449 from Rafostar/new-window
Add "New Window" functionality in UI
2024-05-20 22:55:14 +02:00
Rafał Dzięgiel
439e5831e2 clapper-app: Apply options from active window to newly created one
When a new window is created, apply all current values to it (volume, speed,
set GStreamer elements, etc.). It would not be the best experience when user
opens a new window, plays something and 100% volume is used in it.
2024-05-20 22:40:28 +02:00
Rafał Dzięgiel
6484599e46 clapper-gtk: Fix GtkWindowControls style when OSD on video 2024-05-15 21:37:48 +02:00
Rafał Dzięgiel
333f8b4692 clapper-app: Make info window close with Esc key
Fixes #448
2024-05-14 21:13:02 +02:00
Rafał Dzięgiel
9b7c12c3d0 flatpak: Fix MPRIS permission
Since now we do multiple windows, an instance number is added
to owned connection name (as specified in MPRIS spec).

Update Flatpak MPRIS permission to handle that.
2024-05-13 20:32:54 +02:00
Rafał Dzięgiel
6fb25dd22b clapper-app: Add new window keyboard shortcut 2024-05-13 20:05:59 +02:00
Rafał Dzięgiel
cc5c2b2403 clapper-app: Add "New Window" menu option
Allow creating new windows from within the app
2024-05-13 19:15:31 +02:00
Rafał Dzięgiel
71142ab0c6 Merge pull request #444 from Rafostar/cmd-options
Add more command line options
2024-05-12 20:47:45 +02:00
Rafał Dzięgiel
cc8ed7b488 clapper-app: Do not store "enqueue" value in options
It is used immediately, so no need to store it.
2024-05-12 20:30:19 +02:00
Rafał Dzięgiel
6f0ed93b08 clapper-app: Only restore saved settings to new windows 2024-05-12 20:30:16 +02:00
Rafał Dzięgiel
10e0421342 clapper-app: Clamp command line args to allowed values
Instead of running into warnings or other problems when user
specifies an out of range value for command line option, just
clamp them to nearest allowed one.
2024-05-12 20:30:14 +02:00
Rafał Dzięgiel
bcd1d48922 clapper-app: Add command line context params string
Describe what kind of remaining (non-options) strings can
be passed when launching via command line.
2024-05-12 20:30:11 +02:00
Rafał Dzięgiel
aac050e252 clapper-app: Add command line option to enter fullscreen 2024-05-12 20:30:09 +02:00
Rafał Dzięgiel
1330e49ed8 clapper-app: Add command line option to set progression mode 2024-05-12 20:30:07 +02:00
Rafał Dzięgiel
22fb88d0f2 clapper-app: Support creating multiple windows 2024-05-12 20:30:01 +02:00
Rafał Dzięgiel
42b5acd967 clapper: mpris: Fix MPRIS own-name documentation 2024-05-12 20:16:28 +02:00
Rafał Dzięgiel
8e14ec1697 clapper-app: Cleanup to not store app options as global and static
Now that we are using both local and global command line vfuncs, we
can just get and apply options in them and free values later.

This avoids having options global and static.
2024-05-12 19:34:37 +02:00
Rafał Dzięgiel
a257d3f003 clapper-app: Add command line option to enqueue files 2024-05-12 19:34:33 +02:00
Rafał Dzięgiel
eb0baa6fe6 clapper-app: Add command line option to set speed 2024-05-12 16:50:04 +02:00
Rafał Dzięgiel
1001fda256 clapper-app: Add command line option to set volume 2024-05-12 16:50:02 +02:00
Rafał Dzięgiel
6edffb9a4b clapper-app: Add command line options to set GStreamer elements
Allows setting audio/video filters and sinks.
By setting value to "none" default filter can be disabled.
2024-05-12 16:49:54 +02:00
Rafał Dzięgiel
b013cb7405 Merge pull request #438 from Rafostar/download-cache
clapper: Add media caching via download to local storage
2024-05-10 00:14:28 +02:00
Rafał Dzięgiel
07ca728b5b workflows: doc: Do not error on nothing to commit
Not always there are changes to the documentation
2024-05-09 23:50:25 +02:00
Rafał Dzięgiel
938cd44d7e workflows: doc: Continue on commit/push errors 2024-05-09 23:43:30 +02:00
Rafał Dzięgiel
8f4723906f Merge pull request #447 from Rafostar/auto-doc
workflows: Add build documentation job
2024-05-09 23:15:58 +02:00
Rafał Dzięgiel
419354fe8f doc: Add "clapper" GIR path when building "clapper-gtk" doc
Fixes building of clapper-gtk documentation on a clean system
2024-05-09 22:54:08 +02:00
Rafał Dzięgiel
4ec7349a04 workflows: Add build documentation job 2024-05-09 22:53:58 +02:00
Rafał Dzięgiel
03b2cb099f examples: Add download cache code example 2024-05-07 22:15:34 +02:00
Rafał Dzięgiel
f67d5bef2e clapper: Add media caching via download to local storage
The aim here is to stream an online video/audio while also at the
same time download/cache it to disk (excluding adaptive content).

After download is complete, further playback and seeking are done using the
locally cached file. This functionality uses GStreamer "downloadbuffer" element.

Player will emit a signal with a local download location after it completes,
so application will know where downloaded file for media item is stored in
case it wants to reuse it in the future.

It is up to application to set download dir and later manage downloaded
content in it, removing files its not going to use on next application
run and any incomplete downloads.
2024-05-07 22:15:25 +02:00
Rafał Dzięgiel
8f4107aab6 examples: Add simple clapper-gtk usage example 2024-05-07 22:09:41 +02:00
Rafał Dzięgiel
6941f1b042 clapper: Small fix for "init_check" doc
The error arg was removed, but documentation was not updated then
2024-05-02 14:38:25 +02:00
Rafał Dzięgiel
df50802871 clapper-gtk: billboard: Documentation fixes
Billboard does not post automatic volume/speed announcements. It did at
some point during development, but it was scrapped in favour of letting
app use callbacks of "notify" signals to call announce speed/volume.
2024-05-02 13:17:09 +02:00
Rafał Dzięgiel
b1613273d0 gst-plugin: Avoid GTK crash after context is destroyed
It seems GTK continues using created contexts, so we cannot unref it here.
Looking at GTK sink implementation for GtkVideo, I see that they do not
unref it either, but since we use surfaceless context it would be probably
better to have a static GstDisplay and reuse the same context in future.
2024-05-02 11:14:29 +02:00
Rafał Dzięgiel
35527e5c14 clapper-gtk: Ignore missing plugins for metadata
Some media files have custom/proprietary metadata.
It should be safe to simply ignore these, since we do
not map metadata to any sort of Clapper stream anyway.

Fixes #441
2024-05-01 16:32:35 +02:00
Rafał Dzięgiel
e060048969 Merge pull request #429 from 1Maxnet1/patch-1
Complement com.github.rafostar.Clapper.metainfo.xml
2024-05-01 11:45:25 +02:00
Rafał Dzięgiel
09648bbc43 Mention Rust bindings in README.md
Closes #411
2024-04-29 21:38:37 +02:00
Max Buchholz
9e5f9e3d07 Add comment to document categories
Co-authored-by: Rafał Dzięgiel <40623528+Rafostar@users.noreply.github.com>
2024-04-29 20:19:10 +02:00
Rafał Dzięgiel
23c5e7ca65 clapper: Fix MARKER_NO_END value in GIR
Needs a cast from int, otherwise GIR is generated
incorrectly and it ends up as positive number.
2024-04-29 17:50:54 +02:00
Rafał Dzięgiel
6d47aa3c6d clapper-app: metainfo: Update branding colors
Change to values suggested by Tobias Bernard
2024-04-27 16:20:33 +02:00
Rafał Dzięgiel
ae3d75a8b5 clapper-app: metainfo: Update app summary
Change to a text suggested by Tobias Bernard
2024-04-27 16:20:17 +02:00
Rafał Dzięgiel
3561bc8c6f Update README.md 2024-04-27 15:59:28 +02:00
Rafał Dzięgiel
368a484741 flatpak: Sync with Flathub 2024-04-27 15:40:38 +02:00
Rafał Dzięgiel
b3ac64e5b1 clapper-app: Show development versions in about window
Since during development we do not put new release tag into metainfo
which about window uses to know app version, set it manually to the
library version since they are the same.
2024-04-27 14:19:45 +02:00
Rafał Dzięgiel
c873c35fa7 Back to development 2024-04-27 14:14:39 +02:00
Max Buchholz
af47dcb5e5 Complement com.github.rafostar.Clapper.metainfo.xml 2024-04-25 10:54:09 +02:00
Rafał Dzięgiel
f0f4801819 0.6.0 2024-04-22 22:27:06 +02:00
Rafał Dzięgiel
b9f3cbef7f clapper-app: metainfo: Add branding colors 2024-04-22 22:04:21 +02:00
Rafał Dzięgiel
772191a396 clapper-app: metainfo: Restore "developer_name" tag
Needed for older appstream compatibility
2024-04-22 21:52:57 +02:00
Rafał Dzięgiel
f4a766ea9d clapper-gtk: seek-bar: Fix marker popover position on RTL
On RTL we need to subtract position from upper scale value to end up at correct coordinates
2024-04-22 21:14:10 +02:00
Rafał Dzięgiel
c928e601bf clapper: Add pipeline debug graph dump support 2024-04-22 20:16:08 +02:00
Rafał Dzięgiel
8fb62d773f New Crowdin updates (#406)
* New translations clapper-app.pot (Polish)

* New translations clapper-gtk.pot (Turkish)

* New translations clapper-app.pot (Turkish)

* New translations clapper-gtk.pot (Turkish)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Turkish)

* New translations clapper-app.pot (Catalan)

* New translations clapper-gtk.pot (Catalan)

* New translations clapper-app.pot (Catalan)

* New translations clapper-gtk.pot (Portuguese)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-gtk.pot (Hungarian)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-gtk.pot (Romanian)

* New translations clapper-gtk.pot (French)

* New translations clapper-gtk.pot (Spanish)

* New translations clapper-gtk.pot (Afrikaans)

* New translations clapper-gtk.pot (Arabic)

* New translations clapper-gtk.pot (Catalan)

* New translations clapper-gtk.pot (Czech)

* New translations clapper-gtk.pot (Danish)

* New translations clapper-gtk.pot (German)

* New translations clapper-gtk.pot (Greek)

* New translations clapper-gtk.pot (Basque)

* New translations clapper-gtk.pot (Finnish)

* New translations clapper-gtk.pot (Hebrew)

* New translations clapper-gtk.pot (Hungarian)

* New translations clapper-gtk.pot (Italian)

* New translations clapper-gtk.pot (Japanese)

* New translations clapper-gtk.pot (Korean)

* New translations clapper-gtk.pot (Lithuanian)

* New translations clapper-gtk.pot (Dutch)

* New translations clapper-gtk.pot (Norwegian)

* New translations clapper-gtk.pot (Polish)

* New translations clapper-gtk.pot (Portuguese)

* New translations clapper-gtk.pot (Russian)

* New translations clapper-gtk.pot (Slovak)

* New translations clapper-gtk.pot (Serbian (Cyrillic))

* New translations clapper-gtk.pot (Swedish)

* New translations clapper-gtk.pot (Turkish)

* New translations clapper-gtk.pot (Ukrainian)

* New translations clapper-gtk.pot (Chinese Simplified)

* New translations clapper-gtk.pot (Chinese Traditional)

* New translations clapper-gtk.pot (Vietnamese)

* New translations clapper-gtk.pot (Portuguese, Brazilian)

* New translations clapper-gtk.pot (Persian)

* New translations clapper-gtk.pot (Croatian)

* New translations clapper-gtk.pot (Asturian)

* New translations clapper-gtk.pot (German)

* New translations clapper-gtk.pot (Portuguese)

* New translations clapper-app.pot (German)

* New translations clapper-gtk.pot (Turkish)

* New translations clapper-gtk.pot (Catalan)

* New translations clapper-gtk.pot (Finnish)

* New translations clapper-app.pot (Finnish)

* New translations clapper-gtk.pot (Finnish)

* New translations clapper-app.pot (Finnish)

* New translations clapper-gtk.pot (Hungarian)

* New translations clapper-gtk.pot (Hungarian)

* New translations clapper-app.pot (French)

* New translations clapper-gtk.pot (French)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Polish)

* New translations clapper-gtk.pot (Polish)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Polish)

* New translations clapper-app.pot (Polish)

* New translations clapper-app.pot (Romanian)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Spanish)

* New translations clapper-app.pot (Afrikaans)

* New translations clapper-app.pot (Arabic)

* New translations clapper-app.pot (Catalan)

* New translations clapper-app.pot (Czech)

* New translations clapper-app.pot (Danish)

* New translations clapper-app.pot (German)

* New translations clapper-app.pot (Greek)

* New translations clapper-app.pot (Basque)

* New translations clapper-app.pot (Finnish)

* New translations clapper-app.pot (Hebrew)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-app.pot (Italian)

* New translations clapper-app.pot (Japanese)

* New translations clapper-app.pot (Korean)

* New translations clapper-app.pot (Lithuanian)

* New translations clapper-app.pot (Dutch)

* New translations clapper-app.pot (Norwegian)

* New translations clapper-app.pot (Polish)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Russian)

* New translations clapper-app.pot (Slovak)

* New translations clapper-app.pot (Serbian (Cyrillic))

* New translations clapper-app.pot (Swedish)

* New translations clapper-app.pot (Turkish)

* New translations clapper-app.pot (Ukrainian)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-app.pot (Chinese Traditional)

* New translations clapper-app.pot (Vietnamese)

* New translations clapper-app.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Persian)

* New translations clapper-app.pot (Croatian)

* New translations clapper-app.pot (Asturian)
2024-04-21 23:24:54 +02:00
Rafał Dzięgiel
f299e1be57 Merge pull request #420 from Rafostar/prerelease-updates
Prerelease updates
2024-04-21 22:48:16 +02:00
Rafał Dzięgiel
9f38f527be clapper-app: Sync POT file 2024-04-21 20:25:15 +02:00
Rafał Dzięgiel
10f626637b Update install steps in README.md 2024-04-21 19:58:44 +02:00
Rafał Dzięgiel
22c93c00f7 clapper-app: gschema: Fix gettext-domain value
In rewritten code "clapper-app" is used for gettext
2024-04-21 19:50:05 +02:00
Rafał Dzięgiel
7a38b605b3 clapper-app: metainfo: Update values
Update description and some other values. Also update whatever
was nowadays considered as deprecated in metainfo guidelines.
2024-04-21 16:07:28 +02:00
Rafał Dzięgiel
5c41c3a8c7 clapper-app: metainfo: Fix invalid values
Flathub validation no longer allows words for "display_length" - should be 360.
Also all "Purism" keys are nowadays invalid. They cause problems as metainfo is
parsed into hash table, thus there cannot be multiple keys with the same name.
2024-04-21 15:22:17 +02:00
Rafał Dzięgiel
51e1dd8493 Remove .gitattributes file
All linguist-vendored stuff was removed, so this git attributes file is unused and no longer needed.
2024-04-20 12:09:41 +02:00
Rafał Dzięgiel
654e6be72a clapper-app: Be more restrictive about key modifiers
Ignore key presses with additional modifiers if we describe them
in shortcuts as sole letters. Combinations might be needed in the future.
2024-04-19 23:10:14 +02:00
Rafał Dzięgiel
681da9e2f3 clapper-gtk: video: Add workaround for better GStreamer 1.24 support 2024-04-19 16:51:44 +02:00
Rafał Dzięgiel
36c166813e clapper-gtk: video: Support finding widget within bin elements
When a video sink is set to some bin, also check sinks within it
in search for a widget that can be used as video main child
2024-04-19 16:39:08 +02:00
Rafał Dzięgiel
2aecd65735 clapper-app: help-overlay: Update progression key accelerator
We allow just "p" key (including any combination with it) for changing
progression mode. Fix its description in help overlay to be just "p" then.

Fixes #417
2024-04-17 19:11:02 +02:00
Rafał Dzięgiel
a46846c24d clapper-app: Use "GDK_MODIFIER_MASK" with key controller state
We need to use "GDK_MODIFIER_MASK" to remove all private fields from key
controller state mask, otherwise its not zero on Xorg.

Fixes #416
2024-04-17 18:26:16 +02:00
Rafał Dzięgiel
fab168283d clapper: player: Make GstElement setters nullable
Allow to set NULL in order to use default value. With this, API users
will not have to check if the element they make from registry is not NULL.
2024-04-16 19:07:16 +02:00
Rafał Dzięgiel
1b38a169dd clapper-gtk: video: Debug message with used video sink
So we can know from debug logging what sink someone is using
2024-04-16 19:03:34 +02:00
Rafał Dzięgiel
a00aea50b0 Merge pull request #413 from Rafostar/workflows
Update workflows
2024-04-15 22:46:58 +02:00
Rafał Dzięgiel
6fc2c78d59 Remove unused OBS service file
This file was referencing build scripts that are no longer in this repo.
An up-to-date OBS config is kept in my opensuse build system account itself.
2024-04-15 22:43:04 +02:00
Rafał Dzięgiel
85038a669f clapper-app: Restore "q" to quit app shortcut
We used to have this and some other players (e.g. Totem) have it too, so no harm in restoring it.
2024-04-15 20:53:32 +02:00
Rafał Dzięgiel
484f2402a3 flatpak-nightly: Update manifest
In latest git, binary name is now simply "clapper". Also we now depend on libmicrodns for the server feature to be available.
2024-04-15 20:07:07 +02:00
Rafał Dzięgiel
1a0158e775 flatpak-nightly: Build dav1d from git master 2024-04-14 20:36:25 +02:00
Rafał Dzięgiel
1d92539b76 clapper-gtk: Various documentation cleanups and fixes 2024-04-14 20:17:38 +02:00
Rafał Dzięgiel
bab3d34349 clapper: Various documentation cleanups and fixes 2024-04-14 20:17:12 +02:00
Rafał Dzięgiel
e751428d6c workflows: Update to use latest versions of actions 2024-04-14 17:23:33 +02:00
Rafał Dzięgiel
a9769f9537 gst-plugin: sink: Stop preferring GL over GLES with GStreamer 1.24+
GStreamer 1.24 have implemented DRM modifiers negotiation that its lack of we were
working around with using GL on unpatched GStreamer (non-Flatpak builds).

Since GStreamer 1.24 does this and moreover it has disabled DMABuf codepath for
non-GLES we should start preferring GLES with this version always.
2024-04-14 15:47:20 +02:00
Rafał Dzięgiel
fe6b3fcf29 clapper-app: Fix window buttons on initial state
Also handle different buttons placements on initial state, similarly as we do now in headerbar.
With this commit, application menu is replicated in initial state UI, but its actually a good thing,
since this will allow us to have more current video related items in it only in main window.
2024-04-14 15:11:18 +02:00
Rafał Dzięgiel
6447944b21 clapper-app: Handle alternative headerbar buttons placements
Handle all possible combinations of window state buttons placement.
These are "right" and "left" combined along with either LTR or RTL.

Fixes #402
2024-04-13 18:32:36 +02:00
Rafał Dzięgiel
42fa31cc4b Merge pull request #404 from Rafostar/scroll-fixes
Scroll fixes
2024-04-13 14:28:23 +02:00
Rafał Dzięgiel
4baade3b32 Merge pull request #408 from sp1ritCS/devenv
meson: Ensure clapper uses local translations within the devenv
2024-04-12 21:38:16 +02:00
Florian "sp1rit"​
bcd8e470ad po: Updated German translation
I've taken a bit of liberty with some of the translations, but I feel
like they should be fine.

Signed-off-by: Florian "sp1rit"​ <sp1rit@disroot.org>
2024-04-12 20:57:04 +02:00
Florian "sp1rit"​
3841a906fd meson: Ensure clapper uses local translations within the devenv
This patch modifies the initialization routines of clapper to check for
    CLAPPER_GTK_OVERRIDE_LOCALEDIR and
    CLAPPER_APP_OVERRIDE_LOCALEDIR
and uses that instead of the LOCALEDIR specified in the config.h.

It also fixes the bug where libclapper-gtk loads the translations for
the clapper application and the clapper application loads the
translations for the libclapper-gtk. (It took me shockingly long to
figure out why the translations weren't working 🙃)

Co-authored-by: Rafał Dzięgiel <rafostar.github@gmail.com>
Signed-off-by: Florian "sp1rit"​ <sp1rit@disroot.org>
2024-04-12 20:38:46 +02:00
Rafał Dzięgiel
5e7305516e clapper-gtk: Update POT file 2024-04-12 20:29:30 +02:00
Rafał Dzięgiel
f1ef299c10 clapper-gtk: status: Fix missing translations 2024-04-12 20:28:23 +02:00
Rafał Dzięgiel
1606a165e4 clapper-gtk: extra-menu-button: Use "Show Subtitles" text
As pointed in #410, the word "Enabled" and a checkmark next to it is a bad UX.
Change this text to "Show Subtitles" instead.
2024-04-12 20:25:49 +02:00
Rafał Dzięgiel
87f51c6755 clapper: Also update decoders after preroll
Sometimes decoders might not be active yet until media starts playing, to fix that being racy also try to update them after preroll
2024-04-12 20:22:48 +02:00
Rafał Dzięgiel
ca73b3a3ef clapper-gtk: extra-menu-button: Make text->number conversion more forgiving
Try to parse into a number as much of the string as possible, without caring
about a sign suffix. This way input will be more forgiving instead of resetting
itself to lowest allowed number.

Also when a number exceeds allowed range, set it to maximal allowed value
instead of once again resetting to minimum.
2024-04-11 20:49:36 +02:00
Rafał Dzięgiel
6f1277a2e6 server: Fix invalid JSON caused by locale decimal conversion
When creating JSON data, we must ensure that our decimal numbers are converted
to a string with a "." as separator, otherwise it would be an invalid JSON.
2024-04-11 20:20:37 +02:00
Rafał Dzięgiel
76f830fa6e Merge pull request #409 from sp1ritCS/fix_pbspeed
clapper-gtk/extra-menu: Fixed speed being forced to the lowest value
2024-04-11 20:07:44 +02:00
Florian "sp1rit"​
a63d92601f clapper-gtk/extra-menu: Fixed speed being forced to the lowest value
As the SpinButton input callback attempted to parse the value inserted
as a string by printf using g_ascii_strtod, only if the language also
used . (full stop / u002E) as decimal seperator worked correctly.
Otherwise, parsing would fail and result (after a few iterations) in the
lowest value being set.

The usually correct approach is to use g_ascii_dtostr / g_ascii_formatd
instead of printf to format a decimal number, but given that this number
is actually presented to the user, going with g_strtod seems like a
better choice (I've decided against just using the stdlib strtod as to
allow the SpinButton to also recognize manual user input containing the
full stop  instead of their languages native decimal seperator (not
that that'll ever happen, given the user can't focus the SpinButton
entry while media is running).

I've also fixed this for the volume SpinButton too, but it wasn't really
affected in the first place as it appearently always gets rounded up to
a number without decimal places.

Signed-off-by: Florian "sp1rit"​ <sp1rit@disroot.org>
2024-04-10 12:26:50 +02:00
Rafał Dzięgiel
0c9973ef85 Add .flatpak-builder to .gitignore 2024-04-09 20:02:31 +02:00
Rafał Dzięgiel
65c974d539 Merge pull request #407 from sp1ritCS/devenv
Allow clapper to be ran within the meson devenv
2024-04-09 17:21:54 +02:00
Florian "sp1rit"​
43e2e88a4c meson: Use gnome.compile_schemas()
This causes meson to automatically build the clapper gsettings schemas
and set GSETTINGS_SCHEMA_DIR to the correct location within the devenv.

This means that can now be ran without needing to install it somewhere
using:
    meson devenv -C <builddir>
    clapper
    exit

More devenv overrides should be investigated (such as automatically
adopting the correct directory for translated locales etc.)

Signed-off-by: Florian "sp1rit"​ <sp1rit@disroot.org>
2024-04-09 11:39:32 +02:00
Rafał Dzięgiel
c327734ca6 clapper-app: Do not trigger default scroll handler on GtkRange
In addition to GtkScrolledWindow, when also hovering over GtkRange
subclassing widgets like GtkScale, do not trigger accidentally
default app window scroll handler.

We want the hovered upon widget and only that widget to handle scroll
events in such case.
2024-04-08 20:37:32 +02:00
Rafał Dzięgiel
48b5a7c12a Remove TODO.md
Most of it was implemented and what is left already has an open issue which is easier to track progress
2024-04-08 19:07:21 +02:00
Rafał Dzięgiel
1dd47ad2a9 Remove old translation files
They are no longer used and translated strings from them were moved to new files
2024-04-08 19:04:35 +02:00
Rafał Dzięgiel
fbeafbccd1 crowdin: Remove legacy app translations
Now that old translated strings are moved to new .po files, remove what is left unused.
2024-04-08 18:34:12 +02:00
Rafał Dzięgiel
f391e2ea87 New Crowdin updates (#405)
* New translations clapper-gtk.pot (Romanian)

* New translations clapper-gtk.pot (French)

* New translations clapper-gtk.pot (Spanish)

* New translations clapper-gtk.pot (Afrikaans)

* New translations clapper-gtk.pot (Arabic)

* New translations clapper-gtk.pot (Catalan)

* New translations clapper-gtk.pot (Czech)

* New translations clapper-gtk.pot (Danish)

* New translations clapper-gtk.pot (German)

* New translations clapper-gtk.pot (Greek)

* New translations clapper-gtk.pot (Basque)

* New translations clapper-gtk.pot (Finnish)

* New translations clapper-gtk.pot (Hebrew)

* New translations clapper-gtk.pot (Hungarian)

* New translations clapper-gtk.pot (Italian)

* New translations clapper-gtk.pot (Japanese)

* New translations clapper-gtk.pot (Korean)

* New translations clapper-gtk.pot (Lithuanian)

* New translations clapper-gtk.pot (Dutch)

* New translations clapper-gtk.pot (Norwegian)

* New translations clapper-gtk.pot (Polish)

* New translations clapper-gtk.pot (Portuguese)

* New translations clapper-gtk.pot (Russian)

* New translations clapper-gtk.pot (Slovak)

* New translations clapper-gtk.pot (Serbian (Cyrillic))

* New translations clapper-gtk.pot (Swedish)

* New translations clapper-gtk.pot (Turkish)

* New translations clapper-gtk.pot (Ukrainian)

* New translations clapper-gtk.pot (Chinese Simplified)

* New translations clapper-gtk.pot (Chinese Traditional)

* New translations clapper-gtk.pot (Vietnamese)

* New translations clapper-gtk.pot (Portuguese, Brazilian)

* New translations clapper-gtk.pot (Persian)

* New translations clapper-gtk.pot (Croatian)

* New translations clapper-gtk.pot (Asturian)

* New translations clapper-app.pot (Romanian)

* New translations clapper-app.pot (French)

* New translations clapper-app.pot (Spanish)

* New translations clapper-app.pot (Afrikaans)

* New translations clapper-app.pot (Arabic)

* New translations clapper-app.pot (Catalan)

* New translations clapper-app.pot (Czech)

* New translations clapper-app.pot (Danish)

* New translations clapper-app.pot (German)

* New translations clapper-app.pot (Greek)

* New translations clapper-app.pot (Basque)

* New translations clapper-app.pot (Finnish)

* New translations clapper-app.pot (Hebrew)

* New translations clapper-app.pot (Hungarian)

* New translations clapper-app.pot (Italian)

* New translations clapper-app.pot (Japanese)

* New translations clapper-app.pot (Korean)

* New translations clapper-app.pot (Lithuanian)

* New translations clapper-app.pot (Dutch)

* New translations clapper-app.pot (Norwegian)

* New translations clapper-app.pot (Polish)

* New translations clapper-app.pot (Portuguese)

* New translations clapper-app.pot (Russian)

* New translations clapper-app.pot (Slovak)

* New translations clapper-app.pot (Serbian (Cyrillic))

* New translations clapper-app.pot (Swedish)

* New translations clapper-app.pot (Turkish)

* New translations clapper-app.pot (Ukrainian)

* New translations clapper-app.pot (Chinese Simplified)

* New translations clapper-app.pot (Chinese Traditional)

* New translations clapper-app.pot (Vietnamese)

* New translations clapper-app.pot (Portuguese, Brazilian)

* New translations clapper-app.pot (Persian)

* New translations clapper-app.pot (Croatian)

* New translations clapper-app.pot (Asturian)
2024-04-08 18:22:06 +02:00
Rafał Dzięgiel
37bf374283 crowdin: Add new translation paths to config 2024-04-08 17:33:41 +02:00
Rafał Dzięgiel
1327dc23e4 clapper-gtk: Fix seek bar touchpad scrolling
Since we only do seek on scale drop, handle scrubbing using touchpad
the same way by marking it as "dragging" after scrubbing starts and
doing seek after it ends.
2024-04-07 20:08:53 +02:00
Rafał Dzięgiel
6e17996691 clapper-app: Fix wrong direction of touchpad scrolling
We should not invert axis. Otherwise its opposite compared to the same gesture performed on GtkScale.
2024-04-07 20:05:20 +02:00
Rafał Dzięgiel
606b9c5170 Update README.md 2024-04-06 18:17:38 +02:00
Rafał Dzięgiel
e4814877de Merge pull request #374 from Rafostar/libclapper
Introduce Clapper libraries
2024-04-05 22:30:55 +02:00
Rafał Dzięgiel
6b135d51f3 flatpak: Switch to using Adelie Linux a52dec
Original repo is removed, change to maintained fork.
Others are doing the same e.g. FreeBSD
2024-04-05 21:18:46 +02:00
Rafał Dzięgiel
1a52576be3 flatpak: Update Flatpak manifests
Update GitHub Flatpak builds to latest runtime version, add new libs
that we need and remove the ones that are not needed anymore.
2024-04-05 21:18:42 +02:00
Rafał Dzięgiel
cc004a8144 bin: Rewrite Clapper player binary
A rewritten Clapper video player made using "Clapper" and "ClapperGtk" libraries.

Since both libraries from this repo are in C, newly rewritten Clapper binary is also in C to
avoid mixing different programming languages in a single repo, thus making maintenance easier.
Not depending on GJS gives us also an additional benefit of supporting different operating
systems or linux shells without pulling GJS as dependency.

Licensed under GPL-3.0-or-later.
2024-04-05 21:18:39 +02:00
Rafał Dzięgiel
675ddc85a1 lib: Introduce Clapper GTK integration library
An easy to use GTK integration library. Meant as a GtkVideo alternative.

While GtkVideo is more of a simple example of video playback under GTK4, this
acts as a full-fledged video player in the form of a GtkWidget that can be placed
anywhere within application.

The widget offers customization options for both top header and bottom playback
controls panels. The Clapper playback API is exposed under widget "player" property
making it easy for the programmer to set media and control playback programically.

The new library will be distributed with Clapper player. This includes public headers
and GObject Introspection support.

Licensed under LGPL-2.1-or-later.
2024-04-05 21:18:35 +02:00
Rafał Dzięgiel
d7f069d6c3 lib: Introduce Clapper playback library
An easy to use media playback library (libclapper) as a GstPlayer replacement.

Previously we tried to use upstream `gstplayer` library to control playback and
pass all events from multiple threads GStreamer uses into an app main thread.
Since this caused some thread racy problems and we needed additional ABI breaking
changes to better suit our needs, we ended up with a modified fork of said library
renamed to `gstclapper` as a temporary solution.

This new library simply named `clapper` replaces our previous `gstclapper` solution
and is written completely from scratch by myself. The aim here is to have an easy to
use playback library better suited to work with (but not limited to) GTK and GObject
properties bindings by relying on "notify" signals.

Major differences include:
* Operates on a playback queue (inherits `GListModel` interface) instead of a single URI
* Uses "notify" signals for property changes always dispatched to app thread
* Time is passed/read as decimal number in seconds instead of int64 in nanoseconds
* Integrates `GstDiscoverer` to figure out media info (such as title) before playback
* Easy to use MPRIS support as part of library
* Optional playback remote controls with WebSocket messages

The new library will be distributed with Clapper player. This includes public headers
and GObject Introspection support.

Licensed under LGPL-2.1-or-later.

Enjoy
2024-04-05 21:18:08 +02:00
Rafał Dzięgiel
edaba00658 Merge pull request #378 from TriVoxel/master
Add standard shortcut for preferences
2023-10-31 21:19:30 +01:00
Rafał Dzięgiel
8cf3e57d51 Merge pull request #385 from Rafostar/nightly-fix
flatpak-nightly: Update to 23.08 runtime
2023-10-31 18:49:37 +01:00
Rafał Dzięgiel
32723c49ad flatpak-nightly: Update to 23.08 runtime 2023-10-30 23:08:37 +01:00
cadenmitchell
058844c010 Add standard shortcut for preferences 2023-09-06 12:53:01 -06:00
Rafał Dzięgiel
b4aaea1940 Merge pull request #364 from Rafostar/ws-fix
webServer: Listen on all interfaces
2023-06-27 19:58:49 +02:00
Rafał Dzięgiel
2dd08b7b33 webServer: Listen on all interfaces
Listen on all network interfaces for incoming connections.

Previous soup_server_listen_local() only listens on local
loopback device preventing access from network, so use
listen_all() instead to allow access through any interface.

Fixes #362
2023-06-27 18:44:59 +02:00
Rafał Dzięgiel
086b134483 flatpak: Sync with Flathub 2023-06-05 21:25:05 +02:00
Rafał Dzięgiel
9da04c549b Update LINGUAS file 2023-06-05 21:22:40 +02:00
Rafał Dzięgiel
ac7ec5fc12 New Crowdin updates (#355)
* New translations com.github.rafostar.Clapper.pot (Croatian)

* New translations com.github.rafostar.Clapper.pot (Swedish)
2023-06-05 21:17:45 +02:00
Rafał Dzięgiel
6e705485f5 Merge pull request #354 from milotype/Croatian-translation
Croatian translation
2023-05-06 20:31:30 +02:00
Rafał Dzięgiel
18caee32d7 New Crowdin updates (#348)
* New translations com.github.rafostar.Clapper.pot (Lithuanian)

* New translations com.github.rafostar.Clapper.pot (Finnish)
2023-05-05 13:51:08 +02:00
Milo Ivir
c7590b653b Add Croatian translation 2023-05-03 19:05:52 +02:00
Milo Ivir
dce74148a7 Add hr for Croatian 2023-05-03 19:05:17 +02:00
Rafał Dzięgiel
5ed9861530 Merge pull request #349 from g7/rotation
Allow detecting and setting media rotation
2023-05-02 20:47:58 +02:00
Rafał Dzięgiel
3f86b236d9 flatpak: Sync with Flathub 2023-04-29 16:38:58 +02:00
Eugenio Paolantonio (g7)
e275c3017a plugin: sink: allow detecting and/or setting media rotation. Fixes #310
GstClapperSink now allows to specify the media rotation via the `rotation`
property, which should be of type GstVideoOrientationMethod.

The default behaviour is to detect the media rotation automatically.

Signed-off-by: Eugenio Paolantonio (g7) <me@medesimo.eu>
2023-04-23 22:43:22 +02:00
Eugenio Paolantonio (g7)
4e250c8f2a plugin: paintable: Support setting media rotation. Contributes to #310
Rotation can be set by passing a GstVideoOrientationMethod to the
gst_clapper_paintable_set_rotation() function.

The actual rotation is done through GskTransforms directly on the
Snapshot.

Signed-off-by: Eugenio Paolantonio (g7) <me@medesimo.eu>
2023-04-23 22:24:29 +02:00
Eugenio Paolantonio (g7)
7fc93fbebc plugin: Add helper to get the actual width and height for a specific rotation
Signed-off-by: Eugenio Paolantonio (g7) <me@medesimo.eu>
2023-04-23 22:24:29 +02:00
Rafał Dzięgiel
bf52197896 plugin: Present fallback window right after assembled UI
When started from gst-play/launch-1.0 show window right after it was created.
No need to idle dispatch window present when changing state, since we are
already on correct thread when opening resources using start() method.
2023-02-12 13:53:51 +01:00
Rafał Dzięgiel
9556ec4da2 plugin: Ensure allocation using the same importer
Instead of locking mutex twice and praying that importer will not change in between, just ref it to ensure that
2023-02-12 13:16:18 +01:00
Rafał Dzięgiel
bd8f0280e2 plugin: Check importer presence before proposing allocation
In some cases importer might not be determined here yet.
Check if we have it to avoid a crash.
2023-02-09 11:38:36 +01:00
Rafał Dzięgiel
40b6f4c724 Update LINGUAS file 2023-01-08 19:00:16 +01:00
Rafał Dzięgiel
456d621ee3 New Crowdin updates (#332)
* New translations com.github.rafostar.Clapper.pot (Slovak)
2023-01-08 18:57:28 +01:00
Rafał Dzięgiel
263d3f8196 Merge pull request #324 from Rafostar/flatpak-translated
flatpak: Build with translations included
2023-01-08 18:54:20 +01:00
Rafał Dzięgiel
44db8c0d3b flatpak: Sync with Flathub 2023-01-07 18:55:01 +01:00
Rafał Dzięgiel
272e3a036c flatpak-nightly: Build with translations included
Flatpak git action does not support uploading a separate .Locale runtime.
Build it as part of the main app then.
2022-11-18 22:51:20 +01:00
Rafał Dzięgiel
540c294b2a flatpak: Build with translations included
Flatpak git action does not support uploading a separate .Locale runtime.
Build it as part of the main app then.
2022-11-18 22:50:54 +01:00
Rafał Dzięgiel
6c5753db53 Merge pull request #317 from Rafostar/gnome43
flatpak: Update to GNOME 43
2022-10-14 08:13:17 +02:00
Rafał Dzięgiel
a25bfa5418 flatpak: Update to GNOME 43
Update git actions builds to GNOME 43 runtime. #315
2022-10-13 20:54:26 +02:00
Rafał Dzięgiel
aaa3f6c4da Merge pull request #316 from Rafostar/nights
Update nightly Flatpak builds
2022-10-10 22:45:48 +02:00
Rafał Dzięgiel
845de1db8b flatpak-nightly: Only build GStreamer Rust plugins on x64
We are no longer able to build them on aarch64, as CI either runs out of memory or time limit
2022-10-10 18:06:32 +02:00
Rafał Dzięgiel
301e1f2ade flatpak-nightly: Skip compiling libadwaita
Nightly has now newer version, so we do not need to build it ourselves anymore
2022-10-09 20:17:56 +02:00
Rafał Dzięgiel
ff5091e7d3 flatpak-nightly: Update to llvm14 2022-10-09 15:00:22 +02:00
Rafał Dzięgiel
0d74fbb3e6 workflow: Update Flatpak nightly to 22.08 2022-10-09 14:22:19 +02:00
Rafał Dzięgiel
9d6ec43b0a Merge pull request #312 from jakedane/jakedane-patch-1
plugin: sink: Replace deprecated method
2022-09-28 22:10:40 +02:00
Jake Dane
cbc3061714 plugin: sink: Replace deprecated method
The method gtk_picture_set_keep_aspect_ratio is deprecated. As per the
warnings given when compiling clapper, it is replaced with
gtk_picture_set_content_fit with the same behavior as before.
2022-09-27 20:50:16 +02:00
Rafał Dzięgiel
d8b02824f3 Update gitattributes
The contents of extras and lib/plugin folders should not be marked as linguist-vendored since they include only my own code made for Clapper. Lets include them in git stats.
2022-09-07 13:15:34 +02:00
Rafał Dzięgiel
dd255dd337 New translations com.github.rafostar.Clapper.pot (Persian) (#305) 2022-09-03 20:40:35 +02:00
Rafał Dzięgiel
447c6f30d0 meson: Validate appstream file with "--nonet" arg
We do not need network connection to validate our appstream file.
Make it easier to run tests in containers that do not have network access.

Closes #307
2022-07-31 19:12:42 +02:00
Rafał Dzięgiel
afa06d4579 Merge pull request #299 from Rafostar/web-fix
api: Do not set default user-agent string
2022-07-25 10:23:27 +02:00
Rafał Dzięgiel
b04bf11c42 api: Do not set default user-agent string
Similarly as with other properties, we should aim to make this into user config option.
For the time being remove, as our outdated default user-agent seems to be breaking
few HLS streaming services.
2022-07-24 19:39:11 +02:00
Rafał Dzięgiel
939f75763d Merge pull request #302 from Rafostar/crowdin_sync
New Crowdin updates
2022-07-21 18:07:18 +02:00
Rafał Dzięgiel
d4c44049ca New translations com.github.rafostar.Clapper.pot (Chinese Simplified) 2022-07-18 10:48:44 +02:00
Rafał Dzięgiel
11c27eccaa Merge pull request #279 from Rafostar/fix-gl-caps
Make GL caps negotiation check what HW supports
2022-07-04 18:51:45 +02:00
Rafał Dzięgiel
823cb0a894 Update LINGUAS file 2022-07-04 18:20:40 +02:00
Rafał Dzięgiel
b27db1ac22 New Crowdin updates (#283)
* New translations com.github.rafostar.Clapper.pot (Persian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Asturian)
2022-07-04 18:16:55 +02:00
Rafał Dzięgiel
564c6e7299 flatpak: Sync with Flathub 2022-07-04 12:30:27 +02:00
Rafał Dzięgiel
6f4632d940 New translations com.github.rafostar.Clapper.pot (German) (#282) 2022-06-24 20:23:50 +02:00
Rafał Dzięgiel
23bb253ca2 0.5.2 2022-06-24 10:05:02 +02:00
Rafał Dzięgiel
8ebf4e3b2f plugin: gluploader: Check for formats actually supported
Do not assume that HW can do every format that GLUpload/GLColorConvert can.
Check what video formats GL context actually supports and advertise that,
so a format that HW cannot do will never be picked up.
2022-06-16 15:41:44 +02:00
Rafał Dzięgiel
04a028d689 plugin: Rework code to use new GL context handler
Create a GL context handler subclass of recently added context handler base class and
rework code to use it. This simplifies a lot of things, like: switching of importers
at runtime, handling context queries, sharing data between importers, etc.
2022-06-16 15:41:30 +02:00
Rafał Dzięgiel
0920914b89 plugin: Add context handler base class
In order to bridge work with GL between GTK and GStreamer reliably, we need to create and
check context capabilities ahead of time. We also need to be able to query context at any
time during playback. Also we should avoid changing importers on context queries, this can
lead to all sort of problems.

To be able to achieve all of above, introduce new context handler base class that works
separately of importers.
2022-06-12 13:58:51 +02:00
Rafał Dzięgiel
2343e84a41 plugin: Use set_static_metadata in class init
Use static version of this function, so our static strings will not be copied
2022-06-06 21:04:17 +02:00
Rafał Dzięgiel
c288223321 Merge pull request #278 from Rafostar/flatpak-gvfs
flatpak: Add missing GVFS access permissions
2022-06-06 20:48:53 +02:00
Rafał Dzięgiel
2ba6645462 flatpak-nightly: Add missing GVFS access permissions
Needed to make GVFS mounted filesystems work with GVFS 1.48+.
See: https://docs.flatpak.org/en/latest/sandbox-permissions.html#gvfs-access
2022-06-06 09:32:12 +02:00
Rafał Dzięgiel
adcbb5d827 flatpak: Add missing GVFS access permissions
Needed to make GVFS mounted filesystems work with GVFS 1.48+.
See: https://docs.flatpak.org/en/latest/sandbox-permissions.html#gvfs-access
2022-06-06 09:31:55 +02:00
Rafał Dzięgiel
9885a2f424 Merge pull request #275 from Rafostar/smart-colon
Use U+003A colon character on RTL languages
2022-06-03 16:17:27 +02:00
Rafał Dzięgiel
66b2d8c7de plugin: Also use min GL version when auto selecting context
When we prefer GLES, make sure its no lower then 3.1 version, so it can color convert 10bit videos,
otherwise core GL 3.2 that GTK4 normally defaults to takes precedence.

With auto behavior we should select the best one, both performance and support wise.
Otherwise user can request one or another with GST_GL_API env that works best
with his specific HW.
2022-06-03 14:36:34 +02:00
Rafał Dzięgiel
2c5d65d0b3 flatpak: Sync with Flathub 2022-06-02 14:08:17 +02:00
Rafał Dzięgiel
e37f2a0a30 Use U+003A colon character on RTL languages
Unfortunately U+2236 seems to break time labels on RTL languages. Check text direction at startup and select best one that works.
2022-06-01 17:09:39 +02:00
Rafał Dzięgiel
387bc7a2f3 Update LINGUAS file 2022-06-01 16:44:05 +02:00
Rafał Dzięgiel
495a59a07a New Crowdin updates (#274)
* New translations com.github.rafostar.Clapper.pot (Hebrew)
2022-06-01 16:41:59 +02:00
Rafał Dzięgiel
e5723cd25a 0.5.1 2022-05-29 14:17:25 +02:00
Rafostar
e7808df7cc plugin: paintable: Fix widget size calculations on non-100% display scaling
Unlike legacy sink that used GLArea, GdkPaintable snapshots without pre-multiplying
sizes with scale factor. Remove scaling multiply of our widget dimensions,
so both video and widget width/height will be calculated correctly.

This fixes both image and black borders displaying issues on displays with
non-100% scaling applied.
2022-05-29 10:19:48 +02:00
Rafał Dzięgiel
8f22b36045 0.5.0 2022-05-28 19:19:05 +02:00
Rafał Dzięgiel
dc257846ce New Crowdin updates (#268)
* New translations com.github.rafostar.Clapper.pot (Romanian)

* New translations com.github.rafostar.Clapper.pot (Korean)

* New translations com.github.rafostar.Clapper.pot (Vietnamese)

* New translations com.github.rafostar.Clapper.pot (Chinese Traditional)

* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Ukrainian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Swedish)

* New translations com.github.rafostar.Clapper.pot (Serbian (Cyrillic))

* New translations com.github.rafostar.Clapper.pot (Russian)

* New translations com.github.rafostar.Clapper.pot (Portuguese)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Norwegian)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Japanese)

* New translations com.github.rafostar.Clapper.pot (French)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Hungarian)

* New translations com.github.rafostar.Clapper.pot (Hebrew)

* New translations com.github.rafostar.Clapper.pot (Finnish)

* New translations com.github.rafostar.Clapper.pot (Basque)

* New translations com.github.rafostar.Clapper.pot (Greek)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Danish)

* New translations com.github.rafostar.Clapper.pot (Czech)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Arabic)

* New translations com.github.rafostar.Clapper.pot (Afrikaans)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Portuguese, Brazilian)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (German)
2022-05-27 19:48:48 +02:00
Rafał Dzięgiel
af77873205 plugin: paintable: Remove unused value 2022-05-27 19:46:54 +02:00
Rafał Dzięgiel
5289b2f0a4 plugin: Fix scaled subtitles position on anamorph video
GStreamer does not take pixel aspect ratio into account for overlay rectangles.
If we do so, we end up with subtitles that are displayed off-center.
Behave like any other GStreamer sink on this matter.
2022-05-27 19:38:10 +02:00
Rafał Dzięgiel
87b3fbc15a Update POT file 2022-05-26 18:43:34 +02:00
Rafał Dzięgiel
59ff5bc006 Merge pull request #267 from Rafostar/fix-glx
Fix caps negotiation on GLX
2022-05-26 11:51:11 +02:00
Rafał Dzięgiel
91efc4ecdb plugin: gluploader: Use GLUpload provided propose_allocation method
Instead figuring out what kind of pool we should make just use the upstream provided
functionality that comes as part of GLUpload API.

Fixes uploads with GstVideoGLTextureUploadMeta, which legacy VAAPI plugin uses on GLX.
2022-05-26 10:21:11 +02:00
Rafał Dzięgiel
713449b4ab plugin: sink: Only add pool to query if there is one 2022-05-26 10:17:36 +02:00
Rafał Dzięgiel
3f7ba0674f plugin: importers: Support different template and actual caps
Make a template caps during class_init. It will be used for e.g. gst-inspect-1.0, while do and use an actual caps that current HW can handle.
2022-05-25 20:37:18 +02:00
Rafał Dzięgiel
5b89879031 plugin: gluploader: Remove DMABuf caps features on GLX
GLX cannot do DMABufs. Do not advertise its support in caps, so upstream elements will never try using this kind of memory on GLX.
2022-05-25 15:46:04 +02:00
Rafał Dzięgiel
2385af9b94 Merge pull request #265 from Rafostar/devel
Merge devel branch changes
2022-05-25 10:42:35 +02:00
Rafał Dzięgiel
54e4644236 app: Call window_present without timestamp
GTK4 now handles this internally via xdg-activation. To make it work correctly we should stop using custom timestamp so default handlers will be used.
2022-05-24 18:23:15 +02:00
Rafał Dzięgiel
3c248250f3 plugin: Always make sure we have Gdk display
Give up creating GL context in an unlikely situation that there is no default display
2022-05-24 16:48:00 +02:00
Rafał Dzięgiel
51619cbd2a plugin: Temporarily try to avoid direct DMABuf import on desktop
This tries to avoid "scrambled" image on Linux with Intel GPUs that are mostly used
together with x86 CPUs at the expense of using slightly slower non-direct DMABuf import,
by not going with GLES by default on EGL.

The "GST_GL_API" env can still be used to force one or another context type.

We need for GStreamer to be aware of currently used DRM modifier first. On the other
hand forcing GL everywhere would break most embedded systems that only work with GLES,
so do it for x86 processors only... and pray for it to work.

See: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1236
2022-05-24 16:36:43 +02:00
Rafał Dzięgiel
f9e84ac99b plugin: Improve GL context realization code
We only want GLES on EGL display, so check for it one by one instead of always trying to realize GLES with everything that is not a macOS
2022-05-24 16:36:32 +02:00
Rafał Dzięgiel
1bd371dabd app: Always activate before opening files
Make sure app window was created and bring it on top when started with file(s) as args
2022-05-23 15:32:32 +02:00
Rafał Dzięgiel
5f6c0922c0 plugin: Clear paintable importer in dispose
Remove our ref on importer a little earlier, with a lock taken
2022-05-23 15:02:25 +02:00
Rafał Dzięgiel
041deb559c headerbar: Merge code into single subclass
We no longer ship the web app that was reusing parts of this code.
Combine it into single file without additional subclass.
2022-05-23 14:19:37 +02:00
Rafał Dzięgiel
fce8ec59b8 app: Merge code into single subclass
We no longer ship the web app that was reusing parts of this code.
Combine it into single file without additional subclass.

Also put window creation inside first activate code instead of startup
in order to fix running app as a gapplication service.
2022-05-23 14:18:00 +02:00
Rafał Dzięgiel
306505dc4d data: Add missing desktop file options
Mark as DBusActivatable and enable StartupNotify
2022-05-23 11:55:15 +02:00
Rafał Dzięgiel
60234419c2 data: Add DBus service file 2022-05-23 11:54:50 +02:00
Rafał Dzięgiel
c395c6b9be Merge pull request #262 from Rafostar/reloaded
plugin: Make modules management separate per instance
2022-05-20 11:28:27 +02:00
Rafał Dzięgiel
8301cded2f plugin: Make modules management separate per instance
There were various problems with importer loader code. One defect was that
it kept managing a single global list of available importers and marking
which one is currently used on it. This made it not work correctly for
multiple sink instances in single process and was not thread safe.

This commit changes importer loader code into a GstObject subclass, which
keeps its own list of importers per instance and unlike before makes it
possible to free this data from memory when destroyed.

Now only open modules are kept always in memory until process finishes
since we cannot unload them once loaded anyway.
2022-05-20 10:13:14 +02:00
Rafał Dzięgiel
34386bc96c plugin: Use different lock for importer within paintable
This way we can avoid an additional importer ref + unref for every frame draw
2022-05-18 19:25:00 +02:00
Rafał Dzięgiel
2b85afc03e plugin: Do not use weak ref on importer
There is no good reason to keep using weak ref on importer within paintable object. Change that to a gst_object_ref which is faster.
2022-05-18 18:28:20 +02:00
Rafał Dzięgiel
bb56efa705 Merge pull request #261 from Rafostar/adw-fixes
libadwaita CSS fixes
2022-05-18 12:26:52 +02:00
Rafał Dzięgiel
82922e51f9 flatpak: Update GTK4 to 4.6.4
With latest GTK 4.6.4 the issues with opening popovers are finally fixed. Stop patching older version and just build the latest one.
2022-05-18 11:39:07 +02:00
Rafał Dzięgiel
ca64d9d2ee flatpak: Build recent libadwaita version
With updated CSS we use some variables intoduced in stable versions of libadwaita. To make it work properly, stop using alpha.2 and build recent stable version.
2022-05-18 11:39:04 +02:00
Rafostar
2a18c6a374 css: Misc fixes for recent Adwaita theme
Fixes for recent libadwaita provided theme, mainly needed to workaround:
https://gitlab.gnome.org/GNOME/libadwaita/-/issues/454

Devs rejected my idea of fixing it upstream. They said to override it
in my own app. So here it is.
2022-05-18 11:38:56 +02:00
Rafał Dzięgiel
af6cf01c98 player: Remove hardcoded ring buffer value
We should aim to have this as a configurable option.
Until then lets use the default value.
2022-05-17 22:07:21 +02:00
Rafał Dzięgiel
85bdbb1132 plugin: Prefer GL over GLES on macOS
Apple decoder uses rectangle texture-target, which GLES does not support
2022-05-16 19:16:36 +02:00
Rafał Dzięgiel
8e89b0d8ca gschema: Make resume video option disabled by default
A resume video question dialog that keeps poping confuses new Clapper users.
Looks like some spam. Change default option value to be disabled, so people
that are interested in this feature can enable it in preferences.
2022-05-16 09:45:36 +02:00
Rafostar
4e3cc3e23f plugin: Set initial display resolution to 1x1
We do not support zero width/height (described in our caps). Set initial video
dimensions to 1x1. They are going to be updated on first buffer after video info is set.

This avoids running into https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1139
and makes sure we do not do any divisions by zero here either.
2022-05-15 20:02:01 +02:00
Rafostar
c6c43346fa lib: Replace usage of "g_str_equal" with "g_strcmp0"
The first one is meant for hash tables comparisons and does not guard against NULL values (#259).
2022-05-15 14:45:49 +02:00
Rafał Dzięgiel
be58af2256 Merge pull request #256 from Rafostar/gl-win
plugin: Add GL support for Windows OS
2022-05-13 16:34:26 +02:00
Rafał Dzięgiel
343eef5894 plugin: Add GL support for Windows OS
Add support for both WGL and EGL on Win32
2022-05-13 15:17:53 +02:00
Rafał Dzięgiel
04657017f9 Merge pull request #257 from Rafostar/gl-macos
plugin: Add GL support for macOS
2022-05-13 14:12:09 +02:00
Rafał Dzięgiel
1cdaa36559 plugin: Add GL support for macOS 2022-05-13 13:53:35 +02:00
Rafał Dzięgiel
f351982067 plugin: Handle premultiplied alpha in RAW frames
Add support for premultiplied alpha flag detection when creating GdkMemoryTextures.
Also check if overlays have premultiplied alpha and if they do set this flag for
their video info, so it will be detected when creating a GdkMemoryTexture out of them.

Fixes performance issues with karaoke subtitles, as now GTK does not have to perform
unnecessary multiplication.
2022-05-12 18:08:53 +02:00
Rafał Dzięgiel
ae531db2b7 plugin: Have a separate mutex lock in GL base class
Make GL base importer class and all its subclasses that access parent props,
use a different mutex lock then the main importer class.

This way main importer class can continue processing buffers without waiting for
GL-based subclasses, as most GL operations (e.g. upload) are time consuming.
2022-05-11 22:00:49 +02:00
Rafał Dzięgiel
66fb8d4a1f Merge pull request #255 from Rafostar/fixes
Misc fixes
2022-05-11 21:21:33 +02:00
Rafał Dzięgiel
8f0ad12795 meson: Make sink compile on Windows OS
We cannot compile app as a whole on MS Windows yet, but with those changes it is now possible to compile and run our new video sink alone on Windows OS
2022-05-11 18:55:06 +02:00
Rafał Dzięgiel
908a388f68 meson: Give up on building GL base without GL windowing
We do not want to build GL-based importers when GTK GL windowing support is missing,
which might happen because of missing deps or on unsupported platform
2022-05-11 18:55:03 +02:00
Rafał Dzięgiel
7f33db4159 plugin: Fix possible buffer and v_info mismatch 2022-05-11 18:54:48 +02:00
Rafał Dzięgiel
288b829139 Further alter default plugin feature ranks on startup
Too many problems with VAAPI decodebin, meanwhile VA works fine and there is already
a pending MR on GStreamer to enable it by default, so we do that a little early.

We also do promise working HW accel out of box, so enable all common NVDEC elements too.
They can always be disabled back in player preferences window if any problems do happen.

We can now remove the alternations of v4l2codecs as those are PRIMARY+1 by default and we
now require GStreamer 1.20+ so no need for version checking there too.

Fixes #236
2022-05-11 11:50:15 +02:00
Rafał Dzięgiel
aa6d21973c gschema: Disable download buffering by default
We had this option enabled to workaround problems with old YT code.
Adaptive streaming now seems to work correctly, so restoring the
default play flags value.
2022-05-10 13:57:11 +02:00
Rafał Dzięgiel
e506063409 gschema: Remove leftover web app settings 2022-05-10 12:09:30 +02:00
Rafał Dzięgiel
e679430d3e meson: Set plugin option to be auto by default
This should allow to still compile and use the player with the legacy sink, without changing meson default options
2022-05-09 12:39:41 +02:00
Rafał Dzięgiel
4b93d4d132 meson: Cleanup plugin build script 2022-05-08 18:47:13 +02:00
Rafał Dzięgiel
b7b99c20cf meson: Do not go down in lib versioning
Install plugin lib stuff into a dir named "clapper-1.0" instead of "clapper-0.0". Even through our API is still very unstable, we cannot go down with versioning. The sink importers being installed there are not part of public API anyway.
2022-05-08 13:54:55 +02:00
Rafał Dzięgiel
5775738f67 plugin: Fix possible dir enumerator NULL unref
On an unlikely chance that sink was compiled without any importers, iterated dir does not exists thus we try to unref a NULL. Avoid doing that.
2022-05-07 13:43:51 +02:00
Rafał Dzięgiel
7159459160 meson: Cleanup of plugin build script 2022-05-06 21:08:03 +02:00
Rafał Dzięgiel
00650a596f obs: Use "trigger_services" step
Instead "rebuild_package" use "trigger_services" for OBS integration, otherwise the same old package is rebuild again and again.
2022-05-06 18:57:12 +02:00
Rafał Dzięgiel
6a995e2143 Merge pull request #253 from Rafostar/clappersink2
Move away from GtkGLArea
2022-05-06 17:52:56 +02:00
Rafał Dzięgiel
01b3feb213 New Crowdin updates (#247)
* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Portuguese)
2022-05-06 17:36:53 +02:00
Rafał Dzięgiel
5b9e7eacba meson: Do not auto build rawimporter when building gluploader
No need to auto build rawimporter if we are building gluploader as it
will be always loaded on startup, but never used.

Skip the build of it when its meson option is set to "auto".
2022-05-06 11:42:47 +02:00
Rafostar
b37ab432d7 player: Use new "clappersink" element
Use brand new clapper video sink for video output. Also add "CLAPPER_USE_LEGACY_SINK" env
to still allow the usage of old video sink if any problems arise.
2022-05-05 11:17:28 +02:00
Rafostar
0410c6e9b5 plugin: Add GL uploader
Add "clappergluploader" module which uses "glupload" and "glcolorconvert" internally,
allowing either uploading RAW system memory into GPU with GL colorspace conversion or
importing DMABufs into GL memory and making a GdkTexture out of them at one go.
2022-05-05 11:17:17 +02:00
Rafostar
3e0a0e0555 plugin: Add GL memory importer
Add "clapperglimporter" and a base class for creating GL importers. This module allows importing GL memory into GdkTexture.
2022-05-05 11:17:04 +02:00
Rafostar
5b7b7085e4 plugin: Add RAW system memory importer
Add "clapperrawimporter" module which allows importing RAW system memory mapped frames
2022-05-05 11:16:44 +02:00
Rafostar
044710f97e plugin: Add clapper GStreamer plugin
Add new GStreamer plugin with custom video sink for Clapper video player.

The main difference is that unlike the old one, this does not operate using `GtkGLArea`
anymore, but processes and displays `GdkTextures` directly through `GtkPicture` widget.
Also this one is installed like any other GStreamer plugin, thus can be used via
`gst-launch-1.0` binary or even by other GTK4 apps if they wish to integrate it.

In order to not depend on GL stuff at build time, this plugin uses seperate GModules
called "importers" in order to import different kind of memories into GdkTexture. This
allows expanding its capabilities further then we were able to do before.
2022-05-05 11:16:34 +02:00
Rafał Dzięgiel
b83d500352 Merge pull request #245 from Rafostar/crowdin_sync
New Crowdin updates
2022-04-11 21:02:50 +02:00
Rafał Dzięgiel
3fadf13125 api: Also check "USE_PLAYBIN3" env
Some mobile distros seem to be under assumption that playbin3 is required to
get HW accel and setting this env by default is good idea. Both are wrong.

Check this env presence to avoid problems as factory will always return
playbin3 if set (even if playbin2 was requested).
2022-04-11 19:44:05 +02:00
Rafał Dzięgiel
f8fe49a809 obs: Add "workflows.yml" file 2022-04-11 18:08:52 +02:00
Rafał Dzięgiel
264f0abb64 New translations com.github.rafostar.Clapper.pot (Dutch) 2022-04-08 18:14:27 +02:00
Rafał Dzięgiel
b330aa1ccd workflow: Increase default timeout time
AArch64 build is taking a lot of time...
2022-04-08 17:27:38 +02:00
Rafał Dzięgiel
de8ecb8f82 flatpak: Do not build pango anymore
GNOME 42 runtime includes version that is new enough
2022-04-08 17:08:32 +02:00
Rafał Dzięgiel
a2bb927502 Update LINGUAS file 2022-04-08 10:08:05 +02:00
Rafał Dzięgiel
df728f383b Merge pull request #237 from Rafostar/crowdin_sync
New Crowdin updates
2022-04-08 10:01:39 +02:00
Rafał Dzięgiel
c80d2e9fd6 New translations com.github.rafostar.Clapper.pot (Turkish) 2022-04-02 03:43:30 +02:00
Rafał Dzięgiel
5a00301935 New translations com.github.rafostar.Clapper.pot (Turkish) 2022-04-02 02:44:03 +02:00
Rafał Dzięgiel
46b5a6df96 New translations com.github.rafostar.Clapper.pot (Japanese) 2022-04-01 11:06:26 +02:00
Rafał Dzięgiel
f771e0320c Merge pull request #240 from Rafostar/pkgs
Update Flatpak, remove RPM specfiles
2022-04-01 11:05:22 +02:00
Rafał Dzięgiel
72a64a41d9 Update README.md 2022-04-01 09:42:06 +02:00
Rafał Dzięgiel
2818d3c91b flatpak: Enable network access for CI GTK4 builds
Make sure CI can satisfy latest GTK4 dependency requirements by allowing it to download libs it needs as fallback projects
2022-04-01 09:27:13 +02:00
Rafał Dzięgiel
ffb481b52b pkgs: Remove RPM build files from git
Clapper is now available in official repos on both Fedora and openSUSE. Considering that, I will not have time to properly maintain them here, so they go away.
2022-04-01 09:27:10 +02:00
Rafał Dzięgiel
c5c289d466 flatpak: Do not build libsoup3 anymore
It is now included in GNOME 42 runtime
2022-04-01 09:27:07 +02:00
Rafał Dzięgiel
3074051b3d flatpak: Build recent GTK 4.6.2 version
We are gonna move into depending on at least 4.6.0, build it for CI to pass
2022-04-01 09:26:58 +02:00
Rafał Dzięgiel
980e1d9e1a flatpak: Update git actions runtime to 42 2022-03-31 16:28:30 +02:00
Rafał Dzięgiel
045e4fc2c4 flatpak: Sync with Flathub 2022-03-31 16:20:47 +02:00
Rafał Dzięgiel
4f27739287 New translations com.github.rafostar.Clapper.pot (Japanese) 2022-03-31 10:08:37 +02:00
Rafał Dzięgiel
52aa7710dc Update README.md 2022-03-30 11:21:01 +02:00
Rafał Dzięgiel
0e49eaec7e New translations com.github.rafostar.Clapper.pot (Arabic) 2022-03-26 14:37:46 +01:00
Rafał Dzięgiel
62a923a3c1 New translations com.github.rafostar.Clapper.pot (Arabic) 2022-03-26 13:39:14 +01:00
Rafał Dzięgiel
f59b937316 New translations com.github.rafostar.Clapper.pot (Arabic) 2022-03-26 12:42:32 +01:00
Rafał Dzięgiel
8c914d0555 New translations com.github.rafostar.Clapper.pot (Arabic) 2022-03-25 22:09:19 +01:00
Rafał Dzięgiel
d2fab16093 New translations com.github.rafostar.Clapper.pot (Arabic) 2022-03-25 20:58:27 +01:00
Rafał Dzięgiel
67e877af0f New translations com.github.rafostar.Clapper.pot (Basque) 2022-03-25 17:45:32 +01:00
Rafał Dzięgiel
c825649a71 New translations com.github.rafostar.Clapper.pot (Basque) 2022-03-25 16:34:21 +01:00
Rafał Dzięgiel
5101fce5a7 Merge pull request #228 from Rafostar/nightly-fix
Flatpak nightly fixes
2022-03-11 00:30:05 +01:00
Rafał Dzięgiel
e0daf8435a flatpak-nightly: Use "--wrap-mode=nodownload" for GStreamer build
We do not have net access during build of GStreamer, nor we want to pull anything, so disable downloads so it will not try
2022-03-10 22:55:31 +01:00
Rafał Dzięgiel
9f18295728 flatpak-nightly: Do not disable GStreamer asserts and checks
We may disable them for stable releases, but should be left to default on nightly
2022-03-10 22:55:27 +01:00
Rafał Dzięgiel
8ce977505e actions: nightly: Manually install SDK extensions via workflow
The github actions Flatpak action only allows to specify single source
for installing missing dependencies. This makes impossible to build
some things from "gnome-nightly" while others from "flathub" repo.

Work around this limitation by manually installing missing SDK
extensions from Flathub prior to using this git action.
2022-03-10 22:55:24 +01:00
Rafał Dzięgiel
8ac839c9aa flatpak-nightly: Disable cloning GStreamer submodules
It seems that now GStreamer ships its testsuite (which we do not need) as a submodule. Do not try to clone it.
2022-03-10 22:55:09 +01:00
Rafał Dzięgiel
8fa2036265 actions: Allow runs on workflow_dispatch 2022-03-10 09:32:11 +01:00
Rafał Dzięgiel
1d5bb1e6aa Merge pull request #227 from Rafostar/nightly-rust
flatpak-nightly: Build dav1d decoder from gst-plugins-rs
2022-03-09 22:09:22 +01:00
Rafał Dzięgiel
9ec87c1b58 flatpak-nightly: Build dav1d decoder from gst-plugins-rs 2022-03-09 20:53:18 +01:00
Rafał Dzięgiel
16c0f8baae Merge pull request #226 from Rafostar/speed-fix
Fix end time calculation with with non-1x speed
2022-03-06 16:52:40 +01:00
Rafał Dzięgiel
c94d21fc53 Fix end time calculation with with non-1x speed 2022-03-06 15:51:06 +01:00
Rafał Dzięgiel
159f96c984 Merge pull request #214 from Rafostar/libsoup3
libsoup3
2022-02-28 16:58:29 +01:00
Rafał Dzięgiel
96ad4fa3db RPM: Require libsoup3 2022-02-17 15:44:45 +01:00
Rafał Dzięgiel
b2e7bef8d4 flatpak: Update git actions runtime to 41
We need to update, so we can build libsoup3. Flathub ver will likely remain as 40 ver to avoid some problems and will be updated directly to 42 later.
2022-02-14 17:37:15 +01:00
Rafał Dzięgiel
40a1dc6960 flatpak: Build libsoup3
Now both Clapper and Gtuber lib require libsoup3, so build it until it will be available in runtime
2022-02-14 17:37:15 +01:00
Rafał Dzięgiel
c4bd604e17 Port to libsoup3
With all apps and modules/plugins porting itself to libsoup3 we also need to do so.

It would appear as a good idea to conditionally import "3.0" and fallback to "2.4"
bindings here, but its not as loaded GStreamer plugins might use libsoup3 already
and we cannot have both libsoup2 and libsoup3 in a single process.
2022-02-14 17:37:15 +01:00
Rafał Dzięgiel
83c0e3b598 Remove unfinished web application
It used Broadway as an easy "reuse the same code into web application" way for me, but Broadway
is not very good for this. This feature should be made using some better dedicated framework for
building websites (so it can work better and support different screen sizes).

All the WebSocket functionality needed for this will remain (and be documented at a later point
when expanded and stable), so if anyone would like to make such remote controlling app, will be
free to do so (outside of Clapper code).
2022-02-14 17:37:15 +01:00
Rafał Dzięgiel
54715023c0 flatpak: Update git actions manifest 2022-02-14 16:36:29 +01:00
Rafał Dzięgiel
95046ceba8 flatpak: Sync with Flathub 2022-02-14 16:06:36 +01:00
Rafał Dzięgiel
b189e24b5e Merge pull request #209 from simonsextras/swdeish-tranlation-nbfreygff
Full Swedish Translation
2022-01-21 12:14:22 +01:00
sastofficial
cb9e2ac979 Update sv.po 2022-01-21 09:35:17 +01:00
sastofficial
545d8826e0 Update sv.po 2022-01-19 13:46:08 +01:00
Rafał Dzięgiel
c2160198b9 Update LINGUAS file 2022-01-19 10:07:09 +01:00
Rafał Dzięgiel
aa7eae2417 New translations com.github.rafostar.Clapper.pot (French) (#208) 2022-01-19 10:00:56 +01:00
Rafał Dzięgiel
3192a32845 Merge pull request #206 from Rafostar/unicode
Use more unicode characters
2022-01-18 18:46:06 +01:00
Rafał Dzięgiel
706c783498 Use unicode U+2215 for division 2022-01-17 22:28:17 +01:00
Rafał Dzięgiel
8ba3ca4af6 Use unicode U+00D7 for multiplication 2022-01-17 21:01:23 +01:00
Rafał Dzięgiel
38efa7ab9f Use unicode U+2236 for time 2022-01-17 20:27:13 +01:00
Rafał Dzięgiel
d19ddbcaca Merge pull request #204 from Rafostar/devel
Misc gstclapper fixes
2022-01-17 11:00:28 +01:00
Rafał Dzięgiel
615f1553fb flatpak: Sync with Flathub 2022-01-17 10:19:29 +01:00
Rafał Dzięgiel
09c9e7560b New Crowdin updates (#201)
* New translations com.github.rafostar.Clapper.pot (Swedish)

* New translations com.github.rafostar.Clapper.pot (Russian)

* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Basque)
2022-01-17 08:56:59 +01:00
Rafał Dzięgiel
f40ce756ad Merge pull request #199 from majjejjam/master
change three dots to ellipsis
2022-01-16 14:10:49 +01:00
majjejjam
23d51be185 changed to ellipses in ui/clapper.ui 2022-01-15 18:20:13 +01:00
Rafał Dzięgiel
0db2a4a045 gstclapper: Fix plugin feature leak 2022-01-14 09:28:26 +01:00
Rafostar
469c06d22b gstclapper: Go into NULL state directly when stopped
Instead of waiting another 60 seconds for user, go into NULL state ASAP to free all resources and open devices.
2022-01-09 13:31:37 +01:00
Rafostar
3feaf225b5 gstclapper: Make tags writable before insert
Someone might be holding a copied media info in which case tag
list ref count is not 1. Use gst_tag_list_make_writable to
assure that ref count is 1, so we can insert more tags into the list.
2022-01-09 13:31:29 +01:00
majjejjam
fc8d881efd change three dots to ellipsis 2022-01-08 16:28:07 +01:00
Rafał Dzięgiel
ac76836fd7 Merge pull request #192 from Rafostar/yt-removal
YouTube code removal
2022-01-05 14:27:59 +01:00
Rafał Dzięgiel
f6a1aaf1dc Remove all YouTube code
It has been broken for quite some time. From now on this is gonna be left to handle for GStreamer plugins.
2021-12-22 08:12:55 +01:00
Rafał Dzięgiel
000dca82d9 flatpak: Sync with Flathub 2021-12-20 21:23:31 +01:00
Rafał Dzięgiel
7a508fef39 0.4.1 2021-12-20 11:33:19 +01:00
Rafał Dzięgiel
d465d9f150 Make floating window update its title earlier
Instead of waiting till animation finishes, update the window title right away when changing modes
2021-12-15 16:58:54 +01:00
Rafał Dzięgiel
5e4dfb322c Append "PiP" suffix to window title when in floating mode
We are gonna take advantage of this simple change elsewhere
2021-12-15 12:44:23 +01:00
Rafał Dzięgiel
0c561ab4b3 Also allow enabling gtuber code path via env
Having to use "gtuber" URI scheme might be inconvenient, so also allow to
whitelist it with "GST_PLUGIN_FEATURE_RANK=gtubersrc:300" env
2021-12-10 11:05:00 +01:00
Rafał Dzięgiel
46ce261524 widget: Make sure we have caps before logging them 2021-12-10 11:03:06 +01:00
Rafał Dzięgiel
50aac8cdd8 gstclapper: Merge global tags instead replacing them
There is no guarantee that received later tags also contain values from
earlier ones, as they might come from different element.
Combine them instead while replacing old values with newer ones.
2021-12-02 08:52:35 +01:00
Rafał Dzięgiel
810aea476f Use gtuber lib for URIs with "gtuber" scheme
Take a different code path when URI uses "gtuber" scheme.
This allows testing new WIP lib as an opt-in.
2021-11-29 22:33:53 +01:00
Rafał Dzięgiel
24905f1d60 flatpak: Build gtuber 2021-11-29 22:30:21 +01:00
Rafał Dzięgiel
82e3c9a52f prefs: Add can-swipe-back compat with latest libadwaita
Recent libadwaita has renamed "can-swipe-back" into "can-navigate-back".
Set both in JS code instead of UI file in order to support all libadwaita versions.

Fixes #185
2021-11-29 10:13:06 +01:00
Rafał Dzięgiel
654b8aaf60 prefs: Fix expander rows compat with latest libadwaita 2021-11-19 18:43:01 +01:00
Rafał Dzięgiel
3c0e33e4a4 css: Few override fixes for latest libadwaita 2021-11-19 18:40:34 +01:00
Rafał Dzięgiel
d2df1c3bd8 app: Use Adw.StyleManager to enable dark-theme
Latest libadwaita (for reasons unknown to me) totally ignores/breaks dark theme usage with gtk_application_prefer_dark_theme property. Lets just try using the new Adw.StyleManager without asking questions why.
2021-11-18 22:42:05 +01:00
Rafał Dzięgiel
af24073590 Update LINGUAS file 2021-11-18 15:37:48 +01:00
Rafał Dzięgiel
44cee14eb2 New translations com.github.rafostar.Clapper.pot (Portuguese) (#175) 2021-11-18 15:34:16 +01:00
Rafał Dzięgiel
b853685dd4 gstclapper: Fix decoder stream ID string leak 2021-10-22 13:11:42 +02:00
Rafał Dzięgiel
15461dd38a gstclapper: Fix video/audio decoder change detection
The video/audio decoder changed signal was not working correctly in case of
multiple streams with multiple decoders in single file.

We need to listen to the current-(video/audio) signal, when it changes find
corresponding "input-selector", get stream ID from its active pad and then
find the decoder in the pipeline that handles this stream ID. Similarly for
playbin3, but use stream ID from the "streams-selected" signal.
2021-10-22 11:05:08 +02:00
Rafał Dzięgiel
1c1989bc32 gstclapper: Fix GST_PLUGIN_FEATURE_RANK env usage
We change few default plugin ranks during init to whitelist them, but we do not update
their values from GST_PLUGIN_FEATURE_RANK env afterwards, so do that.
The ENV should be preferred over default config.
2021-10-21 11:21:07 +02:00
Rafał Dzięgiel
e9c9ae073f flatpak-nightly: Enable GPL gstreamer plugins 2021-10-19 10:23:41 +02:00
Rafał Dzięgiel
22d2c40b0f flatpak-nightly: Build from gstreamer mono repo 2021-10-18 11:13:44 +02:00
Rafał Dzięgiel
5301c8b368 flatpak: Sync with Flathub 2021-10-14 20:35:53 +02:00
Rafał Dzięgiel
e910978590 Update LINGUAS file
Install Portuguese-Brazilian translation
2021-10-14 20:30:18 +02:00
Rafał Dzięgiel
3b99f0ee0c New Crowdin updates (#172)
* New translations com.github.rafostar.Clapper.pot (Portuguese, Brazilian)
2021-10-12 08:44:14 +02:00
Rafał Dzięgiel
f93a0fed98 Update LINGUAS file 2021-10-04 16:06:45 +02:00
Rafał Dzięgiel
6b8c35b16e Merge pull request #166 from GNUuser/patch-1
Update es.po
2021-10-04 15:59:21 +02:00
Rafał Dzięgiel
5fdb6e64be New Crowdin updates (#164)
* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Italian)
2021-10-04 15:14:51 +02:00
Rafał Dzięgiel
60d4b5aec1 widget: Do gestures in capture phase
Capture phase runs from the toplevel down to the event widget and is meant to be used
in containers that might possibly handle events before their children, like our OSD layer.

This avoids an issue where pressing an OSD button does not emit cancelled signal,
accidentally triggering long press gesture signal handler.

Fixes #170
2021-10-04 10:11:53 +02:00
carlosgonz
f5258889cf Update es.po 2021-10-02 10:08:14 -04:00
carlosgonz
31eddf5dd2 Update es.po 2021-10-02 10:07:15 -04:00
carlosgonz
89f7304e0e Update es.po
initial Spanish file
2021-10-01 18:59:03 -04:00
Rafał Dzięgiel
3c918bda73 New Crowdin updates (#163)
* New translations com.github.rafostar.Clapper.pot (Hungarian)
2021-09-22 10:15:35 +02:00
Rafał Dzięgiel
2a8ef2559f New Crowdin updates (#162)
* New translations com.github.rafostar.Clapper.pot (Czech)
2021-09-20 08:34:28 +02:00
Rafał Dzięgiel
7676e18eee New translations com.github.rafostar.Clapper.pot (Russian) (#161) 2021-09-17 11:03:54 +02:00
Rafał Dzięgiel
00b05b460d Merge pull request #158 from igor-dyatlov/master
Added Russian translate
2021-09-17 10:58:05 +02:00
Igor Dyatlov
62f02cf2a3 Added Russian translate 2021-09-16 12:31:19 +03:00
Rafał Dzięgiel
9fc1d9b8c4 sink: Do not leak pool when set config fails 2021-09-15 16:28:23 +02:00
Rafał Dzięgiel
45a5ebb4b6 New Crowdin updates (#157)
* New translations com.github.rafostar.Clapper.pot (Romanian)

* New translations com.github.rafostar.Clapper.pot (Korean)

* New translations com.github.rafostar.Clapper.pot (Vietnamese)

* New translations com.github.rafostar.Clapper.pot (Chinese Traditional)

* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Ukrainian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Swedish)

* New translations com.github.rafostar.Clapper.pot (Serbian (Cyrillic))

* New translations com.github.rafostar.Clapper.pot (Russian)

* New translations com.github.rafostar.Clapper.pot (Portuguese)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Norwegian)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Japanese)

* New translations com.github.rafostar.Clapper.pot (French)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Hungarian)

* New translations com.github.rafostar.Clapper.pot (Hebrew)

* New translations com.github.rafostar.Clapper.pot (Finnish)

* New translations com.github.rafostar.Clapper.pot (Greek)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Danish)

* New translations com.github.rafostar.Clapper.pot (Czech)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Arabic)

* New translations com.github.rafostar.Clapper.pot (Afrikaans)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Portuguese, Brazilian)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Polish)
2021-09-15 10:54:52 +02:00
Rafał Dzięgiel
2500a42286 Fix missing gio-unix-2.0 dep
Our autogenerated MPRIS code needs it. On some packaging systems this might be included outside of glib, so depend on it explicitly.
2021-09-14 17:54:03 +02:00
Rafał Dzięgiel
bafffa59b9 Fix missing translator-credits 2021-09-14 16:40:09 +02:00
Rafał Dzięgiel
201cb6f64c actions: Also allow mute with "M" key alone
For faster access
2021-09-14 13:09:23 +02:00
Rafał Dzięgiel
636098182b actions: Keep consistent letters case 2021-09-14 13:06:44 +02:00
Rafał Dzięgiel
5442b0b70a uri-dialog: Catch errors when reading from clipboard
The clipboard.read_text_finish method might throw an error when something goes wrong. Catch it and print in debug message. There is no alternative clipboard reading, so simply ignore.
2021-09-14 13:00:14 +02:00
Rafał Dzięgiel
67d1b9f5bc flatpak: Sync with Flathub 2021-09-13 14:06:48 +02:00
Rafostar
a62483fda9 0.4.0 2021-09-12 12:14:05 +02:00
Rafał Dzięgiel
c825385a8f New Crowdin updates (#154)
* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Italian)
2021-09-11 12:19:01 +02:00
Rafał Dzięgiel
02a7419d66 Merge pull request #155 from Rafostar/scaling
Scale fullscreen differently depending on monitor res
2021-09-11 12:18:13 +02:00
Rafał Dzięgiel
e727b8fb50 Scale fullscreen differently depending on monitor res 2021-09-11 11:22:15 +02:00
Rafostar
3cbfd1a57c Fix chapter popover parenting 2021-09-10 19:28:27 +02:00
Rafał Dzięgiel
75b728457c New Crowdin updates (#150)
* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Romanian)

* New translations com.github.rafostar.Clapper.pot (Korean)

* New translations com.github.rafostar.Clapper.pot (Vietnamese)

* New translations com.github.rafostar.Clapper.pot (Chinese Traditional)

* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Ukrainian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Swedish)

* New translations com.github.rafostar.Clapper.pot (Serbian (Cyrillic))

* New translations com.github.rafostar.Clapper.pot (Russian)

* New translations com.github.rafostar.Clapper.pot (Portuguese)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Norwegian)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Japanese)

* New translations com.github.rafostar.Clapper.pot (French)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Hungarian)

* New translations com.github.rafostar.Clapper.pot (Hebrew)

* New translations com.github.rafostar.Clapper.pot (Finnish)

* New translations com.github.rafostar.Clapper.pot (Greek)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Danish)

* New translations com.github.rafostar.Clapper.pot (Czech)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Arabic)

* New translations com.github.rafostar.Clapper.pot (Afrikaans)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Portuguese, Brazilian)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Polish)
2021-09-10 15:46:56 +02:00
Rafał Dzięgiel
b293a84df6 Skip hiding already hidden tracks radio buttons
Does not change much, but removes some useless logging
2021-09-09 22:08:20 +02:00
Rafał Dzięgiel
928244dc32 prefs: Show icon in plugins with modified feature ranks 2021-09-09 12:10:54 +02:00
Rafał Dzięgiel
11caafe847 css: Remove higher l/r negative margins
This ensures that scale does not overlap with corresponding buttons
2021-09-09 09:13:18 +02:00
Rafał Dzięgiel
dbeb4cb0b7 misc: Cleanup imports resolve code
It does not look like we will be able to provide gresources in near future (ever?). Remove those checks for less logic at startup.
2021-09-08 21:32:42 +02:00
Rafał Dzięgiel
3e04139288 meson: Fix variable name 2021-09-08 21:09:48 +02:00
Rafał Dzięgiel
c41b77a14b meson: Do not set datadir in bin template
GJS does this automatically for us using prefix and even if set it will be overwritten
2021-09-08 20:50:23 +02:00
Rafał Dzięgiel
3c500e0be9 meson: Rename some options 2021-09-08 20:46:43 +02:00
Rafał Dzięgiel
6cddb1a16d meson: Cleanup build files
Remove some twice declared variables and keep code style
2021-09-08 20:44:12 +02:00
Rafał Dzięgiel
b5007d12a1 remote: Use system play/pause icons
Those were taken from gresource, but since Remote is a different app, it does not use original clapper gresource. Use system icons for now.
2021-09-08 20:22:32 +02:00
Rafał Dzięgiel
0d7274fb03 Optimize TV mode controls size 2021-09-08 11:31:13 +02:00
Rafał Dzięgiel
94be4c08c5 Optimize pause icon height 2021-09-08 11:30:35 +02:00
Rafał Dzięgiel
bfcc468528 meson: Add optional validate appstream file test 2021-09-07 20:54:48 +02:00
Rafał Dzięgiel
98d2b80103 Add PiP and play icons as gresource
Add missing PiP icons from web devel kit. Also add play/pause
icons at the right size and remove all workarounds/scaling
implemented or these two.

Playback icons are always two bars for pause and triangle for play,
so hopefully this will not be problematic, as this guaranties the
right size for them that Adwaita unfortunately cannot provide.
2021-09-07 19:34:59 +02:00
Rafał Dzięgiel
fa39c45773 Remove useless signal connection in about dialog 2021-09-06 20:33:11 +02:00
Rafał Dzięgiel
b2a6e19fe1 Update POT file 2021-09-06 20:22:55 +02:00
Rafał Dzięgiel
e8c44dc400 Make end time label translatable 2021-09-06 20:21:18 +02:00
Rafał Dzięgiel
5cc9c17632 Update POT file 2021-09-06 19:47:29 +02:00
Rafał Dzięgiel
35d359daf9 Mark popovers text as translatable 2021-09-06 19:45:04 +02:00
Rafał Dzięgiel
637fa75484 Merge pull request #151 from Rafostar/comply-gjs
Comply with GJS packaging
2021-09-06 17:56:53 +02:00
Rafał Dzięgiel
8733610a9b Move revealers access away from base classes
Those should not appear in base classes, as they are available in main app only
2021-09-06 17:23:36 +02:00
Rafał Dzięgiel
873e724bf2 Comply with GJS packaging spec
According to spec, package name should always be set to main package name in DBus name format
2021-09-06 17:22:34 +02:00
Rafał Dzięgiel
7aa03f3e72 prefs: PipeWire is only used for audio output here
We only use PipeWire for audio output. Make that more obvious in prefs setting description.
2021-09-06 13:42:09 +02:00
Rafał Dzięgiel
99acd36cc0 api: Always start unmuted 2021-09-06 13:18:57 +02:00
Rafał Dzięgiel
cd7d99606d Improve mute shortcut description
This does both mute and unmute, describe it as a toggle
2021-09-06 13:07:07 +02:00
Rafał Dzięgiel
574e084383 Toggle mute with Ctrl+M
Closes #117
2021-09-06 12:34:11 +02:00
Rafał Dzięgiel
d49df86397 api: Replace mute-changed signal with mute notify
Notify is enough, we do not need a separate signal for mute property. This also allows binding this property to some other GObject props.
2021-09-06 12:18:32 +02:00
Rafał Dzięgiel
3483c94913 Completely disable audio track when set to disabled
Instead of just muting audio when disabled, tell GStreamer to diable it completely. This is slower, but makes this option do what it was supposed to.
2021-09-06 10:29:44 +02:00
Rafał Dzięgiel
a99abc652a Do not store subtitle-offset as gsetting
This is not something we should remember
2021-09-06 10:12:33 +02:00
Rafał Dzięgiel
a9173bb481 css: Put small L/R margins on speed scale
GTK does weird glitches when scale slider inside popover is dragged to the very end. Avoid that by putting small margins on both sides. It also looks better when its shorter a little bit.
2021-09-06 09:09:05 +02:00
Rafostar
a16444cefb Do not set subtitle-offset at startup
We should always start without any offset for subtitles
2021-09-05 20:44:12 +02:00
Rafostar
65673dbf4f Add window mapped debug message 2021-09-05 17:55:16 +02:00
Rafostar
dea67e4712 Prepare for resource loading
Cleanup the Clapper install path detection code in a way to make gresources loading eventually possible for compiled builds
2021-09-05 17:55:11 +02:00
Rafostar
3c765e9f17 Add some init debug messages
To get an overall idea how long initialization takes
2021-09-05 17:54:55 +02:00
Rafostar
a77eb5352e cleanup: Remove unused clapperVersion variable 2021-09-05 11:47:24 +02:00
Rafostar
ca168f34ed controls: Use isFullscreen and isMobile from main widget
The "controls.isMobile" was used incorrectly here as it holds value if
controls are in mobile mode, not if running on mobile screen.
Use those values from clapper main widget instead. This fixes incorrect
chapter popover placement on mobile screens.

Also handle fine-tune in CSS as this code path is hit multiple times
when starting/stopping slider drag.
2021-09-05 11:30:46 +02:00
Rafostar
d0304d4ded mpris: Allow reading properties 2021-09-04 18:57:08 +02:00
Rafał Dzięgiel
cd479f3bb4 api: Set fakesink to be sync
Otherwise seeking will not be possible when this sink is used
2021-09-03 20:32:17 +02:00
Rafał Dzięgiel
70942ba419 prefs: Mark experimental options
Options not fully reliable with possibility to break playback. Better mark them as experimental then listen to users complaining on daily basis.
2021-09-03 20:08:07 +02:00
Rafał Dzięgiel
ad0c6151a9 Merge pull request #149 from Rafostar/experimental-options
Add playbin3 and PipeWire options to prefs
2021-09-03 12:24:00 +02:00
Rafał Dzięgiel
cccc584961 api: Use fakesink when PipeWire enabled but unavailable
Instead of misleading users that they are using PipeWire after enabling it, use fakesink in order to not output any sound at all
2021-09-03 11:50:40 +02:00
Rafał Dzięgiel
38e721be03 prefs: Add playbin3 and pipewire options 2021-09-03 11:35:23 +02:00
Rafał Dzięgiel
cf6d41b725 api: Add property to control PipeWire enablement 2021-09-03 11:12:48 +02:00
Rafał Dzięgiel
b68c1a62b2 api: Add property to control playbin3 enablement 2021-09-03 10:59:44 +02:00
Rafał Dzięgiel
dc25ec976a Name our classes
In order to not end up with random names prefixed with Gjs_, give each class a proper name, so its easier to inspect and allows usage with UI files
2021-09-02 20:12:39 +02:00
Rafał Dzięgiel
914292612b Show libadwaita version in about system 2021-09-02 19:27:00 +02:00
Rafał Dzięgiel
e34b164f5a Auto fill open URI entry with clipboard content
If clipboard contains a valid URI, prefill the entry with it. Also select all of it to make it easier to remove this text.
2021-09-02 18:58:51 +02:00
Rafał Dzięgiel
2e0a455f92 dialogs: Use response virtual function instead of signal 2021-09-02 17:29:56 +02:00
Rafał Dzięgiel
3aab01d35c Improved open URI dialog 2021-09-02 17:22:09 +02:00
Rafał Dzięgiel
e264304c9d Mark text in remaining dialogs as translatable 2021-09-02 13:26:06 +02:00
Rafał Dzięgiel
a145890f9d Fix disabling plugin feature with zero rank 2021-09-01 17:53:23 +02:00
Rafał Dzięgiel
0323c816ad api: Use GstElementFactoryListType to detect decoders
Using simply GST_IS_VIDEO_DECODER is not enough as some special cases like vaapidecodebin are not using decoder base class
2021-09-01 17:41:31 +02:00
Rafał Dzięgiel
4f1d9be423 Fix case with missing subtitle tracks
In case when first video has a lot of subtitles, second video has only a few and third one more then second one, we forgot to make the recycled toggle buttons visible again, causing some tracks to be missing
2021-09-01 17:26:10 +02:00
Rafał Dzięgiel
82557df7c4 Merge pull request #148 from Rafostar/popovers-rework
Popovers rework
2021-09-01 17:18:03 +02:00
Rafał Dzięgiel
c457158541 css: Remove elapsed popover bottom padding
Scale already does a bottom padding, we do not need this much of it
2021-09-01 15:44:45 +02:00
Rafał Dzięgiel
451711b9c6 Show current video/audio decoder in popover 2021-09-01 14:28:15 +02:00
Rafał Dzięgiel
bbada8fb4e Redo controls popovers into GtkMenuButtons 2021-09-01 14:25:42 +02:00
Rafał Dzięgiel
04122d46a7 Move popover separator into .ui
Allows reusing a custom separator in multiple popovers
2021-08-31 10:55:25 +02:00
Rafał Dzięgiel
347d90b1ad actions: Fetch gnome-nightly repo for build 2021-08-29 09:34:28 +02:00
Rafał Dzięgiel
27ffb65d8f api: Remove unused declaration 2021-08-28 10:29:12 +02:00
Rafał Dzięgiel
9328a7af75 meson: Warn about unused variables 2021-08-28 10:27:44 +02:00
Rafał Dzięgiel
1f6e439632 New Crowdin updates (#146)
* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Catalan)
2021-08-28 10:26:15 +02:00
Rafał Dzięgiel
97c1207b40 readme: Update flatpak-nightly badge 2021-08-28 08:43:06 +02:00
Rafał Dzięgiel
833559a208 flatpak: Rename from testing to nightly and use master runtime 2021-08-28 08:42:18 +02:00
Rafał Dzięgiel
9a8655b0a2 meson: Use correct SPDX identifier 2021-08-28 08:28:40 +02:00
Rafał Dzięgiel
d2a03d40a3 Merge pull request #145 from Rafostar/actions-aarch64
Add aarch64 builds to git actions
2021-08-27 21:42:31 +02:00
Rafał Dzięgiel
66998ff6c6 actions: Install docker with arm64 quemu
Flatpak builder needs this to compile aarch64 package
2021-08-27 17:02:40 +02:00
Rafał Dzięgiel
7cdd905d73 actions: Do not fail both runs when one fails 2021-08-27 16:25:02 +02:00
Rafał Dzięgiel
10eb5102c1 actions: Also build for aarch64 in nightly flatpak 2021-08-27 16:24:55 +02:00
Rafał Dzięgiel
9e8854c5e2 actions: Use GNOME nightly repo and rename to nightly
Rename flatpak-testing into flatpak-nightly so it reflects that it uses GNOME nightly sources now and builds itself every night (with nightly gstreamer too).
2021-08-27 16:21:57 +02:00
Rafał Dzięgiel
16a9546c97 actions: Build aarch64 flatpak 2021-08-27 15:51:21 +02:00
Rafał Dzięgiel
2686c2ca03 Quietly handle ranking gsetting change after app update
Do not print errors for everyone who updates Clapper from 0.3.0 version.
How plugin ranking is stored in gsettings changed. Instead reset it quietly
into new defaults to avoid problems.

Also since now GstClapper API sets some default ranks based on installed
GStreamer version, hopefully this ranking will be only an edge case for
people who want to experiment or need to test/debug some GStreamer plugin.
2021-08-27 13:30:14 +02:00
Rafał Dzięgiel
ad563d16d0 Move init functions into main where they should be
It seems that libadwaita does not like being initialized too early. Move the init function into the beggining of main() to make it happy.
2021-08-27 12:56:58 +02:00
Rafał Dzięgiel
12ce95b664 rpm: Install translations 2021-08-26 21:14:19 +02:00
Rafał Dzięgiel
2dbabe52bb Update LINGUAS file 2021-08-26 20:40:21 +02:00
Rafał Dzięgiel
2c35ceb35a New Crowdin updates (#141)
* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Dutch)
2021-08-26 20:20:59 +02:00
Rafał Dzięgiel
5eac1aa675 Merge pull request #140 from sp1ritCS/local_de
l10n: added german localization
2021-08-26 20:15:19 +02:00
Florian "sp1rit"​
0e6a68665d Merge remote-tracking branch 'origin/master' into local_de 2021-08-26 20:04:41 +02:00
Rafał Dzięgiel
86fe1628c3 Merge pull request #139 from juxuanu/master
Translate to Catalan
2021-08-26 19:36:48 +02:00
Rafał Dzięgiel
a427817e53 rpm: Install clapper symlink 2021-08-26 19:23:52 +02:00
Rafał Dzięgiel
7a767c34eb rpm: Fix bogus date 2021-08-26 19:20:19 +02:00
Rafał Dzięgiel
a7298e371e meson: Use DESTDIR env when creating symlink 2021-08-26 19:06:10 +02:00
Rafał Dzięgiel
f6393a177d Merge pull request #143 from Rafostar/symlink
meson: Create symlink to bin named simply "clapper"
2021-08-26 18:17:05 +02:00
Rafał Dzięgiel
45decb8563 meson: Create symlink to bin named simply "clapper" 2021-08-26 18:04:57 +02:00
Florian "sp1rit"​
2e12e52730 l10n: added german localization 2021-08-26 13:06:08 +02:00
Ícar
ffbd8c35e1 Update LINGUAS for Catalan 2021-08-26 10:54:59 +02:00
Ícar
01277f4a71 Add Catalan translation 2021-08-26 10:54:23 +02:00
Rafał Dzięgiel
a54c3e4bcc New Crowdin updates (#136)
* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Romanian)

* New translations com.github.rafostar.Clapper.pot (Korean)

* New translations com.github.rafostar.Clapper.pot (Vietnamese)

* New translations com.github.rafostar.Clapper.pot (Chinese Traditional)

* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Ukrainian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Swedish)

* New translations com.github.rafostar.Clapper.pot (Serbian (Cyrillic))

* New translations com.github.rafostar.Clapper.pot (Russian)

* New translations com.github.rafostar.Clapper.pot (Portuguese)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Norwegian)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Japanese)

* New translations com.github.rafostar.Clapper.pot (French)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Hungarian)

* New translations com.github.rafostar.Clapper.pot (Hebrew)

* New translations com.github.rafostar.Clapper.pot (Finnish)

* New translations com.github.rafostar.Clapper.pot (Greek)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Danish)

* New translations com.github.rafostar.Clapper.pot (Czech)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Arabic)

* New translations com.github.rafostar.Clapper.pot (Afrikaans)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Portuguese, Brazilian)
2021-08-25 21:47:28 +02:00
Rafostar
17b2aec170 YouTube name should not be translated 2021-08-25 17:14:12 +02:00
Rafał Dzięgiel
75bc0d6b69 Update README.md 2021-08-25 15:28:03 +02:00
Rafał Dzięgiel
edef26fc0e New Crowdin updates (#135)
* New translations com.github.rafostar.Clapper.pot (Romanian)

* New translations com.github.rafostar.Clapper.pot (Korean)

* New translations com.github.rafostar.Clapper.pot (Vietnamese)

* New translations com.github.rafostar.Clapper.pot (Chinese Traditional)

* New translations com.github.rafostar.Clapper.pot (Chinese Simplified)

* New translations com.github.rafostar.Clapper.pot (Ukrainian)

* New translations com.github.rafostar.Clapper.pot (Turkish)

* New translations com.github.rafostar.Clapper.pot (Swedish)

* New translations com.github.rafostar.Clapper.pot (Serbian (Cyrillic))

* New translations com.github.rafostar.Clapper.pot (Russian)

* New translations com.github.rafostar.Clapper.pot (Portuguese)

* New translations com.github.rafostar.Clapper.pot (Polish)

* New translations com.github.rafostar.Clapper.pot (Norwegian)

* New translations com.github.rafostar.Clapper.pot (Dutch)

* New translations com.github.rafostar.Clapper.pot (Japanese)

* New translations com.github.rafostar.Clapper.pot (French)

* New translations com.github.rafostar.Clapper.pot (Italian)

* New translations com.github.rafostar.Clapper.pot (Hungarian)

* New translations com.github.rafostar.Clapper.pot (Hebrew)

* New translations com.github.rafostar.Clapper.pot (Finnish)

* New translations com.github.rafostar.Clapper.pot (Greek)

* New translations com.github.rafostar.Clapper.pot (German)

* New translations com.github.rafostar.Clapper.pot (Danish)

* New translations com.github.rafostar.Clapper.pot (Czech)

* New translations com.github.rafostar.Clapper.pot (Catalan)

* New translations com.github.rafostar.Clapper.pot (Arabic)

* New translations com.github.rafostar.Clapper.pot (Afrikaans)

* New translations com.github.rafostar.Clapper.pot (Spanish)

* New translations com.github.rafostar.Clapper.pot (Portuguese, Brazilian)
2021-08-25 15:02:02 +02:00
Rafał Dzięgiel
0edab83f86 Update POT file 2021-08-25 14:39:07 +02:00
Rafał Dzięgiel
9681d0eea1 ui: Change letter case
Should be lowercase as the rest
2021-08-25 14:38:25 +02:00
Rafał Dzięgiel
b6559ee50f Sync shortcuts names with menu items
This option was renamed recently
2021-08-25 14:29:05 +02:00
Rafał Dzięgiel
ce183595cd readme: Add crowdin "localized" badge 2021-08-25 13:51:14 +02:00
Rafał Dzięgiel
71f50ba414 Revert "crowdin: Add some languages mappings"
This reverts commit 0de8ee2d54.
2021-08-25 13:28:49 +02:00
Rafał Dzięgiel
0de8ee2d54 crowdin: Add some languages mappings 2021-08-25 12:58:25 +02:00
Rafał Dzięgiel
8be49f25b4 Update Crowdin configuration file 2021-08-25 12:36:58 +02:00
Rafał Dzięgiel
69bef3d174 Update Crowdin configuration file 2021-08-25 12:26:59 +02:00
Rafał Dzięgiel
d429e9105c Update Crowdin configuration file 2021-08-25 12:25:12 +02:00
Rafał Dzięgiel
a1ce04edfa Initial translations support
Most of the app is now translatable, so put a POT file in git and make app use translations if available
2021-08-25 11:23:43 +02:00
Rafał Dzięgiel
8ca4c30beb Rename "Open Local" into "Open Files"
This is easier to understand, besides file chooser might show online filesystem mounts which makes open "local" an inaccurate name
2021-08-24 22:05:20 +02:00
Rafał Dzięgiel
9b53a3e387 api: Fix plugin feature unref 2021-08-24 20:52:18 +02:00
Rafał Dzięgiel
f31682624f Do not try to translate "GStreamer" name 2021-08-24 15:49:45 +02:00
Rafał Dzięgiel
5874db45ea api: Introduce custom gstreamer init function
Initializes GStreamer library and tweaks some of its defaults to our liking.
This also allows usage of GstClapper API alone without importing GStreamer on the implementation side.

It changes preferred hardware acceleration order (depending on plugins versions) into:
v4l2sl -> nv -> va -> vaapi -> v4l2
2021-08-24 14:15:29 +02:00
Rafał Dzięgiel
87a0dd473e flatpak: Add missing deps to testing manifest
These are required to build libadwaita
2021-08-24 09:26:33 +02:00
Rafał Dzięgiel
c50df5f2a3 Merge pull request #129 from Rafostar/libadwaita
Initialize with libadwaita, port preferences window to be adaptive and do few CSS tweaks to improve overall app look.
2021-08-23 18:33:21 +02:00
Rafał Dzięgiel
a72a8057e5 rpm: Require libadwaita 2021-08-23 17:13:36 +02:00
Rafał Dzięgiel
f29ec78b92 Update readme 2021-08-23 16:55:56 +02:00
Rafał Dzięgiel
10f54c7c3d Remove .deb package
This was unresolvable (and reportedly broken) for quite some time, now even more so with libadwaita added into the mix. Having .deb packages would require a custom PPA with up-to-date dependencies. Anyone interested is free to set it up, but this git repo is not a good place to do so.
2021-08-23 16:18:13 +02:00
Rafał Dzięgiel
2b91056543 Remove Arch PKGBUILD files from git
Both stable and git versions of Clapper are available in AUR, no point maintaining them in two places
2021-08-23 16:11:09 +02:00
Rafał Dzięgiel
2656762cbc Fix chapter popover coordinates 2021-08-23 15:57:11 +02:00
Rafostar
f5ff59f786 css: Remove custom preferences CSS classes
Those are not used anymore
2021-08-22 16:09:45 +02:00
Rafał Dzięgiel
e4fe7844c4 metainfo: Mark as mobile friendly and fix few typos 2021-08-22 16:09:41 +02:00
Rafał Dzięgiel
b7d9a22d33 flatpak: Build libadwaita 2021-08-22 16:09:36 +02:00
Rafał Dzięgiel
c8a5277908 Port preferences window to libadwaita 2021-08-22 16:09:23 +02:00
Rafał Dzięgiel
62fab289b7 Few small CSS optimizations for new Adwaita theme 2021-08-06 09:11:39 +02:00
Rafał Dzięgiel
56ca13b370 Remove GTK 4.0.2+ theme workarounds 2021-08-06 09:11:34 +02:00
Rafał Dzięgiel
ce46905319 css: Remove slider outline in TV mode 2021-08-06 09:11:28 +02:00
Rafał Dzięgiel
5fe5f89e5d css: Reduce sliders size
They are way too big in new Adwaita theme for windowed mode, but leave them bigger when in TV mode
2021-08-06 09:11:20 +02:00
Rafał Dzięgiel
9ba6f5d09e Apply "osd" CSS class to each button in headerbar
Otherwise it does not work correctly with new Adwaita theme
2021-08-06 09:11:14 +02:00
Rafał Dzięgiel
4c0fc1dac2 Init libadwaita 2021-08-06 09:11:06 +02:00
Rafał Dzięgiel
13a792c0a9 Remove Adwaita scale brightness increase
This was fixed inside Adwaita theme
2021-08-06 09:10:58 +02:00
Rafał Dzięgiel
02b0d5f03f Remove theme selection workaround
Libadwaita does not support any other stylesheets then Adwaita. Not my fault.
2021-08-06 09:10:44 +02:00
Rafał Dzięgiel
b577dd762d Fix D&D on GTK 4.3.2+ 2021-08-05 22:29:23 +02:00
Rafał Dzięgiel
d798539dce Merge pull request #128 from Rafostar/gles
Cleanup GL init and use GLES if GTK is using it
2021-08-01 13:47:24 +02:00
Rafostar
19e159d1bd sink: Cleanup GL context init code 2021-08-01 12:44:35 +02:00
Rafał Dzięgiel
c3cdabb050 Merge pull request #127 from Rafostar/show-decoders
API: Add video/audio decoder changed signals
2021-08-01 11:02:28 +02:00
Rafał Dzięgiel
c53cde4d78 Merge pull request #126 from Rafostar/gestures
Add side double tap gesture and update shortcuts window
2021-08-01 10:29:08 +02:00
Rafał Dzięgiel
b308ae367f sink: When GTK is using GLES on EGL, use it too
If for some reason GTK ended up with using EGL with GLES instead of OpenGL and user
did not specify anything other, use it by default in gstreamer part of the app too.
2021-07-28 18:00:08 +02:00
Rafostar
b2005fd34f Describe gestures in shortcuts window 2021-07-28 17:09:32 +02:00
Rafostar
a6dfeeca37 Switch playlist items via double tap on screen side
Double press left side of the touchscreen to play previous item, right side to play next one. #93
2021-07-28 12:06:18 +02:00
Rafostar
90844e49ad API: Add video/audio decoder changed signals 2021-07-28 12:02:52 +02:00
Rafostar
eb60d036db Update PKGBUILD files 2021-07-20 13:44:03 +02:00
Rafał Dzięgiel
6e20a5fa12 Update README.md 2021-07-20 11:25:44 +02:00
Rafał Dzięgiel
cf370961b4 Merge pull request #106 from mattblaha/cleanup-readme
Grammatical cleanups in readme
2021-07-19 20:51:46 +02:00
Matt Blaha
6db36d6ac2 Align build/built with the project description on github, several other small grammatical cleanups. 2021-07-19 12:14:12 -05:00
Rafostar
4738673f7f Fix bottom OSD margins on multi monitors setup
When player enters high resolution display, margins are being recalculated,
but when it goes back dragged to some lower resolution screen they are not.
This is wrong, as they should be reset back to the initial value which is zero.

Fixes #102
2021-07-19 12:43:01 +02:00
Rafostar
1004000ba2 Leave fullscreen with "Esc" key 2021-07-18 15:34:41 +02:00
Rafał Dzięgiel
e40f11def5 sink: Small code cleanup 2021-07-16 23:50:26 +02:00
Rafał Dzięgiel
5378facb46 Add long press gesture to toggle play/pause #93
Press and hold on touchscreen while in fullscreen to toggle between play and pause
2021-07-16 18:31:26 +02:00
Rafał Dzięgiel
c6b252f261 Reduce icon height a little #92
Make icon a tiny bit smaller in height. This also makes the play logo a little more centered vertically.
2021-07-15 11:24:16 +02:00
Rafał Dzięgiel
0f1447b14e sink: Check navigation state with a lock held
This happens as callback from GTK thread, so its not thread safe
2021-07-13 19:57:31 +02:00
Rafał Dzięgiel
cfd6e1bd23 Merge pull request #91 from bridadan/mobile_youtube_urls
Parse mobile youtube URLs
2021-07-12 21:35:03 +02:00
Brian Daniels
0cb89d3a84 Parse mobile youtube URLs.
Add support for youtube URLs with the format m.youtube.com?v=<video id>
2021-07-12 15:09:39 -04:00
Rafał Dzięgiel
3bf636d46b sink: Do not send navigation events when not playing
Before playback starts our video display size is zero, no point in sending navigation events in such case.
Latest gstreamer git prints criticals in such case.

Also do not send mouse navigaion when element is paused and skip keypresses when below paused state.
2021-07-08 20:33:12 +02:00
Rafał Dzięgiel
8f79a76a51 flatpak: Update metainfo description
Clapper was tested and confirmed to work with V4L2 stateless decoders. Also since latest GTK4 version moved to EGL on Xorg we no longer have the GLX related problems we used to have.
2021-07-06 10:00:28 +02:00
Rafał Dzięgiel
0efe9144d8 Merge pull request #90 from Rafostar/external-oes
sink: Support rendering external-oes textures
2021-07-05 22:31:12 +02:00
Rafał Dzięgiel
2e776ddf7b sink: Support rendering external-oes textures
This significantly improves performance on mobile devices by
removing the texture copy from an OES texture to 2D texture.
2021-07-05 22:08:51 +02:00
Rafostar
2eea3b05b1 flatpak: Include run number in testing github action 2021-06-27 11:04:06 +02:00
Rafał Dzięgiel
e647cdc8c6 Update README.md 2021-06-25 09:18:56 +02:00
Rafał Dzięgiel
1f3ddab566 flatpak: Fix duplicated cache key name 2021-06-25 08:56:07 +02:00
Rafał Dzięgiel
a38480c46b Merge pull request #88 from Rafostar/workflow
Add Flatpak workflows
2021-06-24 20:31:17 +02:00
Rafał Dzięgiel
562587846a Add flatpak testing workflow
Builds nightly with latest GStreamer from git (no patches applied)
2021-06-24 19:45:15 +02:00
Rafał Dzięgiel
c6cd829e7b Add flatpak workflow
Builds on push/pull with Flathub patches
2021-06-24 19:44:52 +02:00
Rafał Dzięgiel
9b31581aac flatpak: Add app testing manifest version
The main difference is that it builds latest GStreamer from git master and uses
runtime provided version of GTK4 (both without any patches applied).

This is done for testing purposes or finding regressions.
2021-06-24 16:55:53 +02:00
Rafał Dzięgiel
5018b3a28a Use new PiP icons when available
Use the new "pip-in" and "pip-out" GNOME symbolic icons if user theme has them for enter/leave floating mode button. When icon is unavailable on the host, old icon will be used instead.
2021-06-23 14:24:59 +02:00
Rafostar
bad836cc6d flatpak: Fix wrong module path 2021-06-20 15:50:21 +02:00
Rafał Dzięgiel
e1845a212f Merge pull request #87 from Rafostar/pipewire
Add PipeWire support
2021-06-20 15:46:03 +02:00
Rafostar
f86e32ed88 flatpak: Sync with Flathub 2021-06-20 15:17:15 +02:00
Rafostar
af2c74a4b1 flatpak: Support PipeWire GStreamer plugins
We need to allow PipeWire socket access and symlink the pipewire
plugin to the dir where our custom GStreamer installation is.
2021-06-20 14:44:49 +02:00
Rafostar
1c414ef36b API: allow using PipeWire for audio output
Instead of using PulseAudio sink and making a round way through pipewire-pulse,
access and use PipeWire directly for audio output when user sets env var
GST_CLAPPER_USE_PIPEWIRE=1
2021-06-20 11:27:43 +02:00
Rafał Dzięgiel
11e89dab26 Update README.md 2021-06-18 21:35:15 +02:00
Rafał Dzięgiel
37d2f7aebd 0.3.0 2021-06-18 15:04:01 +02:00
Rafał Dzięgiel
f2ac3b20a3 meson: Install new symbolic icon 2021-06-18 10:28:25 +02:00
Rafał Dzięgiel
ade60b93a4 Merge pull request #86 from SeaDve/master
Add symbolic icon
2021-06-18 10:25:42 +02:00
Dave Patrick
48bc96f074 Add symbolic icon 2021-06-18 08:59:46 +08:00
Rafał Dzięgiel
0d9cb91705 Update TODO.md 2021-06-17 17:20:42 +02:00
Rafał Dzięgiel
21ccab1cc2 Add option to keep showing last video frame after playback
Previously Clapper showed last frame, now it defaults to black screen, so add an option for users to choose what they like better
2021-06-16 15:34:36 +02:00
Rafał Dzięgiel
bea3b1670d API: Raise ignored duration changes to 250 milliseconds
We do not show milliseconds in GUI, so we should not try to handle stream gaps that short.
2021-06-16 11:07:50 +02:00
Rafał Dzięgiel
0d4d3f1a8c sink: Avoid props code duplication 2021-06-16 09:43:55 +02:00
Rafał Dzięgiel
fc525ffcb1 sink: EGL on X11 from GTK 4.3.1
Recent GTK 4.3.1 release already uses EGL on x11, so lower the version check to that version
2021-06-15 16:52:47 +02:00
Rafał Dzięgiel
6f1a5626bc API: get MPRIS with a lock
Otherwise it is not thread safe
2021-06-15 16:16:29 +02:00
Rafał Dzięgiel
fbe6a8804c yt: Set some initial player version
It does not have to be up-to-date and even if it fails, we have a fallback that will update it anyway
2021-06-08 16:54:20 +02:00
Rafał Dzięgiel
c0b92c190b mpris: Fix wrong object type
Fix a copy-paste bug
2021-06-05 22:24:26 +02:00
Rafał Dzięgiel
8fc64eaf73 sink: Automatically draw black when going to NULL state
Remove all workarounds including ignore_textures prop and draw black functions and handle that automatically in sink when going into NULL state.
2021-06-02 20:56:50 +02:00
Rafał Dzięgiel
0b7f31b7c2 API: Properly return a boolean instead of a number 2021-06-02 20:24:40 +02:00
Rafał Dzięgiel
2d4353aaec Append some common subtitle track titles
In order to not end up with multiple subitle tracks simply named for e.g. "English", add some common postfix to it when detected in track title.
2021-06-02 15:47:09 +02:00
Rafał Dzięgiel
7062af472b API: Add function to get subtitle track title 2021-06-02 11:08:30 +02:00
Rafał Dzięgiel
1f4698448a Detect used GStreamer plugin names
Allows seeing what plugins are used with GST_DEBUG=Clapper:4. This is also needed for yet to come functionality of setting elements props.
2021-06-01 21:57:14 +02:00
Rafał Dzięgiel
95c8316af6 Change Enter key help description
OSD makes more sense to users then controls as it also shows top title and time layers
2021-06-01 08:31:02 +02:00
Rafał Dzięgiel
06d9f302c2 Revert "sink: Use g_main_context_invoke_full for drawing"
Not much benefit from using this function and unlike g_idle_add_full it
does not allow to skip a frame when previous one was not finished (slow HW).

This reverts commit f8a7abe195.
2021-05-31 18:07:37 +02:00
Rafał Dzięgiel
6246777f06 Prefer custom title over media info one
Otherwise YT videos will all show filename of dash manifest as title
2021-05-31 17:46:19 +02:00
Rafostar
1f781716d7 Add env variable to display FPS 2021-05-30 11:14:51 +02:00
Rafał Dzięgiel
0d7ef22c88 Merge pull request #77 from Rafostar/mpris
Add MPRIS
2021-05-26 22:01:49 +02:00
Rafał Dzięgiel
57664f32da sink: Do not send the same cursor coords on each GUI redraw 2021-05-26 21:15:58 +02:00
Rafał Dzięgiel
f8a7abe195 sink: Use g_main_context_invoke_full for drawing
Queue draws to application (and GTK) main context using g_main_context_invoke_full method
2021-05-26 20:59:50 +02:00
Rafostar
5f259b28fe mpris: Add "SupportedUriSchemes" and handle "OpenUri" method 2021-05-26 15:14:28 +02:00
Rafostar
9f776e9ecb mpris: Support changing volume 2021-05-26 15:13:30 +02:00
Rafał Dzięgiel
edb799bafa API: Parse title from URI when no title in tags 2021-05-24 15:35:04 +02:00
Rafał Dzięgiel
7535c4e598 mpris: Support position reporting and seeking 2021-05-24 15:34:47 +02:00
Rafał Dzięgiel
f0475ee055 API: Support seeking by offset 2021-05-24 15:33:52 +02:00
Rafał Dzięgiel
68d7205ead mpris: Support metadata url, title and length 2021-05-24 15:33:38 +02:00
Rafał Dzięgiel
f08ffad178 Initial MPRIS support
Implement a working MPRIS DBus connection with a separate API to control it. Right now only player playback state is reflected and Play/Pause/PlayPause calls work.
2021-05-24 15:33:15 +02:00
Rafał Dzięgiel
c2de0b7b33 yt: Use "html5=1" request query string 2021-05-24 13:04:10 +02:00
Rafał Dzięgiel
ac7be5956c Update Flathub submodule 2021-05-20 18:55:17 +02:00
Rafał Dzięgiel
76a1efab58 flatpak: Build from local dir instead of git
Allows doing test builds with unmerged changes
2021-05-20 17:27:47 +02:00
Rafał Dzięgiel
a2bbd2708d sink: Support EGL under x11 with GTK 4.4+ 2021-05-14 18:11:58 +02:00
Rafał Dzięgiel
9e77660cac Mark extras dir contents as linguist-vendored 2021-05-13 21:28:35 +02:00
Rafał Dzięgiel
5ea22450c0 Use custom getUriProtocol function
Gst.Uri.get_protocol function is very simple. It just splits string by ":" and return the first part. We can do the same in JS and by doing that we do not have to initialize GStreamer just to get this function.
2021-05-13 21:24:28 +02:00
Rafał Dzięgiel
6ae38327ca Leave CSS fullscreen optimization applied
Do not apply and remove fullscreen optimization class when going/leaving fullscreen. Instead set it to be applied to fullscreen only with CSS.
2021-05-13 21:13:18 +02:00
Rafał Dzięgiel
9006e56534 Add "text/x-ssa" to list of known subtitle mimes
GStreamer does not do external .ass subs ATM, but we should treat them as subtitles anyway.
2021-05-13 21:01:11 +02:00
Rafał Dzięgiel
af0e082c43 Readapt to changed monitor on the fly
Check and apply/remove TV mode UI on the fly when switching monitors.
This allows for e.g. having a mobile device connected to external big screen,
drag Clapper window from one screen to another and UI should automatically
adapt between mobile and TV modes without interrupting playback.

This also helps in situations where monitor size is not initially known
on window map #74.
2021-05-12 15:31:15 +02:00
Rafostar
2f5d6d60ed API: add debug messages about dropped buffers 2021-05-06 14:34:08 +02:00
Rafał Dzięgiel
9d537c7318 Update TODO.md 2021-05-04 19:05:46 +02:00
Rafostar
970b1487ac Restore manual play call
Autoplay was causing some racy conditions when loaded with subtitle uri. Make it play after uri loaded signal, but still prevent going from stopped to play 2nd time.
2021-05-04 18:46:22 +02:00
Rafostar
fc51fd857c Fix missing actions shortcuts in main menu
Actions were loaded too early, causing GTK to not recognize them and show their keyboard shortcuts next to main menu items
2021-05-03 19:26:22 +02:00
Rafostar
b419ed7922 Add keyboard shortcuts window 2021-05-03 19:26:06 +02:00
Rafostar
4f69183b85 Flatpak: use libs and patches from Flathub as submodule
I do not want to maintain them in two different places
2021-05-03 14:12:05 +02:00
Rafostar
98df55b231 Do not forget to destroy file chooser 2021-05-02 22:20:51 +02:00
Rafostar
6a4f5f2560 Export playlist to file with Ctrl+E 2021-05-02 20:25:15 +02:00
Rafostar
efe9439633 Do not ref all dialogs
The bug that we try to workaround here affects only file chooser dialog and not every dialog, so do not increase ref count on them
2021-05-02 17:29:15 +02:00
Rafostar
4179176ce8 Sink: queue render on GTK settings change
We have turned off auto rendering in video widget, hence we need to manually refresh when user changes some GTK settings (theme, icons etc.)
2021-05-02 15:51:14 +02:00
Rafostar
a7288adf4c Do not check Ids length in shuffle repeat mode
We always have at least 2 playlist items, thus at least 1 Id in array when we reach this point in code
2021-05-01 12:27:56 +02:00
Rafostar
9bb3f999b1 Also seek to 0 for other repeat modes with 1 item playlists 2021-05-01 12:15:07 +02:00
Rafostar
0e6507682a Do not show visualizations button when no audio tracks 2021-05-01 12:11:16 +02:00
Rafał Dzięgiel
2d8471dea0 Add playlist shuffle repeat mode #52 2021-04-29 12:26:40 +02:00
Rafał Dzięgiel
68f49c1495 Replace media playlist playing icon with repeat button #52
Show current and toggle change of repeat mode inside the playlist popover. The previous currently playing icon did not reflect actual playing state, so this should be better and does not take more space in UI.
2021-04-29 11:44:07 +02:00
Rafał Dzięgiel
a8bb6c40f4 Add more WebSocket API actions 2021-04-28 12:40:27 +02:00
Rafał Dzięgiel
71db78a0f6 Use "window.close" action instead of "close-request" 2021-04-28 12:15:20 +02:00
Rafał Dzięgiel
4133557086 Do not send or apply undefined args over WebSocket 2021-04-28 11:50:14 +02:00
Rafał Dzięgiel
d926e6b389 Add keybinding to change repeat mode #52 2021-04-27 15:25:22 +02:00
Rafał Dzięgiel
fd2de8b9b6 Add repeat mode options to playlist #52 2021-04-27 14:50:54 +02:00
Rafał Dzięgiel
de65eee106 API: simplify playbin flags detect function 2021-04-27 12:28:59 +02:00
Rafał Dzięgiel
9b07ff7dc5 Mention that packages from my repo are unstable 2021-04-27 11:23:42 +02:00
Rafał Dzięgiel
047dd12fbb Restore initial GUI state after playback 2021-04-27 11:14:09 +02:00
Rafał Dzięgiel
3238270c0d Ignore duration changes below 1ms during playback 2021-04-27 10:43:13 +02:00
Rafał Dzięgiel
997e47b93c API: let client decide what to do on EOS #52 2021-04-27 09:24:13 +02:00
Rafał Dzięgiel
ec1d4619a7 API: make "state" into a property 2021-04-26 22:30:01 +02:00
Rafał Dzięgiel
f4e48c9f8c Sink: render black on READY_TO_NULL state change
Show black background when playback finishes
2021-04-26 20:42:00 +02:00
Rafał Dzięgiel
1da6b94efc API: simplify EOS handling
Do not try to play smart with EOS by seeking to beginning. This leads to various errors or crashes. Just signal it and stop afterwards.
2021-04-26 20:40:44 +02:00
Rafał Dzięgiel
e4335721be Simplify auto-fullscreen logic 2021-04-26 17:51:20 +02:00
Rafał Dzięgiel
45d2702e01 API: fix missing drop of signals inhibit 2021-04-26 17:36:28 +02:00
Rafał Dzięgiel
a8aca7b3c0 API: make it autoplay on the same context invoke 2021-04-26 14:47:42 +02:00
Rafał Dzięgiel
c6e8824e3b API: add toggle_play method 2021-04-26 14:21:33 +02:00
Rafostar
e92ad68220 Print a warning when plugin rank cannot be changed 2021-04-25 22:00:00 +02:00
Rafostar
a98ca53dfb Use Gio.SimpleAction as only keypress handler 2021-04-25 20:19:44 +02:00
Rafał Dzięgiel
32995fc6a6 Sort chapters arr when switching to prev/next one
TOC representation obtained for some video files might be out of order. Sort them when switching between chapers, otherwise "next" chapter might not be the nearest one.
2021-04-22 15:48:16 +02:00
Rafał Dzięgiel
6b5240ddbc Add missing return value 2021-04-22 15:35:16 +02:00
Rafał Dzięgiel
46ef6bcd1d Use "const" for chapters keys
Array is reversed but variable holding it is not replaced in this function, so "const" can be used here
2021-04-22 15:28:19 +02:00
Rafał Dzięgiel
bd13a3c15a Use Shift+Left/Right to switch video chapters 2021-04-22 14:40:21 +02:00
Rafał Dzięgiel
edfa85b5cc Use Ctrl+Left/Right to switch playlist items. Closes #63 2021-04-22 14:32:02 +02:00
Rafał Dzięgiel
084f78a851 Change actions naming scheme
Use _ instead of capital letters in words for actions names. This will make some other stuff much easier.
2021-04-22 14:29:40 +02:00
Rafał Dzięgiel
c9b2f25192 Act on key press, not release 2021-04-22 14:13:53 +02:00
Rafał Dzięgiel
6f39b3939a Do not get ancestor on key release if unneeded 2021-04-21 18:14:13 +02:00
Rafał Dzięgiel
ee78ffb1e4 Fix seeks when window tiling with Super key
Super key is consumed by shell and never reaches app key press detection. Use that to fix seeking when tiling window by ignoring all key releases that did not have a key press beforehand.
2021-04-21 17:04:09 +02:00
Rafał Dzięgiel
bfbbc517d5 Small cleanup 2021-04-21 16:59:06 +02:00
Rafał Dzięgiel
7559a61c9f Hold Ctrl while doing D&D to append items to playlist instead of replacing it 2021-04-21 14:56:26 +02:00
Rafał Dzięgiel
deb273179f Add append_playlist function 2021-04-21 14:55:20 +02:00
Rafał Dzięgiel
231af36ef6 Enumerate local directories only 2021-04-20 19:31:24 +02:00
Rafał Dzięgiel
2e892c923b Support opening folders with media files
D&D folder with videos onto Clapper window to play them as video playlist. If folder contains exactly one video and subtitle file, then that video will be played with subtitles automatically applied.
2021-04-20 18:44:53 +02:00
Rafał Dzięgiel
0ab0b66825 0.2.1 2021-04-19 13:06:40 +02:00
Rafał Dzięgiel
d901eb4712 Update README.md 2021-04-19 10:31:30 +02:00
Rafał Dzięgiel
fe03719b38 Show tooltip with full playlist item text on hover
Some titles might be more than few words and will not fit in current playlist popover. Instead of stretching it, show full playlist item filename (or path) on hover in a tooltip.
2021-04-18 18:44:16 +02:00
Rafał Dzięgiel
f0ea7ae798 Remove set_seek_mode check
We now use a custom GstPlayer fork that has it added
2021-04-18 15:28:55 +02:00
Rafał Dzięgiel
380236b8ba Cleanup: do not extend player class twice
We only use the base class once, no need to have it separately then. Merge into single file.
2021-04-18 15:25:02 +02:00
Rafał Dzięgiel
e721130a63 YT: live videos with duration are not live anymore 2021-04-18 14:13:30 +02:00
Rafał Dzięgiel
eaf090d2e2 YT: be a little more quiet about some errors
Some errors are to be expected for some videos. Quietly use fallback methods for them without printing those errors.
2021-04-18 14:04:53 +02:00
Rafał Dzięgiel
87115f43d7 YT: store adaptive option value in itag opts
So its easier to access and obtained only once
2021-04-17 20:35:15 +02:00
Rafał Dzięgiel
33a5ec18fa Change prefs adaptive streaming text
This option sets the preferred streaming mode. When unavailable, other might still be used as a fallback.
2021-04-17 18:06:34 +02:00
Rafał Dzięgiel
ab8cafa0b8 YT: support non-adaptive live streaming 2021-04-17 18:03:33 +02:00
Rafał Dzięgiel
62b6de6db2 YT: support live HLS videos 2021-04-17 16:14:21 +02:00
Rafał Dzięgiel
643c2029d0 Fix wrong indentation size
All the other code uses 4 spaces indent
2021-04-17 13:12:58 +02:00
Rafał Dzięgiel
9799783ee5 Use Gst.(M)SECOND constants instead of numbers
It makes code easier to read
2021-04-17 13:08:12 +02:00
Rafał Dzięgiel
457cbde25e Remove unused return value
This function already appends to passed array. No need to return it.
2021-04-16 11:03:44 +02:00
Rafał Dzięgiel
2fd94fdc70 Add some YouTube related preferences 2021-04-16 10:37:17 +02:00
Rafał Dzięgiel
3a998fb91e YT: auto select best matching resolution for used monitor 2021-04-16 09:53:21 +02:00
Rafał Dzięgiel
b02f54a3a6 Do not show mobile controls transition on launch
Start app with the correct controls layout instead of showing the "hide elapsed time"
transition when started on mobile width. It is annoying.

We cannot detect surface width during app widgets assembly, so update the controls
revealers state on first surface update after window is mapped and only if running
on mobile width. Otherwise do not do anything like before which will result in
showing fully revealed controls (default).
2021-04-15 15:27:28 +02:00
Rafał Dzięgiel
ca7b44092e API: do not lock when changing scaled size values
Those values are private and should be accessed only from GTK thread, so locking widget should not be necessary here.
2021-04-15 11:58:12 +02:00
Rafał Dzięgiel
adbcfecb5e API: unset needs_info_update when stopped 2021-04-15 11:30:55 +02:00
Rafał Dzięgiel
a717e481e8 Fix missing top left menu buttons. Fixes #66
On some non-default system configurations the "menu" layout item might be replaced with one named "icon". Handle "icon" the same as "menu" when organizing headerbar buttons.
2021-04-14 17:48:57 +02:00
Rafał Dzięgiel
4766efbbc4 0.2.0 2021-04-13 12:45:03 +02:00
Rafał Dzięgiel
28c1daf709 Save and offer resume only for local files
We do not know if the online URI still leads to the same file as before (or if different one leads to previous). Additionally we would also need to check if media is seekable. Disable for now to avoid problems.
2021-04-12 22:29:20 +02:00
Rafał Dzięgiel
aa49d25df5 Stop pipeline before replacing playlist 2021-04-12 19:28:12 +02:00
Rafał Dzięgiel
774687710f Add setting to enable YouTube adaptive streaming
For now hidden because other related YouTube settings like min/max resolution, codecs etc. are not done yet
2021-04-12 18:45:36 +02:00
Rafał Dzięgiel
901fc8d760 YT: try harder to find suitable DASH streams
Instead of searching for 1080p only, accept also other H.264 formats for DASH streaming
2021-04-12 17:41:42 +02:00
Rafał Dzięgiel
ab32b2dbbc API: emit media info updated signal after video info updates
This fixes problem with wrong video resolution reported in media info due to being emitted before values were updated.
2021-04-12 17:38:44 +02:00
Rafał Dzięgiel
24bb9f298b Avoid situations with no menu in headerbar
Some shells might want to show menu button outside of the app. We do not support that.
2021-04-12 17:30:00 +02:00
Rafostar
2efa3e0bf6 YT: fix non-working best combined URIs
Fix an undefined variable introduced during recent code cleanup
2021-04-11 16:34:02 +02:00
Rafostar
92e3f7d93c YT: move info ready debug message before signal emit
Otherwise it will appear in wrong order in debug output and be misleading
2021-04-11 15:44:08 +02:00
Rafostar
85804ea297 Move YT related functions from player to youtube script 2021-04-11 15:35:41 +02:00
Rafostar
7cf86e92eb YT: resolve redirects on the Clapper side
Instead of providing URIs directly to GStreamer, follow redirects and provide that final URI. With this change souphttpsrc will not have to go through redirects from the beginning for each video segment.
2021-04-11 14:46:08 +02:00
Rafostar
b5711b145b Set Soup import version to 2.4
With Soup 3.0 release, there is a possibility of having both on the host. Set used version to 2.4 to avoid warnings and compatibility errors for now.
2021-04-10 21:41:28 +02:00
Rafostar
9271392397 Change default window size
Controls panel height is now 3px less then before (as intended). Change default window size setting to make it look good with 16:9 video on fresh install.
2021-04-10 14:58:24 +02:00
Rafał Dzięgiel
175de5bd6d Flatpak: update FFmpeg to 4.4 2021-04-09 21:54:54 +02:00
Rafał Dzięgiel
7b97f29aaf Flatpak: fix GTK4 build script 2021-04-09 21:14:56 +02:00
Rafał Dzięgiel
8d7fb761f7 Always reset auto fullscreen boolean value
Otherwise we would keep checking the settings with each playlist file and accidentally entered fullscreen when that setting value was changed in middle of playback.
2021-04-09 19:58:33 +02:00
Rafał Dzięgiel
aec2166c11 Only auto fullscreen with new playlist
This fixes a bug when player would enter fullscreen when changing playlist item
2021-04-09 19:34:17 +02:00
Rafał Dzięgiel
c21b214477 Tweak how auto fullscreen option works
When auto fullscreen is enabled, enter fullscreen on each media load
unless player is in floating mode in which probably user wants it to remain.
2021-04-09 19:11:34 +02:00
Rafał Dzięgiel
d9939a94c2 Fix some error messages not being displayed 2021-04-09 18:49:44 +02:00
Rafał Dzięgiel
dafa2cfdf5 Fix missing file extension in online URIs 2021-04-09 18:16:02 +02:00
Rafał Dzięgiel
ebe72f20b5 Hide end time together with title when stopped 2021-04-09 17:54:48 +02:00
Rafał Dzięgiel
fa1455556b Treat media without duration as live content 2021-04-09 16:07:11 +02:00
Rafał Dzięgiel
8fb6b971fe Always try to update end time after new media info 2021-04-09 13:53:43 +02:00
Rafał Dzięgiel
1bf46a2f12 Fix top time not showing up on fullscreen startup 2021-04-09 11:37:19 +02:00
Rafał Dzięgiel
a39c67e5e7 Check if local subtitle file exists before loading it
Otherwise GStreamer will error out and playback will stop. Non-existing subtitle file is common on Flatpak when user tries to open/drop a file from a folder that container does not have access to.
2021-04-09 10:55:06 +02:00
Rafał Dzięgiel
a3f78432f8 Flatpak: update GTK4 to latest git
GTK 4.2.0 has some problems that were fixed recently. Update to post release git.
2021-04-08 20:56:50 +02:00
Rafał Dzięgiel
7a7a04554f Flatpak: remove glib-networking dependency
Runtime has now up-to-date version
2021-04-08 20:54:46 +02:00
Rafał Dzięgiel
93de3dc056 Flatpak: update runtime to 40 2021-04-08 20:52:35 +02:00
Rafał Dzięgiel
eda80f314e API: replace source-setup with element-setup callback
Otherwise user agent is only set for source elements and not for further pipeline elements (e.g. dashdemux => souphttpsrc)
2021-04-08 18:24:49 +02:00
Rafał Dzięgiel
b3e6890571 Flatpak: add dashdemux sdix range download patch 2021-04-08 17:19:22 +02:00
Rafał Dzięgiel
c767b3e4b2 Separate debug messages for YouTube 2021-04-08 12:09:42 +02:00
Rafał Dzięgiel
ec6157763b YT: do not try to get info again for current download 2021-04-08 11:05:20 +02:00
Rafał Dzięgiel
cca3077936 Fix startup window size on XOrg
The window size was restored too early which caused the window to be a little bigger then it should on each launch. Restore window size after that window was mapped.
2021-04-07 20:07:05 +02:00
Rafał Dzięgiel
b5e1b3ab86 Flatpak: workaround crashes in adaptive streaming on Intel GPUs #51 2021-04-07 17:43:32 +02:00
Rafał Dzięgiel
b15b94fc90 Convenient ways of opening external subtitles
Play video with external subtiles by:
* selecting and opening both video+subs from file chooser/manager
* dropping subtitles file on player window
* opening subtiles from file chooser/manager while video plays
* send their file path/uri to player via WebSocket message
2021-04-07 16:33:21 +02:00
Rafał Dzięgiel
28d8986072 Update .gitattributes 2021-04-07 08:56:30 +02:00
Rafał Dzięgiel
30a7229b33 API: add media info updated signal
Emit media info updated signal only when media info is initially created and when number/format of tracks changes later. This is needed for GUI to detect resolution change (adaptive streaming) or when user adds external subtitles to current video.
2021-04-06 18:49:08 +02:00
Rafał Dzięgiel
9502e062f4 Support "Default" theme
Adwaita was renamed to Default in latest GTK4 code.
We need to detect it and treat it the same way as we did for Adwaita.

More info in related GTK4 MR:
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/3079
2021-04-02 11:43:36 +02:00
Rafał Dzięgiel
6a9c77dfad Fix file paths in debug messages 2021-04-01 22:31:54 +02:00
Rafał Dzięgiel
133cda1b41 Fix forgotten ByteArray import during moving code 2021-04-01 22:31:22 +02:00
Rafał Dzięgiel
e68a7fe31a Work around GioFile promisify bug caused by GLib 2.68 2021-04-01 22:05:43 +02:00
Rafał Dzięgiel
7f69bee11c Move all file operations code to single file 2021-04-01 21:58:50 +02:00
Rafał Dzięgiel
295af9fd24 Improve debug messages for file operations 2021-04-01 20:20:42 +02:00
Rafostar
d04297620b Apply controls offset for Adwaita icons only
Only some icons from Adwaita get size modifications. Others themes do not need this, so they should not have an offset applied.
2021-03-31 21:38:44 +02:00
Rafostar
43acfddb06 Sink: inform about used OpenGL(ES) version 2021-03-31 17:34:49 +02:00
Rafostar
d54781eda7 Revert "Sink: limit GL APIs to OpenGL3+ and GLES2+"
This reverts commit 3fd30e41bf.

Some pipeline elements might still need to use (and work) on
older OpenGL versions.
2021-03-31 16:51:50 +02:00
Rafał Dzięgiel
96e5c5aa7c Restore 5px button margins for TV mode
They were reduced too much recently, causing chapter marks to not fit properly onto the controls bar
2021-03-31 09:04:29 +02:00
Rafał Dzięgiel
66ce006f00 Move buttons margins to CSS and tweak them a little 2021-03-30 22:15:12 +02:00
Rafał Dzięgiel
3fd30e41bf Sink: limit GL APIs to OpenGL3+ and GLES2+
Only allow using OpenGL 3.2+ or OpenGL ES 2.0+. This is what GTK4 supports.

#59
2021-03-29 14:38:19 +02:00
Rafał Dzięgiel
a6316c940c YT: always use up to date timestamp 2021-03-26 11:52:32 +01:00
Rafał Dzięgiel
84d9cc7416 Add DBus init debug message 2021-03-26 11:42:41 +01:00
Rafał Dzięgiel
a3499e9b47 Remove unused variable 2021-03-24 21:20:15 +01:00
Rafał Dzięgiel
4a60e01131 Auto set brighter sliders on Adwaita dark only 2021-03-24 21:16:41 +01:00
Rafał Dzięgiel
b404eb2f56 Increase play/pause icon size only on Adwaita theme
Adwaita theme has unusually small media constrols icons, but other popular themes do not. Instead increasing those icons on every theme do it only for Adwaita where problem occurs.
2021-03-24 20:36:08 +01:00
Rafał Dzięgiel
1f18796e0d Make buttons separator black on all themes
Using default @borders value causes it to be white even when all OSD buttons are half transparent black.
2021-03-24 20:04:09 +01:00
Rafał Dzięgiel
254aa538a5 YT: fix expire calc for long movies
Do not multiply video length when calculating expiration date. Otherwise for very long movies we might end up with with a past date.
2021-03-24 20:02:19 +01:00
Rafał Dzięgiel
58cc45ec7d Support accels for menu items
Add support for keyboard shortcuts for menu items. Additionally enable a common Ctrl+O for opening new file(s) and Ctrl+U for opening an URI.

Closes #45
2021-03-24 14:07:20 +01:00
Rafał Dzięgiel
7a75c6d4ff Merge pull request #55 from Rafostar/gl-mods
Simplify GL Sink code
2021-03-22 08:55:04 +01:00
Rafał Dzięgiel
2e97fc362c Dash: add segment ranges only to streams that have them 2021-03-19 15:19:00 +01:00
Rafał Dzięgiel
d762a59cc4 YT: do not keep URI in temp data twice 2021-03-19 14:27:55 +01:00
Rafał Dzięgiel
b42843be1f YT: do not check playability of saved temp data
Saved video info is always playable, otherwise its not saved in first place.
2021-03-19 11:43:37 +01:00
Rafał Dzięgiel
6dc825dfb3 YT: reduce amount of temp data stored per video 2021-03-19 11:25:36 +01:00
Rafał Dzięgiel
e89b3599c9 Remove "escape" key handler
It was conflicting with GTK build-in escape key functionality for closing popovers
2021-03-19 10:29:44 +01:00
Rafał Dzięgiel
79e12a6e36 YT: support obtaining info from player API 2021-03-19 10:26:46 +01:00
Rafał Dzięgiel
36d4a5c848 YT: replace some URL chars with slashes instead encoding it
Avoid dashdemux string query omission bug by using URL path with slashes instead of query string
2021-03-18 09:40:46 +01:00
Rafał Dzięgiel
38e5bae199 Replace lookbehind regexp
This was only supported in latest GJS version
2021-03-18 09:28:00 +01:00
Rafał Dzięgiel
fcff4b4450 Store all temp files in app named temp subdirectory 2021-03-17 11:57:02 +01:00
Rafał Dzięgiel
4021745a56 YT: set the same user agent as in player client 2021-03-17 10:47:38 +01:00
Rafał Dzięgiel
bd20d305ba YT: store reusable alive info in temp folder 2021-03-17 10:38:39 +01:00
Rafał Dzięgiel
d9b35b7fb8 YT: try only once
Avoid triggering 429 ban, by not trying second time
2021-03-16 19:45:33 +01:00
Rafał Dzięgiel
f1e00434ba Fix reference to undefined object 2021-03-16 13:44:22 +01:00
Rafał Dzięgiel
918157be04 Cooooookies!!! 2021-03-16 13:12:44 +01:00
Rafał Dzięgiel
72b55939b4 YT: abort on 429 error 2021-03-16 10:33:31 +01:00
Rafał Dzięgiel
e0a3ef78db YT: pass download info using object intead of array 2021-03-16 10:20:01 +01:00
Rafał Dzięgiel
4f46a7eaa8 YT: handle embedded videos URIs 2021-03-15 20:15:24 +01:00
Rafał Dzięgiel
050ef440dc Merge pull request #54 from Rafostar/yt-cache
YouTube cache
2021-03-15 16:37:55 +01:00
Rafał Dzięgiel
a4d55f8114 YT: store and load decipher actions from Clapper cache dir 2021-03-15 16:35:36 +01:00
Rafał Dzięgiel
aa60c56a58 Treat "yt" and "youtube" URI schemes as YouTube videos
You can set URI to "yt://VIDEO_ID" for YouTube videos
2021-03-15 13:40:50 +01:00
Rafał Dzięgiel
8c307dc90f YT: save decipher actions only after successful deciphering 2021-03-15 13:14:41 +01:00
Rafał Dzięgiel
5b6141ee8c YT: do not check player ID if actions are cached 2021-03-15 13:07:12 +01:00
Rafał Dzięgiel
8f294604dc Remove drop target from top revealer
It is causing various issues unfortunately
2021-03-14 23:33:29 +01:00
Rafostar
06f8e5d259 YT: cache current decipher actions 2021-03-14 21:00:18 +01:00
Rafostar
6370e1126b YT: check if decipher produced result 2021-03-14 16:50:23 +01:00
Rafostar
270e59137d YT: check if player URI is valid 2021-03-14 16:39:22 +01:00
Rafostar
ec18ca989a YT: decipher videos with signatures
Increase amount of playable YouTube videos by deciphering the ones that require to do so.

Many thanks to "node-ytdl-core" devs for JS regular expressions needed for YouTube player parsing.
2021-03-14 15:51:19 +01:00
Rafał Dzięgiel
46d24536c0 Do not keep invalid YT video info 2021-03-12 15:10:18 +01:00
Rafał Dzięgiel
c89d488c30 Prefetch YouTube video info on hover
Speed up loading of YouTube videos by downloading and parsing their info before video is dropped into player.
2021-03-12 13:05:58 +01:00
Rafał Dzięgiel
01c26cbbc3 Small text formatting fix 2021-03-12 08:50:52 +01:00
Rafał Dzięgiel
4375077dbc Decode custom video title from info
The values in JSON info are URI encoded with "+" signs, add custom decode function that decodes them.
2021-03-11 18:49:08 +01:00
Rafał Dzięgiel
fceb8ff70a YouTube support. Closes #46 2021-03-11 17:34:54 +01:00
Rafał Dzięgiel
6dc37088cf Fix error when playback finishes during controls reveal animation 2021-03-08 10:37:40 +01:00
Rafostar
4e85f6b749 API: set some common user agent
Some internet sites might prevent us from access unless some sort of a user agent is set
2021-03-07 21:37:01 +01:00
Rafostar
0cd82b1b8a API: remove video sink plugin selection
Clapper only has and supports one video sink. I would rather replace it than forcing support for multiple plugins.
2021-03-06 22:09:27 +01:00
Rafostar
39da52dd62 Sink: unlock widget before setting queue
Let GTK handle setting queue resize/render on the widget. We are not accessing widget values at this time, so it can be unlocked. It will be locked back during the render.
2021-03-06 19:16:28 +01:00
Rafał Dzięgiel
9c12afbf80 Sink: rename into GstClapperGLSink
The customized GTK4 sink version has few differences from the one shipped as part of GStreamer. Rename custom sink to GstClapperGLSink to avoid confusion.
2021-03-06 00:24:31 +01:00
Rafał Dzięgiel
e3c9b112e2 Sink: remove gtkconfig header
Remove another leftover meant for GTK3 compatibility
2021-03-05 23:27:08 +01:00
Rafał Dzięgiel
13d675beff Sink: merge gtkwidget into single class
Same as with video sink. Clapper uses only one so no need for subclassing.
2021-03-05 23:23:34 +01:00
Rafał Dzięgiel
95c3845398 Sink: merge gstsink into single class
Clapper only uses single video sink. No need for subclassing it.
2021-03-05 21:06:03 +01:00
Rafał Dzięgiel
93549a67af Sink: remove ignore_alpha property
GTK4 no longer supports ignoring alpha
2021-03-05 19:26:29 +01:00
Rafał Dzięgiel
07fb0a9a46 Sink: remove GTK4 if-defs
Clapper works with GTK4, so reduce codebase by removing GTK3 leftovers
2021-03-05 19:02:14 +01:00
Rafał Dzięgiel
fe3fd32932 Sink: keep track of widget allocation size
Instead of obtaining allocation size on each frame draw, keep track of its current size and update value on its change.
2021-03-05 18:41:26 +01:00
Rafał Dzięgiel
637212f7e8 Sink: move GL drawing logic into single function
No need having it in another function with additional call if it is used only from single place.
2021-03-05 18:10:35 +01:00
Rafał Dzięgiel
8b2e63ac48 Update README.md 2021-02-28 14:56:19 +01:00
Rafał Dzięgiel
f4968e28ab 0.1.0 2021-02-26 10:19:03 +01:00
Rafał Dzięgiel
68e10f1af4 Revert "Flatpak: update GStreamer to 1.18.3"
This reverts commit b3b0371c76.

It seems that newer GStreamer version has more new bugs then noticeable fixes.
2021-02-25 21:02:34 +01:00
Rafał Dzięgiel
2f3fac7d81 Flatpak: add broadway variable type fix patch 2021-02-25 09:51:24 +01:00
Rafał Dzięgiel
6b4521c49a Make video chapter popover easier to read when fullscreen 2021-02-25 09:27:07 +01:00
Rafał Dzięgiel
a0cd05fbe3 Workaround GTK4 revealers transition switch bug
Changing transition in middle or when not fully revealed has dire consequences, seems to be a GTK4 bug. Workaround this bug by switching top revealer transition type only when fully revealed.
2021-02-25 09:24:02 +01:00
Rafał Dzięgiel
d2d43db2c9 Do not update time if top grid is invisible 2021-02-24 18:27:40 +01:00
Rafał Dzięgiel
b7b1dad81c Allow adjusting playback speed with scroll 2021-02-24 17:29:24 +01:00
Rafał Dzięgiel
e859f5d518 Fix opening files from web application
It was trying to send GioFiles over WebSocket. The idea of doing that seems so dumb, that I do not know why I did not notice this issue earlier.
2021-02-24 17:05:49 +01:00
Rafał Dzięgiel
53ad4da7c6 Remove useless run method override 2021-02-24 16:46:25 +01:00
Rafał Dzięgiel
db8d060841 Mark as optimized for Phosh
Player window is considered mobile friendly with its transitions and touch/swipes gestures implemented. The only missing part now is preferences window that needs moving to libadwaita. Due to video playback being mobile friendly, mark this app as Purism Mobile compatible which will allow the app to appear on mobile app store and show the app icon in app launcher.
2021-02-24 15:58:37 +01:00
Rafał Dzięgiel
e2bd8a827c Mention in metainfo description that Wayland+vah264dec works best 2021-02-24 15:48:30 +01:00
Rafał Dzięgiel
0fe1cf5f0d Make volume restore more reliable
Instead setting value to volume scale, set value to the player itself. Scale will be updated due to bidirectional binded property. This fixes cases where slider did not emit value-changed notify as it was being set to the same value as initial one.
2021-02-24 14:26:34 +01:00
Rafał Dzięgiel
0a8e25d27b Prevent adding "fine-tune" class to position scale on TV mode
When scale enters "fine-tune", slider changes position a little. We do not want that to cause seek time change on TV mode.
2021-02-24 13:41:05 +01:00
Rafał Dzięgiel
af6a5ea1b9 Check widget existence when top revealer finishes reveal
Prevent errors when app was closed during top revealer animation.
2021-02-24 12:40:28 +01:00
Rafał Dzięgiel
632fcd34cc Fix overlay buttons not unrevealed when leaving window from bottom side
Bottom revealer motion controller was causing timeout to be cleared. Prevent that by making it child invisible when windowed, which will remove its allocated height and motion events will not be emitted.
2021-02-24 12:34:57 +01:00
Rafał Dzięgiel
186c63bf04 Set unreveal timeout after reveal finishes
Instead of setting hide controls timeout immediately when starting revealing, make the time controls are revealed constant by setting timeout after animation finishes.
2021-02-24 12:04:26 +01:00
Rafał Dzięgiel
68bd65c225 API: snap at nearest keyframe when doing fast seek
GStreamer needs to perform a seek when changing playback rate. Snapping at next keyframe causes viewer to lose few seconds of video when changing playback speed (and ugly fast forward effect when dragging speed slider). Prevent all those issues by seeking to the nearest keyframe instead.
2021-02-24 11:41:40 +01:00
Rafał Dzięgiel
199a8f1931 Bind volume scale with player volume prop
Now that player API itself is operating on a cubic scale (no value conversion required), the volume slider can be bind to the volume property. Thanks to that, player volume scale will correctly reflect Clapper volume set via external applications e.g. gnome-settings.
2021-02-24 11:09:42 +01:00
Rafał Dzięgiel
775ec8a780 API: fix volume functions descriptions 2021-02-24 10:44:26 +01:00
Rafał Dzięgiel
66d201dc3e Flatpak: update GTK to 4.1.1
GTK4 now has new GL renderer. If you wish to test it with Clapper, use GSK_RENDERER=ngl
2021-02-24 10:38:03 +01:00
Rafał Dzięgiel
dbd3e536b2 Limit bottom fullscreen controls panel width
Fullscreen bottom controls panel does not look good when progress bar is too long (especially on "ultrawide" displays), so limit its max width to 1720 application-pixels. This should make it still long enough for convenient chapter seeking.
2021-02-24 10:11:12 +01:00
Rafał Dzięgiel
bfdc85e3e3 Merge pull request #44 from Rafostar/gstclapper-volume
API: use cubic volume
2021-02-24 08:45:38 +01:00
Rafał Dzięgiel
86d365872a API: operate on cubic volume scale
Instead converting volume inside GJS, simplify things by making API operate on cubic volume scale.
2021-02-24 08:42:27 +01:00
Rafostar
b3b0371c76 Flatpak: update GStreamer to 1.18.3 2021-02-23 17:37:39 +01:00
Rafostar
7d79aa97bb Use rounded corners with every theme
AFAIK there is no way to detect theme rounded corners. Having 2/4 corners rounded in floating mode is not good.
2021-02-23 16:18:26 +01:00
Rafał Dzięgiel
6130ffa6c0 API: limit max linear volume to 3.375 (150% in cubic)
Clapper UI does not support volume overamp higher than 150%. Anything higher can lead to audio distortion or damaging your audio equipment.
2021-02-23 13:27:42 +01:00
Rafał Dzięgiel
ddc4030a30 Decrease min allowed video window size
Make sure the app can fit every mobile device by decreasing min window size to 320x180 application-pixels (16:9 aspect).
2021-02-23 12:52:45 +01:00
Rafał Dzięgiel
886dad97c5 WebApp: get active window prop only once 2021-02-23 12:37:33 +01:00
Rafał Dzięgiel
a309ef6099 Make remote app minimize, maximize and close buttons affect Clapper 2021-02-23 11:56:02 +01:00
Rafał Dzięgiel
6950cf1bbb Do not import GstClapper for remote app
No need to import and initialize whole GStreamer for web application if the only thing needed there is a single enum.
2021-02-22 16:34:08 +01:00
Rafał Dzięgiel
8df5c38357 Fix missing headerbar menu in Flatpak build 2021-02-22 13:14:49 +01:00
Rafał Dzięgiel
0ce851b514 Debug headerbar layout info 2021-02-22 12:41:44 +01:00
Rafał Dzięgiel
848fcf892b Merge pull request #43 from Rafostar/gnome4000
GNOME 40 design changes
2021-02-22 11:39:41 +01:00
Rafał Dzięgiel
8407a325af Increase delay of hiding controls when fullscreen 2021-02-22 11:29:26 +01:00
Rafał Dzięgiel
5e66a2bb5a Wait for top revealer transition to finish before changing it
Changing transition in middle can have dire consequences, so change only when not in transition.
2021-02-22 11:27:20 +01:00
Rafał Dzięgiel
61ae543cf9 Separate top revealer title and time 2021-02-22 10:22:05 +01:00
Rafostar
8b254de151 Modern fullscreen UI 2021-02-22 10:22:05 +01:00
Rafostar
edde84f0fc Performance: reduce amount of top shadow offscreen rendering 2021-02-22 10:22:05 +01:00
Rafostar
46103e169f Update current time on top overlay reveal
Previously current hour might not have been updated if someone entered fullscreen without moving mouse cursor or with a touch
2021-02-20 11:12:50 +01:00
Rafał Dzięgiel
86356d5b1b Make linked buttons icons closer to each other 2021-02-19 20:56:58 +01:00
Rafał Dzięgiel
67ad7d8bd4 Add separator to linked buttons 2021-02-19 20:26:59 +01:00
Rafał Dzięgiel
8d9fecd767 Remove obsolete media files
Media files are now part of the wiki to make app cloning faster
2021-02-19 17:45:45 +01:00
Rafał Dzięgiel
fbfddcbb33 Update description with new screenshots 2021-02-19 17:45:36 +01:00
Rafał Dzięgiel
0aa5402e77 Flatpak: update GTK to 4.1.0
While not ideal, only GTK 4.1+ has rounded menu buttons and renders properly with EGL on mobile devices.
2021-02-19 16:12:38 +01:00
Rafał Dzięgiel
59908f808f Show menu and close buttons on mobile fullscreen view 2021-02-19 13:13:25 +01:00
Rafał Dzięgiel
35d1179905 Make OSD position scale height a little bigger on mobile 2021-02-19 13:00:13 +01:00
Rafał Dzięgiel
ef06be464c Use basic GtkBox widget for headerbar replacement
Window headerbar is hidden at all times. We do not want to execute the logic that comes with GtkHeaderBar, so we simplify it by using GtkBox as a dummy widget.
2021-02-19 12:11:19 +01:00
Rafał Dzięgiel
12b38702ab Prevent hiding OSD when menu popover is open 2021-02-19 11:49:25 +01:00
Rafał Dzięgiel
dbfd97d11a Do not block closing OSD when popover opened in windowed mode 2021-02-19 10:52:11 +01:00
Rafał Dzięgiel
6400d251c2 Add a special style class for menu popover button
We want to have a non-osd popover in the button that is placed on OSD headerbar. This is something unusual that Adwaita does not have, so create a custom style that will use common values from user system theme.
2021-02-19 10:12:47 +01:00
Rafał Dzięgiel
e7b446ca9f Extend Gtk.ToggleButton for Popover buttons
Instead of trying to force active state for a normal button that is not designed to be toggle-able, use GTK toggle buttons.
2021-02-19 10:10:09 +01:00
Rafał Dzięgiel
7680b85ea9 Reveal controls only with touch or pen 2021-02-18 19:02:34 +01:00
Rafał Dzięgiel
834a690903 Tweak overlay revealers show/hide logic 2021-02-18 17:13:38 +01:00
Rafał Dzięgiel
12591e106f Move event controllers to widget and add them to top revealer 2021-02-17 16:31:37 +01:00
Rafał Dzięgiel
192ccb379f Limit minimal video widget size to 336x189px 2021-02-17 12:56:02 +01:00
Rafał Dzięgiel
e53f35c1c9 Bind revealers visibility instead of using a timeout 2021-02-17 12:28:49 +01:00
Rafał Dzięgiel
b012ac4c8f Fix typos 2021-02-17 12:28:49 +01:00
Rafał Dzięgiel
e79ce58b26 Rename "fullscreenMode" boolean to "isFullscreenMode" 2021-02-17 12:28:45 +01:00
Rafał Dzięgiel
887f189b60 Save window size only when windowed and not in floating mode 2021-02-17 12:20:44 +01:00
Rafał Dzięgiel
c908305be0 Update window title with video title
Clapper no longer has a title bar to show the media title during playback. Update window title so the video title is also shown on "Activities" view in addition to fullscreen top overlay.
2021-02-16 15:35:10 +01:00
Rafał Dzięgiel
435264cbec Start DBus proxy asynchronously 2021-02-16 15:35:10 +01:00
Rafał Dzięgiel
2347ff52bf Add option to show floating video on all workspaces
Option to stick the floating mode window to all workspaces. Disabled by default. Can be enabled in player preferences.
2021-02-16 15:33:57 +01:00
Rafał Dzięgiel
530f60bce9 Replace GTK headerbar with custom implementation
This avoids D&D controllers clash and allows to freely customize how maximize, minimize and close buttons work (differently for e.g. web application) and where are they placed
2021-02-16 15:23:58 +01:00
Rafał Dzięgiel
6448012edd Auto set floating mode window to be always above 2021-02-14 21:35:16 +01:00
Rafał Dzięgiel
baa5053446 Reset hide controls timer when clicking corresponding button 2021-02-14 14:16:59 +01:00
Rafał Dzięgiel
91703cf7cf Hide both cursor and overlays with a single timer
Simplify hide controls logic code by using single timer to hide both cursor and video overlays at once
2021-02-14 14:07:38 +01:00
Rafał Dzięgiel
8064bab6a2 Remove old floating mode leftovers
Clapper has now much simpler floating mode. This overcomplicated code is not needed anymore.
2021-02-13 20:19:08 +01:00
Rafał Dzięgiel
892e8b55f3 Change floating mode icon
Floating mode now works entirely different then before (only controls gets hidden/revealed with animation). Change the used icon to better match this new behaviour.
2021-02-13 18:57:30 +01:00
Rafał Dzięgiel
662517163b Reduce amount of logic in controls unreveal tick 2021-02-13 18:20:17 +01:00
Rafał Dzięgiel
1d16d3e2ac Add OSD headerbar and transition to floating mode 2021-02-13 17:19:03 +01:00
Rafał Dzięgiel
bb8ae47a66 Enforce rounded corners only on Adwaita theme
Adwaita does not have rounded corners yet, but will have soon. Enforce rounded corners in the app only for Adwaita to avoid bumping min required GTK version.
2021-02-12 12:19:43 +01:00
Rafał Dzięgiel
46e8bef7b8 Use separate CSS class for TV mode 2021-02-12 11:49:34 +01:00
Rafał Dzięgiel
a597de5481 Swipe when fullscreen to seek or adjust volume 2021-02-10 23:11:46 +01:00
Rafał Dzięgiel
68faeca918 API: Disallow pause on very short streams (< 1 sec)
Fixes crash when trying to pause on DVD navigation
2021-02-10 17:03:11 +01:00
Rafał Dzięgiel
821c7f6537 Make hitting "Enter" resume playback position when asked 2021-02-10 12:31:29 +01:00
Rafał Dzięgiel
57a480389f Show GJS version in about dialog 2021-02-10 12:24:10 +01:00
Rafał Dzięgiel
3b7beac075 Major theme changes were done in GTK 4.0.2, not GTK 4.1 2021-02-09 20:49:07 +01:00
Rafał Dzięgiel
894384483b Merge pull request #41 from Rafostar/pinephone
Fix mobile devices transitions and detection
2021-02-09 18:52:28 +01:00
Rafał Dzięgiel
1ee0db1cbc Also do not save resume info for very long titles (random URIs) 2021-02-09 17:19:42 +01:00
Rafał Dzięgiel
1f0979d217 Update TODO.md 2021-02-09 13:52:52 +01:00
Rafał Dzięgiel
662a0ccd67 Flatpak: fix gst-plugins-good manifest 2021-02-09 13:21:11 +01:00
Rafał Dzięgiel
ddbf4d40e6 Merge pull request #40 from Rafostar/resume-playback
Resume playback
2021-02-09 12:49:32 +01:00
Rafał Dzięgiel
d5ab23d5c1 Reduce rounded corners radius 2021-02-09 12:45:22 +01:00
Rafał Dzięgiel
23ef3bb85f Optimize sliders for GTK 4.1 2021-02-09 12:40:11 +01:00
Rafał Dzięgiel
b472c23bf5 Fix volume scale border not turning red when overamp 2021-02-08 22:29:00 +01:00
Rafał Dzięgiel
d1f32955b8 Do not save resume info under certain conditions
Do not save when video is short, just started or almost finished
2021-02-08 22:16:49 +01:00
Rafał Dzięgiel
17f73bb222 Add resume last unfinished video setting to prefs 2021-02-08 21:53:22 +01:00
Rafał Dzięgiel
d952f37b0e Prevent saving unfinished video info when autoclosing 2021-02-08 21:30:52 +01:00
Rafał Dzięgiel
dfbb8b8d70 Ask to resume last unfinished video 2021-02-08 21:16:28 +01:00
Rafał Dzięgiel
15eeea2872 Save resume info of last unfinished video 2021-02-08 21:16:13 +01:00
Rafał Dzięgiel
84232f3c12 Prepare resume playback dialog 2021-02-08 19:22:27 +01:00
Rafał Dzięgiel
c2808e7d9a Update position slider right after seek is done 2021-02-08 18:50:29 +01:00
Rafał Dzięgiel
5dbcb53385 Lower the priority of showing chapter popover 2021-02-08 17:42:02 +01:00
Rafostar
65f1e8e60e Observe surface width instead of video widget 2021-02-07 21:47:25 +01:00
Rafostar
8a5702f296 Detect mobile monitor based on application-pixels 2021-02-07 21:20:14 +01:00
Rafostar
65b4df13a8 Install gstclapper libs to app named subdirectory 2021-02-07 12:35:41 +01:00
Rafał Dzięgiel
4debed92fe Do not restore window size if it exceeds screen size #38 2021-02-06 23:13:29 +01:00
Rafał Dzięgiel
6b6777ffba Remove info about Ubuntu package from README.md
We cannot build Ubuntu deb package currently due to missing gtk4-dev files in Ubuntu repos.
2021-02-06 16:25:28 +01:00
Rafostar
214e2f1d7f Update debian build files 2021-02-06 15:33:00 +01:00
Rafał Dzięgiel
607d414968 Update README.md 2021-02-05 22:11:28 +01:00
Rafał Dzięgiel
a6b2b9dd0a Flatpak: remove patches that are now part of the app 2021-02-05 20:01:09 +01:00
Rafał Dzięgiel
8ca73fd56b Update README.md
We now do normal packages. Remove all info saying that only Flatpak works or some additional compiling is required.
2021-02-05 19:27:27 +01:00
Rafał Dzięgiel
0167f0ab4e Draw black background from CSS when GL fails
When GLArea gets a GL error it leaves user with nothing, but transparent background with error text in the middle. Make it look somewhat decent by drawing black background for the not working video widget.
2021-02-05 19:15:15 +01:00
Rafał Dzięgiel
4aef4b2723 Build from git with "debugoptimized" 2021-02-05 14:38:57 +01:00
Rafał Dzięgiel
25d8cb1440 Update RPM spec file 2021-02-05 14:15:55 +01:00
Rafał Dzięgiel
c32bb269d7 GStreamer meson build script cleanup 2021-02-05 09:58:54 +01:00
Rafał Dzięgiel
1a3a1d0791 Upload .gitattributes
Exclude libs from being scanned by language stats. Otherwise project is incorrectly detected as an app written in C.
2021-02-04 22:19:20 +01:00
Rafał Dzięgiel
9b63d2e6a4 Make Arch PKGBUILD point to git master branch 2021-02-04 16:35:53 +01:00
Rafał Dzięgiel
26b5b0f1cb Update README.md 2021-02-04 16:29:18 +01:00
Rafał Dzięgiel
233c8430bc Remove OBS Arch PKG
Unify Arch PKGs into a single one distributed only on AUR
2021-02-04 16:23:45 +01:00
Rafał Dzięgiel
3bcf01efb6 Merge pull request #37 from Rafostar/gstplayer
Add custom gstreamer libs as part of the app
2021-02-04 16:09:10 +01:00
Rafał Dzięgiel
94fd477324 Merge pull request #36 from sp1ritCS/gstplayer
pkgs: arch: gstplayer update, minor refactor
2021-02-04 15:51:29 +01:00
Rafał Dzięgiel
3cd98befb1 Unify menus and put all headerbar buttons on the left 2021-02-04 15:47:14 +01:00
SpiritCS
04ce5c5018 pkgs: arch: gstplayer update, minor refactor 2021-02-03 17:59:34 +01:00
Rafał Dzięgiel
bf04af23fe Do a lock on a gtk_sink
Same object is unlocked here. Keep consistency.
2021-02-02 13:55:55 +01:00
Rafał Dzięgiel
a7d99c4f81 Use "window-close" icon for playlist current playing item button
The button next to the currently playing playlist item acts as a close window button in order to allow closing app without leaving fullscreen. It should use the theme "window-close" icon to better show what it does.
2021-01-30 22:52:31 +01:00
Rafał Dzięgiel
310ef3af95 Fix not playing URIs
In case of local files the "filename" variable holds the string that is later assigned to the filename property (no difference which is used), but when playing URIs only filename property holds the string. Passing an undefined value to the label caused an error in this case and prevented playback of URIs.
2021-01-30 22:41:27 +01:00
Rafał Dzięgiel
08cde45bad Gtk4Plugin: add drawing black fixes from Flatpak patch 2021-01-29 18:18:41 +01:00
Rafał Dzięgiel
b487d1f2c1 Gtk4Plugin: remove subtitles scaling
Causes jitter (even crashes on i965) when resizing video and honestly I think that subtitles rendered at video size look better.
2021-01-29 17:52:27 +01:00
Rafał Dzięgiel
2ce44d4e63 Combine GStreamer GTK4 plugin with API
Ship custom gtk4glsink plugin as part of API insead of normal gstreamer plugin. This avoids gstreamer plugin registry conflicts with gtk3 plugin and allows more customization.
2021-01-29 17:27:39 +01:00
Rafał Dzięgiel
4ad2b707dd Remove player config options that were changed/fixed in API 2021-01-28 19:09:53 +01:00
Rafał Dzięgiel
fcf9426892 API: remove unused seek-done signal 2021-01-28 18:26:37 +01:00
Rafał Dzięgiel
dea77cc39f API: notify about speed value reset on STOP 2021-01-28 17:39:52 +01:00
Rafał Dzięgiel
f7a24b20c6 API: remove media info updated signal
A signal telling that "something somewhere changed" that is emitted multiple times per second (when bitrate changes). Not useful at all and a disaster performance-wise.
2021-01-28 16:26:20 +01:00
Rafał Dzięgiel
f2971371e1 API: remove clapper config structure
Not useful anymore since the player does 1s interval by default and now supports changing seek mode without stopping playback (unlike config which worked only when stopped).
2021-01-28 16:26:20 +01:00
Rafał Dzięgiel
15302a4b62 API: use 1s update position interval by default 2021-01-28 16:26:20 +01:00
Rafał Dzięgiel
e731842b08 API: remove "volume-changed" signal in favor of "notify::volume"
We do not need both and notify is better here cause it allows binding volume scale value to the volume prop
2021-01-28 16:26:20 +01:00
Rafał Dzięgiel
90697d81a7 API: fix debug category init with bindings 2021-01-28 16:26:09 +01:00
Rafał Dzięgiel
bbcba3ccc6 API: disable notify on props where it is unused
Notify signal is a little problematic here as we already post a signal from player while jumping between APP and API contexts. Limit and disable it where not needed.
2021-01-28 09:10:43 +01:00
Rafał Dzięgiel
5785204c28 API: prevent "notify::caps" from being reconnected on each start 2021-01-28 08:32:49 +01:00
Rafał Dzięgiel
3abfd2a5df API: add TOC support (video chapters) 2021-01-28 00:23:01 +01:00
Rafał Dzięgiel
5cc312130d API: set seek mode without stopping playback 2021-01-28 00:23:01 +01:00
Rafał Dzięgiel
bee1889376 Port app to the new GstClapper API 2021-01-28 00:23:01 +01:00
Rafał Dzięgiel
08f86cf0cc Include "GstPlayer" lib renamed to "GstClapper" as part of the app 2021-01-28 00:22:48 +01:00
Rafał Dzięgiel
acfdb7bac4 Use different icon for removing playlist items
Make it easier to see if the button will either remove the playlist item or close the app (in case of currently playing item).
2021-01-23 09:02:06 +01:00
Rafał Dzięgiel
7eb59317f9 Close app when removing active item from playlist
Make playlist remove button act the same as close button for currently playing file. This allows using it to close the app without leaving fullscreen.
2021-01-23 09:02:06 +01:00
Rafał Dzięgiel
f993a9e16c Make elapsed popover separator creation more universal 2021-01-23 09:02:06 +01:00
Rafał Dzięgiel
a82a36c6b5 Mark active playlist item with "play" icon 2021-01-23 09:02:06 +01:00
Rafał Dzięgiel
70fcc38857 Start labels from capital letter in speed control
Better match whole UI where capital letters are used.
2021-01-23 09:02:06 +01:00
Rafał Dzięgiel
30cc8732de Style only speed separator 2021-01-23 09:02:06 +01:00
Rafał Dzięgiel
d677f88556 Update TODO.md 2021-01-23 09:01:52 +01:00
Rafał Dzięgiel
d4ebb1456f Alter playlist width with box container width 2021-01-22 13:15:27 +01:00
Rafał Dzięgiel
2b77810274 Add a custom separator above speed scale
Let users know what this scale does by having a separator with a "speed" label
2021-01-22 13:13:57 +01:00
Rafał Dzięgiel
8d33766725 Stretch fullscreen speed scale
Make it easier to set it precisely in fullscreen where everything is bigger.
2021-01-22 12:06:56 +01:00
Rafał Dzięgiel
f9c8a3ce33 Do not try to dispose non-existing window 2021-01-22 11:46:50 +01:00
Rafał Dzięgiel
20f03423f3 Make speed scale look consistent with volume scale on fullscreen 2021-01-22 11:45:43 +01:00
Rafał Dzięgiel
d8c6c61f1b Disable shadows for playlist icons in fullscreen 2021-01-22 11:20:34 +01:00
Rafał Dzięgiel
ae89199101 Avoid playlist items stealing keyboard focus 2021-01-22 11:07:00 +01:00
Rafał Dzięgiel
2e1f6203b3 Rename "appdata" to "metainfo"
The appdata name is now deprecated, according to: https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#spec-component-location
2021-01-21 20:00:17 +01:00
Rafał Dzięgiel
340cb36ecd Move "clapper_src" dir to "src"
The "clapper_src" directory name was unusual. This was done to make it work as a widget for other apps. Now that this functionality got removed it can be named simply "src" as recommended by guidelines.
2021-01-21 14:19:04 +01:00
Rafał Dzięgiel
79abc661bc Update README.md 2021-01-21 12:16:50 +01:00
Rafał Dzięgiel
e9c72d3f2e Remove workarounds for GTK 3.99.X versions
Clapper build scripts were updated to GTK 4.0.0 some time ago. Most distros either received GTK 4.0 from start or an update to it. No point in having a special workarounds to support 3.99.X versions.
2021-01-20 19:30:07 +01:00
Rafał Dzięgiel
f5fef2df5b Restore redraw button icon after fullscreen change
This was previously removed, but it looks like it is still needed for GTK4 to draw button icon at correct size after toggling fullscreen.
2021-01-20 18:33:14 +01:00
Rafostar
d36a972864 Simplify playlist drop callback
Use value passed to the callback instead of target property
2021-01-20 11:16:51 +01:00
Rafostar
994491d687 Add playback speed control
Adjustable playback speed control in the form of a slider with a range from 0.01x to 2x.

Closes #33
2021-01-19 16:42:02 +01:00
Rafostar
3ba21d42ec Add playlist widget to elapsed time button popover 2021-01-19 16:41:49 +01:00
Rafostar
fca7966ece Remove app usage as a pre-made widget
This seemed like a good idea when the app still used GTK3, but GTK4 already has a built-in video widget. Maintaning this single functionality would be hard and I cannot promise a stable API anyway. The app main and only purpose will be a video player from now on.
2021-01-18 20:35:32 +01:00
Rafostar
4c0a0da18f Fix chapter popover position not moving for nearby chapters 2021-01-13 19:50:05 +01:00
Rafostar
c0e0592842 Note that video chapters feature is done 2021-01-13 19:19:39 +01:00
Rafostar
d831113925 Fix app close when pressing "Q" during position drag 2021-01-13 19:10:12 +01:00
Rafostar
5d0876bbf7 Do not do fast seeks when seeking to chapter
Fast seeks are always a little off from requested time. When seeking to chapter position, do it by using a normal seek and restore user selected fast seeks afterwards.
2021-01-13 18:49:10 +01:00
Rafostar
df4678d930 Show chapter in popover when dragging position scale 2021-01-13 17:55:22 +01:00
Rafostar
fe7a899aab Add event controllers to top revealer 2021-01-12 23:15:21 +01:00
Rafostar
83bec8e834 Mark video chapters on progress bar 2021-01-12 18:26:28 +01:00
Rafostar
b71aa0a84a Flatpak: add TOC support to GstPlayer 2021-01-12 13:32:10 +01:00
Rafostar
ac065e0b6b Flatpak: increase max matroska block size limit
This limit should be probably removed completely, but I am increasing it for the time being to avoid problems with detecting attached subtitles in matroska files.
2021-01-10 23:10:06 +01:00
Rafostar
64a31718c0 Do not set progress bar top margin in floating mode 2021-01-10 22:09:13 +01:00
Rafostar
f5e6395409 Flatpak: fix parsing of matroska attachments mimetypes 2021-01-10 21:12:45 +01:00
Rafostar
688f092406 Flatpak: fix matroska attachments detection 2021-01-10 15:56:23 +01:00
Rafał Dzięgiel
025a199f6a Update README.md 2021-01-08 23:05:33 +01:00
Rafostar
6829e8fd59 Update TODO list 2021-01-08 22:34:39 +01:00
Rafostar
cff65a989d Revert "Remove unnecessary position scale margin"
This reverts commit 1c82b2288a.

The margin turns out to be necessary for uneven scaling on
some displays resolutions.
2021-01-08 21:45:37 +01:00
Rafostar
f0dbeca5b6 Also move app window to top on file drop 2021-01-08 21:36:40 +01:00
Rafostar
59555c103b Open file(s) by Drag & Drop 2021-01-08 18:07:24 +01:00
Rafostar
2cbabe2887 Do not try to uninhibit when app is closing 2021-01-05 23:42:23 +01:00
Rafostar
234a44a34a Use ARGV from main() instead of importing system utils 2021-01-05 22:49:54 +01:00
Rafostar
a0ad8bf70f Do not return inside player init 2021-01-05 22:48:34 +01:00
Rafostar
8ef1bd662c Fix wrong sink var name
When sink holding variable was renamed to gtk4glsink, I missed this one line.
2021-01-05 22:18:48 +01:00
Rafostar
a9d4555661 Remove fullscreen-changed signal
GTK since 4.0 has fullscreened property that can be used as both a binding and signal with notify. No need to keep the fullscreen-changed signal as part of the app.
2021-01-05 20:47:57 +01:00
Rafostar
3452990c28 Use "const" where possible
Increase readability by using "const" for identifiers that will not be reassigned
2021-01-05 20:13:53 +01:00
Rafostar
f6601766f1 Fix crash on undetected codec
Player StreamInfo might return a null if codec is undetermined
2021-01-04 22:31:25 +01:00
Rafostar
d6ef29c17e Do not hold gtkglsink as a prop
It was remembered only to later access its ignore_textures property, but it is also available on the widget itself, so use that instead
2021-01-04 22:18:20 +01:00
Rafostar
16f26d3207 Move window to top when new file is opened 2020-12-27 23:03:50 +01:00
Rafostar
92cf34c682 Flatpak: Remove GLib build
GNOME runtime now includes a recent stable GLib, so no need to build it ourselves anymore.
2020-12-27 23:03:50 +01:00
Rafostar
732e3675e8 Use custom scripts for logging debug messages
Default "GLib.log_structured" method is painfully slow and time provided by it is not very accurate. It also slows down program execution even when G_MESSAGES_DEBUG env is not set. Use custom debug scripts for faster and more accurate messages logging instead.
2020-12-27 23:03:50 +01:00
Rafostar
b85edbbe8f Remove gstVersionCheck
Leftover from GTK3 version of the app. Since "gtk4glsink" is not available in any GStreamer release yet, no point in checking the version.
2020-12-27 23:03:50 +01:00
Rafostar
117a372189 Pass GioFiles from FileChooser instead of URIs
Otherwise they are converted back to GioFile to check their existance and back again to URI which is unefficient. This change avoids doing that.
2020-12-24 15:08:01 +01:00
Rafostar
a096c43b97 Flatpak: allow access to user "Videos" directory
This is needed to fix loading playlist from file. With that playlists will be limited to videos inside "Videos" directory in Flatpak version (with default permissions) which is still better than no playlists functionality. This is a common thing to do for a Flatpak video player.
2020-12-24 12:41:00 +01:00
Rafostar
094de19018 Remove "new-window" functionality
I were never able to get setifactionary results with this because:
* In GTK apps new window is created from the same process
* OpenGL is single-threaded so performance per window is halfed
* GTK4 has problems with rendeing using multiple contexts resulting in some frames being upside down

So for the time being I am removing a non-working option. There is a chance
that it will be fixed and added in future, but for now lets not
advertise a functionality that does not work.
2020-12-24 12:18:17 +01:00
Rafostar
6afbbc767a Open new file in the same window. Closes #31 2020-12-24 00:23:49 +01:00
Rafostar
f2d8d8ad4f Uninhibit screen when video is not playing
This functionality was broken before GTK 4.0.0, so it needs a minimal required GTK version bump
2020-12-22 23:21:49 +01:00
Rafostar
10e04a8eba Flatpak: fix distorted gstreamer-vaapi colors with GLX on AMD #10 2020-12-22 15:17:47 +01:00
Rafostar
42774f84e4 Update media info on idle after playback starts. Fixes #32 2020-12-21 19:37:58 +01:00
Rafostar
c125df777f Use GTK4 version of update-icon-cache
Even if GTK3 is preinstalled on GNOME, app should use GTK4 version of "update-icon-cache" binary which is a proper thing to do.
2020-12-20 19:25:50 +01:00
Rafostar
b97967e374 RPM: Include additional app binaries 2020-12-20 18:30:51 +01:00
Rafostar
55ae63dad1 Flatpak: update GTK to 4.0
GTK 4.0 was released and now its latest git includes "fullscreen" and "flat" buttons changes I requested. Lets update our app to it :-)
2020-12-17 20:08:39 +01:00
Rafostar
49b3296527 Use simply "Clapper" name for the remote app
The remote app name should match the name of the main app, otherwise different name is displayed in the headerbar and its prefs window
2020-12-17 20:03:01 +01:00
Rafostar
1c93506e79 Add toggle play button to remote app
A single toggle play button for now. Meant for testing the remote communication/delays over local network.
2020-12-17 14:59:31 +01:00
Rafostar
0a1657bbcb Mention thanks to supporters in Readme 2020-12-17 14:55:59 +01:00
Rafostar
c1aae76d6e Customize web app port 2020-12-16 21:15:41 +01:00
Rafostar
84762de76a Add Clapper deamon subprocess
Daemon is responsible for starting and later watching over spawned "broadwayd" and "remote" app needed for remote playback control. We cannot use systemd n Flatpak, so we make do with running optional background subprocesses.
2020-12-16 19:54:30 +01:00
Rafostar
254d1aa9db Make remote app binary name consistent with app ID 2020-12-16 15:33:39 +01:00
Rafostar
57ceb17100 Use proper ID for remote app 2020-12-16 14:42:40 +01:00
Rafostar
04f1d2397f Merge pull request #29 from Rafostar/remote-controller
Control player remotely
2020-12-16 10:55:32 +01:00
Rafostar
b6c947efa6 Fix custom CSS loading for remote app 2020-12-15 23:26:24 +01:00
Rafostar
234451f62a Move defined play flags to prefs
They are used only in prefs and it allows starting prefs in web app.
2020-12-15 22:49:06 +01:00
Rafostar
a056fac1c1 Add logic responsible for starting web app 2020-12-15 22:35:14 +01:00
Rafostar
a1e95dc012 Close remote app on error or disconnect 2020-12-15 19:03:58 +01:00
Rafostar
dde35270ff Consistent source filenames 2020-12-15 18:27:18 +01:00
Rafostar
5231a1f225 Add initial WebSocket client app 2020-12-15 18:20:48 +01:00
Rafostar
8564cc9617 Move WebSocket message parsing to another file
Allows reusing the same code for the client app
2020-12-15 18:19:24 +01:00
Rafostar
4c6e5607fb Check if player has widget before trying to focus it 2020-12-15 18:16:59 +01:00
Rafostar
7431f58034 Prefer "set_playlist" over "set_media" method 2020-12-15 18:15:40 +01:00
Rafostar
6d4cd494fe Customize web server listening port 2020-12-15 14:16:31 +01:00
Rafostar
ca6322339f Do not forget port after web server is stopped 2020-12-15 14:05:48 +01:00
Rafostar
b4e52d654b Pass WebSocket data without additional signal connection 2020-12-15 12:36:06 +01:00
Rafostar
2b62900227 Merge pull request #28 from Rafostar/broadway
Host web application with Broadway backend
2020-12-15 12:01:38 +01:00
Rafostar
b756c15e46 Fix non-updated closing state 2020-12-15 11:59:05 +01:00
Rafostar
062a307613 Add stop method for web app 2020-12-15 11:51:25 +01:00
Rafostar
1c82b2288a Remove unnecessary position scale margin 2020-12-14 23:14:16 +01:00
Rafostar
24a105fbe4 Do not drop old GTK4 support
Recent GTK4 git is way too buggy. We cannot update the GTK version above 3.99.4 yet. So add compatibility with newer versions without dropping support for older ones.
2020-12-14 21:30:00 +01:00
Rafostar
f65bc84c89 Merge pull request #27 from Rafostar/gui-improvements
Fullscreen GUI improvements
2020-12-14 16:40:37 +01:00
Rafostar
39e4e54ad8 Apply icon size to icon and not whole button 2020-12-14 15:46:40 +01:00
Rafostar
bfc318ae70 Reduce controls start/end margin 2020-12-14 15:46:07 +01:00
Rafostar
3936e58ed6 Reduce fullscreen button top margin a little 2020-12-14 15:43:48 +01:00
Rafostar
67389ee295 Fix for negative sizes and separate popovers override 2020-12-14 12:10:02 +01:00
Rafostar
ef12074559 Tweak fullscreen GUI theme
Notable changes:
* Smaller media title font (fits more characters on screen)
* Constant top timer numbers size (time no longer moves left/right when hour changes)
* Reduced top shadow overlay height
* Smaller buttons on bottom controls panel (their icon size remains the same)
* Reduced bottom panel and progress bar height
* Few additional margins and font sizes tweaks
2020-12-14 11:30:19 +01:00
Rafostar
ea67e1e620 Flatpak: compile GTK4 with broadway backend 2020-12-14 11:19:12 +01:00
Rafostar
018a750fbc Add web app for broadway backend 2020-12-12 21:56:35 +01:00
Rafostar
660b5c6c48 Use underscore in WebSocket API 2020-12-12 20:10:06 +01:00
Rafostar
ea7b712b2e Send player state via WebSockets 2020-12-12 19:37:07 +01:00
Rafostar
7a039af798 Allow changing web server port during playback 2020-12-12 00:16:39 +01:00
Rafostar
104db83a1c Clean websocket signal properly 2020-12-12 00:13:02 +01:00
Rafostar
d5d5aa9bac Integrate basic web server functionality into player 2020-12-11 23:38:49 +01:00
Rafostar
26f8b6994e Add WebSocket server 2020-12-11 22:06:00 +01:00
Rafostar
4875a31be4 Add initial ClapperRemote app 2020-12-11 15:38:25 +01:00
Rafostar
6315669933 Split app source file into two
This allows creating different app from the same source code.
2020-12-11 15:32:05 +01:00
Rafostar
083445a830 Split header bar source file into two
This allows creating another headerbar with different functionality from the same source code.
2020-12-11 15:22:35 +01:00
Rafostar
62573d3a88 Move main.js to source files dir 2020-12-11 14:55:50 +01:00
Rafostar
0d54a751bd Add request for native audio formats option 2020-12-10 17:15:22 +01:00
Rafostar
73b803abdb Compatibility with latest GTK4 git 2020-12-10 11:51:55 +01:00
Rafostar
8dfede27ac Add progressive video download option
Buffer download whole network video during playback to allow fast seeking for online media. Can be disabled in prefs (enabled by default).
2020-12-08 20:31:45 +01:00
Rafostar
6ea210ff12 Minor prefs theme improvements 2020-12-08 17:08:55 +01:00
Rafostar
fea1968907 Add "Adaptive UI" demo to features in Readme 2020-12-07 20:58:19 +01:00
Rafostar
b134fd25c8 Move theme settings to "Tweaks" prefs tab
Altering default theme is more of a tweak then a general setting
2020-12-07 20:27:21 +01:00
Rafostar
6949a6e9ef Disable controls focus when not in fullscreen
This should keep focus on video and make seeking from keyboard always work.
2020-12-07 17:29:34 +01:00
Rafostar
c80f34f4ab Fix compatibility with dark themes. Fixes #23 2020-12-07 15:25:10 +01:00
Rafostar
cf26486476 Flatpak: Add GTK4 popover unrealize patch
This is a temporary workaround I came up with for app performance drop on Wayland after any popover is opened. We are waiting for a proper fix from GTK4 devs. Until then, this is still much better that nothing.
2020-12-06 23:12:09 +01:00
Rafostar
64bf1dc172 Apply rotate animation to the icon, not whole button 2020-12-04 09:55:26 +01:00
Rafostar
a2ee14e74f Set revealer animation fill mode to "forwards" 2020-12-03 16:53:22 +01:00
Rafostar
150fdb7cbb Do not show tracks revealer when there are no tracks 2020-12-03 11:59:59 +01:00
Rafostar
c3d60a600e Wait for stop after playback instead of forcing it 2020-12-03 11:20:42 +01:00
Rafostar
7a66da1fed Add option to close player after playback 2020-12-03 11:04:37 +01:00
Rafostar
44e04d7e60 Upload mobile UI presentation video 2020-12-02 16:04:17 +01:00
Rafostar
333b9d8224 Mobile friendly interface transitions #14 2020-12-02 10:59:02 +01:00
Rafostar
4cb743b931 Performance: do not draw header bar bottom border
It is not even noticable and reduces performance by having more pixels to redraw every frame.
2020-12-02 10:56:19 +01:00
Rafostar
6cc07c4e98 Flatpak: update uchardet recipe 2020-12-01 10:02:36 +01:00
Rafostar
def5bc5d96 Change volume scale color when over-amplified 2020-12-01 09:43:36 +01:00
Rafostar
f4da4dec71 Do not keep initial elapsed time
It is not used anymore later, so no need to keep it.
2020-11-30 23:05:56 +01:00
Rafostar
f08d40c1ff Small cleanup 2020-11-30 23:05:33 +01:00
Rafostar
f7f9959c14 Temporarly take a ref on player 2020-11-30 22:18:02 +01:00
Rafostar
58afaa2c76 Apply custom initial volume on realize 2020-11-30 11:26:38 +01:00
Rafostar
5206dc543d Properly store and restore last volume value on startup
We cannot depend on the value saved by GStreamer, cause it is shared with all GStreamer based apps. Lets save the last value to gsettings instead to make sure this is the volume we used with this app. With this change we can also see the right volume on startup before media file is loaded (previously it was shown always as muted).
2020-11-30 11:16:21 +01:00
Rafostar
af6814bace Change open local label
Option can now also open multiple files, so we simply skip the "File" part to make it shorter.
2020-11-30 11:11:08 +01:00
Rafostar
e7ad0143a5 Use cubic scale for volume. Fixes #21
Volume sliders should usually adjust volume using cubic scale. This also changes max volume to 150% which should be louder than previous value anyway.
2020-11-30 09:26:27 +01:00
Rafostar
bc5aa45a8f Fix player volume comparison 2020-11-26 13:02:31 +01:00
Rafostar
d630717b24 Flatpak: autodetect subtitle text encoding
Manually specifying text encoding is just wrong.
Especially for people who have no idea what text encoding they use (or what it is).
Lets try to be a little more user friendly and autodetect the encoding of each file.

The detection will be done inside GStreamer when first text buffer is received,
so another (but this time optional) patch is added, but who cares :-)
2020-11-25 16:20:51 +01:00
Rafostar
6a34fc51bc Merge pull request #20 from sp1ritCS/master
downgraded arch pkgbuild to e7e9b9c07d
2020-11-25 11:00:09 +01:00
Rafostar
2ed3e1dce6 Add some missing info to Readme #19
Add some missing information about why Flatpak right now is recommended, that otherwise patching is required and why Wayland is recommended. Hopefully with this, I will not have to keep repeating those to everyone on each day :-)
2020-11-25 10:58:18 +01:00
sp1rit
1bd39f646f downgraded arch pkgbuild to e7e9b9c07d 2020-11-24 20:52:19 +01:00
Rafostar
9ad1a11452 Customize external subtitles font 2020-11-24 17:54:53 +01:00
Rafostar
3fcd612e6e Support loading external subtitles and multiple videos 2020-11-24 11:12:43 +01:00
Rafostar
ab39da1975 Readme: tell people that using GJS here is fine. 2020-11-24 10:35:53 +01:00
Rafostar
2cd946c6c0 Convert Flatpak manifest to JSON format #12 2020-11-23 14:08:59 +01:00
Rafostar
4c2cca855e Update screenshots 2020-11-22 20:03:13 +01:00
Rafostar
24de7ee8c1 Remove "Playback" tab from prefs
Move items under "Playback" tab to "Player" tab to reduce number of top bar tabs in prefs. Also temporarly disable subtitles settings due to lack of external subtitles support.
2020-11-22 19:37:18 +01:00
Rafostar
66162349ac Use dark theme by default. Closes #13 2020-11-21 15:56:03 +01:00
Rafostar
f5e5071937 Support setting sliders brighter #13
When dark theme is used, sliders (especially progress on fullscreen) tend to look a little too dark (as if they were disabled). To overcome this, add an option to force them to be 20% brighter.
2020-11-21 15:20:09 +01:00
Rafostar
c221f7cdb6 Do not show hours when duration is shorter #14 2020-11-20 22:41:33 +01:00
Rafostar
7ccd6ad424 Add audio and subtitle offset settings to prefs 2020-11-20 21:19:23 +01:00
Rafostar
ac27c364f3 Add dark theme support #13 2020-11-20 17:37:41 +01:00
Rafostar
82c30c6c2d Flatpak: add fix ass subtitles smooth scaling patch
Fix for ass subtitles jittering animations. More info in my GStreamer MR:
https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1822
2020-11-19 18:50:22 +01:00
Rafostar
1947140def Toggle fullscreen with "f" key 2020-11-18 17:05:12 +01:00
Rafostar
24702c55d3 Update README.md 2020-11-18 10:39:51 +01:00
Rafostar
e35968d583 Always show preroll frame
This fixes preview while player is paused
2020-11-17 19:12:25 +01:00
Rafostar
796863a692 Point to GitHub pages from about dialog 2020-11-17 15:30:28 +01:00
Rafostar
856f000799 Update screenshots 2020-11-17 15:29:01 +01:00
Rafostar
652e4eecf2 Update README.md 2020-11-17 15:06:53 +01:00
Rafostar
6788f234aa Flatpak: add more black rendering improvements to patch 2020-11-17 13:20:03 +01:00
Rafostar
7159bf3d5a Flatpak: add vah264dec seeking fix patch 2020-11-16 09:27:40 +01:00
Rafostar
910a289b6d Let floating window have shadow if shadows are enabled
If normal window would have shadow and floting did not, then a size mismatch would occur during transition. Besides it allows to notice if floating window is focused and respects user theme.
2020-11-13 23:00:06 +01:00
Rafostar
373714f161 Performance: do not try to render controls box when empty 2020-11-13 20:12:26 +01:00
Rafostar
f660d900ba Performance: add option to disable window shadows
Rendering window shadows in GTK4 doubles GPU usage. This commit adds an option to disable them for performance gain (useful on low-end devices).
2020-11-13 19:26:49 +01:00
Rafostar
4413fdb8a2 Tweak top revealer size and opacity a little 2020-11-13 13:16:12 +01:00
Rafostar
8e48da2a9f Performance: do not render window background and shadows when fullscreen 2020-11-12 22:51:14 +01:00
Rafostar
63236a8097 Performance: render video and black background in single GL pass 2020-11-12 19:20:03 +01:00
Rafostar
0143f23487 Update TODO.md 2020-11-10 23:42:56 +01:00
Rafostar
7226a59cea Set (un)inhibit screen earlier 2020-11-10 23:16:45 +01:00
Rafostar
e7937162e7 Fix file chooser not being freed from memory 2020-11-10 20:28:57 +01:00
Rafostar
f644710762 Set popover parent only once and unset on app close 2020-11-10 18:11:59 +01:00
Rafostar
0c307bc606 Ignore state change signals during app exit 2020-11-09 21:45:59 +01:00
Rafostar
314b66b7fd Disconnect close-request signal before exit 2020-11-09 21:35:17 +01:00
Rafostar
fa131c0356 flatpak: add glib-networking lib 2020-11-09 20:50:14 +01:00
Rafostar
7577c74a77 Enable ring buffer 2020-11-09 20:49:58 +01:00
Rafostar
010fcf6dcf Update README.md 2020-11-09 20:12:07 +01:00
Rafostar
513904bd6d Make prefs tabs look like the ones in gnome-settings 2020-11-09 19:30:45 +01:00
Rafostar
e6f683bb96 Workaround dialogs double unref 2020-11-09 17:57:31 +01:00
Rafostar
8bb6ce04ef Get initial dimensions only once 2020-11-09 17:56:38 +01:00
Rafostar
f8c47e611a flatpak: update required GTK4 libs 2020-11-09 14:41:37 +01:00
Rafostar
1bb1fc76e1 Update flatpak GTK4 to latest git master 2020-11-09 13:13:09 +01:00
Rafostar
8351066a8b Add changing seek mode during playback patch 2020-11-09 11:42:19 +01:00
Rafostar
dd3ba11c0e Set min GStreamer ver warning to 1.18.x 2020-11-09 11:40:48 +01:00
Rafostar
c2bd6bc894 Set min floating window size 2020-11-09 11:40:01 +01:00
Rafostar
9be93c66f1 Improve obtaining initial player dragging coords 2020-11-06 20:33:14 +01:00
Rafostar
868c39f1cf Store and restore floating window size 2020-11-06 19:43:38 +01:00
Rafostar
eb1a495907 Reduce number of source files (cleanup) 2020-11-06 17:04:54 +01:00
Rafostar
42c208d1df Make file chooser and open URI dialogs modal 2020-11-05 20:19:26 +01:00
Rafostar
da21c2fafc Add fast seeking support as a patch 2020-11-05 16:13:57 +01:00
Rafostar
81bdcf6244 Enable "Fast Seeking" option
Since GstPlayer pipeline ref count is now fixed by a patch, fast seeking option can be enabled. In my tests this seeking method is over 10x faster then normal seeking on some files, but the video time you end up with might differ up to few seconds from the value requested.
2020-11-04 22:57:05 +01:00
Rafostar
2b11f68723 Add new patch for GstPlayer 2020-11-04 22:20:42 +01:00
Rafostar
de7a850cc2 Create gio settings only once 2020-11-04 15:05:16 +01:00
Rafostar
8296f40382 Allow adjusting volume before loading file 2020-11-04 12:37:42 +01:00
Rafostar
11468e2774 Add unexported by GI Gst.PlayFlags 2020-11-04 12:37:36 +01:00
Rafostar
23b39e5f3b Add open URI dialog 2020-11-03 20:56:21 +01:00
Rafostar
dbb25ce474 Add min dimensions in widget example 2020-11-03 19:24:57 +01:00
Rafostar
665f5aa1d6 Update screenshots 2020-11-03 18:18:54 +01:00
Rafostar
ff58713426 Add "Floating Window Mode"
A simple borderless window floating on desktop. Window can be resized and moved by dragging. It also has some minimalistic controls showing on top of the video when cursor is hovering over it.\n\n This was a feature originally requested by @zahid1905.
2020-11-03 17:40:19 +01:00
Rafostar
ba54a36058 Keep a ref to main context
Might help with GJS toggling down object bug. Needs some testing.
2020-11-03 17:18:37 +01:00
Rafostar
02afe2b06d Update appdata 2020-11-02 21:40:15 +01:00
Rafostar
d17c30909a Always build flatpak from latest commit 2020-11-02 11:58:59 +01:00
Rafostar
866e8325e6 Do not show "Ends at" text when player is stopped 2020-11-02 09:11:55 +01:00
Rafostar
2dfeb160ac Add AppStream metadata 2020-10-31 17:43:20 +01:00
Rafostar
157d2ac8c2 Set theme jekyll-theme-cayman 2020-10-31 16:43:27 +01:00
Rafostar
a019ef90ca Remember and restore last window dimensions on launch 2020-10-31 09:04:41 +01:00
Rafostar
36145adf1a Always start with black image 2020-10-31 08:21:18 +01:00
Rafostar
bcd73448de Disable "vah264dec" by default
The "vah264dec" plugin is a new and much better VAAPI implementation then default one in gstreamer-vaapi. Unfortunately as of now it works correctly only on Wayland and causes crashes on XOrg. Wayland users can easily enable it in video player preferences advanced tab settings to get improved performance and lower CPU usage.
2020-10-31 08:07:38 +01:00
Rafostar
19e1a20bf7 Start fullscreen playback after toplevel state is changed 2020-10-30 22:51:30 +01:00
Rafostar
2260c09f2e Remove Intel VAAPI from flatpak spec file
Already comes with GNOME runtime, so no need to specify it here 2nd time
2020-10-30 22:23:49 +01:00
Rafostar
f0a54f97e1 Add all missing deps for building flatpak
With this flatpak is now possible to build and working
2020-10-29 18:58:02 +01:00
Rafostar
9d9759991b Update flatpak sources 2020-10-26 22:41:22 +01:00
Rafostar
ac06e84851 Open files via native file chooser 2020-10-26 21:25:13 +01:00
Rafostar
556809c1f4 Add GStreamer plugin ranking to preferences 2020-10-26 16:45:37 +01:00
Rafostar
31f208006f Add startup fullscreen and volume preferences 2020-10-26 11:07:01 +01:00
Rafostar
9354042379 Add preferences dialog
Allows customizing various settings. For now it includes player seeking times and mode customization. More options will be added in the future.
2020-10-25 10:14:14 +01:00
Rafostar
576440faff Fix update media end time 2020-10-23 10:26:11 +02:00
Rafostar
e7a39d6af8 Upload keyboard test script 2020-10-22 11:44:14 +02:00
Rafostar
cc4757aef5 Do not hide controls while navigating panel 2020-10-21 13:19:38 +02:00
Rafostar
0b1864378b Add Clapper usage as GTK widget 2020-10-21 12:24:42 +02:00
Rafostar
0291377389 Major code cleanup 2020-10-20 22:30:15 +02:00
Rafostar
4dea498f37 Improve position scale alignment in fullscreen 2020-10-19 13:27:41 +02:00
Rafostar
82840d5852 Start loading media after window is shown 2020-10-19 13:26:15 +02:00
Rafostar
b383a89107 Get rid of Noto Sans in CSS
Cantarell is the default font of GNOME. We do not need to specify "Noto Sans" as fallback.
2020-10-17 19:51:23 +02:00
Rafostar
0f56c5967b Update packages
Changes:
* Require the same GStreamer 1.18+ for all plugins
* Remove gst-plugins-gtk4 dependency where build is unavailable
2020-10-17 17:35:34 +02:00
Rafostar
5ea36804b7 Update README.md 2020-10-17 12:19:54 +02:00
Rafostar
b2e052d7a4 Do not show cursor on small movement 2020-10-16 22:11:54 +02:00
Rafostar
c9d9927bb1 Remove unused mainloop 2020-10-16 21:45:32 +02:00
Rafostar
7f1264ae27 Add fast seeking (disabled by default)
The fast seeking option. It seeks to the next keyframe which reduces seeking delay over 10 times, but makes the seeking very inaccurate as a side effect (usually up to few seconds from requested position).
2020-10-16 20:00:22 +02:00
Rafostar
1119e3e792 Fix GstPlayer error logging 2020-10-16 17:03:51 +02:00
Rafostar
8297be45ba Add player seek_done property 2020-10-16 13:24:18 +02:00
Rafostar
eafc65d15d Go back to beginning after playback ends 2020-10-16 12:13:00 +02:00
Rafostar
d0eb28b207 Remove GTK3 "widget.show()" leftovers 2020-10-16 10:59:00 +02:00
Rafostar
12c1251c9b Update video info during non-local file playback
With this player will always show current video resolution when playing fragmented media like HLS or MPD online videos
2020-10-16 00:21:43 +02:00
Rafostar
745747b604 Hide time and position scale on LIVE media 2020-10-15 22:49:37 +02:00
Rafostar
6f2ec62515 Fill position scale to the very end 2020-10-15 20:15:56 +02:00
Rafostar
04abecf511 Refresh position time on startup 2020-10-15 18:13:43 +02:00
Rafostar
fa07c4532c Fix player process not exiting after window close 2020-10-15 17:54:28 +02:00
Rafostar
57a8e6d933 Add about dialog 2020-10-15 16:21:46 +02:00
Rafostar
34d39502b9 Create FUNDING.yml 2020-10-15 10:45:57 +02:00
Rafostar
50a5a527b6 Add screenshots to Readme #5 2020-10-14 20:19:20 +02:00
Rafostar
f1d7b5d151 Upload screenshots #5 2020-10-14 20:05:16 +02:00
Rafostar
acbbfbfcb4 Merge pull request #8 from Rafostar/GTK4
We are moving to GTK4! Porting took a little longer than expected, cause I had to port GStreamer first. This change will be problematic for users of non-rolling linux distros, but its worth it. Both GTK4 and GStreamer 1.18+ have important GL changes. Clapper player takes full advantage of them.
2020-10-14 18:52:23 +02:00
Rafostar
8fb41b41b4 Update README.md 2020-10-14 18:40:23 +02:00
Rafostar
f8a4465fed Add required GTK4 and GStreamer versions to pkgs 2020-10-14 17:17:00 +02:00
Rafostar
ea8226f1d3 Restore seek on drop behavior 2020-10-14 16:45:09 +02:00
Rafostar
a20a0c8160 Grab player focus only when controls are not visible 2020-10-14 12:52:11 +02:00
Rafostar
05c9528723 Auto change focus between player and controls 2020-10-14 12:30:57 +02:00
Rafostar
d78d3c1450 Set position slider minimal fill to zero 2020-10-14 12:25:46 +02:00
Rafostar
1069f151f0 Restore automatic menu hiding 2020-10-14 10:57:43 +02:00
Rafostar
1f6a9b59d6 Restore button presses 2020-10-13 23:47:13 +02:00
Rafostar
b1ca9c15bc Restore scrolling on player 2020-10-13 22:07:22 +02:00
Rafostar
80b9eb7c97 Fix volume button scroll 2020-10-13 21:36:11 +02:00
Rafostar
3e96a13f00 Restore window dragging by drag on player 2020-10-13 20:32:59 +02:00
Rafostar
cdfafd52af Set popover button checked state 2020-10-13 20:29:14 +02:00
Rafostar
e430956752 Allow navigating over buttons via keyboard 2020-10-13 20:27:58 +02:00
Rafostar
d3e4f3bb0f Add player motion and key controllers 2020-10-12 16:25:54 +02:00
Rafostar
e2d6cc440d Tweak play/pause icons size 2020-10-07 23:41:12 +02:00
Rafostar
43a54920ef Change elapsed time into button 2020-10-07 23:10:11 +02:00
Rafostar
4c5d922d47 Fix toggle play button icon change 2020-10-07 20:22:02 +02:00
Rafostar
352eff89b7 Fix volume button icon and window key events 2020-10-07 18:18:44 +02:00
Rafostar
041b31c161 Fix enter fullscreen and popover buttons 2020-10-07 16:40:42 +02:00
Rafostar
dbdb6988a2 Fix window "fullscreen-changed" signal 2020-10-06 12:04:28 +02:00
Rafostar
bae0b805ea Initial GTK4 port
Port most of the player to GTK4. Some things are still broken or disabled due to GTK change, but will be gradually fixed.
2020-10-05 21:19:29 +02:00
Rafostar
e7e9b9c07d Use virtual functions 2020-09-23 15:14:32 +02:00
Rafostar
db8429d73f Use "Cantarell" fonts for OSD with fallback to "Noto" and "sans-serif" 2020-09-21 22:19:37 +02:00
Rafostar
1ce533259b Auto initialize Gst and change one player function name 2020-09-21 20:51:01 +02:00
Rafostar
31db48d137 Replace deprecated Gtk HBox and VBox with normal Box 2020-09-21 20:49:25 +02:00
Rafostar
f6560c11f9 Fix recent OBS for openSUSE builds errors #7 2020-09-20 21:59:04 +02:00
Rafostar
4e42e2be9e Merge pull request #7 from sp1ritCS/master
modified clapper.spec to fit openSUSE packagaging guidelines
2020-09-20 21:00:48 +02:00
Rafostar
fed36ab565 Add "brz" dependency needed for Debian OBS 2020-09-20 00:01:55 +02:00
Rafostar
483c1ba49e Add DEB packaging 2020-09-19 22:31:13 +02:00
SpiritCS
bb71784974 modified clapper.spec to fit openSUSE packagaging guidelines 2020-09-19 22:06:17 +02:00
Rafostar
a504f499c6 Add gst-plugins-good dependency 2020-09-19 21:25:23 +02:00
Rafostar
2185911fde Move OBS _service file to repo root 2020-09-19 12:47:42 +02:00
Rafostar
16087edaff Update Arch PKGBUILD 2020-09-19 12:31:27 +02:00
Rafostar
dc707630f9 Build files cleanup 2020-09-18 19:12:23 +02:00
Rafostar
eed51f0423 Build spec files fixes 2020-09-18 18:37:21 +02:00
Rafostar
80aa3b467b Update rpm spec (#6)
* Update RPM spec file

* Add required deps versions to RPM spec
2020-09-18 17:21:21 +02:00
Rafostar
21de7e7bfd Replace deprecated margin proporties 2020-09-18 13:11:24 +02:00
Rafostar
be359ab27a Smaller play sign on desktop icon 2020-09-17 22:25:44 +02:00
Rafostar
932849af92 Add desktop file, icon and "application/claps" mime type 2020-09-17 18:57:40 +02:00
Rafostar
2225aa2343 Fix playlist file relative path handling 2020-09-17 13:00:45 +02:00
Rafostar
ae766298a8 Lower CPU usage when OSD is visible 2020-09-16 18:24:31 +02:00
Rafostar
1c2a8a476e Move revealers logic to separate file 2020-09-16 13:26:30 +02:00
Rafostar
1918b30bea Cover whole video screen with top revealer
Previously top revealer was set to fixed size, which caused a noticable video tearing along the revealer edge during its animation. This commit removes fixed revealer size, which in turn casues the revealer to cover whole video screen (default behavior), thus eliminates the tearing. Since overlay now becomes the top widget, all player notify signals were reconnected to it.
2020-09-16 11:54:01 +02:00
Rafostar
73e7f1e2a0 Add top overlay with title and current hour
This adds Kodi-like semi-transparent overlay with current media title, hour and estimated time when video will end. The overlay is visible only on fullscreen mode.
2020-09-15 21:08:46 +02:00
Rafostar
779796c2c3 Fix GUI look when video track is disabled 2020-09-14 22:25:42 +02:00
Rafostar
234c49221e Enable scroll on volume button 2020-09-14 16:10:09 +02:00
Rafostar
71659491c0 Support changing rank of codecs
The used GStreamer codecs are picked using rank hierarchy. When there are 2 or more decoders available that can handle the same stream type, the one with higher rank is always picked. This commit adds a function for the codec rank manipulation that can be used for e.g. force disable/enable VAAPI. Should be a neat feature once we have a settings dialog where it can be used.
2020-09-13 20:21:46 +02:00
Rafostar
c34df72f96 Drop all player signals on destroy 2020-09-13 17:20:07 +02:00
Rafostar
5a94ea445b Consistent with Readme packages description 2020-09-13 17:17:17 +02:00
Rafostar
75d4f26b78 Add gstreamer installation info to readme 2020-09-13 15:44:14 +02:00
Rafostar
940a828c46 Merge pull request #4 from sp1ritCS/master
Add prebuild packages links in readme
2020-09-13 13:46:01 +02:00
SpiritCS
e1fceecfac added prebuild packages in readme 2020-09-13 13:08:20 +02:00
Rafostar
1860114b7c Trim playlist from whitespaces 2020-09-13 11:23:55 +02:00
Rafostar
059ee932fe Skip non-existing files in playlist 2020-09-13 11:13:04 +02:00
Rafostar
9c37002925 Update README.md 2020-09-13 10:55:57 +02:00
Rafostar
2951157956 Merge pull request #3 from sp1ritCS/master
Add package files
2020-09-13 10:28:11 +02:00
SpiritCS
404b0f1200 cleaned up comments 2020-09-13 01:29:10 +02:00
Rafostar
5e6b0b9c48 Load playlist from text file
With this change Clapper can open and load a playlist inside a text file. The text file should have a ".claps" extension and include one media file path per line (path can be either absolute, relative or even a HTTP link).
2020-09-12 22:59:10 +02:00
Rafostar
043fe9f75e Move Popover button creation to buttons.js 2020-09-12 21:10:44 +02:00
Rafostar
71c5454547 Fix invisible unfullscreen button 2020-09-12 19:28:17 +02:00
SpiritCS
cb3058dc6f added libav arch optdepend 2020-09-12 17:48:14 +02:00
SpiritCS
c2856d6146 fixed gstreamer1 on RHEL, added libav to suse builds 2020-09-12 15:17:19 +02:00
SpiritCS
c7be556e6e added all codecs from totem, only using gst-libav for now tho; added gst-vaapi, further research required 2020-09-12 14:06:08 +02:00
SpiritCS
f973f15444 fixed my vim so its on par with githubs tab policy 2020-09-12 12:41:17 +02:00
SpiritCS
d37a025500 fixed stuff @Rafostar requested 2020-09-12 12:37:05 +02:00
Spirit
4abca4bd42 fixed x86_64 dep issue 2020-09-11 23:43:54 +00:00
Spirit
2ea19aa769 added potentially missing deps 2020-09-11 20:53:58 +00:00
Rafostar
6938f01433 Add "BoxedIconButton" class 2020-09-11 21:28:00 +02:00
SpiritCS
1267614450 fixed arch build 2020-09-11 20:59:40 +02:00
Florian Singer
4116d3bbe3 Added Arch, Flatpak & RPM package files 2020-09-11 20:51:37 +02:00
Rafostar
5afe5149aa Add music visualizations 2020-09-11 20:33:06 +02:00
Rafostar
a01cc058cd Do not display video FPS when unavailable
Do not try to display video FPS inside video tracks selection popover button. The FPS value can be zero for example when viewing pictures.
2020-09-10 21:41:58 +02:00
Rafostar
1fdbf09cbd Display shorter names for all audio codecs 2020-09-10 21:32:12 +02:00
Rafostar
b446fb943e Hide track selection buttons without contents 2020-09-10 21:21:35 +02:00
Rafostar
ed5d449142 Support for multiple media files
This enables support for starting media player with more than one file path specified. When a file playback finishes, next is loaded automatically.
2020-09-10 19:53:04 +02:00
Rafostar
b8ed6b32dc Reuse old redio buttons
When a media is changed, normally one would expect to create new radio buttons with video/audio/subtitle tracks names corresponding to current video, but this is inefficient. Destroying objects just to create similiar ones again does take a long time and might lead to memory leaks. That is why a better and faster approach is to simply edit already available objects to match our expectations instead. This commit does just that for tracks radio buttons.
2020-09-10 19:50:41 +02:00
Rafostar
e9ec155e7b Move fullscreen and menu buttons to header bar
Follow other GNOME apps designs by having fullscreen button on the right side of window header bar. The control panel had too many buttons already and we still need to make some space for playlist. This way "fullscreen" button will be on top bar while windowed and "unfullscreen" button will appear on the bottom right only when player entered fullscreen mode.
2020-09-10 14:24:02 +02:00
Rafostar
557cbc11e2 Use filename as title when media info doesn't have one 2020-09-10 11:34:50 +02:00
Rafostar
3fb370e1d0 Fix not updated volume icon on startup 2020-09-10 10:41:37 +02:00
Rafostar
06914db0da Add header bar with media title and path 2020-09-10 10:26:20 +02:00
Rafostar
a9ac872c98 Do not hide controls in fullscreen while navigating it 2020-09-09 22:56:11 +02:00
Rafostar
0c5278e844 Make button popovers appear above the controls bar 2020-09-09 21:40:16 +02:00
Rafostar
ab11d52a68 Recreate volume button from scratch
Create volume button with popover instead of using GTK provided volume button.

Creating new button with only needed elements is more efficient then removing unneeded items from pre-made volume button. This should also increase performance a little when changing volume, because now we generate new icon only when a change is needed. In pre-made button icon is regenerated on each volume change.
2020-09-09 21:34:32 +02:00
Rafostar
22e8e44316 Create TODO.md
Note all collected ideas from reddit comments.
2020-09-09 10:28:47 +02:00
Spirit
b65666d4be Clean up meson warnings (#2)
Co-authored-by: Florian Singer <florian@spiritXPS.localdomain>
2020-09-09 09:26:34 +02:00
Rafostar
edcc7b71b9 Add meson build system (#1)
Initial meson build system support. We do not create .desktop file yet, but we need an option to open media files from GUI first anyway.
2020-09-08 19:55:59 +02:00
Rafostar
fd22457857 Reduce fullscreen position scale height a little bit 2020-09-08 10:31:22 +02:00
Rafostar
1c5759af88 Remove "Performace Comparison" from readme
Looks like nowadays VA-API is force disabled in Totem, in which case this comparison does not seem fair.
2020-09-08 09:45:22 +02:00
Rafostar
649ff7682c Support loading files using full or relative paths 2020-09-08 08:58:43 +02:00
Rafostar
689edd9cf3 Always start unmuted 2020-09-07 11:54:57 +02:00
Rafostar
ba37e66054 Add performace comparison to readme 2020-09-07 11:48:07 +02:00
Rafostar
a8fa4bc6de Tweak fullscreen menu appearance 2020-09-07 11:27:06 +02:00
Rafostar
7626813ff3 Update README.md 2020-09-06 14:12:19 +02:00
Rafostar
374e3cc33a Show "Unknown" when language is undetected 2020-09-06 12:44:24 +02:00
Rafostar
f5db250486 Load media after player is drawn
Loading file too early might lead to Xorg related crash. We must first make sure the player widget is fully drawn, before we start drawing video frames.
2020-09-06 12:18:37 +02:00
Rafostar
da652e1ec5 Skip setting player option when unsupported 2020-09-06 10:34:27 +02:00
Rafostar
d8d342a956 Make everything on fullscreen bigger (TV mode) 2020-09-06 10:18:53 +02:00
Rafostar
7d2edec553 Show playback time and switch to dark mode when fullscreen 2020-09-05 13:49:44 +02:00
Rafostar
e76d1c9e6e Add video, audio and subtitle track selection 2020-09-04 23:43:51 +02:00
Rafostar
24e84a397b Assign created elements to player keys 2020-09-04 23:38:29 +02:00
Rafostar
4e235a0e9b Add controls background on fullscreen 2020-09-04 10:47:05 +02:00
Rafostar
54bbcd2eb1 Make all interface buttons flat 2020-09-03 23:08:32 +02:00
Rafostar
e5e06336f3 Add slide animation for fullscreen controls 2020-09-03 21:17:43 +02:00
Rafostar
3d9bab0578 Add overlay for controls when fullscreen
When player is fullscreen playback controls are shown on top of video (at screen bottom). When windowed, controls are shown below the video instead.
2020-09-03 20:01:26 +02:00
Rafostar
2bef72fd95 Change pause icon to play on stopped video 2020-09-03 13:02:29 +02:00
Rafostar
28264da424 Prevent system from lock/suspend when video is playing 2020-09-03 12:53:24 +02:00
Rafostar
f6f2a2f4e4 Add some easy way to install
I know that this should be done using some sort of build system (like meson), but the player is still far from finished and a basic install script should be sufficient for the time being, if anyone wishes to test it.
2020-09-03 11:33:42 +02:00
Rafostar
7d2b1f1118 Add custom debug script with Gst version check 2020-09-03 10:43:07 +02:00
Rafostar
176ddf1cc2 Bind keyboard up/down arrow keys to volume 2020-09-03 10:40:58 +02:00
Rafostar
ec68db73c9 Do not update position slider during buffering 2020-09-03 07:29:02 +02:00
Rafostar
9f18ec35b2 Tweak position and volume slider values 2020-09-02 22:26:48 +02:00
Rafostar
70ec6311c0 Add seeking on slider drop and make it default behaviour
Seeking during slider drag is very CPU and HDD intensive task. We are requesting the player to keep seeking in VERY short amounts of time. This can be performed more effectively by doing a single seek after slider drop. Since this is a different behaviour then usually in media players, I am making this optional (enabled by default).
2020-09-02 18:31:22 +02:00
Rafostar
fd2ad7e596 Listen for key presses on window instead of player
This fixes a GNOME bug where sometimes key press events are not emited
2020-09-02 16:56:58 +02:00
Rafostar
c2bc1e39cc Add "addButton" convenience function 2020-09-02 16:54:58 +02:00
Rafostar
4480bed3bc Auto hide cursor on player window 2020-09-02 11:57:16 +02:00
Rafostar
116dc4dd20 Destroy removed volume control buttons 2020-09-02 09:12:17 +02:00
Rafostar
2333d8fc1c Fix drag sometimes starting from wrong button 2020-09-02 09:06:34 +02:00
Rafostar
7307845646 Initial video playlist support
For now player will load only first video from playlist. Good enough for testing. Full playlist support will be added later on.
2020-09-01 23:46:49 +02:00
Rafostar
9f04b74e05 Fix volume button icon behaviour 2020-09-01 23:43:40 +02:00
Rafostar
647ad3f1ec Drag application from video (MPV like window dragging) 2020-09-01 19:48:25 +02:00
Rafostar
26a571408b Add some keys, buttons and scrolls bindings 2020-09-01 17:50:59 +02:00
Rafostar
fa12f15a9a Start loop optionally 2020-09-01 17:49:24 +02:00
Rafostar
326ba66da0 Spread volume icon changes evenly 2020-09-01 17:46:47 +02:00
Rafostar
18a7d34d95 Do not set position adjustment twice 2020-09-01 17:45:36 +02:00
Rafostar
b401bc15ff Improve volume scale icons logic 2020-09-01 12:10:55 +02:00
Rafostar
80ac01706d Move GtkWindow logic to separate file 2020-09-01 10:50:30 +02:00
Rafostar
e35d18505e Use else-if 2020-08-31 23:13:47 +02:00
Rafostar
bf35da6b91 Recycle old position scale adjustment 2020-08-31 23:11:34 +02:00
Rafostar
f70fe43303 Add toggle fullscreen button 2020-08-31 22:21:46 +02:00
Rafostar
918ba34885 Add Gtk app 2020-08-31 20:47:10 +02:00
Rafostar
734471475f Add "seek_seconds" function
Default "seek" function takes time in nanoseconds as argument which is not that useful, cause we will start playback from the nearest keyframe anyway. The new "seek_seconds" can take a double value for more precise seeking.
2020-08-30 20:19:37 +02:00
Rafostar
f35ac10553 Make sure loop is not running before starting it 2020-08-30 20:09:36 +02:00
Rafostar
ceb8930a88 Rename project to "Clapper" 2020-08-30 20:05:58 +02:00
Rafostar
2b0ad406e5 Rename LICENSE to COPYING 2020-08-30 19:40:14 +02:00
Rafostar
71dee1f410 Update README.md 2020-08-29 23:22:59 +02:00
Rafostar
19dfbb7be1 Add "gex" support 2020-08-29 15:51:06 +02:00
Rafostar
4d1166a952 Initial version upload 2020-08-29 15:48:38 +02:00
390 changed files with 78300 additions and 2 deletions

58
.github/workflows/documentation.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
name: "Documentation"
jobs:
documentation:
runs-on: ubuntu-latest
container:
image: registry.fedoraproject.org/fedora
options: --privileged
steps:
- name: Prepare
run: |
dnf -y install git gcc meson glib2-devel \
gstreamer1-devel gstreamer1-plugins-base-devel \
gtk4-devel libsoup3-devel libmicrodns-devel \
gobject-introspection-devel graphviz gi-docgen
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
- name: Build
run: |
meson setup builddir -Dauto_features=enabled \
-Denhancers-loader=disabled \
-Dclapper-app=disabled -Dvapi=disabled -Ddoc=true \
-Dglimporter=auto -Dgluploader=auto -Drawimporter=auto
cd builddir
meson compile
- name: Commit files
if: ${{ success() && github.ref == 'refs/heads/master' }}
continue-on-error: true
run: |
git config --global --add safe.directory $GITHUB_WORKSPACE
git checkout gh-pages
rm -rf doc/clapper/*
rm -rf doc/clapper-gtk/*
mv builddir/doc/reference/clapper/clapper.toml doc/clapper/
mv builddir/doc/reference/clapper/clapper/* doc/clapper/
mv builddir/doc/reference/clapper-gtk/clapper-gtk.toml doc/clapper-gtk/
mv builddir/doc/reference/clapper-gtk/clapper-gtk/* doc/clapper-gtk/
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add doc/clapper/* doc/clapper-gtk/*
git commit -m "doc: Update" || true
- name: Push changes
uses: ad-m/github-push-action@master
if: ${{ success() && github.ref == 'refs/heads/master' }}
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages

50
.github/workflows/flatpak-nightly.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
name: "Flatpak Nightly"
jobs:
flatpak:
name: "Flatpak"
strategy:
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
include:
- os: ubuntu-24.04
arch: x86_64
- os: ubuntu-24.04-arm
arch: aarch64
fail-fast: false
runs-on: ${{ matrix.os }}
container:
image: registry.fedoraproject.org/fedora
options: --privileged
steps:
- name: Prepare
run: |
dnf install -y git git-lfs dbus-daemon flatpak flatpak-builder libappstream-glib ccache zstd xorg-x11-server-Xvfb
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak remote-add --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.rust-stable/${{ matrix.arch }}/24.08
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.llvm18/${{ matrix.arch }}/24.08
flatpak --system install -y --noninteractive flathub org.flatpak.Builder
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build
uses: flatpak/flatpak-github-actions/flatpak-builder@master
with:
bundle: com.github.rafostar.Clapper.flatpak
manifest-path: pkgs/flatpak/com.github.rafostar.Clapper-nightly.json
repository-name: gnome-nightly
repository-url: https://nightly.gnome.org/gnome-nightly.flatpakrepo
cache-key: flatpak-builder-${{ github.sha }}-testing-${{ github.run_number }}
arch: ${{ matrix.arch }}
upload-artifact: false
- name: Upload
uses: actions/upload-artifact@v4
with:
name: clapper-flatpak-nightly-${{ matrix.arch }}
path: com.github.rafostar.Clapper.flatpak
if-no-files-found: error

49
.github/workflows/flatpak.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
name: "Flatpak"
jobs:
flatpak:
name: "Flatpak"
strategy:
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
include:
- os: ubuntu-24.04
arch: x86_64
- os: ubuntu-24.04-arm
arch: aarch64
fail-fast: false
runs-on: ${{ matrix.os }}
container:
image: registry.fedoraproject.org/fedora
options: --privileged
steps:
- name: Prepare
run: |
dnf install -y git git-lfs dbus-daemon flatpak flatpak-builder libappstream-glib ccache zstd xorg-x11-server-Xvfb
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak --system install -y --noninteractive flathub org.flatpak.Builder
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build
uses: flatpak/flatpak-github-actions/flatpak-builder@master
with:
bundle: com.github.rafostar.Clapper.flatpak
manifest-path: pkgs/flatpak/com.github.rafostar.Clapper.json
cache-key: flatpak-builder-${{ github.sha }}
arch: ${{ matrix.arch }}
upload-artifact: false
- name: Upload
uses: actions/upload-artifact@v4
with:
name: clapper-flatpak-${{ matrix.arch }}
path: com.github.rafostar.Clapper.flatpak
if-no-files-found: error

101
.github/workflows/windows.yml vendored Normal file
View File

@@ -0,0 +1,101 @@
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
name: "Windows"
jobs:
windows:
name: "Windows"
runs-on: windows-latest
strategy:
matrix:
arch: [x86_64]
defaults:
run:
shell: msys2 {0}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: |-
mingw-w64-${{ matrix.arch }}-meson
mingw-w64-${{ matrix.arch }}-gcc
mingw-w64-${{ matrix.arch }}-glib2
mingw-w64-${{ matrix.arch }}-gstreamer
mingw-w64-${{ matrix.arch }}-gst-plugins-base
mingw-w64-${{ matrix.arch }}-gst-plugins-good
mingw-w64-${{ matrix.arch }}-gst-plugins-bad
mingw-w64-${{ matrix.arch }}-gst-plugins-ugly
mingw-w64-${{ matrix.arch }}-gst-libav
mingw-w64-${{ matrix.arch }}-libpeas2
mingw-w64-${{ matrix.arch }}-libsoup3
mingw-w64-${{ matrix.arch }}-libmicrodns
mingw-w64-${{ matrix.arch }}-gtk4
mingw-w64-${{ matrix.arch }}-libadwaita
- name: Prepare
run: |
BUILD_PREFIX="$GITHUB_WORKSPACE/clapper-win-${{ matrix.arch }}"
mkdir -p $BUILD_PREFIX/bin
cp /mingw64/bin/gdbus.exe $BUILD_PREFIX/bin/
cp /mingw64/bin/gst-inspect-1.0.exe $BUILD_PREFIX/bin/
mkdir -p $BUILD_PREFIX/lib
cp -r /mingw64/lib/gio $BUILD_PREFIX/lib/
cp -r /mingw64/lib/gstreamer-1.0 $BUILD_PREFIX/lib/
cp -r /mingw64/lib/gdk-pixbuf-2.0 $BUILD_PREFIX/lib/
mkdir -p $BUILD_PREFIX/share/glib-2.0/schemas
cp -r /mingw64/share/glib-2.0/schemas/*.xml $BUILD_PREFIX/share/glib-2.0/schemas/
cp -r /mingw64/share/icons $BUILD_PREFIX/share/
mkdir -p $BUILD_PREFIX/share/xml/iso-codes
cp /mingw64/share/xml/iso-codes/iso_639.xml $BUILD_PREFIX/share/xml/iso-codes/
cd "$BUILD_PREFIX/lib/gstreamer-1.0"
rm -f \
libgstadpcmenc.dll libgstamfcodec.dll libgstdvbsubenc.dll libgstencoding.dll \
libgstfrei0r.dll libgstinter.dll libgstlame.dll libgstldac.dll libgstmpeg2enc.dll \
libgstmpegpsmux.dll libgstmpegtsmux.dll libgstmplex.dll libgstrealmedia.dll \
libgstsubenc.dll libgstsvtav1.dll libgstsvthevcenc.dll libgsttwolame.dll \
libgstvoamrwbenc.dll libgstwavenc.dll libgstx264.dll libgstx265.dll \
libgstxingmux.dll libgsty4menc.dll libgstzbar.dll
- name: Build
run: |
meson setup builddir --prefix=$GITHUB_WORKSPACE/clapper-win-${{ matrix.arch }}
cd builddir
meson compile
meson install
- name: Package
run: |
BUILD_PREFIX="$GITHUB_WORKSPACE/clapper-win-${{ matrix.arch }}"
ldd $BUILD_PREFIX/bin/clapper.exe | grep '\/mingw.*\.dll' -o | xargs -I{} cp -n "{}" $BUILD_PREFIX/bin
find $BUILD_PREFIX/lib/clapper-0.0/ -name '*\.dll' -type f -exec ldd "{}" \; | grep '\/mingw.*\.dll' -o | xargs -I{} cp -n "{}" $BUILD_PREFIX/bin
find $BUILD_PREFIX/lib/gstreamer-1.0/ -name '*\.dll' -type f -exec ldd "{}" \; | grep '\/mingw.*\.dll' -o | xargs -I{} cp -n "{}" $BUILD_PREFIX/bin
find $BUILD_PREFIX/lib/gio/ -name '*\.dll' -type f -exec ldd "{}" \; | grep '\/mingw.*\.dll' -o | xargs -I{} cp -n "{}" $BUILD_PREFIX/bin
- name: Cleanup
run: |
BUILD_PREFIX="$GITHUB_WORKSPACE/clapper-win-${{ matrix.arch }}"
rm -rf $BUILD_PREFIX/include
rm -rf $BUILD_PREFIX/lib/pkgconfig
- name: Installer
uses: Minionguyjpro/Inno-Setup-Action@v1.2.5
with:
path: builddir/pkgs/windows-installer/clapper.iss
options: /O+
- name: Upload
uses: actions/upload-artifact@v4
with:
name: clapper-win-${{ matrix.arch }}
path: builddir/pkgs/windows-installer/InstallerOutput/Clapper*.exe
if-no-files-found: error

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# meson/ninja
build/
install/
builddir/
# flatpak
.flatpak-builder/

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "pkgs/flatpak/flathub"]
path = pkgs/flatpak/flathub
url = https://github.com/flathub/com.github.rafostar.Clapper.git

10
.obs/workflows.yml Normal file
View File

@@ -0,0 +1,10 @@
rebuild_master:
steps:
- trigger_services:
project: home:Rafostar
package: clapper
filters:
event: push
branches:
only:
- master

501
COPYING-LGPL Normal file
View File

@@ -0,0 +1,501 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
<https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Moe Ghoul>, 1 April 1990
Moe Ghoul, President of Vice
That's all there is to it!

2
FUNDING.yml Normal file
View File

@@ -0,0 +1,2 @@
liberapay: Clapper
custom: ['paypal.me/Rafostar']

View File

@@ -1,2 +1,77 @@
# GtkPlayer
A pre-made GJS Media Player widget powered by GStreamer with OpenGL rendering.
# Clapper
[![Flatpak](https://github.com/Rafostar/clapper/actions/workflows/flatpak.yml/badge.svg?event=push)](https://github.com/Rafostar/clapper/actions/workflows/flatpak.yml)
[![Flatpak Nightly](https://github.com/Rafostar/clapper/actions/workflows/flatpak-nightly.yml/badge.svg?event=schedule)](https://github.com/Rafostar/clapper/actions/workflows/flatpak-nightly.yml)
[![Crowdin](https://badges.crowdin.net/clapper/localized.svg)](https://crowdin.com/project/clapper)
[![Matrix](https://img.shields.io/matrix/clapper-player:matrix.org?label=matrix)](https://matrix.to/#/#clapper-player:matrix.org)
[![Donate](https://img.shields.io/liberapay/receives/Clapper.svg?logo=liberapay)](https://liberapay.com/Clapper)
Clapper is a modern media player designed for simplicity and ease of use. Powered by [GStreamer](https://gstreamer.freedesktop.org/) and built for the GNOME
desktop environment using [GTK4](https://www.gtk.org/) toolkit, it has a clean and stylish interface that lets you focus on enjoying your favorite videos.
This application aim is to offer all the essentials features you'd expect from a video player in a simple form.
<p align="center">
<img src="https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_01.png">
</p>
Clapper uses a playback queue where you can add multiple media files. Think of it like a playlist that you can build.
You can easily reorder items or remove them from the queue with a simple drag and drop operation.
<p align="center">
<img src="https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_03.png">
</p>
### Components
Clapper's codebase consists of 2 libraries using which main application is built:
* [Clapper](https://rafostar.github.io/clapper/doc/clapper/) - a playback library
* [ClapperGtk](https://rafostar.github.io/clapper/doc/clapper-gtk/) - a GTK integration library
Both libraries support *GObject Introspection* bindings. A simple application example can be found [here](https://github.com/Rafostar/clapper-vala-test).
Above libraries are licensed under `LGPL-2.1-or-later`. You are free to use them in your own projects as long as you comply with license terms.
Please note that until version 1.0 they should be considered as an unstable API (some things may change without prior notice).
Clapper `Vala` bindings are part of this repo, while `Rust` bindings can be found [here](https://gitlab.gnome.org/JanGernert/clapper-rs).
## Installation from Flatpak
The `Flatpak` package includes all required dependencies and codecs.
Additionally it also has a few patches, thus some functionalities work better in `Flatpak` version (until my changes are accepted upstream).
List of patches used in this version can be found [here](https://github.com/Rafostar/clapper/issues/35).
<a href='https://flathub.org/apps/details/com.github.rafostar.Clapper'>
<img width='240' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/>
</a>
## Packages in Linux Distributions
[![Packaging status](https://repology.org/badge/vertical-allrepos/clapper.svg)](https://repology.org/project/clapper/versions)
Pre-built RPM packages are also available in [my repo](https://software.opensuse.org//download.html?project=home%3ARafostar&package=clapper) ([see status](https://build.opensuse.org/package/show/home:Rafostar/clapper)).<br>
Those are automatically built on each git commit, thus are considered unstable.
## Installation from Source Code
```sh
meson setup builddir
cd builddir
meson compile
sudo meson install
```
If you want to compile app as `Flatpak`, remember to clone this repo with `--recurse-submodules` option.
## Questions?
Feel free to ask me any questions. Come and talk on Matrix: [#clapper-player:matrix.org](https://matrix.to/#/#clapper-player:matrix.org)
## Translations
Preferred translation method is to use [Clapper Crowdin](https://crowdin.com/project/clapper) web page.
Crowdin does not require any additional tools and translating can be done through web browser.
You can login using GitHub account or create a new one. Only I can add new languages to this project,
so if your language is not available, please contact me first.
## Special Thanks
Many thanks to [sp1ritCS](https://github.com/sp1ritCS) for creating and maintaining package build files.
Big thanks to [bridadan](https://github.com/bridadan) and [Uniformbuffer3](https://github.com/Uniformbuffer3) for helping
with testing V4L2 and NVDEC hardware acceleration methods.
Also words of appreciation for [JanGernert](https://gitlab.gnome.org/JanGernert) who made and is sharing Clapper Rust bindings.
Thanks a lot to all the people who are supporting the development with their anonymous donations through [Liberapay](https://liberapay.com/Clapper/). I :heart: U.

1
_config.yml Normal file
View File

@@ -0,0 +1 @@
theme: jekyll-theme-cayman

5
crowdin.yml Normal file
View File

@@ -0,0 +1,5 @@
files:
- source: /src/lib/clapper-gtk/po/clapper-gtk.pot
translation: /src/lib/clapper-gtk/po/%osx_locale%.po
- source: /src/bin/clapper-app/po/clapper-app.pot
translation: /src/bin/clapper-app/po/%osx_locale%.po

10
doc/meson.build Normal file
View File

@@ -0,0 +1,10 @@
gi_docgen = find_program('gi-docgen', required: get_option('doc'))
dot = find_program('dot', required: get_option('doc')) # Class hierarchy generation
build_doc = (gi_docgen.found() and dot.found() and get_option('doc'))
if build_doc
if not build_gir
error('Building documentation requires introspection to be compiled')
endif
subdir('reference')
endif

View File

@@ -0,0 +1,63 @@
[library]
version = "@CLAPPER_VERSION@"
browse_url = "https://github.com/Rafostar/clapper/"
repository_url = "https://github.com/Rafostar/clapper.git"
website_url = "https://rafostar.github.io/clapper/"
docs_url = "https://rafostar.github.io/clapper/doc/clapper-gtk/"
authors = "Rafał Dzięgiel"
logo_url = "clapper-logo.svg"
license = "LGPL-2.1-or-later"
description = "Clapper GTK integration library"
devhelp = true
search_index = true
dependencies = ["Clapper@CLAPPER_VERSION_SUFFIX@", "Gtk-4.0"]
[dependencies."Clapper@CLAPPER_VERSION_SUFFIX@"]
name = "Clapper"
description = "Clapper playback library"
docs_url = "https://rafostar.github.io/clapper/doc/clapper/"
[dependencies."Gtk-4.0"]
name = "Gtk"
description = "The GTK toolkit"
docs_url = "https://docs.gtk.org/gtk4/"
related = ["GLib-2.0", "GObject-2.0", "Gio-2.0", "Gst-1.0"]
[related."GLib-2.0"]
name = "GLib"
description = "A general-purpose, portable utility library"
docs_url = "https://docs.gtk.org/glib/"
[related."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[related."Gio-2.0"]
name = "Gio"
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
docs_url = "https://docs.gtk.org/gio/"
[related."Gst-1.0"]
name = "Gst"
description = "GStreamer core library"
docs_url = "https://gstreamer.freedesktop.org/documentation/gstreamer/gi-index.html"
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = "https://github.com/Rafostar/clapper/tree/master/"
[extra]
# The same order will be used when generating the index
content_files = [
]
content_images = [
"images/clapper-logo.svg",
]
urlmap_file = "urlmap.js"

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256" width="256" height="256">
<defs>
<path id="b1nGq5BrLC" d="M27.2 243.52C27.2 236.16 27.2 199.83 27.2 134.22C47.64 134.22 211.12 134.22 231.56 134.22C231.56 199.83 231.56 236.16 231.56 243.52C231.56 250.4 225.96 256 218.92 256C183.07 256 57.77 256 39.84 256C32.8 256 27.2 250.4 27.2 243.52Z"></path>
<path id="a3jkaoNn4k" d="M24.32 103.65C24.32 106.22 24.32 127.02 24.32 129.58C24.32 132.78 26.72 135.18 29.92 135.18C50.41 135.18 215.08 135.18 235.72 135.18C238.76 135.18 241.32 132.78 241.32 129.58C241.32 127.02 241.32 106.22 241.32 103.65C241.32 100.45 238.76 98.05 235.72 98.05C194.59 98.05 50.41 98.05 29.92 98.05C26.72 98.05 24.32 100.45 24.32 103.65Z"></path>
<path id="atpVQ8mnd" d="M174.59 135.18L211.87 98.05L171.07 98.05L133.78 135.18L174.59 135.18Z"></path>
<path id="bMtYoNHu0" d="M76.81 135.18L114.1 98.05L73.13 98.05L35.84 135.18L76.81 135.18Z"></path>
<path id="b5oP0Glp4" d="M19.04 69.41C19.84 71.97 25.92 91.97 26.72 94.37C27.68 97.41 30.72 99.01 33.76 98.05C54.09 91.81 216.68 42.04 237 35.8C240.04 35 241.64 31.8 240.84 28.92C240.04 26.36 233.96 6.36 233.16 3.96C232.2 0.92 229.16 -0.68 226.12 0.28C185.47 12.6 43.21 56.29 22.88 62.53C19.84 63.33 18.24 66.53 19.04 69.41Z"></path>
<path id="lwBgev6DR" d="M176.51 54.37L129.94 29.4L169.15 17.56L215.72 42.52L176.51 54.37Z"></path>
<path id="cUsjEMRUu" d="M81.61 83.49L35.04 58.69L74.25 46.69L120.82 71.49L81.61 83.49Z"></path>
<path id="c1bcHZGXe" d="M14.72 66.69C14.72 72.93 14.72 123.02 14.72 129.26C14.72 132.62 17.44 135.18 20.64 135.18C26.56 135.18 74.09 135.18 80.01 135.18C84.33 135.18 87.21 130.86 85.61 127.02C82.89 120.78 61.45 70.53 58.73 64.29C57.77 62.05 55.69 60.77 53.29 60.77C46.73 60.77 24 60.77 20.64 60.77C17.44 60.77 14.72 63.33 14.72 66.69Z"></path>
<path id="f2PtH0V1vC" d="M32.64 60.61C31.52 60.61 21.92 60.61 20.64 60.61C17.44 60.61 14.72 63.33 14.72 66.53C14.72 72.77 14.72 123.02 14.72 129.26C14.72 132.46 17.44 135.18 20.64 135.18C21.92 135.18 31.52 135.18 32.64 135.18C29.44 135.18 26.72 132.46 26.72 129.26C26.72 116.62 26.72 72.77 26.72 66.53C26.72 63.33 29.44 60.61 32.64 60.61Z"></path>
<path id="a1SvrrkqVm" d="M231.56 135.18C231.56 143.82 231.56 148.46 231.56 149.42C231.56 149.42 231.56 149.42 231.56 149.42C108.98 149.42 40.8 149.42 27.2 149.42C27.2 149.42 27.2 149.42 27.2 149.42C27.2 140.94 27.2 136.14 27.2 135.18C27.2 135.18 27.2 135.18 27.2 135.18C149.78 135.18 217.96 135.18 231.56 135.18C231.56 135.18 231.56 135.18 231.56 135.18Z"></path>
<path id="agXcvKqh8" d="M104.22 162.46L104.22 234.46L163.22 198.54L104.22 162.46Z"></path>
</defs>
<g>
<g><use xlink:href="#b1nGq5BrLC" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#a3jkaoNn4k" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#atpVQ8mnd" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#bMtYoNHu0" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#b5oP0Glp4" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#lwBgev6DR" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#cUsjEMRUu" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#c1bcHZGXe" fill="#a9a9a9" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#f2PtH0V1vC" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#a1SvrrkqVm" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#agXcvKqh8" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,30 @@
clappergtk_toml = configure_file(
input: 'clapper-gtk.toml.in',
output: 'clapper-gtk.toml',
configuration: doc_version_conf,
install: true,
install_dir: join_paths(datadir, 'doc', 'clapper-gtk'),
)
custom_target('clapper-gtk-doc',
input: [
clappergtk_toml,
clappergtk_gir[0],
],
output: 'clapper-gtk',
command: [
gi_docgen,
'generate',
gi_docgen_common_args,
'--add-include-path=@0@'.format(join_paths(meson.project_build_root(), 'src', 'lib', 'clapper')),
'--add-include-path=@0@'.format(join_paths(meson.project_build_root(), 'src', 'lib', 'clapper-gtk')),
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_build_dir()),
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT1@',
],
build_by_default: true,
install: true,
install_dir: join_paths(datadir, 'doc'),
)

View File

@@ -0,0 +1,8 @@
baseURLs = [
['GLib', 'https://docs.gtk.org/glib/'],
['GObject', 'https://docs.gtk.org/gobject/'],
['Gio', 'https://docs.gtk.org/gio/'],
['Gtk', 'https://docs.gtk.org/gtk4/'],
['Gst', 'https://gstreamer.freedesktop.org/documentation/gstreamer/gi-index.html?'],
['Clapper', 'https://rafostar.github.io/clapper/doc/clapper/'],
]

View File

@@ -0,0 +1,73 @@
[library]
version = "@CLAPPER_VERSION@"
browse_url = "https://github.com/Rafostar/clapper/"
repository_url = "https://github.com/Rafostar/clapper.git"
website_url = "https://rafostar.github.io/clapper/"
docs_url = "https://rafostar.github.io/clapper/doc/clapper/"
authors = "Rafał Dzięgiel"
logo_url = "clapper-logo.svg"
license = "LGPL-2.1-or-later"
description = "Clapper playback library"
devhelp = true
search_index = true
dependencies = ["GLib-2.0", "GObject-2.0", "Gio-2.0", "Gst-1.0", "GstBase-1.0", "GstAudio-1.0", "GstTag-1.0", "GstPbutils-1.0"]
[dependencies."GLib-2.0"]
name = "GLib"
description = "A general-purpose, portable utility library"
docs_url = "https://docs.gtk.org/glib/"
[dependencies."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[dependencies."Gio-2.0"]
name = "Gio"
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
docs_url = "https://docs.gtk.org/gio/"
[dependencies."Gst-1.0"]
name = "Gst"
description = "GStreamer core library"
docs_url = "https://gstreamer.freedesktop.org/documentation/gstreamer/gi-index.html"
[dependencies."GstBase-1.0"]
name = "GstBase"
description = "GStreamer base and utility classes"
docs_url = "https://gstreamer.freedesktop.org/documentation/base/"
[dependencies."GstAudio-1.0"]
name = "GstAudio"
description = "GStreamer audio library"
docs_url = "https://gstreamer.freedesktop.org/documentation/audio/"
[dependencies."GstTag-1.0"]
name = "GstTag"
description = "GStreamer tag support library"
docs_url = "https://gstreamer.freedesktop.org/documentation/tag/"
[dependencies."GstPbutils-1.0"]
name = "GstPbutils"
description = "GStreamer base utils library"
docs_url = "https://gstreamer.freedesktop.org/documentation/pbutils/"
related = []
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = "https://github.com/Rafostar/clapper/tree/master/"
[extra]
# The same order will be used when generating the index
content_files = [
]
content_images = [
"images/clapper-logo.svg",
]
urlmap_file = "urlmap.js"

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256" width="256" height="256">
<defs>
<path id="b1nGq5BrLC" d="M27.2 243.52C27.2 236.16 27.2 199.83 27.2 134.22C47.64 134.22 211.12 134.22 231.56 134.22C231.56 199.83 231.56 236.16 231.56 243.52C231.56 250.4 225.96 256 218.92 256C183.07 256 57.77 256 39.84 256C32.8 256 27.2 250.4 27.2 243.52Z"></path>
<path id="a3jkaoNn4k" d="M24.32 103.65C24.32 106.22 24.32 127.02 24.32 129.58C24.32 132.78 26.72 135.18 29.92 135.18C50.41 135.18 215.08 135.18 235.72 135.18C238.76 135.18 241.32 132.78 241.32 129.58C241.32 127.02 241.32 106.22 241.32 103.65C241.32 100.45 238.76 98.05 235.72 98.05C194.59 98.05 50.41 98.05 29.92 98.05C26.72 98.05 24.32 100.45 24.32 103.65Z"></path>
<path id="atpVQ8mnd" d="M174.59 135.18L211.87 98.05L171.07 98.05L133.78 135.18L174.59 135.18Z"></path>
<path id="bMtYoNHu0" d="M76.81 135.18L114.1 98.05L73.13 98.05L35.84 135.18L76.81 135.18Z"></path>
<path id="b5oP0Glp4" d="M19.04 69.41C19.84 71.97 25.92 91.97 26.72 94.37C27.68 97.41 30.72 99.01 33.76 98.05C54.09 91.81 216.68 42.04 237 35.8C240.04 35 241.64 31.8 240.84 28.92C240.04 26.36 233.96 6.36 233.16 3.96C232.2 0.92 229.16 -0.68 226.12 0.28C185.47 12.6 43.21 56.29 22.88 62.53C19.84 63.33 18.24 66.53 19.04 69.41Z"></path>
<path id="lwBgev6DR" d="M176.51 54.37L129.94 29.4L169.15 17.56L215.72 42.52L176.51 54.37Z"></path>
<path id="cUsjEMRUu" d="M81.61 83.49L35.04 58.69L74.25 46.69L120.82 71.49L81.61 83.49Z"></path>
<path id="c1bcHZGXe" d="M14.72 66.69C14.72 72.93 14.72 123.02 14.72 129.26C14.72 132.62 17.44 135.18 20.64 135.18C26.56 135.18 74.09 135.18 80.01 135.18C84.33 135.18 87.21 130.86 85.61 127.02C82.89 120.78 61.45 70.53 58.73 64.29C57.77 62.05 55.69 60.77 53.29 60.77C46.73 60.77 24 60.77 20.64 60.77C17.44 60.77 14.72 63.33 14.72 66.69Z"></path>
<path id="f2PtH0V1vC" d="M32.64 60.61C31.52 60.61 21.92 60.61 20.64 60.61C17.44 60.61 14.72 63.33 14.72 66.53C14.72 72.77 14.72 123.02 14.72 129.26C14.72 132.46 17.44 135.18 20.64 135.18C21.92 135.18 31.52 135.18 32.64 135.18C29.44 135.18 26.72 132.46 26.72 129.26C26.72 116.62 26.72 72.77 26.72 66.53C26.72 63.33 29.44 60.61 32.64 60.61Z"></path>
<path id="a1SvrrkqVm" d="M231.56 135.18C231.56 143.82 231.56 148.46 231.56 149.42C231.56 149.42 231.56 149.42 231.56 149.42C108.98 149.42 40.8 149.42 27.2 149.42C27.2 149.42 27.2 149.42 27.2 149.42C27.2 140.94 27.2 136.14 27.2 135.18C27.2 135.18 27.2 135.18 27.2 135.18C149.78 135.18 217.96 135.18 231.56 135.18C231.56 135.18 231.56 135.18 231.56 135.18Z"></path>
<path id="agXcvKqh8" d="M104.22 162.46L104.22 234.46L163.22 198.54L104.22 162.46Z"></path>
</defs>
<g>
<g><use xlink:href="#b1nGq5BrLC" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#a3jkaoNn4k" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#atpVQ8mnd" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#bMtYoNHu0" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#b5oP0Glp4" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#lwBgev6DR" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#cUsjEMRUu" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#c1bcHZGXe" fill="#a9a9a9" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#f2PtH0V1vC" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#a1SvrrkqVm" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#agXcvKqh8" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,29 @@
clapper_toml = configure_file(
input: 'clapper.toml.in',
output: 'clapper.toml',
configuration: doc_version_conf,
install: true,
install_dir: join_paths(datadir, 'doc', 'clapper'),
)
custom_target('clapper-doc',
input: [
clapper_toml,
clapper_gir[0],
],
output: 'clapper',
command: [
gi_docgen,
'generate',
gi_docgen_common_args,
'--add-include-path=@0@'.format(join_paths(meson.project_build_root(), 'src', 'lib', 'clapper')),
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_build_dir()),
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT1@',
],
build_by_default: true,
install: true,
install_dir: join_paths(datadir, 'doc'),
)

View File

@@ -0,0 +1,10 @@
baseURLs = [
['GLib', 'https://docs.gtk.org/glib/'],
['GObject', 'https://docs.gtk.org/gobject/'],
['Gio', 'https://docs.gtk.org/gio/'],
['Gst', 'https://gstreamer.freedesktop.org/documentation/gstreamer/gi-index.html?'],
['GstBase', 'https://gstreamer.freedesktop.org/documentation/base/?'],
['GstAudio', 'https://gstreamer.freedesktop.org/documentation/audio/?'],
['GstTag', 'https://gstreamer.freedesktop.org/documentation/tag/?'],
['GstPbutils', 'https://gstreamer.freedesktop.org/documentation/pbutils/?'],
]

18
doc/reference/meson.build Normal file
View File

@@ -0,0 +1,18 @@
doc_version_conf = configuration_data()
doc_version_conf.set('CLAPPER_VERSION', meson.project_version())
doc_version_conf.set('CLAPPER_VERSION_SUFFIX', clapper_version_suffix)
gi_docgen_common_args = [
'--quiet',
'--no-namespace-dir',
]
if get_option('werror')
gi_docgen_common_args += ['--fatal-warnings']
endif
if build_clapper
subdir('clapper')
endif
if build_clappergtk
subdir('clapper-gtk')
endif

View File

@@ -0,0 +1,57 @@
#!/usr/bin/env python3
import gi
gi.require_version('Adw', '1')
gi.require_version('Clapper', '0.0')
gi.require_version('ClapperGtk', '0.0')
gi.require_version('GLib', '2.0')
gi.require_version('Gtk', '4.0')
from gi.repository import Adw, Clapper, ClapperGtk, GLib, Gtk
import shutil
Clapper.init(None)
download_dir = GLib.build_filenamev([GLib.get_user_cache_dir(), "example_download_dir", None])
print('Using cache directory: {0}'.format(download_dir))
def on_download_complete(player, item, location):
# Media downloaded. Data from this file is still used for current playback (including seeking).
print('Download complete: {0} => {1}'.format(item.props.uri, location))
def on_activate(app):
win = Gtk.ApplicationWindow(application=app, default_width=640, default_height=396)
video = ClapperGtk.Video()
controls = ClapperGtk.SimpleControls(fullscreenable=False)
# Enable local storage caching and monitor it
video.props.player.set_download_dir(download_dir)
video.props.player.set_download_enabled(True)
video.props.player.connect('download-complete', on_download_complete)
# Configure playback
video.props.player.props.queue.set_progression_mode(Clapper.QueueProgressionMode.CAROUSEL)
video.props.player.set_autoplay(True)
# Assemble window
video.add_fading_overlay(controls)
win.set_child(video)
win.present()
# Create and add media for playback
item_1 = Clapper.MediaItem(uri='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4')
item_2 = Clapper.MediaItem(uri='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4')
video.props.player.props.queue.add_item(item_1)
video.props.player.props.queue.add_item(item_2)
# Create a new application
app = Adw.Application(application_id='com.example.ClapperDownloadCache')
app.connect('activate', on_activate)
# Run the application
app.run(None)
# Finally app should cleanup before exit. Possibly moving data to
# another dir if it wants to use it on next run and deleting what's
# left (so any unfinished downloads will also be removed).
print('Cleanup')
shutil.rmtree(download_dir)

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
import gi
gi.require_version('Adw', '1')
gi.require_version('Clapper', '0.0')
gi.require_version('ClapperGtk', '0.0')
gi.require_version('Gtk', '4.0')
from gi.repository import Adw, Clapper, ClapperGtk, Gtk
Clapper.init(None)
def on_toggle_fullscreen(video, win):
# Since this example uses only video inside normal window, all we
# need to toggle fullscreen is to invert its fullscreened property
win.props.fullscreened ^= True
def on_activate(app):
win = Gtk.ApplicationWindow(application=app, default_width=640, default_height=396)
video = ClapperGtk.Video()
controls = ClapperGtk.SimpleControls()
# This signal will be emitted when user requests fullscreen state change.
# It is app job to fullscreen video only (which might require something
# more than simply inverting fullscreen on the whole window).
video.connect('toggle-fullscreen', on_toggle_fullscreen, win)
# Create and add media for playback. First added media item to empty
# playback queue will be automatically selected.
item = Clapper.MediaItem(uri='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4')
video.props.player.props.queue.add_item(item)
# Assemble window
video.add_fading_overlay(controls)
win.set_child(video)
win.present()
# Start playback
video.props.player.play()
# Create a new application
app = Adw.Application(application_id='com.example.ClapperSimple')
app.connect('activate', on_activate)
# Run the application
app.run(None)

173
meson.build Normal file
View File

@@ -0,0 +1,173 @@
project('clapper', 'c',
version: '0.9.1',
meson_version: '>= 0.64.0',
license: 'LGPL-2.1-or-later AND GPL-3.0-or-later', # LGPL-2.1+ for libs and gst-plugin, GPL-3.0+ for app
default_options: [
'warning_level=1',
'buildtype=debugoptimized',
],
)
glib_req = '>= 2.76.0'
gst_req = '>= 1.24.0'
gtk4_req = '>= 4.10.0'
adw_req = '>= 1.5.0'
clapper_version = meson.project_version().split('-')[0]
version_array = clapper_version.split('.')
clapper_version_suffix = '-' + version_array[0] + '.0'
clapper_api_name = meson.project_name() + clapper_version_suffix
devenv = environment()
gnome = import('gnome')
pkgconfig = import('pkgconfig')
i18n = import('i18n')
prefix = get_option('prefix')
bindir = get_option('bindir')
datadir = get_option('datadir')
libdir = get_option('libdir')
localedir = get_option('localedir')
includedir = get_option('includedir')
optimization = get_option('optimization')
clapper_libdir = join_paths(prefix, libdir, clapper_api_name)
build_optimized = optimization in ['2', '3', 's']
gst_dep = dependency('gstreamer-1.0',
version: gst_req,
required: false,
)
gst_base_dep = dependency('gstreamer-base-1.0',
version: gst_req,
required: false,
)
gst_video_dep = dependency('gstreamer-video-1.0',
version: gst_req,
required: false,
)
gst_audio_dep = dependency('gstreamer-audio-1.0',
version: gst_req,
required: false,
)
gst_pbutils_dep = dependency('gstreamer-pbutils-1.0',
version: gst_req,
required: false,
)
gst_tag_dep = dependency('gstreamer-tag-1.0',
version: gst_req,
required: false,
)
glib_dep = dependency('glib-2.0',
version: glib_req,
required: false,
)
gobject_dep = dependency('gobject-2.0',
version: glib_req,
required: false,
)
gio_dep = dependency('gio-2.0',
version: glib_req,
required: false,
)
gmodule_dep = dependency('gmodule-2.0',
version: glib_req,
required: false,
)
gtk4_dep = dependency('gtk4',
version: gtk4_req,
required: false,
)
libadwaita_dep = dependency('libadwaita-1',
version: adw_req,
required: false,
)
# Optional
peas_dep = dependency('libpeas-2',
required: false,
)
cgraph_dep = dependency('libcgraph',
required: false,
)
gvc_dep = dependency('libgvc',
required: false,
)
cc = meson.get_compiler('c')
libm = cc.find_library('m', required: false)
warning_flags = [
'-Wmissing-declarations',
'-Wredundant-decls',
'-Wwrite-strings',
'-Wformat',
'-Wformat-security',
'-Winit-self',
'-Wmissing-include-dirs',
'-Waddress',
'-Wno-multichar',
'-Wvla',
'-Wpointer-arith',
'-Wmissing-prototypes',
'-Wdeclaration-after-statement',
'-Wold-style-definition',
'-Wsign-compare',
]
foreach extra_arg : warning_flags
if cc.has_argument (extra_arg)
add_project_arguments([extra_arg], language: 'c')
endif
endforeach
if build_optimized
message('Disabling GLib cast checks')
add_project_arguments('-DG_DISABLE_CAST_CHECKS', language: 'c')
message('Disabling GLib asserts')
add_project_arguments('-DG_DISABLE_ASSERT', language: 'c')
message('Disabling GLib checks')
add_project_arguments('-DG_DISABLE_CHECKS', language: 'c')
endif
subdir('src')
subdir('doc')
subdir('pkgs')
meson.add_devenv(devenv)
summary({
'prefix': prefix,
'bindir': bindir,
'datadir': datadir,
'libdir': libdir,
'localedir': localedir,
'includedir': includedir,
'optimization': optimization,
}, section: 'Directories')
summary('clapper', build_clapper ? 'Yes' : 'No', section: 'Build')
summary('clapper-gtk', build_clappergtk ? 'Yes' : 'No', section: 'Build')
summary('clapper-app', build_clapperapp ? 'Yes' : 'No', section: 'Build')
summary('gst-plugin', build_gst_plugin ? 'Yes' : 'No', section: 'Build')
summary('introspection', build_gir ? 'Yes' : 'No', section: 'Build')
summary('vapi', build_vapi ? 'Yes' : 'No', section: 'Build')
summary('doc', build_doc ? 'Yes' : 'No', section: 'Build')
if build_clapper
foreach name : clapper_possible_functionalities
summary(name, clapper_available_functionalities.contains(name) ? 'Yes' : 'No', section: 'Functionalities')
endforeach
foreach name : clapper_possible_features
summary(name, clapper_available_features.contains(name) ? 'Yes' : 'No', section: 'Features')
endforeach
endif
if build_clapperapp
foreach name : clapperapp_possible_functionalities
summary(name, clapperapp_available_functionalities.contains(name) ? 'Yes' : 'No', section: 'Functionalities')
endforeach
endif

82
meson_options.txt Normal file
View File

@@ -0,0 +1,82 @@
# Build
option('clapper',
type: 'feature',
value: 'auto',
description: 'Build Clapper library'
)
option('clapper-gtk',
type: 'feature',
value: 'auto',
description: 'Build Clapper GTK integration library'
)
option('clapper-app',
type: 'feature',
value: 'auto',
description: 'Build Clapper application'
)
option('gst-plugin',
type: 'feature',
value: 'auto',
description: 'Build GStreamer plugin (includes GTK video sink element)'
)
option('introspection',
type: 'feature',
value: 'auto',
description: 'Build GObject Introspection data'
)
option('vapi',
type: 'feature',
value: 'auto',
description: 'Build Vala bindings'
)
option('doc',
type: 'boolean',
value: false,
description: 'Build documentation'
)
# Functionalities
option('enhancers-loader',
type: 'feature',
value: 'enabled',
description: 'Ability to load libpeas based plugins that enhance capabilities'
)
option('pipeline-preview',
type: 'feature',
value: 'auto',
description: 'Ability to preview GStreamer pipeline in clapper-app'
)
# Features
option('discoverer',
type: 'feature',
value: 'auto',
description: 'Build Clapper Discoverer feature'
)
option('mpris',
type: 'feature',
value: 'auto',
description: 'Build Clapper MPRIS feature'
)
option('server',
type: 'feature',
value: 'auto',
description: 'Build Clapper Server feature'
)
# GStreamer plugin options
option('glimporter',
type: 'feature',
value: 'auto',
description: 'Build GL memory importer for clappersink'
)
option('gluploader',
type: 'feature',
value: 'auto',
description: 'Build GL uploader for clappersink'
)
option('rawimporter',
type: 'feature',
value: 'auto',
description: 'Build RAW system memory importer for clappersink'
)

6
pkgs/flatpak/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
build/
builddir/
repo/
.flatpak-builder/
com.github.rafostar.Clapper.flatpak
flathub/com.github.rafostar.Clapper.json

View File

@@ -0,0 +1,86 @@
{
"app-id": "com.github.rafostar.Clapper",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"sdk-extensions": [
"org.freedesktop.Sdk.Extension.rust-stable",
"org.freedesktop.Sdk.Extension.llvm18"
],
"add-extensions": {
"org.freedesktop.Platform.ffmpeg-full": {
"version": "24.08",
"directory": "lib/ffmpeg",
"add-ld-path": ".",
"no-autodownload": false,
"autodelete": false
},
"com.github.rafostar.Clapper.Enhancers": {
"versions": "master;test;stable",
"directory": "extensions/clapper/enhancers",
"add-ld-path": "lib",
"no-autodownload": false,
"autodelete": false
}
},
"command": "clapper",
"separate-locales": false,
"finish-args": [
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--device=dri",
"--socket=pulseaudio",
"--share=network",
"--device=all",
"--filesystem=xdg-run/pipewire-0:ro",
"--filesystem=xdg-videos",
"--filesystem=xdg-run/gvfsd",
"--own-name=org.mpris.MediaPlayer2.Clapper.*",
"--talk-name=org.gtk.vfs.*",
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0",
"--env=CLAPPER_ENHANCERS_PATH=/app/extensions/clapper/enhancers/plugins",
"--env=PYTHONPATH=/app/extensions/clapper/enhancers/python/site-packages"
],
"build-options": {
"append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm18/bin",
"prepend-ld-library-path": "/usr/lib/sdk/llvm18/lib",
"env": {
"CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER": "clang",
"CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold",
"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER": "clang",
"CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS": "-C link-arg=-fuse-ld=/usr/lib/sdk/rust-stable/bin/mold"
}
},
"modules": [
"flathub/shared-modules/gudev/gudev.json",
"flathub/lib/liba52.json",
"flathub/lib/libmpeg2.json",
"flathub/lib/libdv.json",
"flathub/lib/libdvdcss.json",
"flathub/lib/libdvdread.json",
"flathub/lib/libdvdnav.json",
"flathub/lib/libass.json",
"flathub/lib/libmicrodns.json",
"flathub/lib/libpeas.json",
"testing/dav1d.json",
"testing/gstreamer.json",
"testing/gst-plugins-rs.json",
"testing/graphviz.json",
{
"name": "clapper",
"buildsystem": "meson",
"sources": [
{
"type": "dir",
"path": "../../."
}
]
}
],
"cleanup-commands": [
"mkdir -p /app/lib/ffmpeg",
"mkdir -p /app/extensions/clapper/enhancers",
"ln -s /lib/$FLATPAK_ARCH-linux-*/gstreamer-1.0/libgstpipewire.so /app/lib/gstreamer-1.0/"
]
}

View File

@@ -0,0 +1,71 @@
{
"app-id": "com.github.rafostar.Clapper",
"runtime": "org.gnome.Platform",
"runtime-version": "47",
"sdk": "org.gnome.Sdk",
"add-extensions": {
"org.freedesktop.Platform.ffmpeg-full": {
"version": "24.08",
"directory": "lib/ffmpeg",
"add-ld-path": ".",
"no-autodownload": false,
"autodelete": false
},
"com.github.rafostar.Clapper.Enhancers": {
"versions": "master;test;stable",
"directory": "extensions/clapper/enhancers",
"add-ld-path": "lib",
"no-autodownload": false,
"autodelete": false
}
},
"command": "clapper",
"separate-locales": false,
"finish-args": [
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--device=dri",
"--socket=pulseaudio",
"--share=network",
"--device=all",
"--filesystem=xdg-run/pipewire-0:ro",
"--filesystem=xdg-videos",
"--filesystem=xdg-run/gvfsd",
"--own-name=org.mpris.MediaPlayer2.Clapper.*",
"--talk-name=org.gtk.vfs.*",
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0",
"--env=CLAPPER_ENHANCERS_PATH=/app/extensions/clapper/enhancers/plugins",
"--env=PYTHONPATH=/app/extensions/clapper/enhancers/python/site-packages"
],
"modules": [
"flathub/shared-modules/gudev/gudev.json",
"flathub/lib/liba52.json",
"flathub/lib/libmpeg2.json",
"flathub/lib/libdv.json",
"flathub/lib/libdvdcss.json",
"flathub/lib/libdvdread.json",
"flathub/lib/libdvdnav.json",
"flathub/lib/libass.json",
"flathub/lib/uchardet.json",
"flathub/lib/libmicrodns.json",
"flathub/lib/libpeas.json",
"flathub/gstreamer-1.0/gstreamer.json",
"testing/graphviz.json",
{
"name": "clapper",
"buildsystem": "meson",
"sources": [
{
"type": "dir",
"path": "../../."
}
]
}
],
"cleanup-commands": [
"mkdir -p /app/lib/ffmpeg",
"mkdir -p /app/extensions/clapper/enhancers",
"ln -s /lib/$FLATPAK_ARCH-linux-*/gstreamer-1.0/libgstpipewire.so /app/lib/gstreamer-1.0/"
]
}

1
pkgs/flatpak/flathub Submodule

Submodule pkgs/flatpak/flathub added at 3a672be190

View File

@@ -0,0 +1,25 @@
{
"name": "dav1d",
"buildsystem": "meson",
"only-arches": [
"x86_64"
],
"config-opts": [
"-Denable_tools=false",
"-Denable_examples=false",
"-Denable_tests=false",
"-Denable_docs=false",
"-Dlogging=false"
],
"cleanup": [
"/include",
"/lib/pkgconfig"
],
"sources": [
{
"type": "git",
"url": "https://code.videolan.org/videolan/dav1d.git",
"branch": "master"
}
]
}

View File

@@ -0,0 +1,38 @@
{
"name": "graphviz",
"buildsystem": "autotools",
"config-opts": [
"--without-x",
"--without-gtk",
"--without-gtkgl",
"--without-gtkglext",
"--without-gdk",
"--without-gdk-pixbuf",
"--without-qt",
"--disable-static",
"--disable-sharp",
"--disable-go",
"--disable-guile",
"--disable-java",
"--disable-javascript",
"--disable-lua",
"--disable-perl",
"--disable-php",
"--disable-python",
"--disable-r",
"--disable-ruby",
"--disable-tcl"
],
"cleanup": [
"/bin",
"/share/man",
"/share/graphviz"
],
"sources": [
{
"type": "archive",
"url": "https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/12.2.1/graphviz-12.2.1.tar.gz",
"sha256": "242bc18942eebda6db4039f108f387ec97856fc91ba47f21e89341c34b554df8"
}
]
}

View File

@@ -0,0 +1,26 @@
{
"name": "gst-plugins-rs",
"buildsystem": "simple",
"only-arches": [
"x86_64"
],
"build-options": {
"build-args": [
"--share=network"
],
"env": {
"CARGO_HOME": "/run/build/gst-plugins-rs/cargo"
}
},
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git",
"branch": "main"
}
],
"build-commands": [
"cargo install cargo-c",
"cargo cinstall --prefix=/app -p gst-plugin-dav1d"
]
}

View File

@@ -0,0 +1,56 @@
{
"name": "gstreamer",
"buildsystem": "meson",
"config-opts": [
"--wrap-mode=nodownload",
"-Dbase=enabled",
"-Dgood=enabled",
"-Dbad=enabled",
"-Dugly=enabled",
"-Dlibav=enabled",
"-Dvaapi=enabled",
"-Dsharp=disabled",
"-Drs=disabled",
"-Dpython=disabled",
"-Ddevtools=disabled",
"-Dges=disabled",
"-Drtsp_server=disabled",
"-Dgst-examples=disabled",
"-Dqt5=disabled",
"-Dtests=disabled",
"-Dexamples=disabled",
"-Dintrospection=enabled",
"-Ddoc=disabled",
"-Dgtk_doc=disabled",
"-Dgpl=enabled",
"-Dgstreamer:benchmarks=disabled",
"-Dgst-plugins-base:gl_api=opengl,gles2",
"-Dgst-plugins-base:gl_platform=egl,glx",
"-Dgst-plugins-good:gtk3=disabled",
"-Dgst-plugins-bad:vulkan=disabled",
"-Dgst-plugins-bad:webrtc=disabled",
"-Dgst-plugins-bad:wasapi=disabled",
"-Dgst-plugins-bad:wasapi2=disabled",
"-Dgst-plugins-bad:winks=disabled",
"-Dgst-plugins-bad:winscreencap=disabled",
"-Dgst-plugins-bad:assrender=enabled",
"-Dgst-plugins-bad:nvcodec=enabled",
"-Dgst-plugins-bad:v4l2codecs=enabled",
"-Dgst-plugins-bad:va=enabled",
"-Dgst-plugins-ugly:mpeg2dec=enabled"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/gstreamer/gstreamer.git",
"branch": "main",
"disable-submodules": true
}
]
}

View File

@@ -0,0 +1,21 @@
{
"name": "libpeas",
"buildsystem": "meson",
"config-opts": [
"--wrap-mode=nodownload",
"-Dgjs=false",
"-Dlua51=false",
"-Dintrospection=false"
],
"sources": [
{
"type": "archive",
"url": "https://download.gnome.org/sources/libpeas/2.0/libpeas-2.0.5.tar.xz",
"sha256": "376f2f73d731b54e13ddbab1d91b6382cf6a980524def44df62add15489de6dd",
"x-checker-data": {
"type": "gnome",
"name": "libpeas"
}
}
]
}

5
pkgs/meson.build Normal file
View File

@@ -0,0 +1,5 @@
is_windows = ['windows'].contains(host_machine.system())
if is_windows
subdir('windows-installer')
endif

View File

@@ -0,0 +1,31 @@
[Setup]
AppName=Clapper
AppVersion=@CLAPPER_APP_VERSION@
AppVerName=Clapper @CLAPPER_APP_VERSION@
VersionInfoVersion=@CLAPPER_APP_VERSION@.0
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
WizardStyle=modern
DefaultDirName={autopf}\Clapper
DefaultGroupName=Clapper
DisableProgramGroupPage=yes
ChangesAssociations=yes
Compression=lzma2
SolidCompression=yes
OutputDir=InstallerOutput
OutputBaseFilename=Clapper_@CLAPPER_APP_VERSION@
SetupIconFile=@PROJECT_ROOT@\src\bin\clapper-app\windows\clapper.ico
LicenseFile=@PROJECT_ROOT@\COPYING-GPL
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "@CLAPPER_APP_DEST@\*"; DestDir: "{app}"; Flags: recursesubdirs replacesameversion
[Icons]
Name: "{autoprograms}\Clapper"; Filename: "{app}\bin\clapper.exe"
Name: "{autodesktop}\Clapper"; Filename: "{app}\bin\clapper.exe"; Tasks: desktopicon
[Registry]
@CLAPPER_APP_REG_ENTRIES@

View File

@@ -0,0 +1,44 @@
# Same as "clapper-app-utils.c"
# FIXME: Have these in one place only
win_extensions = [
'avi', 'claps', 'm2ts', 'mkv', 'mov',
'mp4', 'webm', 'wmv'
]
reg_entries = []
foreach ext : win_extensions
ext_id = 'Clapper.' + ext
exe_path = '{app}\\bin\\clapper.exe'
subkey = 'Software\\Classes\\.' + ext + '\\OpenWithProgids'
reg_entries += 'Root: HKA; Subkey: "@0@"; ValueType: string; ValueName: "@1@"; ValueData: ""; Flags: uninsdeletevalue'.format(subkey, ext_id)
subkey = 'Software\\Classes\\' + ext_id
reg_entries += 'Root: HKA; Subkey: "@0@"; ValueType: string; ValueName: ""; ValueData: "@1@"; Flags: uninsdeletekey'.format(subkey, ext)
subkey = 'Software\\Classes\\' + ext_id + '\\DefaultIcon'
reg_entries += 'Root: HKA; Subkey: "@0@"; ValueType: string; ValueName: ""; ValueData: "@1@,0"'.format(subkey, exe_path)
subkey = 'Software\\Classes\\' + ext_id + '\\shell\\open\\command'
reg_entries += 'Root: HKA; Subkey: "@0@"; ValueType: string; ValueName: ""; ValueData: """@1@"" ""%1"""'.format(subkey, exe_path)
reg_entries += '' # Empty line for clarity
endforeach
# NOTE: In meson replacing "@@" vars after "\" sign does not work.
# For this reason we do not pass app name here.
iss_conf = configuration_data()
iss_conf.set('CLAPPER_APP_VERSION', meson.project_version())
iss_conf.set('CLAPPER_APP_REG_ENTRIES', '\n'.join(reg_entries))
iss_conf.set('PROJECT_ROOT', meson.project_source_root())
# NOTE: We also need to package other dependencies, hence using whole prefix.
# Workaround to reduce package size is to set prefix to some custom dir, install,
# then determine the rest with "ldd" and copy remaining files manually there.
iss_conf.set('CLAPPER_APP_DEST', prefix.replace('/', '\\'))
configure_file(
input: 'clapper.iss.in',
output: 'clapper.iss',
configuration: iss_conf,
)

View File

@@ -0,0 +1,68 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gst/gst.h>
#include <clapper/clapper.h>
#include <adwaita.h>
#include "clapper-app-about-dialog.h"
GtkWidget *
clapper_app_about_dialog_new (void)
{
AdwAboutDialog *about;
GString *string;
gchar *gst_ver, *debug_info;
about = ADW_ABOUT_DIALOG (adw_about_dialog_new_from_appdata (
CLAPPER_APP_RESOURCE_PREFIX "/data/metainfo/" CLAPPER_APP_ID ".metainfo.xml",
NULL));
/* Also show development versions */
adw_about_dialog_set_version (about, CLAPPER_VERSION_S);
/* TRANSLATORS: Put your name(s) here for credits or leave untranslated */
adw_about_dialog_set_translator_credits (about, _("translator-credits"));
string = g_string_new (NULL);
g_string_append_printf (string, "GLib %u.%u.%u\n",
glib_major_version,
glib_minor_version,
glib_micro_version);
g_string_append_printf (string, "GTK %u.%u.%u\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
g_string_append_printf (string, "Adwaita %u.%u.%u\n",
adw_get_major_version (),
adw_get_minor_version (),
adw_get_micro_version ());
gst_ver = gst_version_string ();
g_string_append (string, gst_ver);
g_free (gst_ver);
debug_info = g_string_free_and_steal (string);
adw_about_dialog_set_debug_info (about, debug_info);
g_free (debug_info);
return GTK_WIDGET (about);
}

View File

@@ -0,0 +1,29 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
G_GNUC_INTERNAL
GtkWidget * clapper_app_about_dialog_new (void);
G_END_DECLS

View File

@@ -0,0 +1,861 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <math.h>
#include <glib/gi18n.h>
#include <gst/gst.h>
#include <clapper-gtk/clapper-gtk.h>
#include "clapper-app-application.h"
#include "clapper-app-window.h"
#include "clapper-app-file-dialog.h"
#include "clapper-app-uri-dialog.h"
#include "clapper-app-info-window.h"
#include "clapper-app-preferences-window.h"
#include "clapper-app-about-dialog.h"
#include "clapper-app-utils.h"
#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01)
#define GST_CAT_DEFAULT clapper_app_application_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppApplication
{
GtkApplication parent;
GSettings *settings;
GCancellable *cancellable;
gboolean need_init_state;
};
#define parent_class clapper_app_application_parent_class
G_DEFINE_TYPE (ClapperAppApplication, clapper_app_application, GTK_TYPE_APPLICATION);
struct ClapperPluginFeatureData
{
const gchar *name;
GstRank rank;
};
struct ClapperPluginData
{
const gchar *name;
guint skip_version[3];
struct ClapperPluginFeatureData features[10];
};
typedef struct
{
ClapperAppApplication *app;
guint id;
} ClapperAppWindowData;
typedef struct
{
const gchar *action;
const gchar *accels[3];
} ClapperAppShortcut;
static gboolean
clapper_app_options_get (const gchar *key, const gchar *format, GVariantDict *options,
GObject *src_object, GSettings *settings, gpointer output)
{
if (options && g_variant_dict_lookup (options, key, format, output)) {
return TRUE;
} else if (src_object) {
g_object_get (src_object, key, output, NULL);
return TRUE;
} else if (settings) {
g_settings_get (settings, key, format, output);
return TRUE;
}
return FALSE;
}
static gboolean
clapper_app_options_get_extra (const gchar *key, GVariantDict *options,
const gchar *extra_value, GSettings *settings, gchar **output)
{
if (options && g_variant_dict_lookup (options, key, "s", output)) {
return TRUE;
} else if (extra_value) {
*output = g_strdup (extra_value);
return TRUE;
} else if (settings) {
*output = g_settings_get_string (settings, key);
/* Ensure non-empty string */
if (*output) {
if (strlen (*output) > 0)
return TRUE;
else
g_clear_pointer (output, g_free);
}
}
return FALSE;
}
/*
* Apply options to @dest_window. Option providers will be used in args order.
* If any arg is %NULL it will not be used. For example, passing %NULL as
* @settings will avoid restoring values to @dest_window from GSettings.
*/
static void
clapper_app_apply_options_to_window (ClapperAppWindow *dest_window, GVariantDict *options,
ClapperAppWindow *src_window, GSettings *settings)
{
ClapperPlayer *dest_player;
ClapperAppWindowExtraOptions *src_extra_opts = NULL, *dest_extra_opts = NULL;
GObject *src_player_obj = NULL;
GObject *src_queue_obj = NULL;
gchar *option_str;
gdouble option_dbl;
gint option_int;
gboolean option_bool;
GST_DEBUG ("Applying options to window: %p", dest_window);
dest_player = clapper_app_window_get_player (dest_window);
dest_extra_opts = clapper_app_window_get_extra_options (dest_window);
if (src_window) {
src_player_obj = (GObject *) clapper_app_window_get_player (src_window);
src_queue_obj = (GObject *) clapper_player_get_queue (CLAPPER_PLAYER_CAST (src_player_obj));
src_extra_opts = clapper_app_window_get_extra_options (src_window);
}
/* Apply player values, clamp them to be within allowed range */
if (clapper_app_options_get ("volume", "d", options, src_player_obj, settings, &option_dbl))
clapper_player_set_volume (dest_player, PERCENTAGE_ROUND (CLAMP (option_dbl, 0, 2.0)));
if (clapper_app_options_get ("mute", "b", NULL, src_player_obj, settings, &option_bool))
clapper_player_set_mute (dest_player, option_bool);
if (clapper_app_options_get ("speed", "d", options, src_player_obj, settings, &option_dbl))
clapper_player_set_speed (dest_player, PERCENTAGE_ROUND (CLAMP (option_dbl, 0.05, 2.0)));
if (clapper_app_options_get ("adaptive-start-bitrate", "i", options, src_player_obj, settings, &option_int))
clapper_player_set_adaptive_start_bitrate (dest_player, option_int);
if (clapper_app_options_get ("progression-mode", "i", options, src_queue_obj, settings, &option_int))
clapper_queue_set_progression_mode (clapper_player_get_queue (dest_player), CLAMP (option_int, 0, 4));
if (clapper_app_options_get ("subtitles-enabled", "b", NULL, src_player_obj, settings, &option_bool))
clapper_player_set_subtitles_enabled (dest_player, option_bool);
if (clapper_app_options_get_extra ("video-filter", options,
(src_extra_opts) ? src_extra_opts->video_filter : NULL, NULL, &option_str)) {
clapper_player_set_video_filter (dest_player, clapper_app_utils_make_element (option_str));
g_free (dest_extra_opts->video_filter);
dest_extra_opts->video_filter = option_str;
}
if (clapper_app_options_get_extra ("audio-filter", options,
(src_extra_opts) ? src_extra_opts->audio_filter : NULL, NULL, &option_str)) {
clapper_player_set_audio_filter (dest_player, clapper_app_utils_make_element (option_str));
g_free (dest_extra_opts->audio_filter);
dest_extra_opts->audio_filter = option_str;
}
if (clapper_app_options_get_extra ("video-sink", options,
(src_extra_opts) ? src_extra_opts->video_sink : NULL, NULL, &option_str)) {
clapper_player_set_video_sink (dest_player, clapper_app_utils_make_element (option_str));
g_free (dest_extra_opts->video_sink);
dest_extra_opts->video_sink = option_str;
}
if (clapper_app_options_get_extra ("audio-sink", options,
(src_extra_opts) ? src_extra_opts->audio_sink : NULL, NULL, &option_str)) {
clapper_player_set_audio_sink (dest_player, clapper_app_utils_make_element (option_str));
g_free (dest_extra_opts->audio_sink);
dest_extra_opts->audio_sink = option_str;
}
/* Apply window options */
if ((options && g_variant_dict_contains (options, "fullscreen"))
|| (settings && g_settings_get_boolean (settings, "fullscreened")))
gtk_window_fullscreen (GTK_WINDOW (dest_window));
else if (settings && g_settings_get_boolean (settings, "maximized"))
gtk_window_maximize (GTK_WINDOW (dest_window));
GST_DEBUG ("Options applied");
}
static inline void
_store_settings_from_window (ClapperAppApplication *self, ClapperAppWindow *app_window)
{
ClapperPlayer *player = clapper_app_window_get_player (app_window);
ClapperQueue *queue = clapper_player_get_queue (player);
GtkWindow *window = GTK_WINDOW (app_window);
GST_DEBUG ("Storing current configuration to GSettings");
g_settings_set_double (self->settings, "volume", clapper_player_get_volume (player));
g_settings_set_boolean (self->settings, "mute", clapper_player_get_mute (player));
g_settings_set_double (self->settings, "speed", clapper_player_get_speed (player));
g_settings_set_int (self->settings, "adaptive-start-bitrate",
CLAMP (clapper_player_get_adaptive_bandwidth (player) * 0.8, 0, G_MAXINT));
g_settings_set_boolean (self->settings, "subtitles-enabled", clapper_player_get_subtitles_enabled (player));
g_settings_set_int (self->settings, "progression-mode", clapper_queue_get_progression_mode (queue));
g_settings_set_boolean (self->settings, "maximized", gtk_window_is_maximized (window));
g_settings_set_boolean (self->settings, "fullscreened", gtk_window_is_fullscreen (window));
GST_DEBUG ("Configuration stored");
}
static inline void
_set_initial_plugin_feature_ranks (void)
{
GstRegistry *registry = gst_registry_get ();
guint i;
const struct ClapperPluginData plugins_data[] = {
{
.name = "va",
.skip_version = { 1, 24, 0 },
.features = {
{ "vah264dec", GST_RANK_PRIMARY + 24 },
{ "vah265dec", GST_RANK_PRIMARY + 24 },
{ "vavp8dec", GST_RANK_PRIMARY + 24 },
{ "vavp9dec", GST_RANK_PRIMARY + 24 },
{ "vaav1dec", GST_RANK_PRIMARY + 24 },
{ NULL, 0 }
}
},
{
.name = "nvcodec",
.skip_version = { 1, 24, 0 },
.features = {
{ "nvh264dec", GST_RANK_PRIMARY + 28 },
{ "nvh265dec", GST_RANK_PRIMARY + 28 },
{ "nvvp8dec", GST_RANK_PRIMARY + 28 },
{ "nvvp9dec", GST_RANK_PRIMARY + 28 },
{ "nvav1dec", GST_RANK_PRIMARY + 28 },
{ NULL, 0 }
}
}
};
for (i = 0; i < G_N_ELEMENTS (plugins_data); ++i) {
GList *features;
if (!(features = gst_registry_get_feature_list_by_plugin (
registry, plugins_data[i].name)))
continue;
if (g_list_length (features) > 0) {
guint j;
for (j = 0; G_N_ELEMENTS (plugins_data[i].features); ++j) {
GstPluginFeature *feature;
if (!plugins_data[i].features[j].name)
break;
if (!(feature = gst_registry_lookup_feature (registry,
plugins_data[i].features[j].name)))
continue;
if (!gst_plugin_feature_check_version (feature,
plugins_data[i].skip_version[0],
plugins_data[i].skip_version[1],
plugins_data[i].skip_version[2])) {
gst_plugin_feature_set_rank (feature,
plugins_data[i].features[j].rank);
GST_DEBUG ("Initially set \"%s\" rank to: %i",
plugins_data[i].features[j].name,
plugins_data[i].features[j].rank);
}
gst_object_unref (feature);
}
}
gst_plugin_feature_list_free (features);
}
}
static void
_iter_ranks_func (const gchar *feature_name, GstRank rank,
gboolean from_env, gpointer user_data G_GNUC_UNUSED)
{
GstPluginFeature *feature;
if ((feature = gst_registry_find_feature (gst_registry_get (),
feature_name, GST_TYPE_ELEMENT_FACTORY))) {
gst_plugin_feature_set_rank (feature, rank);
GST_INFO ("Set \"%s\" rank to: %i", feature_name, rank);
gst_object_unref (feature);
}
}
static void
plugin_feature_ranks_settings_changed_cb (GSettings *settings,
gchar *key G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED)
{
clapper_app_utils_iterate_plugin_feature_ranks (settings,
(ClapperAppUtilsIterRanks) _iter_ranks_func, NULL);
}
static void
_assemble_initial_state (GtkWindow *window)
{
GtkWidget *stack = gtk_window_get_child (window);
GtkBuilder *builder = gtk_builder_new_from_resource (
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-initial-state.ui");
GtkWidget *initial_state = GTK_WIDGET (gtk_builder_get_object (builder, "initial_state"));
gtk_stack_add_named (GTK_STACK (stack), initial_state, "initial_state");
gtk_stack_set_visible_child (GTK_STACK (stack), initial_state);
g_object_unref (builder);
}
static void
_show_error_dialog (GError *error, GtkWindow *parent)
{
AdwDialog *dialog;
dialog = adw_alert_dialog_new ("Error", error->message);
adw_alert_dialog_add_response (ADW_ALERT_DIALOG (dialog), "close", _("Close"));
adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (dialog), "close");
adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (dialog), "close");
adw_dialog_present (dialog, GTK_WIDGET (parent));
}
static void
add_files (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
clapper_app_file_dialog_open_files (gtk_app);
}
static void
add_uri (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
clapper_app_uri_dialog_open_uri (gtk_app);
}
static void
clear_queue (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
GtkWindow *window = gtk_application_get_active_window (gtk_app);
ClapperPlayer *player;
ClapperQueue *queue;
while (window && !CLAPPER_APP_IS_WINDOW (window))
window = gtk_window_get_transient_for (window);
player = clapper_app_window_get_player (CLAPPER_APP_WINDOW (window));
queue = clapper_player_get_queue (player);
clapper_queue_clear (queue);
}
static void
new_window (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
GtkWidget *stack = gtk_window_get_child (gtk_application_get_active_window (gtk_app));
const gchar *child_name = gtk_stack_get_visible_child_name (GTK_STACK (stack));
/* Do not allow to open new windows during initial state,
* there already is a free one to use */
if (g_strcmp0 (child_name, "initial_state") != 0) {
ClapperAppWindow *src_window, *dest_window;
src_window = CLAPPER_APP_WINDOW_CAST (gtk_application_get_active_window (gtk_app));
dest_window = CLAPPER_APP_WINDOW_CAST (clapper_app_window_new (gtk_app));
clapper_app_apply_options_to_window (dest_window, NULL, src_window, NULL);
gtk_window_present (GTK_WINDOW (dest_window));
}
}
static void
show_preferences (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
GtkWidget *preferences_window;
preferences_window = clapper_app_preferences_window_new (gtk_app);
gtk_window_present (GTK_WINDOW (preferences_window));
}
static void
show_info (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
GtkWidget *info_window;
GtkWindow *window;
ClapperPlayer *player;
window = gtk_application_get_active_window (gtk_app);
player = clapper_app_window_get_player (CLAPPER_APP_WINDOW (window));
info_window = clapper_app_info_window_new (gtk_app, player);
gtk_window_present (GTK_WINDOW (info_window));
}
static void
_launch_pipeline_cb (GtkFileLauncher *launcher,
GAsyncResult *res, ClapperAppWindowData *win_data)
{
GError *error = NULL;
if (!gtk_file_launcher_launch_finish (launcher, res, &error)) {
if (error->domain != GTK_DIALOG_ERROR || error->code != GTK_DIALOG_ERROR_DISMISSED) {
GtkWindow *window;
GST_ERROR ("Could not launch pipeline preview, reason: %s",
GST_STR_NULL (error->message));
if ((window = gtk_application_get_window_by_id (
GTK_APPLICATION (win_data->app), win_data->id)))
_show_error_dialog (error, window);
}
g_error_free (error);
}
g_free (win_data);
}
static void
_show_pipeline_cb (GObject *source G_GNUC_UNUSED,
GAsyncResult *res, ClapperAppWindowData *win_data)
{
GTask *task = G_TASK (res);
GtkWindow *window;
GFile *svg_file;
GError *error = NULL;
svg_file = (GFile *) g_task_propagate_pointer (task, &error);
window = gtk_application_get_window_by_id (
GTK_APPLICATION (win_data->app), win_data->id);
if (error) {
if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_CANCELLED) {
GST_ERROR ("Could not create pipeline graph file, reason: %s",
GST_STR_NULL (error->message));
if (window)
_show_error_dialog (error, window);
}
g_error_free (error);
g_free (win_data);
return;
}
if (window) {
GtkFileLauncher *launcher = gtk_file_launcher_new (svg_file);
#if GTK_CHECK_VERSION(4,12,0)
gtk_file_launcher_set_always_ask (launcher, TRUE);
#endif
gtk_file_launcher_launch (launcher, window, NULL,
(GAsyncReadyCallback) _launch_pipeline_cb, win_data);
g_object_unref (launcher);
} else {
g_free (win_data);
}
g_object_unref (svg_file);
}
static void
show_pipeline (GSimpleAction *action, GVariant *param, gpointer user_data)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (user_data);
GtkApplication *gtk_app = GTK_APPLICATION (self);
GtkWindow *window;
ClapperAppWindowData *win_data;
window = gtk_application_get_active_window (gtk_app);
while (window && !CLAPPER_APP_IS_WINDOW (window))
window = gtk_window_get_transient_for (window);
if (G_UNLIKELY (window == NULL))
return;
if (self->cancellable) {
g_cancellable_cancel (self->cancellable);
g_object_unref (self->cancellable);
}
self->cancellable = g_cancellable_new ();
win_data = g_new (ClapperAppWindowData, 1);
win_data->app = self;
win_data->id = gtk_application_window_get_id (GTK_APPLICATION_WINDOW (window));
clapper_app_utils_create_pipeline_svg_file_async (
clapper_app_window_get_player (CLAPPER_APP_WINDOW (window)),
self->cancellable, (GAsyncReadyCallback) _show_pipeline_cb, win_data);
}
static void
show_about (GSimpleAction *action, GVariant *param, gpointer user_data)
{
GtkApplication *gtk_app = GTK_APPLICATION (user_data);
GtkWindow *window;
GtkWidget *about_dialog;
window = gtk_application_get_active_window (gtk_app);
about_dialog = clapper_app_about_dialog_new ();
adw_dialog_present (ADW_DIALOG (about_dialog), GTK_WIDGET (window));
}
GApplication *
clapper_app_application_new (void)
{
return g_object_new (CLAPPER_APP_TYPE_APPLICATION,
"application-id", CLAPPER_APP_ID,
"flags", G_APPLICATION_HANDLES_OPEN | G_APPLICATION_HANDLES_COMMAND_LINE,
NULL);
}
static void
clapper_app_application_window_removed (GtkApplication *gtk_app, GtkWindow *window)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (gtk_app);
if (CLAPPER_APP_IS_WINDOW (window)) {
GList *win, *windows = gtk_application_get_windows (gtk_app);
gboolean has_player_windows = FALSE;
for (win = windows; win != NULL; win = win->next) {
GtkWindow *rem_window = GTK_WINDOW (win->data);
if ((has_player_windows = (rem_window != window
&& CLAPPER_APP_IS_WINDOW (rem_window))))
break;
}
/* Last player window is closing, time to store settings */
if (!has_player_windows)
_store_settings_from_window (self, CLAPPER_APP_WINDOW_CAST (window));
}
GTK_APPLICATION_CLASS (parent_class)->window_removed (gtk_app, window);
}
static void
clapper_app_application_activate (GApplication *app)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (app);
GtkApplication *gtk_app = GTK_APPLICATION (app);
GtkWindow *window;
GST_INFO ("Activate");
G_APPLICATION_CLASS (parent_class)->activate (app);
/* When activated through DBus command line does not run,
* so create our first window here instead */
if (!(window = gtk_application_get_active_window (gtk_app))) {
window = GTK_WINDOW (clapper_app_window_new (gtk_app));
clapper_app_apply_options_to_window (CLAPPER_APP_WINDOW_CAST (window),
NULL, NULL, self->settings);
}
if (self->need_init_state) {
_assemble_initial_state (window);
self->need_init_state = FALSE;
}
gtk_window_present (window);
}
static gboolean
clapper_app_application_local_command_line (GApplication *app,
gchar ***arguments, gint *exit_status)
{
gchar **argv = *arguments;
guint i;
GST_INFO ("Handling local command line");
/* NOTE: argv is never NULL, so no need to check */
for (i = 0; argv[i]; ++i) {
/* Handle "-" special case as URI */
if (strlen (argv[i]) == 1 && argv[i][0] == '-') {
g_free (argv[i]);
argv[i] = g_strdup ("fd://0");
}
}
return G_APPLICATION_CLASS (parent_class)->local_command_line (app, arguments, exit_status);
}
static gint
clapper_app_application_command_line (GApplication *app, GApplicationCommandLine *cmd_line)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (app);
ClapperAppWindow *src_window = NULL, *dest_window = NULL;
GtkApplication *gtk_app = GTK_APPLICATION (app);
GVariantDict *options;
GFile **files = NULL;
GSettings *settings;
gint n_files = 0;
GST_INFO ("Handling command line");
options = g_application_command_line_get_options_dict (cmd_line);
dest_window = CLAPPER_APP_WINDOW_CAST (gtk_application_get_active_window (gtk_app));
/* Restore settings only once by making them %NULL when run again */
settings = (!dest_window) ? self->settings : NULL;
if (!dest_window || g_variant_dict_contains (options, "new-window")) {
src_window = dest_window;
dest_window = CLAPPER_APP_WINDOW_CAST (clapper_app_window_new (gtk_app));
}
clapper_app_apply_options_to_window (dest_window, options, src_window, settings);
if (clapper_app_utils_files_from_command_line (cmd_line, &files, &n_files)) {
g_application_open (app, files, n_files,
(g_variant_dict_contains (options, "enqueue")) ? "add-only" : "");
clapper_app_utils_files_free (files);
} else {
g_application_activate (app);
}
return EXIT_SUCCESS;
}
static void
add_item_from_file (GFile *file, ClapperQueue *queue)
{
ClapperMediaItem *item = clapper_media_item_new_from_file (file);
GST_DEBUG ("Adding media item with URI: %s",
clapper_media_item_get_uri (item));
clapper_queue_add_item (queue, item);
gst_object_unref (item);
}
static void
add_item_with_subtitles (GFile *media_file,
GFile *subs_file, ClapperQueue *queue)
{
ClapperMediaItem *item = clapper_media_item_new_from_file (media_file);
gchar *suburi = g_file_get_uri (subs_file);
GST_DEBUG ("Adding media item with URI: %s, SUBURI: %s",
clapper_media_item_get_uri (item), GST_STR_NULL (suburi));
clapper_media_item_set_suburi (item, suburi);
clapper_queue_add_item (queue, item);
gst_object_unref (item);
g_free (suburi);
}
static void
clapper_app_application_open (GApplication *app,
GFile **files, gint n_files, const gchar *hint)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (app);
GtkWindow *window;
ClapperPlayer *player;
ClapperQueue *queue;
guint n_before;
gboolean add_only, handled = FALSE;
GST_INFO ("Open");
/* Since we startup with media,
* no need to show initial state */
self->need_init_state = FALSE;
g_application_activate (app);
g_application_mark_busy (app);
window = gtk_application_get_active_window (GTK_APPLICATION (app));
while (window && !CLAPPER_APP_IS_WINDOW (window))
window = gtk_window_get_transient_for (window);
clapper_app_window_ensure_no_initial_state (CLAPPER_APP_WINDOW (window));
player = clapper_app_window_get_player (CLAPPER_APP_WINDOW (window));
queue = clapper_player_get_queue (player);
n_before = clapper_queue_get_n_items (queue);
/* Special path for opening video with subtitles at once */
if (n_files == 2) {
gboolean first_subs, second_subs;
first_subs = clapper_app_utils_is_subtitles_file (files[0]);
second_subs = clapper_app_utils_is_subtitles_file (files[1]);
if ((handled = first_subs != second_subs)) {
guint media_index, subs_index;
media_index = (second_subs) ? 0 : 1;
subs_index = (media_index + 1) % 2;
add_item_with_subtitles (
files[media_index], files[subs_index], queue);
}
}
if (!handled) {
gint i;
for (i = 0; i < n_files; ++i)
add_item_from_file (files[i], queue);
}
add_only = (g_strcmp0 (hint, "add-only") == 0);
/* Select first thing from added item to play (behave like "open" should),
* when queue was empty first item is automatically selected */
if (!add_only && n_before > 0)
clapper_queue_select_index (queue, n_before);
g_application_unmark_busy (app);
}
static void
clapper_app_application_init (ClapperAppApplication *self)
{
self->need_init_state = TRUE;
}
static void
clapper_app_application_constructed (GObject *object)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (object);
GApplication *app = G_APPLICATION (self);
guint i;
const GOptionEntry app_options[] = {
{ "new-window", 'n', 0, G_OPTION_ARG_NONE, NULL, _("Create a new window"), NULL },
{ "enqueue", 0, 0, G_OPTION_ARG_NONE, NULL, _("Add media to queue in primary application instance"), NULL },
{ "volume", 0, 0, G_OPTION_ARG_DOUBLE, NULL, _("Audio volume to set (0 - 2.0 range)"), NULL },
{ "speed", 0, 0, G_OPTION_ARG_DOUBLE, NULL, _("Playback speed to set (0.05 - 2.0 range)"), NULL },
{ "adaptive-start-bitrate", 0, 0, G_OPTION_ARG_INT, NULL, _("Initial bitrate for adaptive streaming"), NULL },
{ "progression-mode", 0, 0, G_OPTION_ARG_INT, NULL, _("Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"), NULL },
{ "fullscreen", 'f', 0, G_OPTION_ARG_NONE, NULL, _("Set window to be fullscreen"), NULL },
{ "video-filter", 0, 0, G_OPTION_ARG_STRING, NULL, _("Video filter to use (\"none\" to disable)"), NULL },
{ "audio-filter", 0, 0, G_OPTION_ARG_STRING, NULL, _("Audio filter to use (\"none\" to disable)"), NULL },
{ "video-sink", 0, 0, G_OPTION_ARG_STRING, NULL, _("Video sink to use"), NULL },
{ "audio-sink", 0, 0, G_OPTION_ARG_STRING, NULL, _("Audio sink to use"), NULL },
{ NULL }
};
static const GActionEntry app_actions[] = {
{ "add-files", add_files, NULL, NULL, NULL },
{ "add-uri", add_uri, NULL, NULL, NULL },
{ "clear-queue", clear_queue, NULL, NULL, NULL },
{ "new-window", new_window, NULL, NULL, NULL },
{ "info", show_info, NULL, NULL, NULL },
{ "pipeline", show_pipeline, NULL, NULL, NULL },
{ "preferences", show_preferences, NULL, NULL, NULL },
{ "about", show_about, NULL, NULL, NULL },
};
static const ClapperAppShortcut app_shortcuts[] = {
{ "app.add-files", { "<Control>o", NULL, NULL }},
{ "app.add-uri", { "<Control>u", NULL, NULL }},
{ "app.new-window", { "<Control>n", NULL, NULL }},
{ "app.info", { "<Control>i", NULL, NULL }},
{ "app.pipeline", { "<Control><Shift>p", NULL, NULL }},
{ "app.preferences", { "<Control>comma", NULL, NULL }},
{ "app.about", { "F1", NULL, NULL }},
{ "win.toggle-fullscreen", { "F11", "f", NULL }},
{ "win.unfullscreen", { "Escape", NULL, NULL }},
{ "win.auto-resize", { "<Super>r", NULL, NULL }},
{ "win.show-help-overlay", { "<Control>question", NULL, NULL }},
{ "window.close", { "<Control>q", "q", NULL }},
};
/* Override initial ranks, they will be updated
* from both stored settings and env below */
_set_initial_plugin_feature_ranks ();
self->settings = g_settings_new (CLAPPER_APP_ID);
g_signal_connect (self->settings,
"changed::plugin-feature-ranks",
G_CALLBACK (plugin_feature_ranks_settings_changed_cb), self);
plugin_feature_ranks_settings_changed_cb (self->settings, NULL, NULL);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_actions, G_N_ELEMENTS (app_actions), app);
for (i = 0; i < G_N_ELEMENTS (app_shortcuts); ++i)
gtk_application_set_accels_for_action (GTK_APPLICATION (app), app_shortcuts[i].action, app_shortcuts[i].accels);
g_application_set_option_context_parameter_string (app, "[URI1|FILE1] [URI2|FILE2] …");
g_application_add_main_option_entries (app, app_options);
g_application_add_option_group (app, gst_init_get_option_group ());
G_OBJECT_CLASS (parent_class)->constructed (object);
}
static void
clapper_app_application_dispose (GObject *object)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (object);
if (self->cancellable) {
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_app_application_finalize (GObject *object)
{
ClapperAppApplication *self = CLAPPER_APP_APPLICATION_CAST (object);
GST_TRACE ("Finalize");
g_object_unref (self->settings);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_application_class_init (ClapperAppApplicationClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GApplicationClass *application_class = (GApplicationClass *) klass;
GtkApplicationClass *gtk_application_class = (GtkApplicationClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperappapplication", 0,
"Clapper App Application");
gobject_class->constructed = clapper_app_application_constructed;
gobject_class->dispose = clapper_app_application_dispose;
gobject_class->finalize = clapper_app_application_finalize;
gtk_application_class->window_removed = clapper_app_application_window_removed;
application_class->activate = clapper_app_application_activate;
application_class->local_command_line = clapper_app_application_local_command_line;
application_class->command_line = clapper_app_application_command_line;
application_class->open = clapper_app_application_open;
}

View File

@@ -0,0 +1,35 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_APPLICATION (clapper_app_application_get_type())
#define CLAPPER_APP_APPLICATION_CAST(obj) ((ClapperAppApplication *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppApplication, clapper_app_application, CLAPPER_APP, APPLICATION, GtkApplication)
G_GNUC_INTERNAL
GApplication * clapper_app_application_new (void);
G_END_DECLS

View File

@@ -0,0 +1,215 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <gio/gio.h>
#include "clapper-app-file-dialog.h"
#include "clapper-app-utils.h"
static inline void
_open_files_from_model (GtkApplication *gtk_app, GListModel *files_model)
{
GFile **files = NULL;
gint n_files = 0;
if (clapper_app_utils_files_from_list_model (files_model, &files, &n_files)) {
g_application_open (G_APPLICATION (gtk_app), files, n_files, "add-only");
clapper_app_utils_files_free (files);
}
}
static void
_open_files_cb (GtkFileDialog *dialog, GAsyncResult *result, GtkApplication *gtk_app)
{
GError *error = NULL;
GListModel *files_model = gtk_file_dialog_open_multiple_finish (dialog, result, &error);
if (G_LIKELY (error == NULL)) {
_open_files_from_model (gtk_app, files_model);
} else {
if (error->domain != GTK_DIALOG_ERROR || error->code != GTK_DIALOG_ERROR_DISMISSED) {
g_printerr ("Error: %s\n",
(error->message) ? error->message : "Could not open file dialog");
}
g_error_free (error);
}
g_clear_object (&files_model);
}
static void
_open_subtitles_cb (GtkFileDialog *dialog, GAsyncResult *result, ClapperMediaItem *item)
{
GError *error = NULL;
GFile *file = gtk_file_dialog_open_finish (dialog, result, &error);
if (G_LIKELY (error == NULL)) {
gchar *suburi = g_file_get_uri (file);
clapper_media_item_set_suburi (item, suburi);
g_free (suburi);
} else {
if (error->domain != GTK_DIALOG_ERROR || error->code != GTK_DIALOG_ERROR_DISMISSED) {
g_printerr ("Error: %s\n",
(error->message) ? error->message : "Could not open file dialog");
}
g_error_free (error);
}
g_clear_object (&file);
gst_object_unref (item); // Borrowed reference
}
static void
_on_select_file_dir_finish (GFile *file, AdwActionRow *action_row, GError *error)
{
if (G_LIKELY (error == NULL)) {
gchar *path = g_file_get_path (file);
adw_action_row_set_subtitle (action_row, path);
g_free (path);
} else {
if (error->domain != GTK_DIALOG_ERROR || error->code != GTK_DIALOG_ERROR_DISMISSED) {
g_printerr ("Error: %s\n",
(error->message) ? error->message : "Could not open file dialog");
}
g_error_free (error);
}
g_clear_object (&file);
g_object_unref (action_row); // Borrowed reference
}
static void
_select_file_cb (GtkFileDialog *dialog, GAsyncResult *result, AdwActionRow *action_row)
{
GError *error = NULL;
GFile *file = gtk_file_dialog_open_finish (dialog, result, &error);
_on_select_file_dir_finish (file, action_row, error);
}
static void
_select_dir_cb (GtkFileDialog *dialog, GAsyncResult *result, AdwActionRow *action_row)
{
GError *error = NULL;
GFile *file = gtk_file_dialog_select_folder_finish (dialog, result, &error);
_on_select_file_dir_finish (file, action_row, error);
}
static void
_dialog_add_mime_types (GtkFileDialog *dialog, const gchar *filter_name,
const gchar *const *mime_types)
{
GListStore *filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
GtkFileFilter *filter = gtk_file_filter_new ();
guint i;
/* XXX: Windows does not support mime-types file
* filters, so use file extensions instead */
for (i = 0; mime_types[i]; ++i) {
#ifndef G_OS_WIN32
gtk_file_filter_add_mime_type (filter, mime_types[i]);
#else
gtk_file_filter_add_suffix (filter, mime_types[i]);
#endif
}
gtk_file_filter_set_name (filter, filter_name);
g_list_store_append (filters, filter);
gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters));
g_object_unref (filters);
g_object_unref (filter);
}
void
clapper_app_file_dialog_open_files (GtkApplication *gtk_app)
{
GtkWindow *window = gtk_application_get_active_window (gtk_app);
GtkFileDialog *dialog = gtk_file_dialog_new ();
_dialog_add_mime_types (dialog, "Media Files",
#ifndef G_OS_WIN32
clapper_app_utils_get_mime_types ());
#else
clapper_app_utils_get_extensions ());
#endif
gtk_file_dialog_set_modal (dialog, TRUE);
gtk_file_dialog_set_title (dialog, "Add Files");
gtk_file_dialog_open_multiple (dialog, window, NULL,
(GAsyncReadyCallback) _open_files_cb,
gtk_app);
g_object_unref (dialog);
}
void
clapper_app_file_dialog_open_subtitles (GtkApplication *gtk_app, ClapperMediaItem *item)
{
GtkWindow *window = gtk_application_get_active_window (gtk_app);
GtkFileDialog *dialog = gtk_file_dialog_new ();
_dialog_add_mime_types (dialog, "Subtitles",
#ifndef G_OS_WIN32
clapper_app_utils_get_subtitles_mime_types ());
#else
clapper_app_utils_get_subtitles_extensions ());
#endif
gtk_file_dialog_set_modal (dialog, TRUE);
gtk_file_dialog_set_title (dialog, "Open Subtitles");
gtk_file_dialog_open (dialog, window, NULL,
(GAsyncReadyCallback) _open_subtitles_cb,
gst_object_ref (item));
g_object_unref (dialog);
}
void
clapper_app_file_dialog_select_prefs_file (GtkApplication *gtk_app, AdwActionRow *action_row)
{
GtkWindow *window = gtk_application_get_active_window (gtk_app);
GtkFileDialog *dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_modal (dialog, TRUE);
gtk_file_dialog_set_title (dialog, "Select File");
gtk_file_dialog_open (dialog, window, NULL,
(GAsyncReadyCallback) _select_file_cb,
g_object_ref (action_row));
g_object_unref (dialog);
}
void
clapper_app_file_dialog_select_prefs_dir (GtkApplication *gtk_app, AdwActionRow *action_row)
{
GtkWindow *window = gtk_application_get_active_window (gtk_app);
GtkFileDialog *dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_modal (dialog, TRUE);
gtk_file_dialog_set_title (dialog, "Select Folder");
gtk_file_dialog_select_folder (dialog, window, NULL,
(GAsyncReadyCallback) _select_dir_cb,
g_object_ref (action_row));
g_object_unref (dialog);
}

View File

@@ -0,0 +1,39 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <gtk/gtk.h>
#include <adwaita.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
G_GNUC_INTERNAL
void clapper_app_file_dialog_open_files (GtkApplication *gtk_app);
G_GNUC_INTERNAL
void clapper_app_file_dialog_open_subtitles (GtkApplication *gtk_app, ClapperMediaItem *item);
G_GNUC_INTERNAL
void clapper_app_file_dialog_select_prefs_file (GtkApplication *gtk_app, AdwActionRow *action_row);
G_GNUC_INTERNAL
void clapper_app_file_dialog_select_prefs_dir (GtkApplication *gtk_app, AdwActionRow *action_row);
G_END_DECLS

View File

@@ -0,0 +1,185 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "clapper-app-headerbar.h"
#include "clapper-app-utils.h"
#define GST_CAT_DEFAULT clapper_app_headerbar_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppHeaderbar
{
ClapperGtkContainer parent;
GtkWidget *queue_revealer;
GtkWidget *previous_item_revealer;
GtkWidget *next_item_revealer;
GtkWidget *win_buttons_revealer;
GtkDropTarget *drop_target;
gboolean adapt;
};
#define parent_class clapper_app_headerbar_parent_class
G_DEFINE_TYPE (ClapperAppHeaderbar, clapper_app_headerbar, CLAPPER_GTK_TYPE_CONTAINER);
static void
_determine_win_buttons_reveal (ClapperAppHeaderbar *self)
{
gboolean queue_reveal = gtk_revealer_get_reveal_child (GTK_REVEALER (self->queue_revealer));
gtk_revealer_set_reveal_child (GTK_REVEALER (self->win_buttons_revealer),
(queue_reveal) ? !self->adapt : TRUE);
}
static void
container_adapt_cb (ClapperGtkContainer *container, gboolean adapt,
ClapperAppHeaderbar *self)
{
GST_DEBUG_OBJECT (self, "Width adapted: %s", (adapt) ? "yes" : "no");
self->adapt = adapt;
gtk_revealer_set_reveal_child (GTK_REVEALER (self->previous_item_revealer), !adapt);
gtk_revealer_set_reveal_child (GTK_REVEALER (self->next_item_revealer), !adapt);
_determine_win_buttons_reveal (self);
}
static void
queue_reveal_cb (GtkRevealer *revealer,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppHeaderbar *self)
{
_determine_win_buttons_reveal (self);
}
static void
reveal_queue_button_clicked_cb (GtkButton *button, ClapperAppHeaderbar *self)
{
gboolean reveal;
GST_INFO_OBJECT (self, "Reveal queue button clicked");
reveal = gtk_revealer_get_reveal_child (GTK_REVEALER (self->queue_revealer));
gtk_revealer_set_reveal_child (GTK_REVEALER (self->queue_revealer), !reveal);
}
static void
drop_value_notify_cb (GtkDropTarget *drop_target,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppHeaderbar *self)
{
const GValue *value = gtk_drop_target_get_value (drop_target);
if (value && !clapper_app_utils_value_for_item_is_valid (value))
gtk_drop_target_reject (drop_target);
}
static gboolean
drop_cb (GtkDropTarget *drop_target, const GValue *value,
gdouble x, gdouble y, ClapperAppHeaderbar *self)
{
GFile **files = NULL;
gint n_files = 0;
gboolean success = FALSE;
if (clapper_app_utils_files_from_value (value, &files, &n_files)) {
ClapperPlayer *player;
if ((player = clapper_gtk_get_player_from_ancestor (GTK_WIDGET (self)))) {
ClapperQueue *queue = clapper_player_get_queue (player);
gint i;
for (i = 0; i < n_files; ++i) {
ClapperMediaItem *item = clapper_media_item_new_from_file (files[i]);
clapper_queue_add_item (queue, item);
if (i == 0) // Select first added item for playback
clapper_queue_select_item (queue, item);
gst_object_unref (item);
}
success = TRUE;
}
clapper_app_utils_files_free (files);
}
return success;
}
static void
clapper_app_headerbar_init (ClapperAppHeaderbar *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_drop_target_set_gtypes (self->drop_target,
(GType[3]) { GDK_TYPE_FILE_LIST, G_TYPE_FILE, G_TYPE_STRING }, 3);
}
static void
clapper_app_headerbar_dispose (GObject *object)
{
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_APP_TYPE_HEADERBAR);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_app_headerbar_finalize (GObject *object)
{
ClapperAppHeaderbar *self = CLAPPER_APP_HEADERBAR_CAST (object);
GST_TRACE_OBJECT (self, "Finalize");
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_headerbar_class_init (ClapperAppHeaderbarClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperappheaderbar", 0,
"Clapper App Headerbar");
gobject_class->dispose = clapper_app_headerbar_dispose;
gobject_class->finalize = clapper_app_headerbar_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-headerbar.ui");
gtk_widget_class_bind_template_child (widget_class, ClapperAppHeaderbar, queue_revealer);
gtk_widget_class_bind_template_child (widget_class, ClapperAppHeaderbar, previous_item_revealer);
gtk_widget_class_bind_template_child (widget_class, ClapperAppHeaderbar, next_item_revealer);
gtk_widget_class_bind_template_child (widget_class, ClapperAppHeaderbar, win_buttons_revealer);
gtk_widget_class_bind_template_child (widget_class, ClapperAppHeaderbar, drop_target);
gtk_widget_class_bind_template_callback (widget_class, container_adapt_cb);
gtk_widget_class_bind_template_callback (widget_class, reveal_queue_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, queue_reveal_cb);
gtk_widget_class_bind_template_callback (widget_class, drop_value_notify_cb);
gtk_widget_class_bind_template_callback (widget_class, drop_cb);
gtk_widget_class_set_css_name (widget_class, "clapper-app-headerbar");
}

View File

@@ -0,0 +1,31 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <clapper-gtk/clapper-gtk.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_HEADERBAR (clapper_app_headerbar_get_type())
#define CLAPPER_APP_HEADERBAR_CAST(obj) ((ClapperAppHeaderbar *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppHeaderbar, clapper_app_headerbar, CLAPPER_APP, HEADERBAR, ClapperGtkContainer)
G_END_DECLS

View File

@@ -0,0 +1,273 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gst/gst.h>
#include <clapper-gtk/clapper-gtk.h>
#include "clapper-app-info-window.h"
#include "clapper-app-property-row.h"
#include "clapper-app-list-item-utils.h"
#define GST_CAT_DEFAULT clapper_app_info_window_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppInfoWindow
{
AdwWindow parent;
GtkWidget *vstreams_list;
GtkWidget *astreams_list;
GtkWidget *sstreams_list;
GtkWidget *pipeline_button;
ClapperPlayer *player;
};
#define parent_class clapper_app_info_window_parent_class
G_DEFINE_TYPE (ClapperAppInfoWindow, clapper_app_info_window, ADW_TYPE_WINDOW);
enum
{
PROP_0,
PROP_PLAYER,
PROP_LAST
};
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static gchar *
media_duration_closure (ClapperAppInfoWindow *self, gdouble duration)
{
return g_strdup_printf ("%" CLAPPER_TIME_MS_FORMAT, CLAPPER_TIME_MS_ARGS (duration));
}
static gchar *
playback_element_name_closure (ClapperAppInfoWindow *self, GstElement *element)
{
GstElementFactory *factory;
if (!element || !(factory = gst_element_get_factory (element)))
return NULL;
return gst_object_get_name (GST_OBJECT_CAST (factory));
}
static gchar *
playback_decoder_closure (ClapperAppInfoWindow *self, GstElement *decoder)
{
GstElementFactory *factory;
gchar *el_name, *text;
gboolean is_hardware;
if (!decoder || !(factory = gst_element_get_factory (decoder)))
return NULL;
el_name = gst_object_get_name (GST_OBJECT_CAST (factory));
is_hardware = gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_HARDWARE);
text = g_strdup_printf ("%s [%s]", el_name,
(is_hardware) ? _("Hardware") : _("Software"));
g_free (el_name);
return text;
}
static gchar *
playback_sink_closure (ClapperAppInfoWindow *self, GstElement *sink)
{
GstElementFactory *factory;
GParamSpec *pspec;
gchar *text, *el_name, *child_name = NULL;
if (!sink || !(factory = gst_element_get_factory (sink)))
return NULL;
el_name = gst_object_get_name (GST_OBJECT_CAST (factory));
/* We want to show actual sink if it is configurable
* through a property (e.g. sink of "glsinkbin") */
if (GST_IS_BIN (sink)
&& ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (sink), "video-sink"))
|| (pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (sink), "sink")))
&& pspec->value_type == GST_TYPE_ELEMENT) {
GstElement *child = NULL;
GstElementFactory *child_factory;
g_object_get (sink, pspec->name, &child, NULL);
if (child) {
if ((child_factory = gst_element_get_factory (child)))
child_name = gst_object_get_name (GST_OBJECT_CAST (child_factory));
gst_object_unref (child);
}
}
if (child_name) {
text = g_strdup_printf ("%s + %s", el_name, child_name);
g_free (el_name);
g_free (child_name);
} else {
text = el_name;
}
return text;
}
static GtkSelectionModel *
create_no_selection_closure (ClapperAppInfoWindow *self, ClapperStreamList *stream_list)
{
return GTK_SELECTION_MODEL (gtk_no_selection_new (gst_object_ref (stream_list)));
}
static gboolean
has_streams_closure (ClapperAppInfoWindow *self, guint n_streams)
{
return (n_streams > 0);
}
static gboolean
close_cb (GtkWidget *widget, GVariant *args G_GNUC_UNUSED,
gpointer user_data G_GNUC_UNUSED)
{
gtk_window_close (GTK_WINDOW (widget));
return TRUE;
}
GtkWidget *
clapper_app_info_window_new (GtkApplication *gtk_app, ClapperPlayer *player)
{
ClapperAppInfoWindow *window;
window = g_object_new (CLAPPER_APP_TYPE_INFO_WINDOW,
"application", gtk_app,
"transient-for", gtk_application_get_active_window (gtk_app),
"player", player,
NULL);
return GTK_WIDGET (window);
}
static void
clapper_app_info_window_init (ClapperAppInfoWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_widget_remove_css_class (self->vstreams_list, "view");
gtk_widget_remove_css_class (self->astreams_list, "view");
gtk_widget_remove_css_class (self->sstreams_list, "view");
#ifdef HAVE_GRAPHVIZ
gtk_widget_set_visible (self->pipeline_button, TRUE);
#endif
}
static void
clapper_app_info_window_dispose (GObject *object)
{
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_APP_TYPE_INFO_WINDOW);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_app_info_window_finalize (GObject *object)
{
ClapperAppInfoWindow *self = CLAPPER_APP_INFO_WINDOW_CAST (object);
GST_TRACE_OBJECT (self, "Finalize");
gst_clear_object (&self->player);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_info_window_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperAppInfoWindow *self = CLAPPER_APP_INFO_WINDOW_CAST (object);
switch (prop_id) {
case PROP_PLAYER:
g_value_set_object (value, self->player);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_info_window_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperAppInfoWindow *self = CLAPPER_APP_INFO_WINDOW_CAST (object);
switch (prop_id) {
case PROP_PLAYER:
self->player = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_info_window_class_init (ClapperAppInfoWindowClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperappinfowindow", 0,
"Clapper App Info Window");
gobject_class->get_property = clapper_app_info_window_get_property;
gobject_class->set_property = clapper_app_info_window_set_property;
gobject_class->dispose = clapper_app_info_window_dispose;
gobject_class->finalize = clapper_app_info_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-info-window.ui");
param_specs[PROP_PLAYER] = g_param_spec_object ("player",
NULL, NULL, CLAPPER_TYPE_PLAYER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
gtk_widget_class_add_binding (widget_class, GDK_KEY_Escape, 0, close_cb, NULL);
gtk_widget_class_bind_template_child (widget_class, ClapperAppInfoWindow, vstreams_list);
gtk_widget_class_bind_template_child (widget_class, ClapperAppInfoWindow, astreams_list);
gtk_widget_class_bind_template_child (widget_class, ClapperAppInfoWindow, sstreams_list);
gtk_widget_class_bind_template_child (widget_class, ClapperAppInfoWindow, pipeline_button);
gtk_widget_class_bind_template_callback (widget_class, media_duration_closure);
gtk_widget_class_bind_template_callback (widget_class, playback_element_name_closure);
gtk_widget_class_bind_template_callback (widget_class, playback_decoder_closure);
gtk_widget_class_bind_template_callback (widget_class, playback_sink_closure);
gtk_widget_class_bind_template_callback (widget_class, create_no_selection_closure);
gtk_widget_class_bind_template_callback (widget_class, has_streams_closure);
}

View File

@@ -0,0 +1,36 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <adwaita.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_INFO_WINDOW (clapper_app_info_window_get_type())
#define CLAPPER_APP_INFO_WINDOW_CAST(obj) ((ClapperAppInfoWindow *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppInfoWindow, clapper_app_info_window, CLAPPER_APP, INFO_WINDOW, AdwWindow)
G_GNUC_INTERNAL
GtkWidget * clapper_app_info_window_new (GtkApplication *gtk_app, ClapperPlayer *player);
G_END_DECLS

View File

@@ -0,0 +1,83 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include "clapper-app-list-item-utils.h"
gchar *
clapper_app_list_item_make_stream_group_title (GtkListItem *list_item, ClapperStream *stream)
{
ClapperStreamType stream_type = CLAPPER_STREAM_TYPE_UNKNOWN;
guint position = gtk_list_item_get_position (list_item);
gchar *title = NULL;
if (stream)
stream_type = clapper_stream_get_stream_type (stream);
switch (stream_type) {
case CLAPPER_STREAM_TYPE_VIDEO:
title = g_strdup_printf ("%s #%u", _("Video"), position);
break;
case CLAPPER_STREAM_TYPE_AUDIO:
title = g_strdup_printf ("%s #%u", _("Audio"), position);
break;
case CLAPPER_STREAM_TYPE_SUBTITLE:
title = g_strdup_printf ("%s #%u", _("Subtitles"), position);
break;
default:
break;
}
return title;
}
gchar *
clapper_app_list_item_make_resolution (GtkListItem *list_item,
gint width, gint height)
{
return g_strdup_printf ("%ix%i", width, height);
}
gchar *
clapper_app_list_item_make_bitrate (GtkListItem *list_item, guint bitrate)
{
if (bitrate >= 1000000)
return g_strdup_printf ("%.3lf Mbps", (gdouble) bitrate / 1000000);
return g_strdup_printf ("%u kbps", bitrate / 1000);
}
gchar *
clapper_app_list_item_convert_int (GtkListItem *list_item, gint value)
{
return g_strdup_printf ("%i", value);
}
gchar *
clapper_app_list_item_convert_uint (GtkListItem *list_item, guint value)
{
return g_strdup_printf ("%u", value);
}
gchar *
clapper_app_list_item_convert_double (GtkListItem *list_item, gdouble value)
{
return g_strdup_printf ("%.3lf", value);
}

View File

@@ -0,0 +1,46 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <gtk/gtk.h>
#include <clapper/clapper.h>
#include "clapper-app-internal-visibility.h"
G_BEGIN_DECLS
CLAPPER_APP_INTERNAL_API
gchar * clapper_app_list_item_make_stream_group_title (GtkListItem *list_item, ClapperStream *stream);
CLAPPER_APP_INTERNAL_API
gchar * clapper_app_list_item_make_resolution (GtkListItem *list_item, gint width, gint height);
CLAPPER_APP_INTERNAL_API
gchar * clapper_app_list_item_make_bitrate (GtkListItem *list_item, guint value);
CLAPPER_APP_INTERNAL_API
gchar * clapper_app_list_item_convert_int (GtkListItem *list_item, gint value);
CLAPPER_APP_INTERNAL_API
gchar * clapper_app_list_item_convert_uint (GtkListItem *list_item, guint value);
CLAPPER_APP_INTERNAL_API
gchar * clapper_app_list_item_convert_double (GtkListItem *list_item, gdouble value);
G_END_DECLS

View File

@@ -0,0 +1,106 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "clapper-app-media-item-box.h"
struct _ClapperAppMediaItemBox
{
GtkBox parent;
ClapperMediaItem *media_item;
};
enum
{
PROP_0,
PROP_MEDIA_ITEM,
PROP_LAST
};
#define parent_class clapper_app_media_item_box_parent_class
G_DEFINE_TYPE (ClapperAppMediaItemBox, clapper_app_media_item_box, GTK_TYPE_BOX);
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
ClapperMediaItem *
clapper_app_media_item_box_get_media_item (ClapperAppMediaItemBox *self)
{
return self->media_item;
}
static void
clapper_app_media_item_box_init (ClapperAppMediaItemBox *self)
{
}
static void
clapper_app_media_item_box_finalize (GObject *object)
{
ClapperAppMediaItemBox *self = CLAPPER_APP_MEDIA_ITEM_BOX_CAST (object);
gst_clear_object (&self->media_item);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_media_item_box_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperAppMediaItemBox *self = CLAPPER_APP_MEDIA_ITEM_BOX_CAST (object);
switch (prop_id) {
case PROP_MEDIA_ITEM:
g_value_set_object (value, clapper_app_media_item_box_get_media_item (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_media_item_box_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperAppMediaItemBox *self = CLAPPER_APP_MEDIA_ITEM_BOX_CAST (object);
switch (prop_id) {
case PROP_MEDIA_ITEM:
gst_object_replace ((GstObject **) &self->media_item, GST_OBJECT_CAST (g_value_get_object (value)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_media_item_box_class_init (ClapperAppMediaItemBoxClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->get_property = clapper_app_media_item_box_get_property;
gobject_class->set_property = clapper_app_media_item_box_set_property;
gobject_class->finalize = clapper_app_media_item_box_finalize;
param_specs[PROP_MEDIA_ITEM] = g_param_spec_object ("media-item",
NULL, NULL, CLAPPER_TYPE_MEDIA_ITEM,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
}

View File

@@ -0,0 +1,35 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_MEDIA_ITEM_BOX (clapper_app_media_item_box_get_type())
#define CLAPPER_APP_MEDIA_ITEM_BOX_CAST(obj) ((ClapperAppMediaItemBox *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppMediaItemBox, clapper_app_media_item_box, CLAPPER_APP, MEDIA_ITEM_BOX, GtkBox)
G_GNUC_INTERNAL
ClapperMediaItem * clapper_app_media_item_box_get_media_item (ClapperAppMediaItemBox *box);
G_END_DECLS

View File

@@ -0,0 +1,998 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gst/gst.h>
#include <clapper/clapper.h>
#include "clapper-app-preferences-window.h"
#include "clapper-app-application.h"
#include "clapper-app-file-dialog.h"
#include "clapper-app-utils.h"
#define GST_CAT_DEFAULT clapper_app_preferences_window_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppPreferencesWindow
{
AdwPreferencesWindow parent;
AdwComboRow *seek_method_combo_row;
AdwComboRow *seek_unit_combo_row;
AdwSpinRow *seek_value_spin_row;
AdwSwitchRow *server_switch_row;
AdwSpinRow *audio_offset_spin_row;
AdwSpinRow *subtitle_offset_spin_row;
GtkFontDialogButton *font_dialog_button;
GtkStack *enhancers_stack;
GtkWidget *browse_enhancers_page;
GtkWidget *no_enhancers_page;
AdwNavigationPage *enhancers_subpage;
AdwComboRow *enhancers_combo_row;
AdwPreferencesGroup *enhancer_config_group;
AdwNavigationPage *plugins_subpage;
AdwComboRow *plugins_combo_row;
AdwComboRow *features_combo_row;
AdwPreferencesGroup *overrides_group;
GSettings *settings;
GList *enhancer_pspec_rows;
GList *features;
GtkStringList *plugins_list;
GPtrArray *rank_rows;
gulong ranks_setting_changed_id;
gboolean ranking_has_plugins_model;
};
#define parent_class clapper_app_preferences_window_parent_class
G_DEFINE_TYPE (ClapperAppPreferencesWindow, clapper_app_preferences_window, ADW_TYPE_PREFERENCES_WINDOW);
typedef struct
{
ClapperAppPreferencesWindow *prefs;
GHashTable *parsed_overrides;
gboolean updated;
} ClapperAppPreferencesIterRanksData;
typedef struct
{
GSettings *settings;
const gchar *key;
} ClapperAppPreferencesResetData;
typedef struct
{
GSettings *settings;
GParamSpec *pspec;
guint flag;
} ClapperAppPreferencesFlagMapData;
enum
{
PROP_0,
PROP_RANK_ROWS,
PROP_LAST
};
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static void
_flag_map_data_free (ClapperAppPreferencesFlagMapData *data)
{
GST_TRACE ("Destroying flag map data: %p", data);
g_object_unref (data->settings);
g_free (data);
}
static void
_reset_button_closure (ClapperAppPreferencesResetData *data, GClosure *closure)
{
GST_TRACE ("Destroying reset button data: %p", data);
g_object_unref (data->settings);
g_free (data);
}
static void
_reset_button_clicked_cb (GtkButton *button, ClapperAppPreferencesResetData *data)
{
g_settings_reset (data->settings, data->key);
}
static void
file_selection_row_activated_cb (AdwActionRow *action_row, GParamSpec *pspec)
{
GtkApplication *gtk_app;
GtkWidget *window;
if (!(window = gtk_widget_get_ancestor (GTK_WIDGET (action_row), GTK_TYPE_WINDOW))) {
GST_ERROR ("Could not get a hold of parent window");
return;
}
gtk_app = gtk_window_get_application (GTK_WINDOW (window));
if (pspec->flags & CLAPPER_ENHANCER_PARAM_FILEPATH)
clapper_app_file_dialog_select_prefs_file (gtk_app, action_row);
else
clapper_app_file_dialog_select_prefs_dir (gtk_app, action_row);
}
static gboolean
_get_enum_mapping (GValue *value, GVariant *variant, GParamSpec *pspec)
{
GEnumClass *enum_class = G_ENUM_CLASS (g_type_class_peek (pspec->value_type));
const gchar *selected_str = g_variant_get_string (variant, NULL);
guint i, selected = 0;
for (i = 0; i < enum_class->n_values; ++i) {
if (g_strcmp0 (selected_str, enum_class->values[i].value_nick) == 0) {
selected = i;
break;
}
}
g_value_set_uint (value, selected);
return TRUE;
}
static GVariant *
_set_enum_mapping (GValue *value, GVariantType *exp_type, GParamSpec *pspec)
{
GEnumClass *enum_class = G_ENUM_CLASS (g_type_class_peek (pspec->value_type));
guint selected = g_value_get_uint (value);
if (G_UNLIKELY (selected == GTK_INVALID_LIST_POSITION))
selected = 0;
return g_variant_new_string (enum_class->values[selected].value_nick);
}
static gboolean
_get_flag_mapping (GValue *value, GVariant *variant, ClapperAppPreferencesFlagMapData *data)
{
guint flags = g_settings_get_flags (data->settings, data->pspec->name);
g_value_set_boolean (value, (flags & data->flag));
return TRUE;
}
static GVariant *
_set_flag_mapping (GValue *value, GVariantType *exp_type, ClapperAppPreferencesFlagMapData *data)
{
GFlagsClass *flags_class = G_FLAGS_CLASS (g_type_class_peek (data->pspec->value_type));
GStrvBuilder *builder;
GVariant *variant;
gchar **strv;
gboolean active = g_value_get_boolean (value);
guint i, flags = g_settings_get_flags (data->settings, data->pspec->name);
if (active)
flags |= data->flag;
else
flags &= ~(data->flag);
builder = g_strv_builder_new ();
for (i = 0; i < flags_class->n_values; ++i) {
if (flags & flags_class->values[i].value)
g_strv_builder_add (builder, flags_class->values[i].value_nick);
}
strv = g_strv_builder_end (builder);
g_strv_builder_unref (builder);
variant = g_variant_new_strv ((const gchar *const *) strv, -1);
g_strfreev (strv);
return variant;
}
static gboolean
_add_enhancer_config_row (ClapperAppPreferencesWindow *self, GParamSpec *pspec,
GSettings *enhancer_settings)
{
GtkWidget *row = NULL, *reset_button;
ClapperAppPreferencesResetData *reset_data;
const gchar *bind_prop = NULL;
gboolean is_enum = FALSE, is_flags = FALSE;
switch (pspec->value_type) {
case G_TYPE_BOOLEAN:{
row = adw_switch_row_new ();
break;
}
case G_TYPE_INT:{
GParamSpecInt *p = (GParamSpecInt *) pspec;
row = adw_spin_row_new_with_range (p->minimum, p->maximum, 1);
break;
}
case G_TYPE_UINT:{
GParamSpecUInt *p = (GParamSpecUInt *) pspec;
row = adw_spin_row_new_with_range (p->minimum, p->maximum, 1);
break;
}
case G_TYPE_DOUBLE:{
GParamSpecDouble *p = (GParamSpecDouble *) pspec;
row = adw_spin_row_new_with_range (p->minimum, p->maximum, 0.25);
break;
}
case G_TYPE_STRING:{
if (pspec->flags & (CLAPPER_ENHANCER_PARAM_FILEPATH | CLAPPER_ENHANCER_PARAM_DIRPATH)) {
GtkWidget *image;
image = gtk_image_new_from_icon_name ("document-open-symbolic");
gtk_widget_set_margin_end (image, 10); // matches other rows
row = adw_action_row_new ();
adw_action_row_add_suffix (ADW_ACTION_ROW (row), image);
adw_action_row_set_activatable_widget (ADW_ACTION_ROW (row), image);
g_signal_connect (row, "activated",
G_CALLBACK (file_selection_row_activated_cb), pspec);
} else {
row = adw_entry_row_new ();
}
break;
}
default:{
if ((is_enum = G_IS_PARAM_SPEC_ENUM (pspec))) {
GtkExpression *expression;
AdwEnumListModel *enum_model;
row = adw_combo_row_new ();
expression = gtk_property_expression_new (ADW_TYPE_ENUM_LIST_ITEM, NULL, "nick");
adw_combo_row_set_expression (ADW_COMBO_ROW (row), expression);
enum_model = adw_enum_list_model_new (pspec->value_type);
adw_combo_row_set_model (ADW_COMBO_ROW (row), G_LIST_MODEL (enum_model));
gtk_expression_unref (expression);
g_object_unref (enum_model);
break;
} else if ((is_flags = G_IS_PARAM_SPEC_FLAGS (pspec))) {
GFlagsClass *flags_class = G_FLAGS_CLASS (g_type_class_peek (pspec->value_type));
guint i;
row = adw_expander_row_new ();
for (i = 0; i < flags_class->n_values; ++i) {
GtkWidget *flag_row = adw_switch_row_new ();
ClapperAppPreferencesFlagMapData *fm_data;
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (flag_row),
flags_class->values[i].value_nick);
fm_data = g_new (ClapperAppPreferencesFlagMapData, 1);
fm_data->settings = g_object_ref (enhancer_settings);
fm_data->pspec = pspec;
fm_data->flag = flags_class->values[i].value;
GST_TRACE ("Created flag map data: %p", fm_data);
g_settings_bind_with_mapping (enhancer_settings, pspec->name, flag_row,
"active", G_SETTINGS_BIND_DEFAULT,
(GSettingsBindGetMapping) _get_flag_mapping,
(GSettingsBindSetMapping) _set_flag_mapping,
fm_data, (GDestroyNotify) _flag_map_data_free);
adw_expander_row_add_row (ADW_EXPANDER_ROW (row), flag_row);
}
break;
}
g_warning ("Unsupported enhancer \"%s\" property type: %s",
pspec->name, g_type_name (pspec->value_type));
return FALSE;
}
}
reset_button = gtk_button_new_from_icon_name ("view-refresh-symbolic");
gtk_widget_set_tooltip_text (reset_button, _("Restore default"));
gtk_widget_set_halign (reset_button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (reset_button, GTK_ALIGN_CENTER);
gtk_widget_add_css_class (reset_button, "circular");
gtk_widget_set_tooltip_text (row, g_param_spec_get_blurb (pspec));
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), g_param_spec_get_nick (pspec));
if (ADW_IS_SWITCH_ROW (row)) {
bind_prop = "active";
} else if (ADW_IS_SPIN_ROW (row)) {
bind_prop = "value";
adw_spin_row_set_numeric (ADW_SPIN_ROW (row), TRUE);
} else if (ADW_IS_ENTRY_ROW (row)) {
bind_prop = "text";
} else if (ADW_IS_COMBO_ROW (row)) {
bind_prop = "selected";
} else if (ADW_IS_ACTION_ROW (row)) {
bind_prop = "subtitle";
} else if (!is_flags) { // In case of flags we bind individual widgets
g_assert_not_reached ();
return FALSE;
}
if (ADW_IS_ENTRY_ROW (row))
adw_entry_row_add_prefix (ADW_ENTRY_ROW (row), reset_button);
else if (ADW_IS_ACTION_ROW (row))
adw_action_row_add_prefix (ADW_ACTION_ROW (row), reset_button);
else if (ADW_IS_EXPANDER_ROW (row))
adw_expander_row_add_prefix (ADW_EXPANDER_ROW (row), reset_button);
if (is_enum) {
g_settings_bind_with_mapping (enhancer_settings, pspec->name, row,
bind_prop, G_SETTINGS_BIND_DEFAULT,
(GSettingsBindGetMapping) _get_enum_mapping,
(GSettingsBindSetMapping) _set_enum_mapping,
pspec, NULL);
} else if (!is_flags) {
g_settings_bind (enhancer_settings, pspec->name, row,
bind_prop, G_SETTINGS_BIND_DEFAULT);
}
reset_data = g_new (ClapperAppPreferencesResetData, 1);
reset_data->settings = g_object_ref (enhancer_settings);
reset_data->key = pspec->name;
GST_TRACE ("Created reset button data: %p", reset_data);
g_signal_connect_data (reset_button, "clicked",
G_CALLBACK (_reset_button_clicked_cb), reset_data,
(GClosureNotify) _reset_button_closure, G_CONNECT_DEFAULT);
adw_preferences_group_add (self->enhancer_config_group, row);
self->enhancer_pspec_rows = g_list_append (self->enhancer_pspec_rows, row);
return TRUE;
}
static void
selected_enhancer_changed_cb (AdwComboRow *combo_row,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppPreferencesWindow *self)
{
guint selected = adw_combo_row_get_selected (combo_row);
/* Remove old rows */
if (self->enhancer_pspec_rows) {
GList *el;
for (el = self->enhancer_pspec_rows; el; el = g_list_next (el))
adw_preferences_group_remove (self->enhancer_config_group, GTK_WIDGET (el->data));
g_clear_list (&self->enhancer_pspec_rows, NULL);
}
/* Add new rows */
if (selected != GTK_INVALID_LIST_POSITION) {
ClapperEnhancerProxyList *proxies = clapper_get_global_enhancer_proxies ();
ClapperEnhancerProxy *proxy = clapper_enhancer_proxy_list_peek_proxy (proxies, selected);
GParamSpec **pspecs;
guint n_pspecs;
gboolean has_props = FALSE;
if ((pspecs = clapper_enhancer_proxy_get_target_properties (proxy, &n_pspecs))) {
GSettings *enhancer_settings = NULL;
guint i;
for (i = 0; i < n_pspecs; ++i) {
if (pspecs[i]->flags & CLAPPER_ENHANCER_PARAM_GLOBAL) {
if (!enhancer_settings)
enhancer_settings = clapper_enhancer_proxy_get_settings (proxy);
if (enhancer_settings)
has_props |= _add_enhancer_config_row (self, pspecs[i], enhancer_settings);
}
}
g_clear_object (&enhancer_settings);
}
if (!has_props) {
GtkWidget *row = adw_action_row_new ();
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), _("No configurable properties"));
adw_preferences_group_add (self->enhancer_config_group, row);
self->enhancer_pspec_rows = g_list_append (self->enhancer_pspec_rows, row);
}
}
}
static void
enhancers_config_activated_cb (AdwActionRow *action_row, ClapperAppPreferencesWindow *self)
{
/* If no model set yet */
if (!adw_combo_row_get_model (self->enhancers_combo_row)) {
ClapperEnhancerProxyList *proxies = clapper_get_global_enhancer_proxies ();
adw_combo_row_set_model (self->enhancers_combo_row, G_LIST_MODEL (proxies));
adw_combo_row_set_selected (self->enhancers_combo_row, GTK_INVALID_LIST_POSITION);
GST_DEBUG ("Populated names combo row in enhancers subpage");
if (clapper_enhancer_proxy_list_get_n_proxies (proxies) > 0)
gtk_stack_set_visible_child (self->enhancers_stack, self->browse_enhancers_page);
else
gtk_stack_set_visible_child (self->enhancers_stack, self->no_enhancers_page);
}
adw_preferences_window_push_subpage (ADW_PREFERENCES_WINDOW (self), self->enhancers_subpage);
}
/* Sort by plugin name and if the same, sort by element name */
static gint
_compare_plugins_cb (gconstpointer ptr_a, gconstpointer ptr_b)
{
GstPluginFeature *feature_a = GST_PLUGIN_FEATURE_CAST (ptr_a);
GstPluginFeature *feature_b = GST_PLUGIN_FEATURE_CAST (ptr_b);
gint result;
result = strcmp (
gst_plugin_feature_get_plugin_name (feature_a),
gst_plugin_feature_get_plugin_name (feature_b));
if (result == 0) {
result = strcmp (
gst_plugin_feature_get_name (feature_a),
gst_plugin_feature_get_name (feature_b));
}
return result;
}
static gint
_compare_names_cb (gconstpointer ptr_a, gconstpointer ptr_b)
{
GstPluginFeature *feature = GST_PLUGIN_FEATURE_CAST (ptr_a);
const gchar *plugin_name = (const gchar *) ptr_b;
return strcmp (gst_plugin_feature_get_plugin_name (feature), plugin_name);
}
static gboolean
_prefs_rows_compare_func (gconstpointer ptr_a, gconstpointer ptr_b)
{
AdwPreferencesRow *row = (AdwPreferencesRow *) ptr_a;
const gchar *name = (const gchar *) ptr_b;
return (strcmp (adw_preferences_row_get_title (row), name) == 0);
}
static gboolean
_find_rank_overide_for_name (ClapperAppPreferencesWindow *self,
const gchar *plugin_feature, guint *index)
{
return g_ptr_array_find_with_equal_func (self->rank_rows,
plugin_feature, (GEqualFunc) _prefs_rows_compare_func, index);
}
static gboolean
_plugin_feature_filter_cb (GstPluginFeature *feature, gpointer user_data G_GNUC_UNUSED)
{
return GST_IS_ELEMENT_FACTORY (feature);
}
static void
remove_rank_override_button_clicked_cb (GtkButton *button, ClapperAppPreferencesWindow *self)
{
GtkWidget *spin_row;
const gchar *feature_name;
spin_row = gtk_widget_get_ancestor (GTK_WIDGET (button), ADW_TYPE_SPIN_ROW);
feature_name = adw_preferences_row_get_title (ADW_PREFERENCES_ROW (spin_row));
GST_DEBUG ("Removing rank override for: %s", feature_name);
g_ptr_array_remove (self->rank_rows, spin_row);
adw_preferences_group_remove (self->overrides_group, GTK_WIDGET (spin_row));
gtk_widget_set_visible (GTK_WIDGET (self->overrides_group), self->rank_rows->len > 0);
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_RANK_ROWS]);
}
static void
_add_rank_override (ClapperAppPreferencesWindow *self,
const gchar *feature_name, GstRank rank, gboolean from_env)
{
GtkWidget *spin_row, *remove_button;
spin_row = adw_spin_row_new_with_range (0, G_MAXINT, 1);
remove_button = gtk_button_new_from_icon_name ("user-trash-symbolic");
gtk_widget_set_halign (remove_button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (remove_button, GTK_ALIGN_CENTER);
gtk_widget_add_css_class (remove_button, "circular");
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (spin_row), feature_name);
adw_action_row_add_prefix (ADW_ACTION_ROW (spin_row), remove_button);
adw_spin_row_set_numeric (ADW_SPIN_ROW (spin_row), TRUE);
adw_spin_row_set_value (ADW_SPIN_ROW (spin_row), rank);
gtk_widget_set_sensitive (spin_row, !from_env);
if (!from_env) {
g_signal_connect (remove_button, "clicked",
G_CALLBACK (remove_rank_override_button_clicked_cb), self);
}
adw_preferences_group_add (self->overrides_group, spin_row);
g_ptr_array_add (self->rank_rows, spin_row);
}
static void
_iter_ranks_func (const gchar *feature_name, GstRank rank,
gboolean from_env, ClapperAppPreferencesIterRanksData *data)
{
ClapperAppPreferencesWindow *self = data->prefs;
guint index = 0;
if (_find_rank_overide_for_name (self, feature_name, &index)) {
GtkWidget *spin_row = g_ptr_array_index (self->rank_rows, index);
if (rank != adw_spin_row_get_value (ADW_SPIN_ROW (spin_row))) {
adw_spin_row_set_value (ADW_SPIN_ROW (spin_row), rank);
data->updated = TRUE;
}
if (from_env == gtk_widget_get_sensitive (spin_row)) {
gtk_widget_set_sensitive (spin_row, !from_env);
data->updated = TRUE;
}
} else {
_add_rank_override (self, feature_name, rank, from_env);
data->updated = TRUE;
}
g_hash_table_insert (data->parsed_overrides,
g_strdup (feature_name), GINT_TO_POINTER (rank));
}
static void
_update_rank_overrides (ClapperAppPreferencesWindow *self)
{
ClapperAppPreferencesIterRanksData *data;
gint i;
data = g_new (ClapperAppPreferencesIterRanksData, 1);
data->prefs = self;
data->parsed_overrides = g_hash_table_new (g_str_hash, g_str_equal);
data->updated = FALSE;
GST_DEBUG ("Updating rank overrides");
clapper_app_utils_iterate_plugin_feature_ranks (self->settings,
(ClapperAppUtilsIterRanks) _iter_ranks_func, data);
for (i = self->rank_rows->len - 1; i >= 0; --i) {
AdwPreferencesRow *prefs_row = ADW_PREFERENCES_ROW (g_ptr_array_index (self->rank_rows, i));
const gchar *feature_name = adw_preferences_row_get_title (prefs_row);
if (!g_hash_table_contains (data->parsed_overrides, feature_name)) {
g_ptr_array_remove_index (self->rank_rows, i);
adw_preferences_group_remove (self->overrides_group, GTK_WIDGET (prefs_row));
data->updated = TRUE;
}
}
if (data->updated) {
gtk_widget_set_visible (GTK_WIDGET (self->overrides_group), self->rank_rows->len > 0);
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_RANK_ROWS]);
}
g_hash_table_unref (data->parsed_overrides);
g_free (data);
}
static void
add_override_button_clicked_cb (GtkButton *button, ClapperAppPreferencesWindow *self)
{
GstPluginFeature *plugin_feature;
GstRank rank;
GtkStringObject *string_obj;
const gchar *feature_name;
string_obj = GTK_STRING_OBJECT (adw_combo_row_get_selected_item (self->features_combo_row));
/* Should never happen, as button is insensitive when no selection */
if (G_UNLIKELY (string_obj == NULL))
return;
feature_name = gtk_string_object_get_string (string_obj);
GST_DEBUG ("Adding rank override for: %s", feature_name);
plugin_feature = gst_registry_lookup_feature (gst_registry_get (), feature_name);
rank = gst_plugin_feature_get_rank (plugin_feature);
_add_rank_override (self, feature_name, rank, FALSE);
gtk_widget_set_visible (GTK_WIDGET (self->overrides_group), self->rank_rows->len > 0);
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_RANK_ROWS]);
gst_object_unref (plugin_feature);
}
static GtkStringList *
_make_plugin_features_string_list (ClapperAppPreferencesWindow *self, const gchar *plugin_name)
{
GList *features, *feat;
GtkStringList *features_list;
GStrvBuilder *builder;
gchar **features_names;
GST_DEBUG ("Reading plugin features for plugin: %s", plugin_name);
features = g_list_find_custom (self->features, plugin_name, (GCompareFunc) _compare_names_cb);
builder = g_strv_builder_new ();
for (feat = features; feat != NULL; feat = feat->next) {
GstPluginFeature *feature = GST_PLUGIN_FEATURE_CAST (feat->data);
const gchar *feature_name = gst_plugin_feature_get_name (feature);
if (strcmp (gst_plugin_feature_get_plugin_name (feature), plugin_name) != 0)
break;
g_strv_builder_add (builder, feature_name);
}
features_names = g_strv_builder_end (builder);
g_strv_builder_unref (builder);
features_list = gtk_string_list_new ((const gchar *const *) features_names);
g_strfreev (features_names);
GST_DEBUG ("Found plugin features: %u", g_list_model_get_n_items (G_LIST_MODEL (features_list)));
return features_list;
}
static gboolean
list_has_selection_closure (ClapperAppPreferencesWindow *self, guint selected)
{
return (selected != GTK_INVALID_LIST_POSITION);
}
static GtkStringList *
ranking_features_model_closure (ClapperAppPreferencesWindow *self, GtkStringObject *string_obj)
{
if (!string_obj || !self->ranking_has_plugins_model)
return NULL;
return _make_plugin_features_string_list (self, gtk_string_object_get_string (string_obj));
}
static gboolean
add_override_button_sensitive_closure (ClapperAppPreferencesWindow *self,
GtkStringObject *string_obj, GPtrArray *rank_rows)
{
return (string_obj && !_find_rank_overide_for_name (self,
gtk_string_object_get_string (string_obj), NULL));
}
static void
plugin_feature_ranks_settings_changed_cb (GSettings *settings,
gchar *key G_GNUC_UNUSED, ClapperAppPreferencesWindow *self)
{
GST_DEBUG ("Plugin feature ranks stored setting changed");
_update_rank_overrides (self);
}
static void
_ensure_plugins_and_features_lists (ClapperAppPreferencesWindow *self)
{
GList *feat;
GStrvBuilder *builder;
gchar **plugin_names;
const gchar *last_plugin_name = NULL;
/* Return if we were here already. Features can be NULL
* when no plugins are found at specified directory */
if (self->features || self->plugins_list)
return;
GST_DEBUG ("Reading available plugin features...");
self->features = gst_registry_feature_filter (gst_registry_get (),
(GstPluginFeatureFilter) _plugin_feature_filter_cb,
FALSE, NULL);
self->features = g_list_sort (self->features, (GCompareFunc) _compare_plugins_cb);
builder = g_strv_builder_new ();
for (feat = self->features; feat != NULL; feat = feat->next) {
GstPluginFeature *feature = GST_PLUGIN_FEATURE_CAST (feat->data);
const gchar *plugin_name = gst_plugin_feature_get_plugin_name (feature);
if (g_strcmp0 (plugin_name, last_plugin_name) != 0) {
g_strv_builder_add (builder, plugin_name);
last_plugin_name = plugin_name;
}
}
plugin_names = g_strv_builder_end (builder);
g_strv_builder_unref (builder);
GST_DEBUG ("Read all available plugin features");
self->plugins_list = gtk_string_list_new ((const gchar *const *) plugin_names);
g_strfreev (plugin_names);
}
static void
plugin_ranking_activated_cb (AdwActionRow *action_row, ClapperAppPreferencesWindow *self)
{
_ensure_plugins_and_features_lists (self);
if (!self->ranking_has_plugins_model) {
adw_combo_row_set_model (self->plugins_combo_row, G_LIST_MODEL (self->plugins_list));
adw_combo_row_set_selected (self->plugins_combo_row, GTK_INVALID_LIST_POSITION);
GST_DEBUG ("Populated plugins combo row in ranking subpage");
/* This is needed here so we will not populate plugin features row after setting
* model and unset it again after changing back to GTK_INVALID_LIST_POSITION */
self->ranking_has_plugins_model = TRUE;
}
if (self->ranks_setting_changed_id == 0) {
self->ranks_setting_changed_id = g_signal_connect (self->settings,
"changed::plugin-feature-ranks",
G_CALLBACK (plugin_feature_ranks_settings_changed_cb), self);
}
_update_rank_overrides (self);
adw_preferences_window_push_subpage (ADW_PREFERENCES_WINDOW (self), self->plugins_subpage);
}
static void
plugin_ranking_unrealize_cb (GtkWidget *widget, ClapperAppPreferencesWindow *self)
{
GString *string;
gchar *ranks_str;
guint i;
/* Since we are closing ranking subpage, disconnect this
* signal as we do not need to update widgets immediately */
if (self->ranks_setting_changed_id != 0) {
g_signal_handler_disconnect (self->settings, self->ranks_setting_changed_id);
self->ranks_setting_changed_id = 0;
}
GST_DEBUG ("Saving current rank overrides");
string = g_string_new (NULL);
for (i = 0; i < self->rank_rows->len; ++i) {
GtkWidget *spin_row = g_ptr_array_index (self->rank_rows, i);
GstRank rank;
const gchar *feature_name;
/* Insensitive are from env, we do not want to save these */
if (!gtk_widget_get_sensitive (spin_row))
continue;
rank = adw_spin_row_get_value (ADW_SPIN_ROW (spin_row));
feature_name = adw_preferences_row_get_title (ADW_PREFERENCES_ROW (spin_row));
if (string->len == 0)
g_string_append_printf (string, "%s:%i", feature_name, rank);
else
g_string_append_printf (string, ",%s:%i", feature_name, rank);
}
ranks_str = g_string_free_and_steal (string);
g_settings_set_string (self->settings, "plugin-feature-ranks", ranks_str);
g_free (ranks_str);
}
static gchar *
seek_method_name_closure (AdwEnumListItem *list_item, gpointer *user_data G_GNUC_UNUSED)
{
switch (adw_enum_list_item_get_value (list_item)) {
case CLAPPER_PLAYER_SEEK_METHOD_ACCURATE:
return g_strdup (_("Accurate"));
case CLAPPER_PLAYER_SEEK_METHOD_NORMAL:
return g_strdup (_("Normal"));
case CLAPPER_PLAYER_SEEK_METHOD_FAST:
return g_strdup (_("Fast"));
default:
return NULL;
}
}
static gboolean
_get_font_mapping (GValue *value,
GVariant *variant, gpointer user_data G_GNUC_UNUSED)
{
PangoFontDescription *desc;
const gchar *desc_str = g_variant_get_string (variant, NULL);
desc = pango_font_description_from_string (desc_str);
g_value_set_boxed (value, desc);
pango_font_description_free (desc);
return TRUE;
}
static GVariant *
_set_font_mapping (const GValue *value,
const GVariantType *expected_type, gpointer user_data G_GNUC_UNUSED)
{
PangoFontDescription *desc;
gchar *desc_str;
desc = (PangoFontDescription *) g_value_get_boxed (value);
desc_str = pango_font_description_to_string (desc);
return g_variant_new_take_string (desc_str);
}
GtkWidget *
clapper_app_preferences_window_new (GtkApplication *gtk_app)
{
ClapperAppPreferencesWindow *window;
window = g_object_new (CLAPPER_APP_TYPE_PREFERENCES_WINDOW,
"application", gtk_app,
"transient-for", gtk_application_get_active_window (gtk_app),
NULL);
return GTK_WIDGET (window);
}
static void
clapper_app_preferences_window_init (ClapperAppPreferencesWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
self->rank_rows = g_ptr_array_new ();
self->settings = g_settings_new (CLAPPER_APP_ID);
g_settings_bind (self->settings, "seek-method",
self->seek_method_combo_row, "selected", G_SETTINGS_BIND_DEFAULT);
g_settings_bind (self->settings, "seek-unit",
self->seek_unit_combo_row, "selected", G_SETTINGS_BIND_DEFAULT);
g_settings_bind (self->settings, "seek-value",
self->seek_value_spin_row, "value", G_SETTINGS_BIND_DEFAULT);
#if CLAPPER_HAVE_SERVER
g_settings_bind (self->settings, "server-enabled",
self->server_switch_row, "active", G_SETTINGS_BIND_DEFAULT);
#else
gtk_widget_set_sensitive (GTK_WIDGET (self->server_switch_row), FALSE);
#endif
g_settings_bind (self->settings, "audio-offset",
self->audio_offset_spin_row, "value", G_SETTINGS_BIND_DEFAULT);
g_settings_bind (self->settings, "subtitle-offset",
self->subtitle_offset_spin_row, "value", G_SETTINGS_BIND_DEFAULT);
g_settings_bind_with_mapping (self->settings, "subtitle-font-desc",
self->font_dialog_button, "font-desc", G_SETTINGS_BIND_DEFAULT,
(GSettingsBindGetMapping) _get_font_mapping,
(GSettingsBindSetMapping) _set_font_mapping,
NULL, NULL);
}
static void
clapper_app_preferences_window_dispose (GObject *object)
{
ClapperAppPreferencesWindow *self = CLAPPER_APP_PREFERENCES_WINDOW_CAST (object);
g_clear_pointer (&self->rank_rows, g_ptr_array_unref);
gtk_widget_dispose_template (GTK_WIDGET (self), CLAPPER_APP_TYPE_PREFERENCES_WINDOW);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_app_preferences_window_finalize (GObject *object)
{
ClapperAppPreferencesWindow *self = CLAPPER_APP_PREFERENCES_WINDOW_CAST (object);
GST_TRACE_OBJECT (self, "Finalize");
g_object_unref (self->settings);
g_clear_list (&self->enhancer_pspec_rows, NULL);
g_clear_object (&self->plugins_list);
if (self->features)
gst_plugin_feature_list_free (self->features);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_preferences_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperAppPreferencesWindow *self = CLAPPER_APP_PREFERENCES_WINDOW_CAST (object);
switch (prop_id) {
case PROP_RANK_ROWS:
g_value_set_boxed (value, self->rank_rows);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_preferences_window_class_init (ClapperAppPreferencesWindowClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperapppreferenceswindow", 0,
"Clapper App Preferences Window");
gobject_class->get_property = clapper_app_preferences_get_property;
gobject_class->dispose = clapper_app_preferences_window_dispose;
gobject_class->finalize = clapper_app_preferences_window_finalize;
gtk_widget_class_set_template_from_resource (widget_class,
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-preferences-window.ui");
param_specs[PROP_RANK_ROWS] = g_param_spec_boxed ("rank-rows",
NULL, NULL, G_TYPE_PTR_ARRAY,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, seek_method_combo_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, seek_unit_combo_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, seek_value_spin_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, server_switch_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, audio_offset_spin_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, subtitle_offset_spin_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, font_dialog_button);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, enhancers_stack);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, browse_enhancers_page);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, no_enhancers_page);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, enhancers_subpage);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, enhancers_combo_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, enhancer_config_group);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, plugins_subpage);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, plugins_combo_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, features_combo_row);
gtk_widget_class_bind_template_child (widget_class, ClapperAppPreferencesWindow, overrides_group);
gtk_widget_class_bind_template_callback (widget_class, seek_method_name_closure);
gtk_widget_class_bind_template_callback (widget_class, enhancers_config_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, selected_enhancer_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, plugin_ranking_activated_cb);
gtk_widget_class_bind_template_callback (widget_class, plugin_ranking_unrealize_cb);
gtk_widget_class_bind_template_callback (widget_class, list_has_selection_closure);
gtk_widget_class_bind_template_callback (widget_class, ranking_features_model_closure);
gtk_widget_class_bind_template_callback (widget_class, add_override_button_sensitive_closure);
gtk_widget_class_bind_template_callback (widget_class, add_override_button_clicked_cb);
}

View File

@@ -0,0 +1,35 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <adwaita.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_PREFERENCES_WINDOW (clapper_app_preferences_window_get_type())
#define CLAPPER_APP_PREFERENCES_WINDOW_CAST(obj) ((ClapperAppPreferencesWindow *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppPreferencesWindow, clapper_app_preferences_window, CLAPPER_APP, PREFERENCES_WINDOW, AdwPreferencesWindow)
G_GNUC_INTERNAL
GtkWidget * clapper_app_preferences_window_new (GtkApplication *gtk_app);
G_END_DECLS

View File

@@ -0,0 +1,77 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "clapper-app-property-row.h"
struct _ClapperAppPropertyRow
{
AdwActionRow parent;
};
#define parent_class clapper_app_property_row_parent_class
G_DEFINE_TYPE (ClapperAppPropertyRow, clapper_app_property_row, ADW_TYPE_ACTION_ROW);
static inline void
_ensure_subtitle (AdwActionRow *action_row)
{
const gchar *subtitle = adw_action_row_get_subtitle (action_row);
if (!subtitle || strlen (subtitle) == 0)
adw_action_row_set_subtitle (action_row, "-");
}
static void
_subtitle_changed_cb (AdwActionRow *action_row,
GParamSpec *pspec G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED)
{
_ensure_subtitle (action_row);
}
static void
clapper_app_property_row_realize (GtkWidget *widget)
{
_ensure_subtitle (ADW_ACTION_ROW (widget));
g_signal_connect (widget, "notify::subtitle",
G_CALLBACK (_subtitle_changed_cb), NULL);
GTK_WIDGET_CLASS (parent_class)->realize (widget);
}
static void
clapper_app_property_row_unrealize (GtkWidget *widget)
{
g_signal_handlers_disconnect_by_func (widget,
_subtitle_changed_cb, NULL);
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}
static void
clapper_app_property_row_init (ClapperAppPropertyRow *self)
{
gtk_widget_add_css_class (GTK_WIDGET (self), "property");
}
static void
clapper_app_property_row_class_init (ClapperAppPropertyRowClass *klass)
{
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
widget_class->realize = clapper_app_property_row_realize;
widget_class->unrealize = clapper_app_property_row_unrealize;
}

View File

@@ -0,0 +1,31 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <adwaita.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_PROPERTY_ROW (clapper_app_property_row_get_type())
#define CLAPPER_APP_PROPERTY_ROW_CAST(obj) ((ClapperAppPropertyRow *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppPropertyRow, clapper_app_property_row, CLAPPER_APP, PROPERTY_ROW, AdwActionRow)
G_END_DECLS

View File

@@ -0,0 +1,472 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdk.h>
#include "clapper-app-queue-list.h"
#include "clapper-app-queue-selection.h"
#include "clapper-app-media-item-box.h"
#include "clapper-app-utils.h"
#define GST_CAT_DEFAULT clapper_app_queue_list_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppQueueList
{
GtkBox parent;
GtkWidget *progression_drop_down;
GtkWidget *list_view;
GtkWidget *stack;
GtkWidget *stack_default_page;
GtkWidget *stack_trash_page;
GtkDropTarget *trash_drop_target;
GtkDropTarget *drop_target;
GBinding *queue_progression_binding;
GtkWidget *list_target; // store last target
gboolean drop_after; // if should drop below list_target
};
#define parent_class clapper_app_queue_list_parent_class
G_DEFINE_TYPE (ClapperAppQueueList, clapper_app_queue_list, GTK_TYPE_BOX);
typedef struct
{
ClapperMediaItem *item;
GtkWidget *widget;
GdkPaintable *paintable;
gdouble x, y;
} ClapperAppQueueListDragData;
static GdkContentProvider *
drag_item_prepare_cb (GtkDragSource *drag_source, gdouble x, gdouble y, ClapperAppQueueList *self)
{
GtkWidget *list_view, *pickup, *list_widget;
GdkPaintable *paintable;
ClapperMediaItem *item;
ClapperAppQueueListDragData *drag_data;
graphene_point_t p;
/* Ensure no target yet */
self->list_target = NULL;
list_view = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag_source));
pickup = gtk_widget_pick (list_view, x, y, GTK_PICK_DEFAULT);
if (G_UNLIKELY (pickup == NULL) || !CLAPPER_APP_IS_MEDIA_ITEM_BOX (pickup))
return NULL;
list_widget = gtk_widget_get_parent (pickup);
item = clapper_app_media_item_box_get_media_item (CLAPPER_APP_MEDIA_ITEM_BOX_CAST (pickup));
if (G_UNLIKELY (item == NULL || list_widget == NULL))
return NULL;
GST_DEBUG_OBJECT (self, "Preparing drag for: %" GST_PTR_FORMAT, item);
if (!gtk_widget_compute_point (list_view, list_widget, &GRAPHENE_POINT_INIT (x, y), &p))
graphene_point_init (&p, x, y);
paintable = gtk_widget_paintable_new (list_widget);
drag_data = g_new0 (ClapperAppQueueListDragData, 1);
drag_data->item = gst_object_ref (item);
drag_data->widget = g_object_ref_sink (pickup);
drag_data->paintable = gdk_paintable_get_current_image (paintable);
drag_data->x = p.x;
drag_data->y = p.y;
g_object_set_data (G_OBJECT (self), "drag-data", drag_data);
g_object_unref (paintable);
return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, pickup);
}
static void
drag_item_drag_begin_cb (GtkDragSource *drag_source, GdkDrag *drag, ClapperAppQueueList *self)
{
ClapperAppQueueListDragData *drag_data;
GtkWidget *list_view;
drag_data = (ClapperAppQueueListDragData *) g_object_get_data (G_OBJECT (self), "drag-data");
gtk_drag_source_set_icon (drag_source, drag_data->paintable, drag_data->x, drag_data->y);
gtk_widget_set_opacity (drag_data->widget, 0.3);
list_view = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag_source));
gtk_widget_add_css_class (list_view, "dnd");
gtk_stack_set_visible_child (GTK_STACK (self->stack), self->stack_trash_page);
}
static void
drag_item_drag_end_cb (GtkDragSource *drag_source, GdkDrag *drag,
gboolean delete_data, ClapperAppQueueList *self)
{
ClapperAppQueueListDragData *drag_data;
GtkWidget *list_view;
drag_data = (ClapperAppQueueListDragData *) g_object_get_data (G_OBJECT (self), "drag-data");
g_object_set_data (G_OBJECT (self), "drag-data", NULL);
list_view = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drag_source));
gtk_widget_remove_css_class (list_view, "dnd");
gtk_widget_set_opacity (drag_data->widget, 1.0);
gtk_stack_set_visible_child (GTK_STACK (self->stack), self->stack_default_page);
gst_object_unref (drag_data->item);
g_object_unref (drag_data->widget);
g_object_unref (drag_data->paintable);
g_free (drag_data);
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (drag_source));
}
static void
queue_drop_value_notify_cb (GtkDropTarget *drop_target,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppQueueList *self)
{
const GValue *value = gtk_drop_target_get_value (drop_target);
if (value && !clapper_app_utils_value_for_item_is_valid (value))
gtk_drop_target_reject (drop_target);
}
static GdkDragAction
queue_drop_motion_cb (GtkDropTarget *drop_target,
gdouble x, gdouble y, ClapperAppQueueList *self)
{
GtkWidget *list_view, *pickup;
GdkDrop *drop;
list_view = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (drop_target));
pickup = gtk_widget_pick (list_view, x, y, GTK_PICK_DEFAULT);
if (pickup && CLAPPER_APP_IS_MEDIA_ITEM_BOX (pickup)) {
ClapperAppQueueListDragData *drag_data;
GtkWidget *list_widget;
graphene_point_t point;
gint height, margin_top = 0, margin_bottom = 0;
drag_data = (ClapperAppQueueListDragData *) g_object_get_data (G_OBJECT (self), "drag-data");
list_widget = gtk_widget_get_parent (pickup);
height = gtk_widget_get_height (list_widget);
if ((!drag_data || pickup != drag_data->widget)
&& gtk_widget_compute_point (list_view, list_widget, &GRAPHENE_POINT_INIT (x, y), &point)) {
GtkWidget *sibling = NULL;
if (point.y < (gfloat) height / 2) {
if (drag_data)
sibling = gtk_widget_get_prev_sibling (list_widget);
if (!sibling || gtk_widget_get_parent (drag_data->widget) != sibling)
margin_top = height;
} else {
if (drag_data)
sibling = gtk_widget_get_next_sibling (list_widget);
if (!sibling || gtk_widget_get_parent (drag_data->widget) != sibling)
margin_bottom = height;
}
}
if (self->list_target && self->list_target != list_widget) {
gtk_widget_set_margin_top (self->list_target, 0);
gtk_widget_set_margin_bottom (self->list_target, 0);
}
gtk_widget_set_margin_top (list_widget, margin_top);
gtk_widget_set_margin_bottom (list_widget, margin_bottom);
self->list_target = list_widget;
self->drop_after = (margin_bottom > margin_top);
}
if ((drop = gtk_drop_target_get_current_drop (drop_target))) {
GdkContentFormats *formats = gdk_drop_get_formats (drop);
/* If it is a widget we move it from one place to another */
if (gdk_content_formats_contain_gtype (formats, GTK_TYPE_WIDGET))
return GDK_ACTION_MOVE;
}
return GDK_ACTION_COPY;
}
static void
queue_drop_leave_cb (GtkDropTarget *drop_target, ClapperAppQueueList *self)
{
if (self->list_target) {
gtk_widget_set_margin_top (self->list_target, 0);
gtk_widget_set_margin_bottom (self->list_target, 0);
}
}
static gboolean
queue_drop_cb (GtkDropTarget *drop_target, const GValue *value,
gdouble x, gdouble y, ClapperAppQueueList *self)
{
ClapperQueue *queue;
ClapperMediaItem *item;
GtkWidget *pickup;
guint drop_index = 0;
gboolean success = FALSE;
if (G_UNLIKELY (self->list_target == NULL))
return FALSE;
pickup = gtk_widget_get_first_child (self->list_target);
/* Reset margins on drop */
gtk_widget_set_margin_top (self->list_target, 0);
gtk_widget_set_margin_bottom (self->list_target, 0);
self->list_target = NULL;
if (G_UNLIKELY (pickup == NULL) || !CLAPPER_APP_IS_MEDIA_ITEM_BOX (pickup))
return FALSE;
item = clapper_app_media_item_box_get_media_item (CLAPPER_APP_MEDIA_ITEM_BOX_CAST (pickup));
queue = CLAPPER_QUEUE (gst_object_get_parent (GST_OBJECT (item)));
if (G_UNLIKELY (queue == NULL))
return FALSE;
if (!clapper_queue_find_item (queue, item, &drop_index)) {
gst_object_unref (queue);
return FALSE;
}
if (self->drop_after)
drop_index++;
/* Moving item with widget */
if (G_VALUE_HOLDS (value, GTK_TYPE_WIDGET)) {
ClapperAppQueueListDragData *drag_data;
drag_data = (ClapperAppQueueListDragData *) g_object_get_data (G_OBJECT (self), "drag-data");
/* Insert at different place */
if (item != drag_data->item) {
guint index = 0;
if (clapper_queue_find_item (queue, drag_data->item, &index)) {
if (drop_index > index)
drop_index--;
clapper_queue_reposition_item (queue, drag_data->item, drop_index);
success = TRUE;
}
}
} else {
GFile **files = NULL;
gint n_files = 0;
if (clapper_app_utils_files_from_value (value, &files, &n_files)) {
gint i;
for (i = 0; i < n_files; ++i) {
ClapperMediaItem *new_item = clapper_media_item_new_from_file (files[i]);
clapper_queue_insert_item (queue, new_item, drop_index + i);
gst_object_unref (new_item);
}
clapper_app_utils_files_free (files);
success = TRUE;
}
}
gst_object_unref (queue);
return success;
}
static gboolean
trash_drop_cb (GtkDropTarget *drop_target, const GValue *value,
gdouble x, gdouble y, ClapperAppQueueList *self)
{
ClapperAppQueueListDragData *drag_data;
ClapperQueue *queue;
drag_data = (ClapperAppQueueListDragData *) g_object_get_data (G_OBJECT (self), "drag-data");
if ((queue = CLAPPER_QUEUE (gst_object_get_parent (GST_OBJECT (drag_data->item))))) {
clapper_queue_remove_item (queue, drag_data->item);
gst_object_unref (queue);
}
return TRUE;
}
static void
_item_selected_cb (ClapperAppQueueSelection *selection, guint index, ClapperAppQueueList *self)
{
GtkWidget *list_revealer;
/* Auto hide queue list after selection */
list_revealer = gtk_widget_get_ancestor (self->list_view, GTK_TYPE_REVEALER);
if (G_LIKELY (list_revealer != NULL))
gtk_revealer_set_reveal_child (GTK_REVEALER (list_revealer), FALSE);
}
static gboolean
_queue_progression_mode_transform_to_func (GBinding *binding, const GValue *from_value,
GValue *to_value, ClapperAppQueueList *self)
{
ClapperQueueProgressionMode mode = g_value_get_enum (from_value);
g_value_set_uint (to_value, (guint) mode);
return TRUE;
}
static gboolean
_queue_progression_mode_transform_from_func (GBinding *binding, const GValue *from_value,
GValue *to_value, ClapperAppQueueList *self)
{
guint mode = g_value_get_uint (from_value);
if (mode == GTK_INVALID_LIST_POSITION)
return FALSE;
g_value_set_enum (to_value, (ClapperQueueProgressionMode) mode);
return TRUE;
}
static void
clapper_app_queue_list_realize (GtkWidget *widget)
{
ClapperAppQueueList *self = CLAPPER_APP_QUEUE_LIST_CAST (widget);
ClapperPlayer *player;
GTK_WIDGET_CLASS (parent_class)->realize (widget);
GST_TRACE_OBJECT (self, "Realize");
if ((player = clapper_gtk_get_player_from_ancestor (widget))) {
ClapperQueue *queue = clapper_player_get_queue (player);
ClapperAppQueueSelection *selection = clapper_app_queue_selection_new (queue);
g_signal_connect (selection, "item-selected",
G_CALLBACK (_item_selected_cb), self);
self->queue_progression_binding = g_object_bind_property_full (queue, "progression-mode",
self->progression_drop_down, "selected", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
(GBindingTransformFunc) _queue_progression_mode_transform_to_func,
(GBindingTransformFunc) _queue_progression_mode_transform_from_func,
self, NULL);
gtk_list_view_set_model (GTK_LIST_VIEW (self->list_view),
GTK_SELECTION_MODEL (selection));
g_object_unref (selection);
}
}
static void
clapper_app_queue_list_unrealize (GtkWidget *widget)
{
ClapperAppQueueList *self = CLAPPER_APP_QUEUE_LIST_CAST (widget);
GST_TRACE_OBJECT (self, "Unrealize");
g_clear_pointer (&self->queue_progression_binding, g_binding_unbind);
gtk_list_view_set_model (GTK_LIST_VIEW (self->list_view), NULL);
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}
static void
clapper_app_queue_list_init (ClapperAppQueueList *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
/* Does not work correctly with OSD */
gtk_widget_remove_css_class (self->list_view, "view");
gtk_drop_target_set_gtypes (self->trash_drop_target,
(GType[1]) { GTK_TYPE_WIDGET }, 1);
gtk_drop_target_set_gtypes (self->drop_target,
(GType[4]) { GTK_TYPE_WIDGET, GDK_TYPE_FILE_LIST, G_TYPE_FILE, G_TYPE_STRING }, 4);
}
static void
clapper_app_queue_list_dispose (GObject *object)
{
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_APP_TYPE_QUEUE_LIST);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_app_queue_list_finalize (GObject *object)
{
ClapperAppQueueList *self = CLAPPER_APP_QUEUE_LIST_CAST (object);
GST_TRACE_OBJECT (self, "Finalize");
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_queue_list_class_init (ClapperAppQueueListClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperappqueuelist", 0,
"Clapper App Queue List");
gobject_class->dispose = clapper_app_queue_list_dispose;
gobject_class->finalize = clapper_app_queue_list_finalize;
widget_class->realize = clapper_app_queue_list_realize;
widget_class->unrealize = clapper_app_queue_list_unrealize;
gtk_widget_class_set_template_from_resource (widget_class,
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-queue-list.ui");
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, progression_drop_down);
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, list_view);
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, stack);
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, stack_default_page);
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, stack_trash_page);
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, trash_drop_target);
gtk_widget_class_bind_template_child (widget_class, ClapperAppQueueList, drop_target);
gtk_widget_class_bind_template_callback (widget_class, drag_item_prepare_cb);
gtk_widget_class_bind_template_callback (widget_class, drag_item_drag_begin_cb);
gtk_widget_class_bind_template_callback (widget_class, drag_item_drag_end_cb);
gtk_widget_class_bind_template_callback (widget_class, queue_drop_value_notify_cb);
gtk_widget_class_bind_template_callback (widget_class, queue_drop_motion_cb);
gtk_widget_class_bind_template_callback (widget_class, queue_drop_leave_cb);
gtk_widget_class_bind_template_callback (widget_class, queue_drop_cb);
gtk_widget_class_bind_template_callback (widget_class, trash_drop_cb);
gtk_widget_class_set_css_name (widget_class, "clapper-app-queue-list");
}

View File

@@ -0,0 +1,32 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <clapper-gtk/clapper-gtk.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_QUEUE_LIST (clapper_app_queue_list_get_type())
#define CLAPPER_APP_QUEUE_LIST_CAST(obj) ((ClapperAppQueueList *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppQueueList, clapper_app_queue_list, CLAPPER_APP, QUEUE_LIST, GtkBox)
G_END_DECLS

View File

@@ -0,0 +1,107 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <glib.h>
#include "clapper-app-queue-progression-item.h"
struct _ClapperAppQueueProgressionItem
{
GObject parent;
gchar *icon_name;
gchar *label;
};
enum
{
PROP_0,
PROP_ICON_NAME,
PROP_LABEL,
PROP_LAST
};
#define parent_class clapper_app_queue_progression_item_parent_class
G_DEFINE_TYPE (ClapperAppQueueProgressionItem, clapper_app_queue_progression_item, G_TYPE_OBJECT);
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
ClapperAppQueueProgressionItem *
clapper_app_queue_progression_item_new (const gchar *icon_name, const gchar *label)
{
ClapperAppQueueProgressionItem *item;
item = g_object_new (CLAPPER_APP_TYPE_QUEUE_PROGRESSION_ITEM, NULL);
item->icon_name = g_strdup (icon_name);
item->label = g_strdup (label);
return item;
}
static void
clapper_app_queue_progression_item_init (ClapperAppQueueProgressionItem *self)
{
}
static void
clapper_app_queue_progression_item_finalize (GObject *object)
{
ClapperAppQueueProgressionItem *self = CLAPPER_APP_QUEUE_PROGRESSION_ITEM_CAST (object);
g_free (self->icon_name);
g_free (self->label);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_queue_progression_item_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperAppQueueProgressionItem *self = CLAPPER_APP_QUEUE_PROGRESSION_ITEM_CAST (object);
switch (prop_id) {
case PROP_ICON_NAME:
g_value_set_string (value, self->icon_name);
break;
case PROP_LABEL:
g_value_set_string (value, self->label);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_queue_progression_item_class_init (ClapperAppQueueProgressionItemClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->get_property = clapper_app_queue_progression_item_get_property;
gobject_class->finalize = clapper_app_queue_progression_item_finalize;
param_specs[PROP_ICON_NAME] = g_param_spec_string ("icon-name",
NULL, NULL, NULL,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
param_specs[PROP_LABEL] = g_param_spec_string ("label",
NULL, NULL, NULL,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
}

View File

@@ -0,0 +1,33 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_QUEUE_PROGRESSION_ITEM (clapper_app_queue_progression_item_get_type())
#define CLAPPER_APP_QUEUE_PROGRESSION_ITEM_CAST(obj) ((ClapperAppQueueProgressionItem *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppQueueProgressionItem, clapper_app_queue_progression_item, CLAPPER_APP, QUEUE_PROGRESSION_ITEM, GObject)
ClapperAppQueueProgressionItem * clapper_app_queue_progression_item_new (const gchar *icon_name, const gchar *label);
G_END_DECLS

View File

@@ -0,0 +1,109 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "clapper-app-queue-progression-model.h"
#include "clapper-app-queue-progression-item.h"
#include "clapper-app-utils.h"
#define N_PROGRESSION_MODES 5
struct _ClapperAppQueueProgressionModel
{
GObject parent;
GListStore *store;
};
static GType
clapper_app_queue_progression_model_get_item_type (GListModel *model)
{
return CLAPPER_APP_TYPE_QUEUE_PROGRESSION_ITEM;
}
static guint
clapper_app_queue_progression_model_get_n_items (GListModel *model)
{
ClapperAppQueueProgressionModel *self = CLAPPER_APP_QUEUE_PROGRESSION_MODEL_CAST (model);
return g_list_model_get_n_items (G_LIST_MODEL (self->store));
}
static gpointer
clapper_app_queue_progression_model_get_item (GListModel *model, guint index)
{
ClapperAppQueueProgressionModel *self = CLAPPER_APP_QUEUE_PROGRESSION_MODEL_CAST (model);
return g_list_model_get_item (G_LIST_MODEL (self->store), index);
}
static void
_list_model_iface_init (GListModelInterface *iface)
{
iface->get_item_type = clapper_app_queue_progression_model_get_item_type;
iface->get_n_items = clapper_app_queue_progression_model_get_n_items;
iface->get_item = clapper_app_queue_progression_model_get_item;
}
#define parent_class clapper_app_queue_progression_model_parent_class
G_DEFINE_TYPE_WITH_CODE (ClapperAppQueueProgressionModel, clapper_app_queue_progression_model, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, _list_model_iface_init));
static void
clapper_app_queue_progression_model_init (ClapperAppQueueProgressionModel *self)
{
self->store = g_list_store_new (CLAPPER_APP_TYPE_QUEUE_PROGRESSION_ITEM);
}
static void
clapper_app_queue_progression_model_constructed (GObject *object)
{
ClapperAppQueueProgressionModel *self = CLAPPER_APP_QUEUE_PROGRESSION_MODEL_CAST (object);
guint i;
for (i = 0; i < N_PROGRESSION_MODES; ++i) {
ClapperAppQueueProgressionItem *item;
const gchar *icon = NULL, *label = NULL;
clapper_app_utils_parse_progression (i, &icon, &label);
item = clapper_app_queue_progression_item_new (icon, label);
g_list_store_append (self->store, item);
g_object_unref (item);
}
G_OBJECT_CLASS (parent_class)->constructed (object);
}
static void
clapper_app_queue_progression_model_finalize (GObject *object)
{
ClapperAppQueueProgressionModel *self = CLAPPER_APP_QUEUE_PROGRESSION_MODEL_CAST (object);
g_object_unref (self->store);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_queue_progression_model_class_init (ClapperAppQueueProgressionModelClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->constructed = clapper_app_queue_progression_model_constructed;
gobject_class->finalize = clapper_app_queue_progression_model_finalize;
}

View File

@@ -0,0 +1,30 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_QUEUE_PROGRESSION_MODEL (clapper_app_queue_progression_model_get_type())
#define CLAPPER_APP_QUEUE_PROGRESSION_MODEL_CAST(obj) ((ClapperAppQueueProgressionModel *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppQueueProgressionModel, clapper_app_queue_progression_model, CLAPPER_APP, QUEUE_PROGRESSION_MODEL, GObject)
G_END_DECLS

View File

@@ -0,0 +1,364 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <gst/gst.h>
#include <gtk/gtk.h>
#include "clapper-app-queue-selection.h"
#define GST_CAT_DEFAULT clapper_app_queue_selection_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppQueueSelection
{
GObject parent;
ClapperQueue *queue;
ClapperMediaItem *current_item;
guint current_position;
};
enum
{
PROP_0,
PROP_QUEUE,
PROP_LAST
};
enum
{
SIGNAL_ITEM_SELECTED,
SIGNAL_LAST
};
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static guint signals[SIGNAL_LAST] = { 0, };
static GType
clapper_app_queue_selection_get_item_type (GListModel *model)
{
return CLAPPER_TYPE_MEDIA_ITEM;
}
static guint
clapper_app_queue_selection_get_n_items (GListModel *model)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (model);
return (self->queue) ? clapper_queue_get_n_items (self->queue) : 0;
}
static gpointer
clapper_app_queue_selection_get_item (GListModel *model, guint index)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (model);
return (self->queue) ? clapper_queue_get_item (self->queue, index) : NULL;
}
static void
_list_model_iface_init (GListModelInterface *iface)
{
iface->get_item_type = clapper_app_queue_selection_get_item_type;
iface->get_n_items = clapper_app_queue_selection_get_n_items;
iface->get_item = clapper_app_queue_selection_get_item;
}
static inline void
_refresh_current_selection (ClapperAppQueueSelection *self)
{
guint position, old_position, index, n_changed;
position = clapper_queue_get_current_index (self->queue);
/* Clapper -> GTK expected value change.
* Should be the same, but better be safe. */
if (position == CLAPPER_QUEUE_INVALID_POSITION)
position = GTK_INVALID_LIST_POSITION;
/* No change */
if (position == self->current_position)
return;
old_position = self->current_position;
self->current_position = position;
if (old_position == GTK_INVALID_LIST_POSITION) {
index = position;
n_changed = 1;
} else if (position == GTK_INVALID_LIST_POSITION) {
index = old_position;
n_changed = 1;
} else if (position < old_position) {
index = position;
n_changed = old_position - position + 1;
} else {
index = old_position;
n_changed = position - old_position + 1;
}
GST_DEBUG ("Selection changed, index: %u, n_changed: %u", index, n_changed);
gtk_selection_model_selection_changed (GTK_SELECTION_MODEL (self), index, n_changed);
}
static gboolean
clapper_app_queue_selection_is_selected (GtkSelectionModel *model, guint position)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (model);
return (position == self->current_position);
}
static GtkBitset *
clapper_app_queue_selection_get_selection_in_range (GtkSelectionModel *model, guint position, guint n_items)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (model);
GtkBitset *bitset = gtk_bitset_new_empty ();
if (self->current_position != GTK_INVALID_LIST_POSITION
&& position <= self->current_position
&& position + n_items > self->current_position)
gtk_bitset_add (bitset, self->current_position);
return bitset;
}
static gboolean
clapper_app_queue_selection_select_item (GtkSelectionModel *model, guint position, gboolean exclusive)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (model);
gboolean res = TRUE;
if (G_UNLIKELY (self->queue == NULL))
return FALSE;
/* Disallow reselecting of the same item */
if (self->current_position != position)
res = clapper_queue_select_index (self->queue, position);
/* Need to always emit this signal when select item succeeds */
if (G_LIKELY (res))
g_signal_emit (self, signals[SIGNAL_ITEM_SELECTED], 0, position);
return res;
}
static gboolean
clapper_app_queue_selection_unselect_item (GtkSelectionModel *model, guint position)
{
return FALSE;
}
static void
_selection_model_iface_init (GtkSelectionModelInterface *iface)
{
iface->is_selected = clapper_app_queue_selection_is_selected;
iface->get_selection_in_range = clapper_app_queue_selection_get_selection_in_range;
iface->select_item = clapper_app_queue_selection_select_item;
iface->unselect_item = clapper_app_queue_selection_unselect_item;
}
#define parent_class clapper_app_queue_selection_parent_class
G_DEFINE_TYPE_WITH_CODE (ClapperAppQueueSelection, clapper_app_queue_selection, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, _list_model_iface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_SELECTION_MODEL, _selection_model_iface_init))
static void
_queue_model_items_changed_cb (GListModel *model, guint position, guint removed, guint added,
ClapperAppQueueSelection *self)
{
/* Forward event from internal model */
g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
}
static void
_queue_current_index_changed_cb (ClapperQueue *queue,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppQueueSelection *self)
{
_refresh_current_selection (self);
}
/*
* clapper_app_queue_selection_new:
* @queue: (nullable): a #ClapperQueue
*
* Creates a new #ClapperAppQueueSelection instance.
*
* Returns: (transfer full): a new #ClapperAppQueueSelection.
*/
ClapperAppQueueSelection *
clapper_app_queue_selection_new (ClapperQueue *queue)
{
return g_object_new (CLAPPER_APP_TYPE_QUEUE_SELECTION, "queue", queue, NULL);
}
/*
* clapper_app_queue_selection_set_queue:
* @selection: a #ClapperAppQueueSelection
* @queue: a #ClapperQueue
*
* Set #ClapperQueue to be managed by this selection model.
*/
void
clapper_app_queue_selection_set_queue (ClapperAppQueueSelection *self, ClapperQueue *queue)
{
guint n_before = 0, n_after = 0;
g_return_if_fail (CLAPPER_APP_IS_QUEUE_SELECTION (self));
g_return_if_fail (CLAPPER_IS_QUEUE (queue));
if (self->queue) {
g_signal_handlers_disconnect_by_func (G_LIST_MODEL (self->queue), _queue_model_items_changed_cb, self);
g_signal_handlers_disconnect_by_func (self->queue, _queue_current_index_changed_cb, self);
n_before = clapper_queue_get_n_items (self->queue);
}
gst_object_replace ((GstObject **) &self->queue, GST_OBJECT_CAST (queue));
g_signal_connect (G_LIST_MODEL (self->queue), "items-changed",
G_CALLBACK (_queue_model_items_changed_cb), self);
g_signal_connect (self->queue, "notify::current-index",
G_CALLBACK (_queue_current_index_changed_cb), self);
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_QUEUE]);
n_after = clapper_queue_get_n_items (self->queue);
/* Refresh selected item after queue change */
self->current_position = GTK_INVALID_LIST_POSITION;
_queue_model_items_changed_cb (G_LIST_MODEL (self->queue), 0, n_before, n_after, self);
_refresh_current_selection (self);
}
/*
* clapper_app_queue_selection_get_queue:
* @selection: a #ClapperAppQueueSelection
*
* Get #ClapperQueue managed by this selection model.
*
* Returns: (transfer none): #ClapperQueue being managed.
*/
ClapperQueue *
clapper_app_queue_selection_get_queue (ClapperAppQueueSelection *self)
{
g_return_val_if_fail (CLAPPER_APP_IS_QUEUE_SELECTION (self), NULL);
return self->queue;
}
static void
clapper_app_queue_selection_init (ClapperAppQueueSelection *self)
{
self->current_position = GTK_INVALID_LIST_POSITION;
}
static void
clapper_app_queue_selection_finalize (GObject *object)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (object);
if (self->queue) {
g_signal_handlers_disconnect_by_func (G_LIST_MODEL (self->queue), _queue_model_items_changed_cb, self);
g_signal_handlers_disconnect_by_func (self->queue, _queue_current_index_changed_cb, self);
g_object_unref (self->queue);
}
g_clear_object (&self->current_item);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
clapper_app_queue_selection_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (object);
switch (prop_id) {
case PROP_QUEUE:
g_value_set_object (value, clapper_app_queue_selection_get_queue (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_queue_selection_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperAppQueueSelection *self = CLAPPER_APP_QUEUE_SELECTION_CAST (object);
switch (prop_id) {
case PROP_QUEUE:
clapper_app_queue_selection_set_queue (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_queue_selection_class_init (ClapperAppQueueSelectionClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperappqueueselection", 0,
"Clapper App Queue Selection");
gobject_class->get_property = clapper_app_queue_selection_get_property;
gobject_class->set_property = clapper_app_queue_selection_set_property;
gobject_class->finalize = clapper_app_queue_selection_finalize;
/*
* ClapperAppQueueSelection:queue:
*
* The queue being managed.
*/
param_specs[PROP_QUEUE] = g_param_spec_object ("queue",
NULL, NULL, CLAPPER_TYPE_QUEUE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/*
* ClapperAppQueueSelection::item-selected:
* @selection: a #ClapperAppQueueSelection
* @index: an index of selected item
*
* Signals when user selected item within the [iface@Gtk.SelectionModel].
*
* Note that this signal is emitted only when item gets selected from
* the GTK side (also when the same item is reselected). If item was
* changed internally by e.g. progression of [class@Clapper.Queue],
* this signal will not be emitted.
*
* #ClapperAppQueueSelection automatically takes care of having its
* selection in sync with passed [class@Clapper.Queue], so you do not
* have to listen for the changes. This signal is useful if you need
* to differentiate what caused item selection, otherwise use either
* [signal@Gtk.SelectionModel::selection-changed] signal or listen for
* changes of [property@Clapper.Queue:current-item] property.
*/
signals[SIGNAL_ITEM_SELECTED] = g_signal_new ("item-selected",
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
}

View File

@@ -0,0 +1,37 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_QUEUE_SELECTION (clapper_app_queue_selection_get_type())
#define CLAPPER_APP_QUEUE_SELECTION_CAST(obj) ((ClapperAppQueueSelection *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppQueueSelection, clapper_app_queue_selection, CLAPPER_APP, QUEUE_SELECTION, GObject)
ClapperAppQueueSelection * clapper_app_queue_selection_new (ClapperQueue *queue);
void clapper_app_queue_selection_set_queue (ClapperAppQueueSelection *selection, ClapperQueue *queue);
ClapperQueue * clapper_app_queue_selection_get_queue (ClapperAppQueueSelection *selection);
G_END_DECLS

View File

@@ -0,0 +1,42 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "clapper-app-types.h"
#include "clapper-app-headerbar.h"
#include "clapper-app-media-item-box.h"
#include "clapper-app-property-row.h"
#include "clapper-app-queue-list.h"
#include "clapper-app-queue-progression-model.h"
#include "clapper-app-window-state-buttons.h"
/*
* clapper_app_types_init:
*
* Ensure private types that appear in UI files in order for
* GtkBuilder to be able to find them when building templates.
*/
inline void
clapper_app_types_init (void)
{
g_type_ensure (CLAPPER_APP_TYPE_HEADERBAR);
g_type_ensure (CLAPPER_APP_TYPE_MEDIA_ITEM_BOX);
g_type_ensure (CLAPPER_APP_TYPE_PROPERTY_ROW);
g_type_ensure (CLAPPER_APP_TYPE_QUEUE_LIST);
g_type_ensure (CLAPPER_APP_TYPE_QUEUE_PROGRESSION_MODEL);
g_type_ensure (CLAPPER_APP_TYPE_WINDOW_STATE_BUTTONS);
}

View File

@@ -0,0 +1,27 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
G_BEGIN_DECLS
G_GNUC_INTERNAL
void clapper_app_types_init (void);
G_END_DECLS

View File

@@ -0,0 +1,115 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gio/gio.h>
#include <adwaita.h>
#include <gst/gst.h>
#include "clapper-app-uri-dialog.h"
#include "clapper-app-utils.h"
static void
_entry_text_changed_cb (AdwEntryRow *entry,
GParamSpec *pspec G_GNUC_UNUSED, AdwAlertDialog *dialog)
{
const gchar *text = gtk_editable_get_text (GTK_EDITABLE (entry));
gboolean enabled = FALSE;
if (text && *text != '\0') {
enabled = gst_uri_is_valid (text);
}
adw_alert_dialog_set_response_enabled (dialog, "add", enabled);
}
static void
_open_uri_cb (AdwAlertDialog *dialog, GAsyncResult *result, GtkApplication *gtk_app)
{
const gchar *response = adw_alert_dialog_choose_finish (dialog, result);
if (strcmp (response, "add") == 0) {
GtkWidget *extra_child = adw_alert_dialog_get_extra_child (dialog);
AdwEntryRow *entry_row = ADW_ENTRY_ROW (gtk_list_box_get_row_at_index (GTK_LIST_BOX (extra_child), 0));
const gchar *text = gtk_editable_get_text (GTK_EDITABLE (entry_row));
GFile **files = NULL;
gint n_files = 0;
if (clapper_app_utils_files_from_string (text, &files, &n_files)) {
g_application_open (G_APPLICATION (gtk_app), files, n_files, "add-only");
clapper_app_utils_files_free (files);
}
}
}
static void
_read_text_cb (GdkClipboard *clipboard, GAsyncResult *result, GtkWidget *entry_row)
{
GError *error = NULL;
gchar *text = gdk_clipboard_read_text_finish (clipboard, result, &error);
if (G_LIKELY (error == NULL)) {
if (gst_uri_is_valid (text)) {
gtk_editable_set_text (GTK_EDITABLE (entry_row), text);
gtk_editable_select_region (GTK_EDITABLE (entry_row), 0, -1);
}
} else {
/* Common error when clipboard is empty or has unsupported content.
* This we can safely ignore and not notify user. */
if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_NOT_SUPPORTED) {
g_printerr ("Error: %s\n",
(error->message) ? error->message : "Could not read clipboard");
}
g_error_free (error);
}
g_free (text);
}
void
clapper_app_uri_dialog_open_uri (GtkApplication *gtk_app)
{
GtkWindow *window = gtk_application_get_active_window (gtk_app);
GtkBuilder *builder;
AdwAlertDialog *dialog;
GtkWidget *entry_row;
GdkDisplay *display;
builder = gtk_builder_new_from_resource (
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-uri-dialog.ui");
dialog = ADW_ALERT_DIALOG (gtk_builder_get_object (builder, "dialog"));
entry_row = GTK_WIDGET (gtk_builder_get_object (builder, "entry_row"));
g_signal_connect (GTK_EDITABLE (entry_row), "notify::text",
G_CALLBACK (_entry_text_changed_cb), dialog);
if ((display = gdk_display_get_default ())) {
GdkClipboard *clipboard = gdk_display_get_clipboard (display);
gdk_clipboard_read_text_async (clipboard, NULL,
(GAsyncReadyCallback) _read_text_cb, entry_row);
}
/* NOTE: Dialog will automatically unref itself after response */
adw_alert_dialog_choose (dialog, GTK_WIDGET (window), NULL,
(GAsyncReadyCallback) _open_uri_cb,
gtk_app);
g_object_unref (builder);
}

View File

@@ -0,0 +1,28 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
G_GNUC_INTERNAL
void clapper_app_uri_dialog_open_uri (GtkApplication *gtk_app);
G_END_DECLS

View File

@@ -0,0 +1,718 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "clapper-app-utils.h"
#include "clapper-app-media-item-box.h"
#ifdef HAVE_GRAPHVIZ
#include <graphviz/cgraph.h>
#include <graphviz/gvc.h>
#endif
#ifdef G_OS_WIN32
#include <windows.h>
#ifdef HAVE_WIN_PROCESS_THREADS_API
#include <processthreadsapi.h>
#endif
#ifdef HAVE_WIN_TIME_API
#include <timeapi.h>
#endif
#endif
#define GST_CAT_DEFAULT clapper_app_utils_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
void
clapper_app_utils_debug_init (void)
{
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperapputils", 0,
"Clapper App Utils");
}
/* Windows specific functions */
#ifdef G_OS_WIN32
/*
* clapper_app_utils_win_enforce_hi_res_clock:
*
* Enforce high resolution clock by explicitly disabling Windows
* timer resolution power throttling. When disabled, system remembers
* and honors any previous timer resolution request by the process.
*
* By default, Windows 11 may automatically ignore the timer
* resolution requests in certain scenarios.
*/
void
clapper_app_utils_win_enforce_hi_res_clock (void)
{
#ifdef HAVE_WIN_PROCESS_THREADS_API
PROCESS_POWER_THROTTLING_STATE PowerThrottling;
gboolean success;
RtlZeroMemory (&PowerThrottling, sizeof (PowerThrottling));
PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
PowerThrottling.ControlMask = PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
PowerThrottling.StateMask = 0; // Always honor timer resolution requests
success = (gboolean) SetProcessInformation(
GetCurrentProcess (),
ProcessPowerThrottling,
&PowerThrottling,
sizeof (PowerThrottling));
/* Not an error. Older Windows does not have this functionality, but
* also honor hi-res clock by default anyway, so do not print then. */
GST_INFO ("Windows hi-res clock support is %senforced",
(success) ? "" : "NOT ");
#endif
}
/*
* clapper_app_utils_win_hi_res_clock_start:
*
* Start Windows high resolution clock which will improve
* accuracy of various Windows timer APIs and precision
* of #GstSystemClock during playback.
*
* On Windows 10 version 2004 (and older), this function affects
* a global Windows setting. On any other (newer) version this
* will only affect a single process.
*
* Returns: Timer resolution period value.
*/
guint
clapper_app_utils_win_hi_res_clock_start (void)
{
guint resolution = 0;
#ifdef HAVE_WIN_TIME_API
TIMECAPS time_caps;
MMRESULT res;
if ((res = timeGetDevCaps (&time_caps, sizeof (TIMECAPS))) != TIMERR_NOERROR) {
GST_WARNING ("Could not query timer resolution, code: %u", res);
return 0;
}
resolution = MIN (MAX (time_caps.wPeriodMin, 1), time_caps.wPeriodMax);
if ((res = timeBeginPeriod (resolution)) != TIMERR_NOERROR) {
GST_WARNING ("Could not request timer resolution, code: %u", res);
return 0;
}
GST_INFO ("Started Windows hi-res clock, precision: %ums", resolution);
#endif
return resolution;
}
/*
* clapper_app_utils_win_hi_res_clock_stop:
* @resolution: started resolution value (non-zero)
*
* Stop previously started Microsoft Windows high resolution clock.
*/
void
clapper_app_utils_win_hi_res_clock_stop (guint resolution)
{
#ifdef HAVE_WIN_TIME_API
MMRESULT res;
if ((res = timeEndPeriod (resolution)) == TIMERR_NOERROR)
GST_INFO ("Stopped Windows hi-res clock");
else
GST_ERROR ("Could not stop hi-res clock, code: %u", res);
#endif
}
/* Extensions are used only on Windows */
const gchar *const *
clapper_app_utils_get_extensions (void)
{
static const gchar *const all_extensions[] = {
"avi", "claps", "m2ts", "mkv", "mov",
"mp4", "webm", "wmv", NULL
};
return all_extensions;
}
const gchar *const *
clapper_app_utils_get_subtitles_extensions (void)
{
static const gchar *const subs_extensions[] = {
"srt", "vtt", NULL
};
return subs_extensions;
}
#endif // G_OS_WIN32
const gchar *const *
clapper_app_utils_get_mime_types (void)
{
static const gchar *const all_mime_types[] = {
"video/*",
"audio/*",
"application/claps",
"application/x-subrip",
"text/x-ssa",
NULL
};
return all_mime_types;
}
const gchar *const *
clapper_app_utils_get_subtitles_mime_types (void)
{
static const gchar *const subs_mime_types[] = {
"application/x-subrip",
"text/x-ssa",
NULL
};
return subs_mime_types;
}
void
clapper_app_utils_parse_progression (ClapperQueueProgressionMode mode,
const gchar **icon, const gchar **label)
{
const gchar *const icon_names[] = {
"action-unavailable-symbolic",
"media-playlist-consecutive-symbolic",
"media-playlist-repeat-song-symbolic",
"media-playlist-repeat-symbolic",
"media-playlist-shuffle-symbolic",
NULL
};
const gchar *const labels[] = {
_("No progression"),
_("Consecutive"),
_("Repeat item"),
_("Carousel"),
_("Shuffle"),
NULL
};
*icon = icon_names[mode];
*label = labels[mode];
}
gboolean
clapper_app_utils_is_subtitles_file (GFile *file)
{
GFileInfo *info;
gboolean is_subs = FALSE;
if ((info = g_file_query_info (file,
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
G_FILE_QUERY_INFO_NONE,
NULL, NULL))) {
const gchar *content_type = NULL;
if (g_file_info_has_attribute (info,
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)) {
content_type = g_file_info_get_content_type (info);
} else if (g_file_info_has_attribute (info,
G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE)) {
content_type = g_file_info_get_attribute_string (info,
G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
}
is_subs = (content_type && g_strv_contains (
clapper_app_utils_get_subtitles_mime_types (),
content_type));
g_object_unref (info);
}
return is_subs;
}
gboolean
clapper_app_utils_value_for_item_is_valid (const GValue *value)
{
if (G_VALUE_HOLDS (value, GTK_TYPE_WIDGET))
return CLAPPER_APP_IS_MEDIA_ITEM_BOX (g_value_get_object (value));
if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST)
|| G_VALUE_HOLDS (value, G_TYPE_FILE))
return TRUE;
if (G_VALUE_HOLDS (value, G_TYPE_STRING))
return gst_uri_is_valid (g_value_get_string (value));
return FALSE;
}
gboolean
clapper_app_utils_files_from_list_model (GListModel *files_model, GFile ***files, gint *n_files)
{
guint i, len = g_list_model_get_n_items (files_model);
if (G_UNLIKELY (len == 0 || len > G_MAXINT))
return FALSE;
*files = g_new (GFile *, len + 1);
if (n_files)
*n_files = (gint) len;
for (i = 0; i < len; ++i) {
(*files)[i] = g_list_model_get_item (files_model, i);
}
(*files)[i] = NULL;
return TRUE;
}
gboolean
clapper_app_utils_files_from_slist (GSList *file_list, GFile ***files, gint *n_files)
{
GSList *fl;
guint len, i = 0;
len = g_slist_length (file_list);
if (G_UNLIKELY (len == 0 || len > G_MAXINT))
return FALSE;
*files = g_new (GFile *, len + 1);
if (n_files)
*n_files = (gint) len;
for (fl = file_list; fl != NULL; fl = fl->next) {
(*files)[i] = (GFile *) g_object_ref (fl->data);
i++;
}
(*files)[i] = NULL;
return TRUE;
}
gboolean
clapper_app_utils_files_from_string (const gchar *string, GFile ***files, gint *n_files)
{
GSList *slist = NULL;
gchar **uris = g_strsplit (string, "\n", 0);
guint i;
gboolean success;
for (i = 0; uris[i]; ++i) {
const gchar *uri = uris[i];
if (!gst_uri_is_valid (uri))
continue;
slist = g_slist_append (slist, g_file_new_for_uri (uri));
}
g_strfreev (uris);
if (!slist)
return FALSE;
success = clapper_app_utils_files_from_slist (slist, files, n_files);
g_slist_free_full (slist, g_object_unref);
return success;
}
gboolean
clapper_app_utils_files_from_command_line (GApplicationCommandLine *cmd_line, GFile ***files, gint *n_files)
{
GSList *slist = NULL;
gchar **argv;
gint i, argc = 0;
gboolean success;
argv = g_application_command_line_get_arguments (cmd_line, &argc);
for (i = 1; i < argc; ++i)
slist = g_slist_append (slist, g_application_command_line_create_file_for_arg (cmd_line, argv[i]));
g_strfreev (argv);
if (!slist)
return FALSE;
success = clapper_app_utils_files_from_slist (slist, files, n_files);
g_slist_free_full (slist, g_object_unref);
return success;
}
static inline gboolean
_files_from_file (GFile *file, GFile ***files, gint *n_files)
{
*files = g_new (GFile *, 2);
(*files)[0] = g_object_ref (file);
(*files)[1] = NULL;
if (n_files)
*n_files = 1;
return TRUE;
}
gboolean
clapper_app_utils_files_from_value (const GValue *value, GFile ***files, gint *n_files)
{
if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST)) {
return clapper_app_utils_files_from_slist (
(GSList *) g_value_get_boxed (value), files, n_files);
} else if (G_VALUE_HOLDS (value, G_TYPE_FILE)) {
return _files_from_file (
(GFile *) g_value_get_object (value), files, n_files);
} else if (G_VALUE_HOLDS (value, G_TYPE_STRING)) {
return clapper_app_utils_files_from_string (
g_value_get_string (value), files, n_files);
}
return FALSE;
}
void
clapper_app_utils_files_free (GFile **files)
{
gint i;
for (i = 0; files[i]; ++i)
g_object_unref (files[i]);
g_free (files);
}
static inline gboolean
_parse_feature_name (gchar *str, const gchar **feature_name)
{
if (!str)
return FALSE;
g_strstrip (str);
if (str[0] == '\0')
return FALSE;
*feature_name = str;
return TRUE;
}
static inline gboolean
_parse_feature_rank (gchar *str, GstRank *rank)
{
if (!str)
return FALSE;
g_strstrip (str);
if (str[0] == '\0')
return FALSE;
if (g_ascii_isdigit (str[0])) {
gulong l;
gchar *endptr;
l = strtoul (str, &endptr, 10);
if (endptr > str && endptr[0] == 0) {
*rank = (GstRank) l;
} else {
return FALSE;
}
} else if (g_ascii_strcasecmp (str, "NONE") == 0) {
*rank = GST_RANK_NONE;
} else if (g_ascii_strcasecmp (str, "MARGINAL") == 0) {
*rank = GST_RANK_MARGINAL;
} else if (g_ascii_strcasecmp (str, "SECONDARY") == 0) {
*rank = GST_RANK_SECONDARY;
} else if (g_ascii_strcasecmp (str, "PRIMARY") == 0) {
*rank = GST_RANK_PRIMARY;
} else if (g_ascii_strcasecmp (str, "MAX") == 0) {
*rank = (GstRank) G_MAXINT;
} else {
return FALSE;
}
return TRUE;
}
void
clapper_app_utils_iterate_plugin_feature_ranks (GSettings *settings,
ClapperAppUtilsIterRanks callback, gpointer user_data)
{
gchar **split, **walk, *stored_overrides;
const gchar *env_overrides;
gboolean from_env = FALSE;
stored_overrides = g_settings_get_string (settings, "plugin-feature-ranks");
env_overrides = g_getenv ("GST_PLUGIN_FEATURE_RANK");
/* Iterate from GSettings, then from ENV */
parse_overrides:
split = g_strsplit ((from_env) ? env_overrides : stored_overrides, ",", 0);
for (walk = split; *walk; walk++) {
gchar **values;
if (!strchr (*walk, ':'))
continue;
values = g_strsplit (*walk, ":", 2);
if (g_strv_length (values) == 2) {
GstRank rank;
const gchar *feature_name;
if (_parse_feature_name (values[0], &feature_name)
&& _parse_feature_rank (values[1], &rank))
callback (feature_name, rank, from_env, user_data);
}
g_strfreev (values);
}
g_strfreev (split);
if (!from_env && env_overrides) {
from_env = TRUE;
goto parse_overrides;
}
g_free (stored_overrides);
}
GstElement *
clapper_app_utils_make_element (const gchar *string)
{
gchar *char_loc;
if (strcmp (string, "none") == 0)
return NULL;
char_loc = strchr (string, ' ');
if (char_loc) {
GstElement *element;
GError *error = NULL;
element = gst_parse_bin_from_description (string, TRUE, &error);
if (error) {
GST_ERROR ("Bin parse error: \"%s\", reason: %s", string, error->message);
g_error_free (error);
}
return element;
}
return gst_element_factory_make (string, NULL);
}
/*
* _get_tmp_dir:
* @subdir: (nullable): an optional subdirectory
*
* Returns: (transfer full): a newly constructed #GFile
*/
static inline GFile *
_get_tmp_dir (const gchar *subdir)
{
/* XXX: System tmp directory does not work within containers such as Flatpak
* for our usage with file launcher, so make our own temp in app data dir */
return g_file_new_build_filename (
g_get_user_data_dir (), CLAPPER_APP_ID, "tmp", subdir, NULL);
}
#ifdef HAVE_GRAPHVIZ
static GFile *
_create_tmp_subdir (const gchar *subdir, GCancellable *cancellable, GError **error)
{
GFile *tmp_dir;
GError *my_error = NULL;
tmp_dir = _get_tmp_dir (subdir);
if (!g_file_make_directory_with_parents (tmp_dir, cancellable, &my_error)) {
if (my_error->domain != G_IO_ERROR || my_error->code != G_IO_ERROR_EXISTS) {
*error = g_error_copy (my_error);
g_clear_object (&tmp_dir); // return NULL
}
g_error_free (my_error);
}
return tmp_dir;
}
#endif
static void
_create_pipeline_svg_file_in_thread (GTask *task, GObject *source G_GNUC_UNUSED,
ClapperPlayer *player, GCancellable *cancellable)
{
GFile *tmp_file = NULL;
GError *error = NULL;
#ifdef HAVE_GRAPHVIZ
GFile *tmp_subdir;
Agraph_t *graph;
GVC_t *gvc;
gchar *path, *template = NULL, *dot_data = NULL, *img_data = NULL;
gint fd;
gsize size = 0;
if (!(tmp_subdir = _create_tmp_subdir ("pipelines", cancellable, &error)))
goto finish;
path = g_file_get_path (tmp_subdir);
g_object_unref (tmp_subdir);
template = g_build_filename (path, "pipeline-XXXXXX.svg", NULL);
g_free (path);
fd = g_mkstemp (template); // Modifies template to actual filename
if (G_UNLIKELY (fd == -1)) {
g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
"Could not open temp file for writing");
goto finish;
}
dot_data = clapper_player_make_pipeline_graph (player, GST_DEBUG_GRAPH_SHOW_ALL);
if (g_cancellable_is_cancelled (cancellable))
goto close_and_finish;
graph = agmemread (dot_data);
gvc = gvContext ();
gvLayout (gvc, graph, "dot");
#ifdef HAVE_GVC_13
gvRenderData (gvc, graph, "svg", &img_data, &size);
#else
{
guint tmp_size = 0; // Temporary uint to satisfy older API
gvRenderData (gvc, graph, "svg", &img_data, &tmp_size);
size = tmp_size;
}
#endif
agclose (graph);
gvFreeContext (gvc);
if (g_cancellable_is_cancelled (cancellable))
goto close_and_finish;
if (write (fd, img_data, size) != -1) {
tmp_file = g_file_new_for_path (template);
} else {
g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
"Could not write data to temp file");
}
close_and_finish:
/* Always close the file IO */
if (G_UNLIKELY (close (fd) == -1))
GST_ERROR ("Could not close temp file!");
finish:
g_free (template);
g_free (dot_data);
g_free (img_data);
#else
g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
"Cannot create graph file when compiled without Graphviz");
#endif
if (tmp_file)
g_task_return_pointer (task, tmp_file, (GDestroyNotify) g_object_unref);
else
g_task_return_error (task, error);
}
void
clapper_app_utils_create_pipeline_svg_file_async (ClapperPlayer *player,
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
{
GTask *task;
task = g_task_new (NULL, cancellable, callback, user_data);
g_task_set_task_data (task, gst_object_ref (player), (GDestroyNotify) gst_object_unref);
g_task_run_in_thread (task, (GTaskThreadFunc) _create_pipeline_svg_file_in_thread);
g_object_unref (task);
}
static gboolean
_delete_dir_recursive (GFile *dir, GError **error)
{
GFileEnumerator *dir_enum;
if ((dir_enum = g_file_enumerate_children (dir,
G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, error))) {
while (TRUE) {
GFileInfo *info = NULL;
GFile *child = NULL;
if (!g_file_enumerator_iterate (dir_enum, &info,
&child, NULL, error) || !info)
break;
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
if (!_delete_dir_recursive (child, error))
break;
} else if (!g_file_delete (child, NULL, error)) {
break;
}
}
g_object_unref (dir_enum);
}
if (*error != NULL)
return FALSE;
return g_file_delete (dir, NULL, error);
}
void
clapper_app_utils_delete_tmp_dir (void)
{
GFile *tmp_dir = _get_tmp_dir (NULL);
GError *error = NULL;
if (!_delete_dir_recursive (tmp_dir, &error)) {
if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_NOT_FOUND) {
GST_ERROR ("Could not remove temp dir, reason: %s",
GST_STR_NULL (error->message));
}
g_error_free (error);
}
g_object_unref (tmp_dir);
}

View File

@@ -0,0 +1,93 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <gio/gio.h>
#include <gst/gst.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
typedef void (* ClapperAppUtilsIterRanks) (const gchar *feature_name, GstRank rank, gboolean from_env, gpointer user_data);
void clapper_app_utils_debug_init (void);
#ifdef G_OS_WIN32
G_GNUC_INTERNAL
void clapper_app_utils_win_enforce_hi_res_clock (void);
G_GNUC_INTERNAL
guint clapper_app_utils_win_hi_res_clock_start (void);
G_GNUC_INTERNAL
void clapper_app_utils_win_hi_res_clock_stop (guint resolution);
G_GNUC_INTERNAL
const gchar *const * clapper_app_utils_get_extensions (void);
G_GNUC_INTERNAL
const gchar *const * clapper_app_utils_get_subtitles_extensions (void);
#endif
G_GNUC_INTERNAL
const gchar *const * clapper_app_utils_get_mime_types (void);
G_GNUC_INTERNAL
const gchar *const * clapper_app_utils_get_subtitles_mime_types (void);
G_GNUC_INTERNAL
void clapper_app_utils_parse_progression (ClapperQueueProgressionMode mode, const gchar **icon, const gchar **label);
G_GNUC_INTERNAL
gboolean clapper_app_utils_is_subtitles_file (GFile *file);
G_GNUC_INTERNAL
gboolean clapper_app_utils_value_for_item_is_valid (const GValue *value);
G_GNUC_INTERNAL
gboolean clapper_app_utils_files_from_list_model (GListModel *files_model, GFile ***files, gint *n_files);
G_GNUC_INTERNAL
gboolean clapper_app_utils_files_from_slist (GSList *file_list, GFile ***files, gint *n_files);
G_GNUC_INTERNAL
gboolean clapper_app_utils_files_from_string (const gchar *string, GFile ***files, gint *n_files);
G_GNUC_INTERNAL
gboolean clapper_app_utils_files_from_command_line (GApplicationCommandLine *cmd_line, GFile ***files, gint *n_files);
G_GNUC_INTERNAL
gboolean clapper_app_utils_files_from_value (const GValue *value, GFile ***files, gint *n_files);
G_GNUC_INTERNAL
void clapper_app_utils_files_free (GFile **files);
G_GNUC_INTERNAL
void clapper_app_utils_iterate_plugin_feature_ranks (GSettings *settings, ClapperAppUtilsIterRanks callback, gpointer user_data);
G_GNUC_INTERNAL
GstElement * clapper_app_utils_make_element (const gchar *string);
G_GNUC_INTERNAL
void clapper_app_utils_create_pipeline_svg_file_async (ClapperPlayer *player, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
G_GNUC_INTERNAL
void clapper_app_utils_delete_tmp_dir (void);
G_END_DECLS

View File

@@ -0,0 +1,365 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <clapper/clapper.h>
#include "clapper-app-window-state-buttons.h"
#define GST_CAT_DEFAULT clapper_app_window_state_buttons_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperAppWindowStateButtons
{
GtkBox parent;
GtkWidget *minimize_button;
GtkWidget *maximize_button;
GtkWidget *close_button;
/* Props */
GtkWidget *menu_button;
GtkPositionType position;
gboolean has_minimize;
gboolean has_maximize;
gboolean has_close;
gboolean has_buttons;
gboolean is_maximized;
gboolean is_fullscreen;
GtkSettings *settings;
};
enum
{
PROP_0,
PROP_POSITION,
PROP_MENU_BUTTON,
PROP_LAST
};
#define parent_class clapper_app_window_state_buttons_parent_class
G_DEFINE_TYPE (ClapperAppWindowStateButtons, clapper_app_window_state_buttons, GTK_TYPE_BOX)
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static void
minimize_button_clicked_cb (GtkButton *button, ClapperAppWindowStateButtons *self)
{
GST_INFO_OBJECT (self, "Minimize button clicked");
gtk_widget_activate_action (GTK_WIDGET (self), "window.minimize", NULL);
}
static void
maximize_button_clicked_cb (GtkButton *button, ClapperAppWindowStateButtons *self)
{
GST_INFO_OBJECT (self, "Maximize button clicked");
gtk_widget_activate_action (GTK_WIDGET (self), "window.toggle-maximized", NULL);
}
static void
close_button_clicked_cb (GtkButton *button, ClapperAppWindowStateButtons *self)
{
GST_INFO_OBJECT (self, "Close button clicked");
gtk_widget_activate_action (GTK_WIDGET (self), "window.close", NULL);
}
static void
_refresh_buttons_visibility (ClapperAppWindowStateButtons *self)
{
gboolean show_minimize = (self->has_minimize && !self->is_fullscreen);
gboolean show_maximize = (self->has_maximize && !self->is_fullscreen);
gboolean has_buttons;
gtk_widget_set_visible (self->minimize_button, show_minimize);
gtk_widget_set_visible (self->maximize_button, show_maximize);
gtk_widget_set_visible (self->close_button, self->has_close);
has_buttons = (self->menu_button != NULL || show_minimize
|| show_maximize || self->has_close);
if (self->has_buttons != has_buttons) {
self->has_buttons = has_buttons;
if (self->has_buttons)
gtk_widget_add_css_class (GTK_WIDGET (self), "filled");
else
gtk_widget_remove_css_class (GTK_WIDGET (self), "filled");
}
}
static void
clapper_app_window_state_buttons_parse_layout (ClapperAppWindowStateButtons *self)
{
gchar *org_layout = NULL;
gboolean has_minimize = FALSE;
gboolean has_maximize = FALSE;
gboolean has_close = FALSE;
GST_DEBUG_OBJECT (self, "Buttons layout update");
g_object_get (self->settings, "gtk-decoration-layout", &org_layout, NULL);
if (G_LIKELY (org_layout != NULL)) {
GtkWidget *last_widget = self->menu_button;
gboolean can_parse = (self->position == GTK_POS_LEFT);
gboolean had_sign = can_parse;
guint i;
for (i = 0; org_layout[i] != '\0'; ++i) {
const gchar *layout = org_layout + i;
if (layout[0] == ',') {
had_sign = TRUE;
continue;
}
if (layout[0] == ':') {
if (self->position == GTK_POS_LEFT)
break;
else
can_parse = TRUE;
had_sign = TRUE;
continue;
}
if (had_sign && can_parse) {
GtkWidget *widget = NULL;
GST_TRACE_OBJECT (self, "Remaining layout: %s", layout);
if (g_str_has_prefix (layout, "minimize")) {
widget = self->minimize_button;
has_minimize = TRUE;
} else if (g_str_has_prefix (layout, "maximize")) {
widget = self->maximize_button;
has_maximize = TRUE;
} else if (g_str_has_prefix (layout, "close")) {
widget = self->close_button;
has_close = TRUE;
}
if (widget) {
gtk_box_reorder_child_after (GTK_BOX (self), widget, last_widget);
last_widget = widget;
}
had_sign = FALSE;
}
}
}
self->has_minimize = has_minimize;
self->has_maximize = has_maximize;
self->has_close = has_close;
GST_DEBUG_OBJECT (self, "Buttons layout parsed");
g_free (org_layout);
}
static void
_decoration_layout_changed_cb (GtkSettings *settings,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppWindowStateButtons *self)
{
clapper_app_window_state_buttons_parse_layout (self);
_refresh_buttons_visibility (self);
}
static void
_surface_state_changed_cb (GdkSurface *surface,
GParamSpec *pspec G_GNUC_UNUSED, ClapperAppWindowStateButtons *self)
{
GdkToplevelState state = gdk_toplevel_get_state (GDK_TOPLEVEL (surface));
gboolean is_maximized, is_fullscreen;
GST_LOG_OBJECT (self, "Surface state changed");
is_maximized = (state & GDK_TOPLEVEL_STATE_MAXIMIZED);
is_fullscreen = (state & GDK_TOPLEVEL_STATE_FULLSCREEN);
if (self->is_maximized != is_maximized) {
self->is_maximized = is_maximized;
gtk_button_set_icon_name (GTK_BUTTON (self->maximize_button),
(self->is_maximized) ? "window-restore-symbolic" : "window-maximize-symbolic");
}
if (self->is_fullscreen != is_fullscreen) {
self->is_fullscreen = is_fullscreen;
_refresh_buttons_visibility (self);
}
}
static void
clapper_app_window_state_buttons_init (ClapperAppWindowStateButtons *self)
{
self->position = GTK_POS_RIGHT;
gtk_widget_init_template (GTK_WIDGET (self));
}
static void
clapper_app_window_state_buttons_constructed (GObject *object)
{
ClapperAppWindowStateButtons *self = CLAPPER_APP_WINDOW_STATE_BUTTONS_CAST (object);
if (self->position == GTK_POS_RIGHT)
gtk_widget_add_css_class (GTK_WIDGET (self), "right");
else
gtk_widget_add_css_class (GTK_WIDGET (self), "left");
G_OBJECT_CLASS (parent_class)->constructed (object);
}
static void
_clear_stored_settings (ClapperAppWindowStateButtons *self)
{
if (self->settings) {
g_signal_handlers_disconnect_by_func (self->settings,
_decoration_layout_changed_cb, self);
g_clear_object (&self->settings);
}
}
static void
clapper_app_window_state_buttons_realize (GtkWidget *widget)
{
ClapperAppWindowStateButtons *self = CLAPPER_APP_WINDOW_STATE_BUTTONS_CAST (widget);
GtkSettings *settings;
GtkRoot *root;
GdkSurface *surface;
GST_TRACE_OBJECT (self, "Realize");
GTK_WIDGET_CLASS (parent_class)->realize (widget);
settings = gtk_settings_get_for_display (gtk_widget_get_display (widget));
if (self->settings != settings) {
_clear_stored_settings (self);
self->settings = g_object_ref (settings);
g_signal_connect (self->settings, "notify::gtk-decoration-layout",
G_CALLBACK (_decoration_layout_changed_cb), self);
_decoration_layout_changed_cb (self->settings, NULL, self);
}
root = gtk_widget_get_root (widget);
surface = gtk_native_get_surface (GTK_NATIVE (root));
g_signal_connect (surface, "notify::state",
G_CALLBACK (_surface_state_changed_cb), self);
_surface_state_changed_cb (surface, NULL, self);
}
static void
clapper_app_window_state_buttons_unrealize (GtkWidget *widget)
{
ClapperAppWindowStateButtons *self = CLAPPER_APP_WINDOW_STATE_BUTTONS_CAST (widget);
GtkRoot *root;
GdkSurface *surface;
GST_TRACE_OBJECT (self, "Unrealize");
_clear_stored_settings (self);
root = gtk_widget_get_root (widget);
surface = gtk_native_get_surface (GTK_NATIVE (root));
g_signal_handlers_disconnect_by_func (surface,
_surface_state_changed_cb, self);
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}
static void
clapper_app_window_state_buttons_dispose (GObject *object)
{
ClapperAppWindowStateButtons *self = CLAPPER_APP_WINDOW_STATE_BUTTONS_CAST (object);
_clear_stored_settings (self);
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_APP_TYPE_WINDOW_STATE_BUTTONS);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_app_window_state_buttons_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperAppWindowStateButtons *self = CLAPPER_APP_WINDOW_STATE_BUTTONS_CAST (object);
switch (prop_id) {
case PROP_POSITION:
self->position = g_value_get_enum (value);
break;
case PROP_MENU_BUTTON:
if ((self->menu_button = GTK_WIDGET (g_value_get_object (value)))) {
gtk_box_prepend (GTK_BOX (self), self->menu_button);
_refresh_buttons_visibility (self);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_app_window_state_buttons_class_init (ClapperAppWindowStateButtonsClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperappwindowstatebuttons", 0,
"Clapper App Window State Buttons");
gobject_class->constructed = clapper_app_window_state_buttons_constructed;
gobject_class->set_property = clapper_app_window_state_buttons_set_property;
gobject_class->dispose = clapper_app_window_state_buttons_dispose;
widget_class->realize = clapper_app_window_state_buttons_realize;
widget_class->unrealize = clapper_app_window_state_buttons_unrealize;
param_specs[PROP_POSITION] = g_param_spec_enum ("position",
NULL, NULL, GTK_TYPE_POSITION_TYPE, GTK_POS_RIGHT,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
param_specs[PROP_MENU_BUTTON] = g_param_spec_object ("menu-button",
NULL, NULL, GTK_TYPE_MENU_BUTTON,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
gtk_widget_class_set_template_from_resource (widget_class,
CLAPPER_APP_RESOURCE_PREFIX "/ui/clapper-app-window-state-buttons.ui");
gtk_widget_class_bind_template_child (widget_class, ClapperAppWindowStateButtons, minimize_button);
gtk_widget_class_bind_template_child (widget_class, ClapperAppWindowStateButtons, maximize_button);
gtk_widget_class_bind_template_child (widget_class, ClapperAppWindowStateButtons, close_button);
gtk_widget_class_bind_template_callback (widget_class, minimize_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, maximize_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, close_button_clicked_cb);
gtk_widget_class_set_css_name (widget_class, "clapper-app-window-state-buttons");
}

View File

@@ -0,0 +1,31 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_WINDOW_STATE_BUTTONS (clapper_app_window_state_buttons_get_type())
#define CLAPPER_APP_WINDOW_STATE_BUTTONS_CAST(obj) ((ClapperAppWindowStateButtons *)(obj))
G_DECLARE_FINAL_TYPE (ClapperAppWindowStateButtons, clapper_app_window_state_buttons, CLAPPER_APP, WINDOW_STATE_BUTTONS, GtkBox)
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <clapper/clapper.h>
G_BEGIN_DECLS
#define CLAPPER_APP_TYPE_WINDOW (clapper_app_window_get_type())
#define CLAPPER_APP_WINDOW_CAST(obj) ((ClapperAppWindow *)(obj))
typedef struct
{
gchar *video_filter;
gchar *audio_filter;
gchar *video_sink;
gchar *audio_sink;
} ClapperAppWindowExtraOptions;
G_DECLARE_FINAL_TYPE (ClapperAppWindow, clapper_app_window, CLAPPER_APP, WINDOW, GtkApplicationWindow)
G_GNUC_INTERNAL
GtkWidget * clapper_app_window_new (GtkApplication *application);
G_GNUC_INTERNAL
GtkWidget * clapper_app_window_get_video (ClapperAppWindow *window);
G_GNUC_INTERNAL
ClapperPlayer * clapper_app_window_get_player (ClapperAppWindow *window);
G_GNUC_INTERNAL
ClapperAppWindowExtraOptions * clapper_app_window_get_extra_options (ClapperAppWindow *window);
G_GNUC_INTERNAL
void clapper_app_window_ensure_no_initial_state (ClapperAppWindow *window);
G_END_DECLS

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/github/rafostar/Clapper/clapper-app">
<file preprocess="xml-stripblanks">data/metainfo/com.github.rafostar.Clapper.metainfo.xml</file>
<file preprocess="xml-stripblanks">ui/clapper-app-initial-state.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-uri-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-headerbar.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-help-overlay.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-info-window.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-queue-list.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-queue-list-item.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-queue-progression-item.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-video-stream-list-item.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-audio-stream-list-item.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-subtitle-stream-list-item.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-preferences-window.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-window.ui</file>
<file preprocess="xml-stripblanks">ui/clapper-app-window-state-buttons.ui</file>
<file compressed="true">css/styles.css</file>
</gresource>
</gresources>

View File

@@ -0,0 +1,110 @@
window .initialstate {
padding-left: 6px;
padding-right: 6px;
padding-top: 8px;
background-color: @dark_4;
}
window.info .maincontent {
margin: 16px;
margin-top: 0px;
}
window.info .subcontent {
margin: 16px;
margin-top: 0px;
margin-bottom: 8px;
}
window.info .subcontent streamlist preferencesgroup {
margin-bottom: 8px;
}
window.preferences .subcontent {
margin: 16px;
}
window.preferences .configsubpage .subcontent popover {
min-width: 264px;
}
window.preferences .configsubpage .subcontent button.pill {
margin-top: 8px;
margin-bottom: 8px;
}
clapper-gtk-seek-bar scale trough highlight {
color: @accent_fg_color;
background-color: @accent_bg_color;
}
clapper-gtk-video .overamp trough highlight {
color: @error_fg_color;
background-color: @error_bg_color;
}
clapper-app-headerbar .mainbox {
margin: 6px;
padding: 2px;
}
clapper-app-headerbar .titlelabel label {
margin-left: 8px;
margin-right: 8px;
}
clapper-app-headerbar clapper-app-window-state-buttons {
margin-top: 8px;
}
clapper-app-headerbar clapper-app-window-state-buttons.filled.right:dir(ltr) {
padding-right: 6px;
}
clapper-app-headerbar clapper-app-window-state-buttons.filled.right:dir(rtl) {
padding-left: 6px;
}
clapper-app-headerbar clapper-app-window-state-buttons.filled.left:dir(ltr) {
padding-left: 6px;
}
clapper-app-headerbar clapper-app-window-state-buttons.filled.left:dir(rtl) {
padding-right: 6px;
}
clapper-app-queue-list .topseparator {
margin-top: 2px;
margin-bottom: 4px;
}
clapper-app-queue-list .buttonsbox {
padding-left: 6px;
padding-right: 6px;
}
clapper-app-queue-list .buttonsbox dropdown .toggle row {
background-color: transparent;
}
clapper-app-queue-list .buttonsbox .additemsbutton box {
padding-left: 6px;
padding-right: 6px;
}
clapper-app-queue-list .buttonsbox .additemsbutton box image {
margin-left: 3px;
margin-right: 3px;
}
clapper-app-queue-list .buttonsbox .progressiondropdown popover label {
min-width: 100px;
}
clapper-app-queue-list .removeitembox {
margin-left: 6px;
margin-right: 6px;
border-radius: 9999px;
background-color: alpha(@destructive_bg_color, 0.9);
}
clapper-app-queue-list .queue {
padding: 3px;
}
clapper-app-queue-list .queue listview {
padding: 2px;
padding-bottom: 0px;
border-radius: 0px 0px 19px 19px;
}
clapper-app-queue-list .queue listview row {
padding-left: 10px;
padding-right: 10px;
min-height: 30px;
border-radius: 9999px;
}
/* Disable background light on hover when doing D&D */
clapper-app-queue-list .queue listview.dnd row.activatable:not(:selected):hover {
background: none;
}

View File

@@ -0,0 +1,22 @@
[Desktop Entry]
# Translators: Do NOT translate app name!
Name=Clapper
GenericName=Multimedia Player
Comment=Play videos and music
Categories=GTK;GNOME;AudioVideo;Player;Video;TV;
MimeType=application/claps;application/mpeg4-iod;application/mpeg4-muxcodetable;application/mxf;application/ogg;application/ram;application/sdp;application/streamingmedia;application/vnd.apple.mpegurl;application/vnd.ms-asf;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;application/x-extension-m4a;application/x-extension-mp4;application/x-flac;application/x-flash-video;application/x-matroska;application/x-ogg;application/x-streamingmedia;audio/3gpp;audio/3gpp2;audio/aac;audio/ac3;audio/amr;audio/amr-wb;audio/basic;audio/dv;audio/eac3;audio/flac;audio/m4a;audio/midi;audio/mp1;audio/mp2;audio/mp3;audio/mp4;audio/mpeg;audio/mpegurl;audio/mpg;audio/ogg;audio/opus;audio/scpls;audio/vnd.dolby.heaac.1;audio/vnd.dolby.heaac.2;audio/vnd.dolby.mlp;audio/vnd.dts;audio/vnd.dts.hd;audio/vnd.rn-realaudio;audio/wav;audio/webm;audio/x-aac;audio/x-aiff;audio/x-ape;audio/x-flac;audio/x-gsm;audio/x-it;audio/x-m4a;audio/x-matroska;audio/x-mod;audio/x-mp1;audio/x-mp2;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-mpg;audio/x-ms-asf;audio/x-ms-wma;audio/x-musepack;audio/x-pn-aiff;audio/x-pn-au;audio/x-pn-realaudio;audio/x-pn-wav;audio/x-real-audio;audio/x-realaudio;audio/x-s3m;audio/x-scpls;audio/x-shorten;audio/x-speex;audio/x-tta;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-wav;audio/x-wavpack;audio/x-xm;video/3gp;video/3gpp;video/3gpp2;video/divx;video/dv;video/fli;video/flv;video/mp2t;video/mp4;video/mp4v-es;video/mpeg;video/mpeg-system;video/msvideo;video/ogg;video/quicktime;video/vnd.mpegurl;video/vnd.rn-realvideo;video/webm;video/x-avi;video/x-flc;video/x-fli;video/x-flv;video/x-m4v;video/x-matroska;video/x-mpeg;video/x-mpeg-system;video/x-mpeg2;video/x-ms-asf;video/x-ms-wm;video/x-ms-wmv;video/x-ms-wmx;video/x-msvideo;video/x-nsv;video/x-ogm+ogg;video/x-theora;video/x-theora+ogg;x-content/audio-cdda;x-content/audio-player;x-content/video-dvd;x-scheme-handler/mms;x-scheme-handler/mmsh;x-scheme-handler/rtmp;x-scheme-handler/rtp;x-scheme-handler/rtsp;
Exec=clapper %U
Icon=com.github.rafostar.Clapper
DBusActivatable=true
StartupNotify=true
Terminal=false
Type=Application
# Translators: Search terms to find this application. Do NOT translate the semicolons!
Keywords=Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;
# Translators: Do NOT translate or transliterate this text (these are enum types)!
X-Purism-FormFactor=Workstation;Mobile;
Actions=new-window;
[Desktop Action new-window]
Name=New Window
Exec=clapper --new-window

View File

@@ -0,0 +1 @@
subdir('services')

View File

@@ -0,0 +1,3 @@
[D-BUS Service]
Name=@app_id@
Exec=@bindir@/@bin@ --gapplication-service

View File

@@ -0,0 +1,12 @@
dbus_conf = configuration_data()
dbus_conf.set('app_id', app_id)
dbus_conf.set('bindir', join_paths(prefix, bindir))
dbus_conf.set('bin', meson.project_name())
configure_file(
input: 'com.github.rafostar.Clapper.service.in',
output: 'com.github.rafostar.Clapper.service',
configuration: dbus_conf,
install: true,
install_dir: join_paths(prefix, datadir, 'dbus-1', 'services'),
)

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="clapper-app">
<schema id="com.github.rafostar.Clapper" path="/com/github/rafostar/Clapper/">
<!-- General -->
<key name="seek-method" type="i">
<default>1</default>
<summary>Method used for seeking</summary>
</key>
<key name="seek-unit" type="i">
<default>0</default>
<summary>Unit ID to use with seeking value</summary>
</key>
<key name="seek-value" type="i">
<default>10</default>
<summary>Time amount to seek with single press of arrow keys</summary>
</key>
<key name="server-enabled" type="b">
<default>false</default>
<summary>Enable Server feature for remote playback control</summary>
</key>
<!-- Playback -->
<key name="audio-offset" type="d">
<default>0</default>
<summary>Offset time for audio stream relative to video</summary>
</key>
<key name="subtitle-offset" type="d">
<default>0</default>
<summary>Offset time for subtitle stream relative to video</summary>
</key>
<key name="subtitle-font-desc" type="s">
<default>"Sans 12"</default>
<summary>Default subtitle stream font description</summary>
</key>
<!-- Tweaks -->
<key name="plugin-feature-ranks" type="s">
<default>''</default>
<summary>Overrides for GStreamer plugin ranking</summary>
</key>
<!-- Other -->
<key name="volume" type="d">
<default>1.0</default>
<summary>Stores last volume value to apply on startup</summary>
</key>
<key name="mute" type="b">
<default>false</default>
<summary>Stores last mute state to apply on startup</summary>
</key>
<key name="speed" type="d">
<default>1.0</default>
<summary>Stores last speed value to apply on startup</summary>
</key>
<key name="adaptive-start-bitrate" type="i">
<default>1600000</default>
<summary>Stores initial adaptive streaming bitrate to apply on startup</summary>
</key>
<key name="progression-mode" type="i">
<default>1</default>
<summary>Stores last queue progression mode used to apply on startup</summary>
</key>
<key name="subtitles-enabled" type="b">
<default>true</default>
<summary>Stores whether subtitles are enabled value to apply on startup</summary>
</key>
<key name="maximized" type="b">
<default>false</default>
<summary>Stores whether window was last time maximized to restore on startup</summary>
</key>
<key name="fullscreened" type="b">
<default>false</default>
<summary>Stores whether window was last time in fullscreen to restore on startup</summary>
</key>
</schema>
</schemalist>

View File

@@ -0,0 +1,8 @@
gnome.compile_schemas(
build_by_default: true,
depend_files: ['com.github.rafostar.Clapper.gschema.xml']
)
install_data('com.github.rafostar.Clapper.gschema.xml',
install_dir: join_paths(prefix, datadir, 'glib-2.0', 'schemas')
)

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256" width="256" height="256">
<defs>
<path id="b1nGq5BrLC" d="M27.2 243.52C27.2 236.16 27.2 199.83 27.2 134.22C47.64 134.22 211.12 134.22 231.56 134.22C231.56 199.83 231.56 236.16 231.56 243.52C231.56 250.4 225.96 256 218.92 256C183.07 256 57.77 256 39.84 256C32.8 256 27.2 250.4 27.2 243.52Z"></path>
<path id="a3jkaoNn4k" d="M24.32 103.65C24.32 106.22 24.32 127.02 24.32 129.58C24.32 132.78 26.72 135.18 29.92 135.18C50.41 135.18 215.08 135.18 235.72 135.18C238.76 135.18 241.32 132.78 241.32 129.58C241.32 127.02 241.32 106.22 241.32 103.65C241.32 100.45 238.76 98.05 235.72 98.05C194.59 98.05 50.41 98.05 29.92 98.05C26.72 98.05 24.32 100.45 24.32 103.65Z"></path>
<path id="atpVQ8mnd" d="M174.59 135.18L211.87 98.05L171.07 98.05L133.78 135.18L174.59 135.18Z"></path>
<path id="bMtYoNHu0" d="M76.81 135.18L114.1 98.05L73.13 98.05L35.84 135.18L76.81 135.18Z"></path>
<path id="b5oP0Glp4" d="M19.04 69.41C19.84 71.97 25.92 91.97 26.72 94.37C27.68 97.41 30.72 99.01 33.76 98.05C54.09 91.81 216.68 42.04 237 35.8C240.04 35 241.64 31.8 240.84 28.92C240.04 26.36 233.96 6.36 233.16 3.96C232.2 0.92 229.16 -0.68 226.12 0.28C185.47 12.6 43.21 56.29 22.88 62.53C19.84 63.33 18.24 66.53 19.04 69.41Z"></path>
<path id="lwBgev6DR" d="M176.51 54.37L129.94 29.4L169.15 17.56L215.72 42.52L176.51 54.37Z"></path>
<path id="cUsjEMRUu" d="M81.61 83.49L35.04 58.69L74.25 46.69L120.82 71.49L81.61 83.49Z"></path>
<path id="c1bcHZGXe" d="M14.72 66.69C14.72 72.93 14.72 123.02 14.72 129.26C14.72 132.62 17.44 135.18 20.64 135.18C26.56 135.18 74.09 135.18 80.01 135.18C84.33 135.18 87.21 130.86 85.61 127.02C82.89 120.78 61.45 70.53 58.73 64.29C57.77 62.05 55.69 60.77 53.29 60.77C46.73 60.77 24 60.77 20.64 60.77C17.44 60.77 14.72 63.33 14.72 66.69Z"></path>
<path id="f2PtH0V1vC" d="M32.64 60.61C31.52 60.61 21.92 60.61 20.64 60.61C17.44 60.61 14.72 63.33 14.72 66.53C14.72 72.77 14.72 123.02 14.72 129.26C14.72 132.46 17.44 135.18 20.64 135.18C21.92 135.18 31.52 135.18 32.64 135.18C29.44 135.18 26.72 132.46 26.72 129.26C26.72 116.62 26.72 72.77 26.72 66.53C26.72 63.33 29.44 60.61 32.64 60.61Z"></path>
<path id="a1SvrrkqVm" d="M231.56 135.18C231.56 143.82 231.56 148.46 231.56 149.42C231.56 149.42 231.56 149.42 231.56 149.42C108.98 149.42 40.8 149.42 27.2 149.42C27.2 149.42 27.2 149.42 27.2 149.42C27.2 140.94 27.2 136.14 27.2 135.18C27.2 135.18 27.2 135.18 27.2 135.18C149.78 135.18 217.96 135.18 231.56 135.18C231.56 135.18 231.56 135.18 231.56 135.18Z"></path>
<path id="agXcvKqh8" d="M104.22 162.46L104.22 234.46L163.22 198.54L104.22 162.46Z"></path>
</defs>
<g>
<g><use xlink:href="#b1nGq5BrLC" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#a3jkaoNn4k" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#atpVQ8mnd" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#bMtYoNHu0" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#b5oP0Glp4" fill="#4747d1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#lwBgev6DR" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#cUsjEMRUu" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#c1bcHZGXe" fill="#a9a9a9" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#f2PtH0V1vC" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#a1SvrrkqVm" opacity="0.2" fill="#000000" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
<g><use xlink:href="#agXcvKqh8" fill="#f1f1f1" transform="matrix(1, 0, 0, 0.97, 0, 0)"></use></g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333333 4.2333334"
version="1.1"
id="svg5"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
sodipodi:docname="com.github.rafostar.Clapper-symbolic.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-global="false"
units="px"
inkscape:zoom="32"
inkscape:cx="6.078125"
inkscape:cy="8.09375"
inkscape:window-width="1680"
inkscape:window-height="981"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2">
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1853"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1.8520833,0,1 @ F,0,0,1,0,1.8520833,0,1 @ F,0,0,1,0,1.8520833,0,1 @ F,0,0,1,0,1.8520833,0,1"
unit="px"
method="auto"
mode="F"
radius="7"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1732"
is_visible="true"
lpeversion="1"
satellites_param="F,0,0,1,0,1.8520833,0,1 @ F,0,0,1,0,1.8520833,0,1 @ F,0,0,1,0,1.8520833,0,1 @ F,0,0,1,0,1.8520833,0,1"
unit="px"
method="auto"
mode="F"
radius="7"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2022"
transform="matrix(0.06169519,0,0,0.06168906,-4.7800087,-3.2713603)">
<path
id="rect973"
style="fill:#000000;stroke-width:1.30776;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="m 88.193064,81.795006 c -0.699254,0 -1.342327,0.227875 -1.864484,0.609782 h 51.32503 c -0.52216,-0.381907 -1.16471,-0.609782 -1.86397,-0.609782 z m -3.157945,10.475846 v 26.225278 c 0,1.74939 1.40856,3.15743 3.157945,3.15743 h 47.596576 c 1.74939,0 3.15795,-1.40804 3.15795,-3.15743 V 92.270852 Z m 20.323311,4.964038 15.40009,9.27283 -15.5205,9.56634 z" />
<path
style="fill:#000000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 83.974394,69.464471 7.344033,-0.06509 a 2.7923103,2.7923103 33.047712 0 1 2.587466,1.683384 l 7.009937,16.201526 a 1.2163248,1.2163248 123.30899 0 1 -1.116623,1.699322 l -15.720141,-0.004 a 1.862525,1.862525 44.853691 0 1 -1.862019,-1.852534 l -0.08473,-15.79409 a 1.8585738,1.8585738 134.59241 0 1 1.842075,-1.868472 z"
id="path1422"
inkscape:path-effect="#path-effect1732"
inkscape:original-d="m 82.122383,69.480886 11.048055,-0.09792 8.480852,19.601124 -19.424307,-0.005 z" />
<rect
style="fill:#000000;stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
id="rect1544"
width="59.366463"
height="9.8661175"
x="82"
y="79.292183"
ry="1.2306831" />
<path
id="rect1847"
style="fill:#000000;stroke-width:4.91339;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke markers fill"
d="m 522.12695,200.42773 c -0.45798,3.8e-4 -0.92335,0.0696 -1.38476,0.21289 l -172.88672,53.70313 5.28515,-0.0469 a 10.55362,10.55362 0 0 1 9.7793,6.36328 l 10.69922,24.72656 158.18359,-49.13477 c 2.46089,-0.7644 3.82691,-3.36137 3.0625,-5.82226 l -8.30078,-26.72657 c -0.62108,-1.99947 -2.4529,-3.277 -4.4375,-3.27539 z m -203.69531,63.05469 -3.08398,0.95899 c -2.46089,0.7644 -3.82691,3.35942 -3.0625,5.82031 l 6.29101,20.2539 z"
transform="scale(0.26458333)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,65 @@
appstream_cli = find_program('appstreamcli', required: false)
if appstream_cli.found()
test('Validate appstream file',
appstream_cli,
args: [
'validate',
'--no-net',
'--explain',
join_paths(meson.current_source_dir(), 'metainfo', 'com.github.rafostar.Clapper.metainfo.xml'),
]
)
endif
glib_compile_schemas = find_program('glib-compile-schemas', required: false)
if glib_compile_schemas.found()
test('Validate gsettings schemas',
glib_compile_schemas,
args: [
'--strict',
'--dry-run',
join_paths(meson.current_source_dir(), 'glib-2.0', 'schemas'),
]
)
endif
install_subdir('icons',
install_dir: join_paths(prefix, datadir)
)
install_subdir('metainfo',
install_dir: join_paths(prefix, datadir)
)
is_linux = ['linux'].contains(host_machine.system())
is_windows = ['windows'].contains(host_machine.system())
if is_linux
desktop_file = i18n.merge_file(
input: 'applications/com.github.rafostar.Clapper.desktop.in',
output: 'com.github.rafostar.Clapper.desktop',
type: 'desktop',
po_dir: '../po',
install: true,
install_dir: join_paths(prefix, datadir, 'applications'),
)
desktop_utils = find_program('desktop-file-validate', required: false)
if desktop_utils.found()
test('Validate desktop file', desktop_utils, args: [desktop_file])
endif
subdir('dbus-1')
endif
if not is_windows
install_subdir('mime',
install_dir: join_paths(prefix, datadir)
)
endif
subdir('glib-2.0/schemas')
gnome.post_install(
glib_compile_schemas: true,
gtk_update_icon_cache: true,
update_desktop_database: is_linux,
update_mime_database: not is_windows,
)

View File

@@ -0,0 +1,300 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2024 Rafał Dzięgiel -->
<component type="desktop-application">
<id>com.github.rafostar.Clapper</id>
<name>Clapper</name>
<summary>Lean back and enjoy videos</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<!-- Old AppStream compat -->
<developer_name>Rafał Dzięgiel</developer_name>
<developer id="com.github.rafostar">
<name>Rafał Dzięgiel</name>
</developer>
<translation type="gettext">clapper-app</translation>
<launchable type="desktop-id">com.github.rafostar.Clapper.desktop</launchable>
<url type="homepage">https://rafostar.github.io/clapper</url>
<url type="bugtracker">https://github.com/Rafostar/clapper/issues</url>
<url type="donation">https://liberapay.com/Clapper</url>
<url type="help">https://github.com/Rafostar/clapper/wiki</url>
<url type="vcs-browser">https://github.com/Rafostar/clapper</url>
<description>
<p>
Clapper is a modern media player designed for simplicity and ease of use.
Powered by GStreamer and built for the GNOME desktop environment using
GTK4 toolkit, it has a clean and stylish interface that lets you focus
on enjoying your favorite videos.
</p>
<p>
Clapper uses a playback queue where you can add multiple media files.
Think of it like a playlist that you can build. You can easily reorder
items or remove them from the queue with a simple drag and drop operation.
</p>
</description>
<screenshots>
<screenshot type="default">
<image type="source">https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_01.png</image>
<caption>Modern player with minimalist look</caption>
</screenshot>
<screenshot>
<image type="source">https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_02.png</image>
<caption>See actual title of what you are watching</caption>
</screenshot>
<screenshot>
<image type="source">https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_03.png</image>
<caption>Queue multiple media in any order you like</caption>
</screenshot>
<screenshot>
<image type="source">https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_04.png</image>
<caption>Play either local or network content</caption>
</screenshot>
<screenshot>
<image type="source">https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot_05.png</image>
<caption>Enjoy adaptive UI that fits any screen size</caption>
</screenshot>
</screenshots>
<!-- Linux Phone Apps parses categories from XML -->
<categories>
<category>AudioVideo</category>
<category>Video</category>
</categories>
<releases>
<release version="0.8.0" date="2025-01-20">
<description>
<p>Changes:</p>
<ul>
<li>Now uses playbin3 by default</li>
<li>Added more command line options - including ability to set custom GStreamer filter and sink elements</li>
<li>Support for creating multiple application windows</li>
<li>Added menu option to clear playback queue</li>
<li>Auto resize window to match aspect ratio with middle click or keyboard shortcut</li>
<li>Added unfullscreen with Escape key</li>
<li>Brand new libpeas based plugin system</li>
<li>Remember and restore optimal bitrate (video quality) when starting adaptive streaming</li>
<li>Other various improvements and bug fixes</li>
</ul>
</description>
</release>
<release version="0.6.1" date="2024-07-01">
<description>
<p>Bug fixes and translation updates</p>
</description>
</release>
<release version="0.6.0" date="2024-04-22">
<description>
<p>
In this release Clapper code was rewritten from scratch. Now split into
two libraries and an application built on top of them, with:
</p>
<ul>
<li>Brand new, simplified and consistent UI</li>
<li>Player now operates on playback queue model</li>
<li>Multiple queue progression modes to choose from (consecutive, repeat item, carousel, shuffle)</li>
<li>New media info window (shows media information and GStreamer elements used to play it)</li>
<li>More dialogs and windows use libadwaita</li>
<li>Multiple new status/info overlays showing what is going and other messages</li>
<li>Added video buffering animation</li>
<li>Clapper will now inform users about missing GStreamer plugins needed for playback</li>
<li>Video chapters now appear throughout the seek bar on hover and while dragging slider</li>
<li>Vastly expanded MPRIS implementation</li>
<li>Integrated media discovery (see titles of queued items instead of URIs)</li>
<li>Expanded WebSocket server functionality (for remote playback control)</li>
<li>Increased maximum volume amplification level to 200%</li>
<li>Added some new keyboard shortcuts</li>
<li>In addition to volume, now also speed and queue progression mode are restored on launch</li>
<li>Fixed keyboard shortcuts not being reversed (e.g. seek) in RTL languages</li>
<li>Toggle play moved to left mouse button, right one now opens context menu (which was previously hard to access)</li>
<li>Many bug fixes and QoL improvements</li>
</ul>
</description>
</release>
<release version="0.5.2" date="2022-06-24">
<description>
<p>Fixes:</p>
<ul>
<li>Fix time labels display on RTL languages</li>
<li>Improved GL/GLES context automatic selection</li>
</ul>
<p>New translations:</p>
<ul>
<li>Hebrew</li>
</ul>
</description>
</release>
<release version="0.5.1" date="2022-05-29">
<description>
<p>
A quick hotfix release. Fixes problems with new video sink on displays with non-100% scaling applied.
See 0.5.0 version release notes for full recent changelog.
</p>
</description>
</release>
<release version="0.5.0" date="2022-05-28">
<description>
<p>Changes:</p>
<ul>
<li>Includes and uses new, improved GStreamer video sink</li>
<li>All networking ported to libsoup3</li>
<li>A lot of cleanup, including removal of unfinished web application and old YT code</li>
<li>App now supports D-Bus launching (DBusActivatable)</li>
<li>Other small fixes</li>
</ul>
<p>New translations:</p>
<ul>
<li>Arabic</li>
<li>Basque</li>
<li>French</li>
<li>Japanese</li>
<li>Swedish</li>
<li>Turkish</li>
</ul>
</description>
</release>
<release version="0.4.1" date="2021-12-20">
<description>
<p>Fixes:</p>
<ul>
<li>Compatibility with more recent libadwaita versions</li>
<li>Toggle mute with M button alone</li>
<li>Allow handling YouTube with external GStreamer plugins</li>
<li>Fix catching errors when reading clipboard</li>
<li>Fix missing translator-credits</li>
<li>Fix missing gio-unix-2.0 dep</li>
<li>Fix playback pausing when entering fullscreen with touchscreen</li>
<li>Fix GST_PLUGIN_FEATURE_RANK env usage</li>
<li>Fix video/audio decoder change detection</li>
<li>Merge global video tags instead replacing them</li>
<li>Few other misc bug fixes</li>
</ul>
<p>New translations:</p>
<ul>
<li>Chinese Simplified</li>
<li>Czech</li>
<li>Hungarian</li>
<li>Portuguese</li>
<li>Portuguese, Brazilian</li>
<li>Russian</li>
<li>Spanish</li>
</ul>
</description>
</release>
<release version="0.4.0" date="2021-09-12">
<description>
<p>Changes:</p>
<ul>
<li>Now uses libadwaita</li>
<li>New and adaptive preferences window</li>
<li>Improved open URI dialog</li>
<li>Few small tweaks to fullscreen UI design</li>
<li>Show current video and audio decoders in popovers (easy way to check if HW accel is used)</li>
<li>Enabled NVDEC hardware acceleration by default (requires Nvidia proprietary drivers)</li>
<li>Added option to use PipeWire for audio output (experimental)</li>
<li>Added option to use playbin3 element (experimental)</li>
<li>New PiP icon from icon development kit</li>
<li>Improved performance on devices running OpenGL ES</li>
<li>Translations support</li>
<li>Various bug fixes</li>
</ul>
<p>New keyboard shortcuts:</p>
<ul>
<li>Leave fullscreen with Escape key</li>
<li>Toggle mute with Ctrl+M</li>
</ul>
<p>More touchscreen gestures:</p>
<ul>
<li>Toggle playback with a long press</li>
<li>Switch playlist items via double tap on screen side</li>
</ul>
<p>New translations:</p>
<ul>
<li>Catalan</li>
<li>Dutch</li>
<li>German</li>
<li>Italian</li>
<li>Polish</li>
</ul>
</description>
</release>
<release version="0.3.0" date="2021-06-18">
<description>
<p>Changes:</p>
<ul>
<li>Added MPRIS support</li>
<li>Added repeat modes: single video, whole playlist and shuffle</li>
<li>Support opening folders with media files</li>
<li>Append playlist items by holding Ctrl while doing Drag and Drop</li>
<li>Improved handling of keyboard shortcuts</li>
<li>Added more keyboard shortcuts</li>
<li>Added window that shows available keyboard shortcuts</li>
<li>Show black screen by default after playback (make showing last frame optional instead)</li>
<li>Added ability to export playlist to file</li>
<li>Improve handling of changing displays with different resolutions</li>
<li>Added support for EGL under x11 with GTK 4.3.1 or later</li>
<li>Added missing symbolic app icon</li>
<li>Some misc bug fixes and code cleanups</li>
</ul>
</description>
</release>
<release version="0.2.1" date="2021-04-19">
<description>
<p>Player:</p>
<ul>
<li>Fix missing top left menu buttons on some system configurations</li>
<li>Fix potential video sink deadlock</li>
<li>Do not show mobile controls transition on launch</li>
<li>Show tooltip with full playlist item text on hover</li>
</ul>
<p>YouTube:</p>
<ul>
<li>Auto select best matching resolution for used monitor</li>
<li>Added some YouTube related preferences</li>
<li>Added support for live HLS videos</li>
<li>Added support for non-adaptive live HLS streaming</li>
</ul>
</description>
</release>
<release version="0.2.0" date="2021-04-13">
<description>
<p>New features:</p>
<ul>
<li>YouTube support - drag and drop videos from youtube or use open URI dialog to play them</li>
<li>Added convenient ways of opening external subtitles</li>
</ul>
<p>Changes:</p>
<ul>
<li>Few GUI layout improvements</li>
<li>Simplified video sink code</li>
<li>Fixed missing Ctrl+O common keybinding</li>
<li>Fixed error when playback finishes during controls reveal animation</li>
<li>Fixed startup window size on Xorg</li>
<li>Fixed top time not showing up on fullscreen startup</li>
<li>Fixed missing file extensions in online URIs</li>
<li>Fixed some error messages not being displayed</li>
</ul>
</description>
</release>
<release version="0.1.0" date="2021-02-26">
<description>
<p>First stable release</p>
</description>
</release>
<release version="0.0.0" date="2020-10-31">
<description>
<p>GitHub version</p>
</description>
</release>
</releases>
<content_rating type="oars-1.1"/>
<branding>
<color type="primary" scheme_preference="light">#8484ee</color>
<color type="primary" scheme_preference="dark">#1a1a74</color>
</branding>
<recommends>
<control>keyboard</control>
<control>pointing</control>
<control>touch</control>
</recommends>
<requires>
<display_length compare="ge">360</display_length>
</requires>
</component>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/claps">
<comment>Clapper Playlist</comment>
<glob pattern="*.claps"/>
<icon name="com.github.rafostar.Clapper"/>
</mime-type>
</mime-info>

View File

@@ -0,0 +1,91 @@
/* Clapper Application
* Copyright (C) 2024 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <locale.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <adwaita.h>
#include <clapper/clapper.h>
#include "clapper-app-application.h"
#include "clapper-app-types.h"
#include "clapper-app-utils.h"
gint
main (gint argc, gchar **argv)
{
GApplication *application;
ClapperEnhancerProxyList *proxies;
const gchar *clapper_ldir;
guint i, n_proxies;
gint status;
#ifdef G_OS_WIN32
guint resolution = 0;
#endif
#ifndef G_OS_WIN32
g_setenv ("GSK_RENDERER", "gl", FALSE);
#endif
setlocale (LC_ALL, "");
if (!(clapper_ldir = g_getenv ("CLAPPER_APP_OVERRIDE_LOCALEDIR")))
clapper_ldir = LOCALEDIR;
bindtextdomain (GETTEXT_PACKAGE, clapper_ldir);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
clapper_init (&argc, &argv);
gtk_init ();
adw_init ();
clapper_app_types_init ();
clapper_app_utils_debug_init ();
g_set_application_name ("Clapper");
#ifdef G_OS_WIN32
clapper_app_utils_win_enforce_hi_res_clock ();
resolution = clapper_app_utils_win_hi_res_clock_start ();
#endif
proxies = clapper_get_global_enhancer_proxies ();
n_proxies = clapper_enhancer_proxy_list_get_n_proxies (proxies);
/* Allow usage of all enhancers */
for (i = 0; i < n_proxies; ++i) {
ClapperEnhancerProxy *proxy = clapper_enhancer_proxy_list_peek_proxy (proxies, i);
clapper_enhancer_proxy_set_target_creation_allowed (proxy, TRUE);
}
application = clapper_app_application_new ();
status = g_application_run (application, argc, argv);
g_object_unref (application);
#ifdef G_OS_WIN32
if (resolution > 0)
clapper_app_utils_win_hi_res_clock_stop (resolution);
#endif
clapper_app_utils_delete_tmp_dir ();
return status;
}

View File

@@ -0,0 +1,156 @@
clapperapp_option = get_option('clapper-app')
app_id = 'com.github.rafostar.Clapper'
app_resource_prefix = '/com/github/rafostar/Clapper/clapper-app'
build_clapperapp = false
if clapperapp_option.disabled()
subdir_done()
endif
clapperapp_deps = [
clapper_dep,
clappergtk_dep,
gst_dep,
gtk4_dep,
libadwaita_dep,
glib_dep,
gobject_dep,
]
foreach dep : clapperapp_deps
if not dep.found()
if clapperapp_option.enabled()
error('clapper-app option was enabled, but required dependencies were not found')
endif
subdir_done()
endif
endforeach
subdir('data')
subdir('po')
clapperapp_resources = gnome.compile_resources(
'clapper-app-resources',
'clapper-app.gresources.xml',
c_name: 'clapper_app',
)
# Include the generated headers
clapperapp_conf_inc = [
include_directories('.'),
include_directories('..'),
]
config_h = configuration_data()
config_h.set_quoted('GETTEXT_PACKAGE', meson.project_name() + '-app')
config_h.set_quoted('LOCALEDIR', join_paths (prefix, localedir))
config_h.set_quoted('CLAPPER_APP_NAME', 'Clapper')
config_h.set_quoted('CLAPPER_APP_ID', app_id)
config_h.set_quoted('CLAPPER_APP_RESOURCE_PREFIX', app_resource_prefix)
configure_file(
output: 'config.h',
configuration: config_h,
)
visibility_conf = configuration_data()
visibility_conf.set(
'CLAPPER_API',
'CLAPPER_APP_INTERNAL',
)
configure_file(
input: '../../lib/shared/clapper-api-visibility.h.in',
output: 'clapper-app-internal-visibility.h',
configuration: visibility_conf,
)
clapperapp_sources = [
'clapper-app-about-dialog.c',
'clapper-app-application.c',
'clapper-app-file-dialog.c',
'clapper-app-headerbar.c',
'clapper-app-info-window.c',
'clapper-app-list-item-utils.c',
'clapper-app-media-item-box.c',
'clapper-app-preferences-window.c',
'clapper-app-property-row.c',
'clapper-app-queue-list.c',
'clapper-app-queue-progression-item.c',
'clapper-app-queue-progression-model.c',
'clapper-app-queue-selection.c',
'clapper-app-types.c',
'clapper-app-uri-dialog.c',
'clapper-app-utils.c',
'clapper-app-window.c',
'clapper-app-window-state-buttons.c',
'main.c',
clapperapp_resources,
]
clapperapp_c_args = [
'-DG_LOG_DOMAIN="ClapperApp"',
'-DCLAPPER_APP_INTERNAL_COMPILATION',
'-DGST_USE_UNSTABLE_API',
]
clapperapp_possible_functionalities = [
'pipeline-preview',
]
clapperapp_available_functionalities = []
pp_option = get_option('pipeline-preview')
if not pp_option.disabled()
if cgraph_dep.found() and gvc_dep.found()
clapperapp_c_args += ['-DHAVE_GRAPHVIZ']
clapperapp_deps += [cgraph_dep, gvc_dep]
if gvc_dep.version().version_compare('>= 13.0.0')
clapperapp_c_args += ['-DHAVE_GVC_13']
endif
clapperapp_available_functionalities += 'pipeline-preview'
elif pp_option.enabled()
error('pipeline-preview option was enabled, but required dependencies were not found')
endif
endif
is_windows = ['windows'].contains(host_machine.system())
if is_windows
clapperapp_c_args += ['-D_WIN32_WINNT=_WIN32_WINNT_WIN8']
kernel32_dep = cc.find_library('kernel32', required: false)
if kernel32_dep.found() and cc.has_header('processthreadsapi.h')
clapperapp_deps += kernel32_dep
clapperapp_c_args += ['-DHAVE_WIN_PROCESS_THREADS_API']
endif
winmm_dep = cc.find_library('winmm', required: false)
if winmm_dep.found() and cc.has_header('timeapi.h')
clapperapp_deps += winmm_dep
clapperapp_c_args += ['-DHAVE_WIN_TIME_API']
endif
subdir('windows')
endif
executable(
meson.project_name(),
clapperapp_sources,
dependencies: clapperapp_deps,
include_directories: clapperapp_conf_inc,
c_args: clapperapp_c_args,
install: true,
install_dir: bindir,
win_subsystem: 'windows',
)
if is_windows
executable(
meson.project_name() + '-console',
clapperapp_sources,
dependencies: clapperapp_deps,
include_directories: clapperapp_conf_inc,
c_args: clapperapp_c_args,
install: true,
install_dir: bindir,
win_subsystem: 'console',
)
endif
build_clapperapp = true

View File

@@ -0,0 +1 @@
ar ast ca cs de es eu fa fi fr he hi hr hu it ja lt nl no oc pl pt pt_BR ro ru sk sv tr zh_CN

View File

@@ -0,0 +1,19 @@
src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in
src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui
src/bin/clapper-app/ui/clapper-app-headerbar.ui
src/bin/clapper-app/ui/clapper-app-help-overlay.ui
src/bin/clapper-app/ui/clapper-app-info-window.ui
src/bin/clapper-app/ui/clapper-app-initial-state.ui
src/bin/clapper-app/ui/clapper-app-preferences-window.ui
src/bin/clapper-app/ui/clapper-app-queue-list.ui
src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui
src/bin/clapper-app/ui/clapper-app-uri-dialog.ui
src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui
src/bin/clapper-app/clapper-app-about-dialog.c
src/bin/clapper-app/clapper-app-application.c
src/bin/clapper-app/clapper-app-info-window.c
src/bin/clapper-app/clapper-app-list-item-utils.c
src/bin/clapper-app/clapper-app-preferences-window.c
src/bin/clapper-app/clapper-app-utils.c
src/bin/clapper-app/clapper-app-window.c

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-02-15 12:10\n"
"Last-Translator: \n"
"Language-Team: Afrikaans\n"
"Language: af_ZA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: af\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr ""
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr ""
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr ""
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr ""

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-02-15 12:10\n"
"Last-Translator: \n"
"Language-Team: Arabic\n"
"Language: ar_SA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr "قنوات"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr "الإعدادات"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr ""
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr "حول Clapper"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr "عام"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr "إظهار الاختصارات"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr "تبديل ملء الشاشة"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr "نقرة مزدوجة"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr "خروج"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr "الوسائط"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr "المحتوى التالي"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr "المحتوى السابق"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr "المشغل"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr "بَدْءّ / إيقاف"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr "التقدم للأمام"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr "الرجوع للوراء"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr "رفع مستوى الصوت"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr "خفض مستوى الصوت"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr "كتم الصوت"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr "الفصل التالي"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr "الفصل السابق"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr "العنوان"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr "الصوت"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr "التَّرْجَمَةً"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr "الوضع"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr "القيمة"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr "الوحدة"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr "ثواني"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr "دقائق"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr "النسبة المئوية"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr "الخادم"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr "التحكم بالوسائط عن بعد"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr "الخط الافتراضي"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr "تعديلات"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr "أعدادات الإضافات"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr "تغيير الأعدادات الافتراضية للأضافات GStreamer"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr "أدخل أو الصق URI هنا"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr "إلغاء"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr ""
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr "Yousef Fawaz"
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr "دَقيق"
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr "عادي"
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr "سريع"
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr ""
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr ""

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-02-15 12:11\n"
"Last-Translator: \n"
"Language-Team: Asturian\n"
"Language: ast_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: ast\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr "Preferencies"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr ""
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr "Tocante a Clapper"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr "Xenerales"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr "Amosar los atayos"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr "Colar"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr "Títulu"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr "Audio"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr "Sotítulos"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr "Segundu"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr "Minutu"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr "Porcentaxe"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr "Sirvidor"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr "Encaboxar"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr ""
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr "Adolfo Jayme Barrientos <fitojb@ubuntu.com>, 2022"
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr "Normal"
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr ""
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr ""

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-02-15 12:10\n"
"Last-Translator: \n"
"Language-Team: Catalan\n"
"Language: ca_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr "Còdec"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr "Canals"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr "Format d'exemple"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr "Freqüència de mostreig"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr "Taxa de bits"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr "Idioma"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr "Preferències"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr "Dreceres del teclat"
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr "Quant al Clapper"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr "General"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr "Obre les preferències"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr "Mostra les dreceres"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr "Commuta la pantalla completa"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr "Prem dues vegades | Doble clic"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr "Surt"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr "Mèdia"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr "Afegeix fitxers…"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr "Afegeix un URI…"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr "Cua"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr "Element següent"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr "Element anterior"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr "Canvia el mode de progressió"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr "Reproducció"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr "Commuta la reproducció"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr "Toc | Clic esquerre"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr "Avança"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr "Doble toc (costat dret) | Desplaçar-se a la dreta"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr "Doble toc (costat esquerre) | Desplaçar-se a l'esquerra"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr "Retrocedeix"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr "Apuja el volum"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr "Roda del ratolí amunt"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr "Baixa el volum"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr "Roda del ratolí avall"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr "Commuta el silenci"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr "Accelera"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr "Alenteix"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr "Capítol següent"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr "Capítol anterior"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr "Informació"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr "Títol"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr "Format del contenidor"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr "Duració"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr "Fluxos de dades"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr "Vídeo"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr "Àudio"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr "Subtítols"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr "Reproducció de vídeo"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr "Descodificador"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr "Filtre"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr "Receptor"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr "Reproducció d'àudio"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr "Fluxos de vídeo"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr "Fluxos d'àudio"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr "Fluxos de subtítols"
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr "Comença per afegir multimèdia a la cua de reproducció"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr "Desplaçament"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr "Mètode"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr "El mètode preferit pel desplaçament"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr "Valor"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr "Valor usat per desplaçar-se endavant i enrere"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr "Unitat"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr "La unitat de mesura pel desplaçament endavant i enrere"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr "Segon"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr "Minut"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr "Percentatge"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr "Característiques"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr "Servidor"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr "Controla el reproductor remotament"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr "Decalatge"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr "Decalatge en segons per la sincronia entre el vídeo i l'àudio"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr "Decalatge en segons per la sincronia entre els subtítols i el vídeo"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr "Tipus de lletra per defecte"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr "Família tipogràfica dels subtítols quan cap s'especifica"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr "Ajustaments"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr "Classificació dels connectors"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr "Altera els rangs predeterminats dels connectors del GStreamer"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr "Classificació dels connectors"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr "Connectors disponibles"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr "Selecciona un connector i llur característica per sobreseure'n el rang. Quan múltiples elements tenen funcionalitats semblants, es prefereix el que té el valor més alt."
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr "Connector"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr "Característica del connector"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr "Afegeix un sobreseïment"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr "Sobreseïments de rangs"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr "Afegeix"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr "Progressió de la cua"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr "Afegeix un URI"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr "Insereix un URI a afegir a la cua de reproducció"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr "Escriu o deixa anar una URI aquí"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr "Cancel·la"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr "Resolució"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr "Taxa de fotogrames"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr "Format del píxel"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr "Ícar Nin Solana <icar.nin@protonmail.com>, 2021"
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr "Maquinari"
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr "Programari"
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr "Acurat"
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr "Normal"
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr "Ràpid"
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr "Sense progressió"
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr "Consecutiu"
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr "Repeteix l'ítem"
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr "Carrusel"
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr "Aleatori"
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr "Deixa anar a sobre la barra de títol per reproduir-ho ara o a qualsevol altre lloc per posar-ho en cua."

View File

@@ -0,0 +1,560 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the clapper-app package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: clapper-app\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr ""
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid ""
"Synchronisation offset in seconds between the subtitle and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid ""
"Select a plugin and its feature to override rank for. When multiple elements "
"have similiar capabilities, the one with highest value is preferred."
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr ""
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid ""
"Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, "
"3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr ""
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr ""

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-02-15 12:10\n"
"Last-Translator: \n"
"Language-Team: Czech\n"
"Language: cs_CZ\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr "Kodek"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr "Kanály"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr "Vzorkovací Formát"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr "Vzorkovací Frekvence"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr "Datový Tok"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr "Jazyk"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr "Předvolby"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr "Klávesové Zkratky"
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr "O aplikaci Clapper"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr "Obecné"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr "Otevřít předvolby"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr "Zobrazit klávesové zkratky"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr "Celá obrazovka"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr "Dvojitým poklepáním | Dvojitým kliknutím"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr "Ukončit"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr "Média"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr "Přidat Soubory…"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr "Přidat URI…"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr "Fronta"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr "Další položka"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr "Předchozí položka"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr "Změnit způsob postupování"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr "Přehrávání"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr "Přepnout přehrávání"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr "Klepnutím | Levým tlačítkem"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr "Přetočit vpřed"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr "Dvojitě klepnout (pravá strana) | Posun vpravo"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr "Dvojitě klepnout (levá strana) | Posun vlevo"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr "Přetočit zpět"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr "Zesílit"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr "Posun nahoru"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr "Zeslabit"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr "Posun dolů"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr "Vypnout/zapnout zvuk"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr "Zrychlit"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr "Zpomalit"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr "Další kapitola"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr "Předchozí kapitola"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr "Informace"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr "Název"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr "Formát Kontejneru"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr "Doba Trvání"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr "Kanály"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr "Video"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr "Zvuk"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr "Titulky"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr "Přehrávání Videa"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr "Dekodér"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr "Filtr"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr "Sink"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr "Přehrávání Audia"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr "Video Kanály"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr "Audio Kanály"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr "Titulkové Kanály"
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr "Začněte přidáním média do přehrávací fronty"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr "Přetáčení"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr "Způsob"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr "Upřednostňovaný způsob použitý pro přetáčení"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr "Hodnota"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr "Hodnota použitá pro přetáčení dopředu/dozadu"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr "Jednotka"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr "Jednotka hodnoty pro přetáčení dopředu/dozadu"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr "Sekundy"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr "Minuty"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr "Procenta"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr "Funkce"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr "Server"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr "Vzdáleně ovládat přehrávač"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr "Posun"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr "Synchronizační posun v sekundách mezi audio a video kanály"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr "Synchronizační posun v sekundách mezi titulkovými a video kanály"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr "Výchozí styl písma"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr "Písmo používané pro titulky, když jej médium výslovně neupřesní"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr "Vylepšení"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr "Pořadí pluginů"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr "Změna výchozího pořadí zásuvných modulů GStreameru"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr "Pořadí Pluginů"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr "Dostupné pluginy"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr "Vyberte plugin a jeho funkci, pro kterou chcete přepsat pořadí. Pokud má více prvků podobnou schopnost, je preferována ta s nejvyšší hodnotou."
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr "Plugin"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr "Funkce pluginy"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr "Přidat přepsání"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr "Pořadí přepsání"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr "Přidat"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr "Postup fronty"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr "Přidat URI"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr "Vložte URI, která bude přidána do fronty přehrávání"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr "Zde zadejte nebo přetáhněte URI"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr "Zrušit"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr "Rozlišení"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr "Snímky za sekundu"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr "Formát Pixelu"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr "Vojtěch Perník <translations@pervoj.cz>"
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr "Hardware"
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr "Software"
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr "Přesný"
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr "Normální"
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr "Rychlý"
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr "Žádný postup"
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr "Po sobě"
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr "Opakovat položku"
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr "Opakovat frontu"
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr "Náhodně"
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr "Přetáhněte na titulní lištu pro okamžité přehrání nebo kdekoliv jinde pro zařazení."

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-02-15 12:10\n"
"Last-Translator: \n"
"Language-Team: Danish\n"
"Language: da_DK\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr ""
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr ""
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr ""
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr ""
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr ""
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr ""
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr ""
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr ""
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr ""

View File

@@ -0,0 +1,556 @@
msgid ""
msgstr ""
"Project-Id-Version: clapper\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-02-15 12:47+0100\n"
"PO-Revision-Date: 2025-04-11 18:29\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: clapper\n"
"X-Crowdin-Project-ID: 473374\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/src/bin/clapper-app/po/clapper-app.pot\n"
"X-Crowdin-File-ID: 48\n"
#. Translators: Do NOT translate app name!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:4
msgid "Clapper"
msgstr "Clapper"
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:5
msgid "Multimedia Player"
msgstr "Multimedia Wiedergabe"
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:6
msgid "Play videos and music"
msgstr "Gebe Videos uns Musik wieder"
#. Translators: Search terms to find this application. Do NOT translate the semicolons!
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:16
msgid "Video;Movie;Film;Clip;Series;Player;Playlist;DVD;TV;Disc;"
msgstr ""
#: src/bin/clapper-app/data/applications/com.github.rafostar.Clapper.desktop.in:22
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:183
msgid "New Window"
msgstr "Neues Fenster"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:14
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:14
msgid "Codec"
msgstr "Codec"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:24
msgid "Channels"
msgstr "Audio-Kanäle"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:36
msgid "Sample Format"
msgstr "Abtastformat"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:46
msgid "Sample Rate"
msgstr "Abtastrate"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:58
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:51
msgid "Bitrate"
msgstr "Bitrate"
#: src/bin/clapper-app/ui/clapper-app-audio-stream-list-item.ui:70
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:24
msgid "Language"
msgstr "Sprache"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:189
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:80
msgid "Preferences"
msgstr "Einstellungen"
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:193
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:84
msgid "Keyboard Shortcuts"
msgstr "Tastaturkürzel"
#. TRANSLATORS: Please do not translate application name
#: src/bin/clapper-app/ui/clapper-app-headerbar.ui:200
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:91
msgid "About Clapper"
msgstr "Über Clapper"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:10
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:11
msgid "General"
msgstr "Allgemein"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:13
msgid "New window"
msgstr "Neues Fenster"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:19
msgid "Open preferences"
msgstr "Einstellungen öffnen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:25
msgid "Show shortcuts"
msgstr "Tastenkombinationen zeigen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:31
msgid "Toggle fullscreen"
msgstr "In Vollbildmodus wechseln"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:32
msgid "Double tap | Double click"
msgstr "Doppelt tippen bzw. klicken"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:38
msgid "Unfullscreen"
msgstr "Vollbildmodus deaktivieren"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:44
msgid "Auto window resize"
msgstr "Automatische Größenanpassung des Fensters"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:45
msgid "Middle click"
msgstr "Mittlere Maustaste"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:51
msgid "Quit"
msgstr "Clapper beenden"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:59
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:32
msgid "Media"
msgstr "Medien"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:62
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:55
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:178
msgid "Add Files…"
msgstr "Dateien hinzufügen…"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:68
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:65
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:182
msgid "Add URI…"
msgstr "URI hinzufügen…"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:76
msgid "Queue"
msgstr "Warteschlange"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:80
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:87
msgid "Next item"
msgstr "Nächster Titel"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:94
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:101
msgid "Previous item"
msgstr "Vorheriger Titel"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:107
msgid "Change progression mode"
msgstr "Wiedergabemodus wechseln"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:115
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:76
msgid "Playback"
msgstr "Wiedergabe"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:118
msgid "Toggle play"
msgstr "Wiedergabe umschalten"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:119
msgid "Tap | Left click"
msgstr "Tippen | Linke Maustaste"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:126
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:134
msgid "Seek forward"
msgstr "Vorwärts springen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:127
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:151
msgid "Double tap (right side) | Scroll right"
msgstr "Doppelt auf die rechte Seite tippen | Nach rechts scrollen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:135
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:143
msgid "Double tap (left side) | Scroll left"
msgstr "Doppelt auf die linke Seite tippen | Nach links scrollen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:142
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:150
msgid "Seek backward"
msgstr "Rückwärts springen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:157
msgid "Volume up"
msgstr "Lautstärke erhöhen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:158
msgid "Scroll up"
msgstr "Hochscrollen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:164
msgid "Volume down"
msgstr "Lautstärke verringern"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:165
msgid "Scroll down"
msgstr "Runterscrollen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:171
msgid "Toggle mute"
msgstr "Stummschaltung umschalten"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:177
msgid "Speed up"
msgstr "Geschwindigkeit erhöhen"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:183
msgid "Speed down"
msgstr "Geschwindigkeit verringern"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:190
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:197
msgid "Next chapter"
msgstr "Nächstes Kapitel"
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:204
#: src/bin/clapper-app/ui/clapper-app-help-overlay.ui:211
msgid "Previous chapter"
msgstr "Vorheriges Kapitel"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:13
msgid "Info"
msgstr "Informationen"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:35
#: src/bin/clapper-app/ui/clapper-app-subtitle-stream-list-item.ui:14
msgid "Title"
msgstr "Titel"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:49
msgid "Container Format"
msgstr "Containerformat"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:63
msgid "Duration"
msgstr "Länge"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:81
msgid "Streams"
msgstr "Spuren"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:84
#: src/bin/clapper-app/clapper-app-list-item-utils.c:36
msgid "Video"
msgstr "Video"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:107
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:80
#: src/bin/clapper-app/clapper-app-list-item-utils.c:39
msgid "Audio"
msgstr "Audio"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:130
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:100
#: src/bin/clapper-app/clapper-app-list-item-utils.c:42
msgid "Subtitles"
msgstr "Untertitel"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:155
msgid "Video Playback"
msgstr "Videowiedergabe"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:158
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:199
msgid "Decoder"
msgstr "Dekodierer"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:170
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:211
msgid "Filter"
msgstr "Filter"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:182
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:223
msgid "Sink"
msgstr "Ausgabeziel"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:196
msgid "Audio Playback"
msgstr "Audiowiedergabe"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:247
msgid "Video Streams"
msgstr "Videospuren"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:290
msgid "Audio Streams"
msgstr "Audiospuren"
#: src/bin/clapper-app/ui/clapper-app-info-window.ui:333
msgid "Subtitle Streams"
msgstr "Untertitelspuren"
#: src/bin/clapper-app/ui/clapper-app-initial-state.ui:46
msgid "Start by adding media to playback queue"
msgstr "Beginnen sie damit, Medien zur Wiedergabewarteschlange hinzuzufügen"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:15
msgid "Seeking"
msgstr "Springen"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:18
msgid "Method"
msgstr "Verhalten"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:19
msgid "A preferred method used for seeking"
msgstr "Das bevorzugte Sprungverhalten"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:32
msgid "Value"
msgstr "Wert"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:33
msgid "Value used for seeking forward/backward"
msgstr "Um diesen Wert wird vor-/rückwärts gesprungen"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:46
msgid "Unit"
msgstr "Einheit"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:47
msgid "An unit of a seek forward/backward value"
msgstr "Die Einheit für den Sprungwert"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:51
msgid "Second"
msgstr "Sekunden"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:52
msgid "Minute"
msgstr "Minuten"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:53
msgid "Percentage"
msgstr "Prozentsatz"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:63
msgid "Features"
msgstr "Erweiterungen"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:66
msgid "Server"
msgstr "Server"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:67
msgid "Control player remotely"
msgstr "Clapper fernsteuern"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:83
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:103
msgid "Offset"
msgstr "Versetzung"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:84
msgid "Synchronisation offset in seconds between the audio and video streams"
msgstr "Versatz zwischen der Audio- und Videospur (in Sekunden)"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:104
msgid "Synchronisation offset in seconds between the subtitle and video streams"
msgstr "Versatz zwischen der Untertitel- und Videospur (in Sekunden)"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:118
msgid "Default font"
msgstr "Standardschriftart"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:119
msgid "Text font used for subtitles when media does not explicitly specify one"
msgstr "Schriftart, welche für Untertitel verwendet wird, falls das Medium selbst keine vorgibt"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:137
msgid "Tweaks"
msgstr "Optimierungen"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:144
msgid "Plugin ranking"
msgstr "Plugin-Reihenfolge"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:145
msgid "Alter default ranks of GStreamer plugins"
msgstr "Standard GStreamer Plugin Reihenfolge verändern"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:164
msgid "Plugin Ranking"
msgstr "Pluginreihenfolge"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:182
msgid "Available plugins"
msgstr "Verfügbare Plugins"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:183
msgid "Select a plugin and its feature to override rank for. When multiple elements have similiar capabilities, the one with highest value is preferred."
msgstr "Wähle ein Plugin und seine Funktion für welches sie die Position der Reihenfolge überschreiben möchten. Falls mehrere Plugins ähnliche Fähigkeiten besitzen, wird dasjenige mit dem höchsten Rang bevorzugt."
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:186
msgid "Plugin"
msgstr "Plugin"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:195
msgid "Plugin feature"
msgstr "Pluginfunktion"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:213
msgid "Add override"
msgstr "Hinzufügen"
#: src/bin/clapper-app/ui/clapper-app-preferences-window.ui:229
msgid "Rank overrides"
msgstr "Funktionsrangliste"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:60
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:23
msgid "Add"
msgstr "Hinzufügen"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:87
msgid "Queue progression"
msgstr "Warteschlangenwiedergabe"
#: src/bin/clapper-app/ui/clapper-app-queue-list.ui:188
msgid "Clear Queue"
msgstr "Warteschlange leeren"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:6
msgid "Add URI"
msgstr "URI hinzufügen"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:7
msgid "Insert an URI to be added to playback queue"
msgstr "Geben sie eine URI an, welche zur Wiedergabewarteschlange hinzugefügt werden soll"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:18
msgid "Enter or drop URI here"
msgstr "URI hier einfügen"
#: src/bin/clapper-app/ui/clapper-app-uri-dialog.ui:22
msgid "Cancel"
msgstr "Abbrechen"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:24
msgid "Resolution"
msgstr "Auflösung"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:39
msgid "Framerate"
msgstr "Bildwiederholrate"
#: src/bin/clapper-app/ui/clapper-app-video-stream-list-item.ui:63
msgid "Pixel Format"
msgstr "Pixelformat"
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
#: src/bin/clapper-app/clapper-app-about-window.c:47
msgid "translator-credits"
msgstr "Florian \"sp1rit\" <sp1rit@disroot.org>"
#: src/bin/clapper-app/clapper-app-application.c:696
msgid "Create a new window"
msgstr "Erstelle ein neues Fenster"
#: src/bin/clapper-app/clapper-app-application.c:697
msgid "Add media to queue in primary application instance"
msgstr "Füge ein Medium zur Warteschlange der primären Anwendungsinstanz hinzu"
#: src/bin/clapper-app/clapper-app-application.c:698
msgid "Audio volume to set (0 - 2.0 range)"
msgstr "Wiedergabelautstärke ändern (zwischen 0 - 2.0)"
#: src/bin/clapper-app/clapper-app-application.c:699
msgid "Playback speed to set (0.05 - 2.0 range)"
msgstr "Wiedergabelautstärke ändern (zwischen 0.05 - 2.0)"
#: src/bin/clapper-app/clapper-app-application.c:700
msgid "Initial bitrate for adaptive streaming"
msgstr "Initiale Bitrate für adaptives Streaming"
#: src/bin/clapper-app/clapper-app-application.c:701
msgid "Initial queue progression mode (0=none, 1=consecutive, 2=repeat-item, 3=carousel, 4=shuffle)"
msgstr "Initialer Warteschlangenfortschrittsmodus (0=keiner, 1=fortlaufend, 2=element wiederholen, 3=karussell, 4=zufällig)"
#: src/bin/clapper-app/clapper-app-application.c:702
msgid "Set window to be fullscreen"
msgstr "In den Vollbildmodus wechseln"
#: src/bin/clapper-app/clapper-app-application.c:703
msgid "Video filter to use (\"none\" to disable)"
msgstr "Zu verwendender Videofilter (\"none\" für keinen)"
#: src/bin/clapper-app/clapper-app-application.c:704
msgid "Audio filter to use (\"none\" to disable)"
msgstr "Zu verwendender Audiofilter (\"none\" für keinen)"
#: src/bin/clapper-app/clapper-app-application.c:705
msgid "Video sink to use"
msgstr "Zu verwendender Videoabfuss"
#: src/bin/clapper-app/clapper-app-application.c:706
msgid "Audio sink to use"
msgstr "Zu verwendender Audioabfuss"
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Hardware"
msgstr "Hardware"
#: src/bin/clapper-app/clapper-app-info-window.c:86
msgid "Software"
msgstr "Software"
#: src/bin/clapper-app/clapper-app-preferences-window.c:441
msgid "Accurate"
msgstr "Genau"
#: src/bin/clapper-app/clapper-app-preferences-window.c:443
msgid "Normal"
msgstr "Normal"
#: src/bin/clapper-app/clapper-app-preferences-window.c:445
msgid "Fast"
msgstr "Schnell"
#: src/bin/clapper-app/clapper-app-utils.c:207
msgid "No progression"
msgstr "Kein Fortschritt"
#: src/bin/clapper-app/clapper-app-utils.c:208
msgid "Consecutive"
msgstr "Fortlaufend"
#: src/bin/clapper-app/clapper-app-utils.c:209
msgid "Repeat item"
msgstr "Wiederholen"
#: src/bin/clapper-app/clapper-app-utils.c:210
msgid "Carousel"
msgstr "Kreislauf"
#: src/bin/clapper-app/clapper-app-utils.c:211
msgid "Shuffle"
msgstr "Zufallswiedergabe"
#: src/bin/clapper-app/clapper-app-window.c:1036
msgid "Drop on title bar to play now or anywhere else to enqueue."
msgstr "Zur direkten Wiedergabe legen Sie die Datei auf der Titelleiste ab, andernfalls wird die Datei der Warteschlange hinzugefügt."

Some files were not shown because too many files have changed in this diff Show More