Compare commits
1 Commits
dmabufimpo
...
gstplaylis
Author | SHA1 | Date | |
---|---|---|---|
|
f64f438f1e |
41
.github/workflows/flatpak-nightly.yml
vendored
@@ -1,41 +0,0 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
name: "Flatpak Nightly"
|
||||
jobs:
|
||||
flatpak:
|
||||
name: "Flatpak"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-nightly
|
||||
options: --privileged
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, aarch64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install Docker
|
||||
run: |
|
||||
dnf -y install docker
|
||||
- name: Setup QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: arm64
|
||||
- name: Prepare Runtime
|
||||
run: |
|
||||
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.rust-nightly/${{ matrix.arch }}/21.08
|
||||
flatpak --system install -y --noninteractive flathub org.freedesktop.Sdk.Extension.llvm13/${{ matrix.arch }}/21.08
|
||||
- uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v4
|
||||
name: Build
|
||||
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 }}
|
39
.github/workflows/flatpak.yml
vendored
@@ -1,39 +0,0 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
name: "Flatpak"
|
||||
jobs:
|
||||
flatpak:
|
||||
name: "Flatpak"
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: bilelmoussaoui/flatpak-github-actions:gnome-42
|
||||
options: --privileged
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, aarch64]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install Docker
|
||||
run: |
|
||||
dnf -y install docker
|
||||
- name: Setup QEMU
|
||||
id: qemu
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: arm64
|
||||
- uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v4
|
||||
name: "Build"
|
||||
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 }}
|
59
README.md
@@ -1,12 +1,6 @@
|
||||
# Clapper
|
||||
[](https://github.com/Rafostar/clapper/actions/workflows/flatpak.yml)
|
||||
[](https://github.com/Rafostar/clapper/actions/workflows/flatpak-nightly.yml)
|
||||
[](https://crowdin.com/project/clapper)
|
||||
[](https://matrix.to/#/#clapper-player:matrix.org)
|
||||
[](https://liberapay.com/Clapper)
|
||||
|
||||
A GNOME media player built using [GJS](https://gitlab.gnome.org/GNOME/gjs) with [GTK4](https://www.gtk.org) toolkit.
|
||||
The media player uses [GStreamer](https://gstreamer.freedesktop.org/) as a media backend and renders everything via [OpenGL](https://www.opengl.org).
|
||||
A GNOME media player build using [GJS](https://gitlab.gnome.org/GNOME/gjs) with [GTK4](https://www.gtk.org) toolkit.
|
||||
The media player is using [GStreamer](https://gstreamer.freedesktop.org/) as a media backend and renders everything via [OpenGL](https://www.opengl.org).
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot-windowed.png"><br>
|
||||
@@ -29,42 +23,49 @@ The media player uses [GStreamer](https://gstreamer.freedesktop.org/) as a media
|
||||
* [Adaptive UI](https://raw.githubusercontent.com/wiki/Rafostar/clapper/media/screenshot-mobile.png)
|
||||
* [Playlist from file](https://github.com/Rafostar/clapper/wiki/Playlists)
|
||||
* Chapters on progress bar
|
||||
* MPRIS support
|
||||
|
||||
## Installation from Flatpak
|
||||
The `Flatpak` package includes all required dependencies and codecs.
|
||||
Additionally it also has a few patches, thus some functionalities work better (or are only available) 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).
|
||||
Additionally it also has a few patches, thus some functionalities work better (or are only available) 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>
|
||||
<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
|
||||
[](https://repology.org/project/clapper/versions)
|
||||
**Important:** If you have been using the flatpak package from my custom 3rd party repo, please remove it and replace your installation with version from Flathub. That repository will not be maintained any longer. Thank you for understanding.
|
||||
|
||||
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.
|
||||
## Packages
|
||||
The [pkgs folder](https://github.com/Rafostar/clapper/tree/master/pkgs) in this repository contains build scripts for various package formats. You can use them to build package yourself or download one of pre-built packages:
|
||||
|
||||
## Installation from Source Code
|
||||
#### Debian, Fedora & openSUSE
|
||||
Pre-built packages are 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 build on each git commit, thus are considered unstable.
|
||||
|
||||
#### Arch Linux
|
||||
You can get Clapper from the AUR:
|
||||
* [clapper](https://aur.archlinux.org/packages/clapper) (stable version)
|
||||
* [clapper-git](https://aur.archlinux.org/packages/clapper-git)
|
||||
|
||||
## Installation from source code
|
||||
```sh
|
||||
meson builddir --prefix=/usr/local
|
||||
sudo meson install -C builddir
|
||||
```
|
||||
|
||||
## Questions?
|
||||
## Q&A
|
||||
**Q:** Does using `GJS` negatively impact video performance?<br>
|
||||
**A:** Absolutely not. `GJS` here is used to put together the GUI during startup.
|
||||
It has nothing to do with video rendering. All used `GTK4` and `GStreamer` libraries are in C.
|
||||
Even the custom video widget that I prepared for this player (based on original `GTK3` implementation) is a compiled C code.
|
||||
All these libs are acting "on their own" and no function calls from `GJS` related to video decoding and rendering are performed during playback.
|
||||
|
||||
**Q:** What settings should I set to maximize performance?<br>
|
||||
**A:** As of now, player works best on `Wayland` session. `Wayland` users can try enabling highly experimental `vah264dec` plugin for improved performance (this plugin does not work on `Xorg` right now) for standard (8-bit) `H.264` videos.
|
||||
It can be enabled from inside player preferences dialog inside `Advanced -> GStreamer` tab using customizable `Plugin Ranking` feature.
|
||||
Since the whole app is rendered using your GPU, users of VERY weak GPUs might want to disable the "render window shadows" option to have more GPU power available for non-fullscreen video rendering.
|
||||
|
||||
## Other 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.
|
||||
|
||||
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.
|
||||
|
6
TODO.md
@@ -40,7 +40,7 @@
|
||||
- [X] Remote playback controls via HTTP (VLC) + WebSockets
|
||||
- [ ] Expand available API
|
||||
- [ ] API documentation
|
||||
- [X] Integration with the top bar
|
||||
- [X] MPRIS support
|
||||
- [X] Controls in the notifications panel
|
||||
- [ ] Integration with the top bar
|
||||
- [ ] MPRIS support
|
||||
- [ ] Controls in the notifications panel
|
||||
- [ ] Progress bar in the notifications panel (maybe via extension)
|
||||
|
1
_service
@@ -4,6 +4,7 @@
|
||||
<param name="url">https://github.com/Rafostar/clapper.git</param>
|
||||
<param name="extract">pkgs/rpm/clapper.spec</param>
|
||||
<param name="extract">pkgs/rpm/clapper.rpmlintrc</param>
|
||||
<param name="extract">pkgs/deb/clapper.dsc</param>
|
||||
</service>
|
||||
<service name="tar" mode="buildtime"/>
|
||||
<service name="recompress" mode="buildtime">
|
||||
|
17
bin/com.github.rafostar.Clapper.Subprocess.in
Normal file
@@ -0,0 +1,17 @@
|
||||
#!@GJS@
|
||||
|
||||
/* pkg init enforces the imports path to the folder
|
||||
* named after the pkg name, but I would prefer to have
|
||||
* the bundled subprocess stored in the same directory */
|
||||
imports.searchPath.unshift('@datadir@/@PACKAGE_NAME@');
|
||||
|
||||
const Package = imports.package;
|
||||
|
||||
Package.init({
|
||||
name: '@PACKAGE_NAME@.@ID_POSTFIX@',
|
||||
version: '@PACKAGE_VERSION@',
|
||||
prefix: '@prefix@',
|
||||
libdir: '@libdir@',
|
||||
datadir: '@datadir@',
|
||||
});
|
||||
Package.run(imports.src.main@ID_POSTFIX@);
|
@@ -1,9 +1,12 @@
|
||||
#!@GJS@
|
||||
|
||||
imports.package.init({
|
||||
const Package = imports.package;
|
||||
|
||||
Package.init({
|
||||
name: '@PACKAGE_NAME@',
|
||||
version: '@PACKAGE_VERSION@',
|
||||
prefix: '@prefix@',
|
||||
libdir: '@libdir@',
|
||||
datadir: '@datadir@',
|
||||
});
|
||||
imports.package.run(imports.src.main);
|
||||
Package.run(imports.src.main);
|
||||
|
@@ -1,22 +1,24 @@
|
||||
bin_conf = configuration_data()
|
||||
clapper_apps = ['', 'Remote', 'Daemon']
|
||||
|
||||
bin_conf.set('GJS', find_program('gjs').path())
|
||||
bin_conf.set('PACKAGE_NAME', meson.project_name())
|
||||
bin_conf.set('PACKAGE_VERSION', meson.project_version())
|
||||
bin_conf.set('prefix', get_option('prefix'))
|
||||
bin_conf.set('libdir', libdir)
|
||||
foreach id_postfix : clapper_apps
|
||||
app_postfix = (id_postfix != '') ? '.' + id_postfix : ''
|
||||
template_type = (id_postfix != '') ? '.Subprocess' : ''
|
||||
|
||||
configure_file(
|
||||
input: 'com.github.rafostar.Clapper.in',
|
||||
output: 'com.github.rafostar.Clapper',
|
||||
configuration: bin_conf,
|
||||
install: true,
|
||||
install_dir: bindir,
|
||||
install_mode: 'rwxr-xr-x'
|
||||
)
|
||||
bin_conf = configuration_data()
|
||||
bin_conf.set('GJS', find_program('gjs').path())
|
||||
bin_conf.set('PACKAGE_NAME', meson.project_name())
|
||||
bin_conf.set('PACKAGE_VERSION', meson.project_version())
|
||||
bin_conf.set('ID_POSTFIX', id_postfix)
|
||||
bin_conf.set('prefix', get_option('prefix'))
|
||||
bin_conf.set('libdir', join_paths(get_option('prefix'), get_option('libdir')))
|
||||
bin_conf.set('datadir', join_paths(get_option('prefix'), get_option('datadir')))
|
||||
|
||||
clapper_symlink_cmd = 'ln -fs @0@ $DESTDIR@1@'.format(
|
||||
'com.github.rafostar.Clapper',
|
||||
join_paths(bindir, 'clapper')
|
||||
)
|
||||
meson.add_install_script('sh', '-c', clapper_symlink_cmd)
|
||||
configure_file(
|
||||
input: 'com.github.rafostar.Clapper' + template_type + '.in',
|
||||
output: 'com.github.rafostar.Clapper' + app_postfix,
|
||||
configuration: bin_conf,
|
||||
install: true,
|
||||
install_dir: get_option('bindir'),
|
||||
install_mode: 'rwxr-xr-x'
|
||||
)
|
||||
endforeach
|
||||
|
@@ -1,3 +0,0 @@
|
||||
files:
|
||||
- source: /po/com.github.rafostar.Clapper.pot
|
||||
translation: /po/%osx_locale%.po
|
215
css/styles.css
@@ -5,35 +5,19 @@ scale marks {
|
||||
radio {
|
||||
margin-left: -2px;
|
||||
}
|
||||
scrolledwindow scrollbar.vertical slider {
|
||||
min-height: 16px;
|
||||
}
|
||||
|
||||
/* Adwaita is missing osd ListBox */
|
||||
.clapperplaylist {
|
||||
.osd list {
|
||||
background: none;
|
||||
}
|
||||
.clapperplaylist row {
|
||||
border-radius: 5px;
|
||||
}
|
||||
.clapperplaylist row {
|
||||
color: @theme_fg_color;
|
||||
}
|
||||
.clapperplaylist row button {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
min-width: 28px;
|
||||
min-height: 28px;
|
||||
}
|
||||
.fullscreen.tvmode .clapperplaylist row button {
|
||||
min-width: 36px;
|
||||
min-height: 36px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.osd .clapperplaylist row image {
|
||||
.osd list row image {
|
||||
-gtk-icon-shadow: none;
|
||||
}
|
||||
.gtk402 trough highlight {
|
||||
border-color: transparent;
|
||||
}
|
||||
.gtk402 .osd trough highlight {
|
||||
border-color: inherit;
|
||||
}
|
||||
.osdheaderbar {
|
||||
background: transparent;
|
||||
}
|
||||
@@ -50,18 +34,18 @@ scrolledwindow scrollbar.vertical slider {
|
||||
.linkedright image {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
/* Flat popovers */
|
||||
popover arrow,
|
||||
popover contents {
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
/* Non-osd style for popover menu */
|
||||
.menupopover label {
|
||||
color: @theme_text_color;
|
||||
}
|
||||
.popoverseparator separator {
|
||||
background-color: @insensitive_fg_color;
|
||||
.menupopover arrow {
|
||||
background: @theme_base_color;
|
||||
border-color: @insensitive_base_color;
|
||||
}
|
||||
.menupopover contents {
|
||||
background: @theme_base_color;
|
||||
border-color: @insensitive_base_color;
|
||||
}
|
||||
|
||||
/* Rounded corners */
|
||||
.adwrounded.csd {
|
||||
border-radius: 8px;
|
||||
}
|
||||
@@ -77,15 +61,8 @@ popover contents {
|
||||
.roundedcorners {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Reduce sliders size */
|
||||
scale trough slider {
|
||||
min-height: 18px;
|
||||
min-width: 18px;
|
||||
}
|
||||
.fullscreen.tvmode scale trough slider {
|
||||
min-height: 20px;
|
||||
min-width: 20px;
|
||||
.adwthemedark scale trough highlight {
|
||||
filter: brightness(120%);
|
||||
}
|
||||
|
||||
.videowidget {
|
||||
@@ -98,29 +75,24 @@ scale trough slider {
|
||||
font-size: 21px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.clappercontrols {
|
||||
.adwicons .playercontrols {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.playercontrols {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.fullscreen.tvmode .clappercontrols {
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
.clappercontrolsbutton {
|
||||
.playercontrols button {
|
||||
margin: 3px;
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
.fullscreen.tvmode .clappercontrolsbutton {
|
||||
.fullscreen.tvmode .playercontrols button {
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
margin: 5px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.clappercontrolsbutton.text-button {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.fullscreen.tvmode button image {
|
||||
-gtk-icon-shadow: none;
|
||||
@@ -133,16 +105,24 @@ scale trough slider {
|
||||
min-height: 17px;
|
||||
}
|
||||
|
||||
/* Also affects popover buttons */
|
||||
.fullscreen.tvmode .clappercontrols button image {
|
||||
-gtk-icon-size: 26px;
|
||||
.fullscreen.tvmode .playercontrols button image {
|
||||
-gtk-icon-size: 24px;
|
||||
}
|
||||
.clappercontrolsbutton.text-button label {
|
||||
.adwicons .playbackicon {
|
||||
-gtk-icon-size: 20px;
|
||||
}
|
||||
.adwicons.fullscreen.tvmode .playbackicon {
|
||||
-gtk-icon-size: 28px;
|
||||
}
|
||||
.labelbuttonlabel {
|
||||
margin-left: -4px;
|
||||
margin-right: -4px;
|
||||
min-width: 8px;
|
||||
font-family: 'Cantarell', sans-serif;
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-weight: 600;
|
||||
}
|
||||
.fullscreen.tvmode .clappercontrolsbutton.text-button label {
|
||||
.fullscreen.tvmode .labelbuttonlabel {
|
||||
font-size: 22px;
|
||||
text-shadow: none;
|
||||
}
|
||||
@@ -173,27 +153,29 @@ scale trough slider {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
/* Button Inside Popover */
|
||||
.popoverbutton {
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
/* Position Scale */
|
||||
.positionscale {
|
||||
margin: -2px;
|
||||
margin-left: -4px;
|
||||
margin-right: -4px;
|
||||
}
|
||||
.positionscale trough highlight {
|
||||
min-height: 4px;
|
||||
}
|
||||
.osd .positionscale trough highlight {
|
||||
min-height: 6px;
|
||||
}
|
||||
.fullscreen.tvmode .positionscale {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
.fullscreen.tvmode .positionscale.fine-tune {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
.fullscreen.tvmode .positionscale trough slider {
|
||||
color: transparent;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
.positionscale mark indicator {
|
||||
min-height: 6px;
|
||||
@@ -223,9 +205,6 @@ scale trough slider {
|
||||
.fullscreen.tvmode .positionscale marks.bottom {
|
||||
margin-top: 2px;
|
||||
}
|
||||
.fullscreen.tvmode .positionscale trough {
|
||||
border-radius: 3px;
|
||||
}
|
||||
.fullscreen.tvmode .positionscale trough highlight {
|
||||
border-radius: 3px;
|
||||
min-height: 20px;
|
||||
@@ -253,9 +232,6 @@ scale trough slider {
|
||||
margin-top: -4px;
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
.volumescale trough highlight {
|
||||
min-width: 4px;
|
||||
}
|
||||
.fullscreen.tvmode .volumescale trough highlight {
|
||||
min-width: 6px;
|
||||
}
|
||||
@@ -264,21 +240,14 @@ scale trough slider {
|
||||
}
|
||||
|
||||
/* Elapsed Popover */
|
||||
.elapsedpopover {
|
||||
min-width: 326px;
|
||||
.elapsedpopoverbox {
|
||||
min-width: 260px;
|
||||
}
|
||||
.fullscreen.tvmode .elapsedpopover {
|
||||
min-width: 448px;
|
||||
.elapsedpopoverbox box separator {
|
||||
background: @insensitive_fg_color;
|
||||
}
|
||||
.elapsedpopover contents {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
.speedscale {
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.speedscale trough highlight {
|
||||
min-height: 4px;
|
||||
.fullscreen.tvmode .elapsedpopoverbox {
|
||||
min-width: 360px;
|
||||
}
|
||||
.fullscreen.tvmode .speedscale trough highlight {
|
||||
min-height: 6px;
|
||||
@@ -310,9 +279,26 @@ scale trough slider {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Preferences */
|
||||
.prefsnotebook grid {
|
||||
margin: 10px;
|
||||
}
|
||||
.prefssubpage header {
|
||||
background: none;
|
||||
}
|
||||
.prefssubpage header tabs tab {
|
||||
box-shadow: none;
|
||||
margin: 0px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
.prefssubpage header tabs tab:checked {
|
||||
color: initial;
|
||||
background: @theme_selected_bg_color;
|
||||
}
|
||||
|
||||
/* Open URI Dialog */
|
||||
.uridialogbox {
|
||||
margin: 10px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
/* Tweaks */
|
||||
@@ -336,52 +322,3 @@ scale trough slider {
|
||||
.blackbackground {
|
||||
background: black;
|
||||
}
|
||||
|
||||
/** SCALING LOW-RES **/
|
||||
.fullscreen.tvmode.lowres .clappercontrols button image {
|
||||
-gtk-icon-size: 22px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .clappercontrolsbutton {
|
||||
min-width: 28px;
|
||||
min-height: 28px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .clappercontrolsbutton.text-button label {
|
||||
font-size: 21px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .positionscale trough highlight {
|
||||
min-height: 18px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .positionscale.fine-tune trough highlight {
|
||||
min-height: 18px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres popover box {
|
||||
font-size: 19px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres radio {
|
||||
min-width: 15px;
|
||||
min-height: 15px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .clapperplaylist row button {
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .tvtitle {
|
||||
font-size: 26px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .tvtime {
|
||||
font-size: 34px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .tvendtime {
|
||||
font-size: 21px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .elapsedpopover {
|
||||
min-width: 410px;
|
||||
}
|
||||
.fullscreen.tvmode.lowres .chapterlabel {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
/** SCALING HI-RES **/
|
||||
.fullscreen.tvmode.hires .clappercontrols button image {
|
||||
-gtk-icon-size: 24px; /* Sharpest on 2160p with scaling 2x */
|
||||
}
|
||||
|
@@ -1,115 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 4.8 KiB |
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/com/github/rafostar/Clapper">
|
||||
<file preprocess="xml-stripblanks" alias="icons/scalable/actions/play-symbolic.svg">icons/play-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="icons/scalable/actions/pause-symbolic.svg">icons/pause-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="icons/scalable/actions/pip-in-symbolic.svg">icons/pip-in-symbolic.svg</file>
|
||||
<file preprocess="xml-stripblanks" alias="icons/scalable/actions/pip-out-symbolic.svg">icons/pip-out-symbolic.svg</file>
|
||||
</gresource>
|
||||
</gresources>
|
@@ -6,31 +6,31 @@
|
||||
<default>false</default>
|
||||
<summary>Automatically enter fullscreen when first file is loaded</summary>
|
||||
</key>
|
||||
<key name="volume-custom" type="b">
|
||||
<default>false</default>
|
||||
<summary>Set custom volume value at startup</summary>
|
||||
<key name="volume-initial" type="s">
|
||||
<default>"restore"</default>
|
||||
<summary>Mode used for startup volume value</summary>
|
||||
</key>
|
||||
<key name="volume-value" type="i">
|
||||
<default>100</default>
|
||||
<summary>Custom initial volume value in percentage after startup</summary>
|
||||
</key>
|
||||
<key name="after-playback" type="i">
|
||||
<default>0</default>
|
||||
<summary>What to do after playback finishes</summary>
|
||||
<key name="close-auto" type="b">
|
||||
<default>false</default>
|
||||
<summary>Automatically close the app after playback finishes</summary>
|
||||
</key>
|
||||
|
||||
<!-- Behavior -->
|
||||
<key name="seeking-mode" type="i">
|
||||
<default>0</default>
|
||||
<!-- Behaviour -->
|
||||
<key name="seeking-mode" type="s">
|
||||
<default>"normal"</default>
|
||||
<summary>Mode used for seeking</summary>
|
||||
</key>
|
||||
<key name="seeking-value" type="i">
|
||||
<default>10</default>
|
||||
<summary>Time amount to seek with single press of arrow keys</summary>
|
||||
</key>
|
||||
<key name="seeking-unit" type="i">
|
||||
<default>0</default>
|
||||
<summary>Unit ID to use with seeking value</summary>
|
||||
<key name="seeking-unit" type="s">
|
||||
<default>"second"</default>
|
||||
<summary>Unit to use with seeking value</summary>
|
||||
</key>
|
||||
<key name="resume-enabled" type="b">
|
||||
<default>true</default>
|
||||
@@ -46,12 +46,16 @@
|
||||
</key>
|
||||
|
||||
<!-- Audio -->
|
||||
<key name="audio-offset" type="i">
|
||||
<key name="audio-offset" type="d">
|
||||
<default>0</default>
|
||||
<summary>Offset time for audio tracks relative to video (milliseconds)</summary>
|
||||
</key>
|
||||
|
||||
<!-- Subtitles -->
|
||||
<key name="subtitle-offset" type="d">
|
||||
<default>0</default>
|
||||
<summary>Offset time for subtitle tracks relative to video (milliseconds)</summary>
|
||||
</key>
|
||||
<key name="subtitle-font" type="s">
|
||||
<default>"Sans 12"</default>
|
||||
<summary>The subtitles font description</summary>
|
||||
@@ -87,22 +91,24 @@
|
||||
|
||||
<!-- GStreamer -->
|
||||
<key name="plugin-ranking" type="s">
|
||||
<default>'{}'</default>
|
||||
<default>'[{"apply":false,"name":"vah264dec","rank":300}]'</default>
|
||||
<summary>Custom values for GStreamer plugin ranking</summary>
|
||||
</key>
|
||||
<key name="use-playbin3" type="b">
|
||||
<default>false</default>
|
||||
<summary>Use playbin3 element instead of playbin2</summary>
|
||||
</key>
|
||||
<key name="use-pipewire" type="b">
|
||||
<default>false</default>
|
||||
<summary>Use PipeWire for audio output</summary>
|
||||
</key>
|
||||
<key name="play-flags" type="i">
|
||||
<default>1687</default>
|
||||
<summary>Set PlayFlags for playbin</summary>
|
||||
</key>
|
||||
|
||||
<!-- YouTube -->
|
||||
<key name="yt-adaptive-enabled" type="b">
|
||||
<default>false</default>
|
||||
<summary>Enable to use adaptive streaming for YouTube</summary>
|
||||
</key>
|
||||
<key name="yt-quality-type" type="s">
|
||||
<default>"hfr"</default>
|
||||
<summary>Max YouTube video quality type</summary>
|
||||
</key>
|
||||
|
||||
<!-- Other -->
|
||||
<key name="window-size" type="s">
|
||||
<default>'[800, 490]'</default>
|
||||
|
@@ -9,20 +9,24 @@
|
||||
<launchable type="desktop-id">com.github.rafostar.Clapper.desktop</launchable>
|
||||
<description>
|
||||
<p>
|
||||
Clapper is a GNOME media player built using GJS with GTK4 toolkit.
|
||||
Clapper is a GNOME media player build using GJS with GTK4 toolkit.
|
||||
The media player is using GStreamer as a media backend and renders
|
||||
everything via OpenGL. Player works natively on both Xorg and Wayland.
|
||||
It also supports hardware acceleration through VA-API on AMD/Intel GPUs,
|
||||
NVDEC on Nvidia and V4L2 on mobile devices.
|
||||
It also supports VA-API on AMD/Intel GPUs.
|
||||
</p>
|
||||
<p>
|
||||
The media player has an adaptive GUI. When viewing videos in "Windowed Mode",
|
||||
Clapper will use mostly unmodified GTK widgets to match your OS look nicely.
|
||||
When player enters "Fullscreen Mode" all GUI elements will become darker, bigger
|
||||
and semi-transparent for your viewing comfort. It also has a "Floating Mode" which
|
||||
displays only video on top of all other windows for a PiP-like viewing experience.
|
||||
displays video only on top of all other windows for a PiP-like viewing experience.
|
||||
Mobile friendly transitions are also supported.
|
||||
</p>
|
||||
<p>
|
||||
For best stability Wayland session is recommended. Wayland users with AMD/Intel GPUs
|
||||
can try enabling HIGHLY EXPERIMENTAL "vah264dec" plugin inside player preferences
|
||||
for reduced CPU and GPU usage on standard (8-bit) H.264 videos.
|
||||
</p>
|
||||
</description>
|
||||
<developer_name>Rafał Dzięgiel</developer_name>
|
||||
<url type="homepage">https://rafostar.github.io/clapper</url>
|
||||
@@ -48,91 +52,6 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<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>
|
||||
@@ -183,14 +102,6 @@
|
||||
</release>
|
||||
</releases>
|
||||
<content_rating type="oars-1.1" />
|
||||
<recommends>
|
||||
<control>keyboard</control>
|
||||
<control>pointing</control>
|
||||
<control>touch</control>
|
||||
</recommends>
|
||||
<requires>
|
||||
<display_length compare="ge">small</display_length>
|
||||
</requires>
|
||||
<custom>
|
||||
<value key="Purism::form_factor">workstation</value>
|
||||
<value key="Purism::form_factor">mobile</value>
|
||||
|
@@ -1,29 +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>
|
||||
<path 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" id="b1nGq5BrLC"></path>
|
||||
<path 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" id="a3jkaoNn4k"></path>
|
||||
<path d="M174.59 135.18L211.87 98.05L171.07 98.05L133.78 135.18L174.59 135.18Z" id="atpVQ8mnd"></path>
|
||||
<path d="M76.81 135.18L114.1 98.05L73.13 98.05L35.84 135.18L76.81 135.18Z" id="bMtYoNHu0"></path>
|
||||
<path 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" id="b5oP0Glp4"></path>
|
||||
<path d="M176.51 54.37L129.94 29.4L169.15 17.56L215.72 42.52L176.51 54.37Z" id="lwBgev6DR"></path>
|
||||
<path d="M81.61 83.49L35.04 58.69L74.25 46.69L120.82 71.49L81.61 83.49Z" id="cUsjEMRUu"></path>
|
||||
<path 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" id="c1bcHZGXe"></path>
|
||||
<path 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" id="f2PtH0V1vC"></path>
|
||||
<path 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" id="a1SvrrkqVm"></path>
|
||||
<path d="M104.22 162.46L104.22 234.46L163.22 198.54L104.22 162.46Z" id="agXcvKqh8"></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><use xlink:href="#b1nGq5BrLC" fill="#4747d1"></use></g>
|
||||
<g><use xlink:href="#a3jkaoNn4k" fill="#4747d1"></use></g>
|
||||
<g><use xlink:href="#atpVQ8mnd" fill="#f1f1f1"></use></g>
|
||||
<g><use xlink:href="#bMtYoNHu0" fill="#f1f1f1"></use></g>
|
||||
<g><use xlink:href="#b5oP0Glp4" fill="#4747d1"></use></g>
|
||||
<g><use xlink:href="#lwBgev6DR" fill="#f1f1f1"></use></g>
|
||||
<g><use xlink:href="#cUsjEMRUu" fill="#f1f1f1"></use></g>
|
||||
<g><use xlink:href="#c1bcHZGXe" fill="#a9a9a9"></use></g>
|
||||
<g><use xlink:href="#f2PtH0V1vC" opacity="0.2" fill="#000000"></use></g>
|
||||
<g><use xlink:href="#a1SvrrkqVm" opacity="0.2" fill="#000000"></use></g>
|
||||
<g><use xlink:href="#agXcvKqh8" fill="#f1f1f1"></use></g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="#2e3436">
|
||||
<path d="m 3 3 h 4 v 10 h -4 z m 0 0"/>
|
||||
<path d="m 9 3 h 4 v 10 h -4 z m 0 0"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 262 B |
@@ -1,112 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<filter id="a" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="b">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="c">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="d">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="e">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="f">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="g">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="h">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="i">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="j">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="k">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="l">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="m">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="n">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="o">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="p">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="q">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="r">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="s">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<g fill="#2e3436">
|
||||
<path d="m 1 2.007812 c -0.550781 0 -1 0.449219 -1 1 v 9 c 0 0.550782 0.449219 1 1 1 h 4 v -2 h -3 v -7 h 10 v 3 h 2 v -4 c 0 -0.550781 -0.449219 -1 -1 -1 z m 0 0" fill-opacity="0.35"/>
|
||||
<path d="m 9 10 c -0.550781 0 -1 0.449219 -1 1 v 4.007812 c 0 0.550782 0.449219 1 1 1 h 6 c 0.550781 0 1 -0.449218 1 -1 v -4.007812 c 0 -0.550781 -0.449219 -1 -1 -1 z m 1 2 h 4 v 2.007812 h -4 z m 0 0"/>
|
||||
<path d="m 3.132812 5.140625 c 0.171876 -0.164063 0.496094 -0.1875 0.757813 0.015625 l 3.109375 3.089844 v 0.753906 h -0.753906 l -3.109375 -3.089844 c -0.191407 -0.191406 -0.179688 -0.597656 -0.003907 -0.769531 z m 0 0"/>
|
||||
<path d="m 4 9 h 4 v 1 h -4 z m 0 0"/>
|
||||
<path d="m 7 6 h 1 v 4 h -1 z m 0 0"/>
|
||||
</g>
|
||||
<g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 562.460938 212.058594 h 10.449218 c -1.183594 0.492187 -1.296875 2.460937 0 3 h -10.449218 z m 0 0" fill="#2e3436"/>
|
||||
</g>
|
||||
<g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 16 632 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 17 631 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 18 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#k)" mask="url(#j)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 16 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#m)" mask="url(#l)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 17 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#o)" mask="url(#n)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 19 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#q)" mask="url(#p)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 136 660 v 7 h 7 v -7 z m 0 0" fill="#2e3436"/>
|
||||
</g>
|
||||
<g clip-path="url(#s)" mask="url(#r)" transform="matrix(1 0 0 1 -580 -764)">
|
||||
<path d="m 219 642 h 3 v 12 h -3 z m 0 0" fill="#2e3436"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,112 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<filter id="a" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="b">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="c">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="d">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="e">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="f">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="g">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="h">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="i">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="j">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="k">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="l">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="m">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="n">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="o">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="p">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="q">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<mask id="r">
|
||||
<g filter="url(#a)">
|
||||
<path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="s">
|
||||
<path d="m 0 0 h 1024 v 800 h -1024 z"/>
|
||||
</clipPath>
|
||||
<g fill="#2e3436">
|
||||
<path d="m 1 2.007812 c -0.550781 0 -1 0.449219 -1 1 v 9 c 0 0.550782 0.449219 1 1 1 h 4 v -2 h -3 v -7 h 10 v 3 h 2 v -4 c 0 -0.550781 -0.449219 -1 -1 -1 z m 0 0"/>
|
||||
<path d="m 9 10 c -0.550781 0 -1 0.449219 -1 1 v 4.007812 c 0 0.550782 0.449219 1 1 1 h 6 c 0.550781 0 1 -0.449218 1 -1 v -4.007812 c 0 -0.550781 -0.449219 -1 -1 -1 z m 1 2 h 4 v 2.007812 h -4 z m 0 0" fill-opacity="0.35"/>
|
||||
<path d="m 7.863281 9.871094 c -0.167969 0.164062 -0.492187 0.1875 -0.753906 -0.019532 l -3.113281 -3.085937 v -0.753906 h 0.753906 l 3.109375 3.085937 c 0.191406 0.191406 0.179687 0.601563 0.003906 0.773438 z m 0 0"/>
|
||||
<path d="m 6.996094 6.011719 h -4 v -1 h 4 z m 0 0"/>
|
||||
<path d="m 3.996094 9.011719 h -1 v -4 h 1 z m 0 0"/>
|
||||
</g>
|
||||
<g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 562.460938 212.058594 h 10.449218 c -1.183594 0.492187 -1.296875 2.460937 0 3 h -10.449218 z m 0 0" fill="#2e3436"/>
|
||||
</g>
|
||||
<g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 16 632 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 17 631 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 18 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#k)" mask="url(#j)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 16 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#m)" mask="url(#l)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 17 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#o)" mask="url(#n)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 19 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
|
||||
</g>
|
||||
<g clip-path="url(#q)" mask="url(#p)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 136 660 v 7 h 7 v -7 z m 0 0" fill="#2e3436"/>
|
||||
</g>
|
||||
<g clip-path="url(#s)" mask="url(#r)" transform="matrix(1 0 0 1 -600 -764)">
|
||||
<path d="m 219 642 h 3 v 12 h -3 z m 0 0" fill="#2e3436"/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.7 KiB |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="2 2 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M 5 3.746094 L 5 16.246094 L 6.25 16.246094 C 6.46875 16.246094 6.683594 16.195312 6.875 16.089844 L 15.625 11.089844 C 16.015625 10.875 16.210938 10.433594 16.210938 9.996094 C 16.210938 9.554688 16.015625 9.117188 15.625 8.902344 L 6.875 3.902344 C 6.683594 3.792969 6.46875 3.746094 6.25 3.746094 Z M 5 3.746094" fill="#2e3436"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 480 B |
@@ -1,34 +1,18 @@
|
||||
iconsdir = join_paths(datadir, 'icons', 'hicolor')
|
||||
|
||||
appstream_util = find_program('appstream-util', required: false)
|
||||
if appstream_util.found()
|
||||
test('Validate appstream file', appstream_util, args: [
|
||||
'validate-relax',
|
||||
join_paths(meson.current_source_dir(), 'com.github.rafostar.Clapper.metainfo.xml')
|
||||
])
|
||||
endif
|
||||
sharedir = join_paths(get_option('prefix'), 'share')
|
||||
iconsdir = join_paths(sharedir, 'icons', 'hicolor')
|
||||
|
||||
install_data('com.github.rafostar.Clapper.svg',
|
||||
install_dir: join_paths(iconsdir, 'scalable', 'apps')
|
||||
)
|
||||
install_data('com.github.rafostar.Clapper-symbolic.svg',
|
||||
install_dir: join_paths(iconsdir, 'symbolic', 'apps')
|
||||
)
|
||||
install_data('com.github.rafostar.Clapper.gschema.xml',
|
||||
install_dir: join_paths(datadir, 'glib-2.0', 'schemas')
|
||||
install_dir: join_paths(sharedir, 'glib-2.0', 'schemas')
|
||||
)
|
||||
install_data('com.github.rafostar.Clapper.xml',
|
||||
install_dir: join_paths(datadir, 'mime', 'packages')
|
||||
install_dir: join_paths(sharedir, 'mime', 'packages')
|
||||
)
|
||||
install_data('com.github.rafostar.Clapper.desktop',
|
||||
install_dir: join_paths(datadir, 'applications')
|
||||
install_dir: join_paths(sharedir, 'applications')
|
||||
)
|
||||
install_data('com.github.rafostar.Clapper.metainfo.xml',
|
||||
install_dir: join_paths(datadir, 'metainfo')
|
||||
)
|
||||
gnome.compile_resources('com.github.rafostar.Clapper.data',
|
||||
'com.github.rafostar.Clapper.data.gresource.xml',
|
||||
gresource_bundle: true,
|
||||
install: true,
|
||||
install_dir: pkgdatadir,
|
||||
install_dir: join_paths(sharedir, 'metainfo')
|
||||
)
|
||||
|
2
lib/gst/clapper/clapper.h
vendored
@@ -28,6 +28,8 @@
|
||||
#include <gst/clapper/gstclapper-g-main-context-signal-dispatcher.h>
|
||||
#include <gst/clapper/gstclapper-video-overlay-video-renderer.h>
|
||||
#include <gst/clapper/gstclapper-visualization.h>
|
||||
#include <gst/clapper/gstclapper-playlist.h>
|
||||
#include <gst/clapper/gstclapper-playlist-item.h>
|
||||
#include <gst/clapper/gstclapper-mpris.h>
|
||||
#include <gst/clapper/gstclapper-gtk4-plugin.h>
|
||||
|
||||
|
@@ -147,31 +147,31 @@ gst_clapper_mpris_class_init (GstClapperMprisClass * klass)
|
||||
param_specs[PROP_OWN_NAME] =
|
||||
g_param_spec_string ("own-name", "DBus own name",
|
||||
"DBus name to own on connection",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_ID_PATH] =
|
||||
g_param_spec_string ("id-path", "DBus id path",
|
||||
"A valid D-Bus path describing this player",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_IDENTITY] =
|
||||
g_param_spec_string ("identity", "Player name",
|
||||
"A friendly name to identify the media player",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_DESKTOP_ENTRY] =
|
||||
g_param_spec_string ("desktop-entry", "Desktop entry filename",
|
||||
"The basename of an installed .desktop file",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_DEFAULT_ART_URL] =
|
||||
g_param_spec_string ("default-art-url", "Default Art URL",
|
||||
"Default art to show when media does not provide one",
|
||||
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_VOLUME] =
|
||||
@@ -220,21 +220,6 @@ gst_clapper_mpris_get_property (GObject * object, guint prop_id,
|
||||
GstClapperMpris *self = GST_CLAPPER_MPRIS (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_OWN_NAME:
|
||||
g_value_set_string (value, self->own_name);
|
||||
break;
|
||||
case PROP_ID_PATH:
|
||||
g_value_set_string (value, self->id_path);
|
||||
break;
|
||||
case PROP_IDENTITY:
|
||||
g_value_set_string (value, self->identity);
|
||||
break;
|
||||
case PROP_DESKTOP_ENTRY:
|
||||
g_value_set_string (value, self->desktop_entry);
|
||||
break;
|
||||
case PROP_DEFAULT_ART_URL:
|
||||
g_value_set_string (value, self->default_art_url);
|
||||
break;
|
||||
case PROP_VOLUME:
|
||||
g_object_get_property (G_OBJECT (self->player_skeleton), "volume", value);
|
||||
break;
|
||||
@@ -407,11 +392,17 @@ handle_open_uri_cb (GstClapperMprisMediaPlayer2Player * player_skeleton,
|
||||
gpointer user_data)
|
||||
{
|
||||
GstClapper *clapper = GST_CLAPPER (user_data);
|
||||
GstClapperPlaylist *playlist;
|
||||
GstClapperPlaylistItem *item;
|
||||
|
||||
GST_DEBUG ("Handle OpenUri");
|
||||
|
||||
/* FIXME: set one item playlist instead */
|
||||
gst_clapper_set_uri (clapper, uri);
|
||||
playlist = gst_clapper_playlist_new ();
|
||||
item = gst_clapper_playlist_item_new (uri);
|
||||
|
||||
gst_clapper_playlist_append (playlist, item);
|
||||
|
||||
gst_clapper_set_playlist (clapper, playlist);
|
||||
gst_clapper_mpris_media_player2_player_complete_open_uri (player_skeleton, invocation);
|
||||
|
||||
return TRUE;
|
||||
@@ -786,8 +777,12 @@ gst_clapper_mpris_new (const gchar * own_name, const gchar * id_path,
|
||||
const gchar * identity, const gchar * desktop_entry,
|
||||
const gchar * default_art_url)
|
||||
{
|
||||
return g_object_new (GST_TYPE_CLAPPER_MPRIS,
|
||||
GstClapperMpris *self;
|
||||
|
||||
self = g_object_new (GST_TYPE_CLAPPER,
|
||||
"own-name", own_name, "id_path", id_path,
|
||||
"identity", identity, "desktop-entry", desktop_entry,
|
||||
"default-art-url", default_art_url, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@@ -1,8 +1,5 @@
|
||||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
|
||||
* Copyright (C) 2015 Thibault Saunier <tsaunier@gnome.org>
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -20,14 +17,33 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __GST_CLAPPER_PLAYLIST_ITEM_PRIVATE_H__
|
||||
#define __GST_CLAPPER_PLAYLIST_ITEM_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/video/video.h>
|
||||
#include "gstclapper-playlist.h"
|
||||
|
||||
gpointer gst_gtk_invoke_on_main (GThreadFunc func, gpointer data);
|
||||
struct _GstClapperPlaylistItem
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
GdkMemoryFormat gst_video_format_to_gdk_memory_format (GstVideoFormat format);
|
||||
/* ID of the playlist this item belongs to */
|
||||
gchar *owner_uuid;
|
||||
gint id;
|
||||
|
||||
GdkTexture * gst_video_frame_into_gdk_texture (GstVideoFrame *frame, GDestroyNotify free_func);
|
||||
gchar *uri;
|
||||
gchar *suburi;
|
||||
gchar *custom_title;
|
||||
|
||||
/* Signals */
|
||||
gulong activated_signal_id;
|
||||
};
|
||||
|
||||
struct _GstClapperPlaylistItemClass
|
||||
{
|
||||
GstObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gst_clapper_playlist_item_mark_added (GstClapperPlaylistItem *item, GstClapperPlaylist *playlist);
|
||||
|
||||
#endif /* __GST_CLAPPER_PLAYLIST_ITEM_PRIVATE_H__ */
|
281
lib/gst/clapper/gstclapper-playlist-item.c
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapper-playlist-item.h"
|
||||
#include "gstclapper-playlist-item-private.h"
|
||||
#include "gstclapper-playlist-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_URI,
|
||||
PROP_SUBURI,
|
||||
PROP_CUSTOM_TITLE,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_ACTIVATED,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
#define parent_class gst_clapper_playlist_item_parent_class
|
||||
G_DEFINE_TYPE (GstClapperPlaylistItem, gst_clapper_playlist_item, GST_TYPE_OBJECT);
|
||||
|
||||
static guint signals[SIGNAL_LAST] = { 0, };
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static void gst_clapper_playlist_item_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
static void gst_clapper_playlist_item_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec);
|
||||
static void gst_clapper_playlist_item_dispose (GObject * object);
|
||||
static void gst_clapper_playlist_item_finalize (GObject * object);
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_item_init (GstClapperPlaylistItem * self)
|
||||
{
|
||||
self->owner_uuid = NULL;
|
||||
self->id = -1;
|
||||
|
||||
self->uri = NULL;
|
||||
self->suburi = NULL;
|
||||
self->custom_title = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_item_class_init (GstClapperPlaylistItemClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
|
||||
gobject_class->set_property = gst_clapper_playlist_item_set_property;
|
||||
gobject_class->get_property = gst_clapper_playlist_item_get_property;
|
||||
gobject_class->dispose = gst_clapper_playlist_item_dispose;
|
||||
gobject_class->finalize = gst_clapper_playlist_item_finalize;
|
||||
|
||||
param_specs[PROP_URI] = g_param_spec_string ("uri",
|
||||
"URI", "Playlist Item URI", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_SUBURI] = g_param_spec_string ("suburi",
|
||||
"Subtitle URI", "Playlist Item Subtitle URI", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_CUSTOM_TITLE] = g_param_spec_string ("custom-title",
|
||||
"Custom Title", "Playlist Item Custom Title", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
signals[SIGNAL_ACTIVATED] =
|
||||
g_signal_new ("activated", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 0, G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_item_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstClapperPlaylistItem *self = GST_CLAPPER_PLAYLIST_ITEM (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_URI:
|
||||
self->uri = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_SUBURI:
|
||||
g_free (self->suburi);
|
||||
self->suburi = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_CUSTOM_TITLE:
|
||||
self->custom_title = g_value_dup_string (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_item_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstClapperPlaylistItem *self = GST_CLAPPER_PLAYLIST_ITEM (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, self->uri);
|
||||
break;
|
||||
case PROP_SUBURI:
|
||||
g_value_set_string (value, self->suburi);
|
||||
break;
|
||||
case PROP_CUSTOM_TITLE:
|
||||
g_value_set_string (value, self->custom_title);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_item_dispose (GObject * object)
|
||||
{
|
||||
GstClapperPlaylistItem *self = GST_CLAPPER_PLAYLIST_ITEM (object);
|
||||
|
||||
if (self->activated_signal_id) {
|
||||
g_signal_handler_disconnect (self, self->activated_signal_id);
|
||||
self->activated_signal_id = 0;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_item_finalize (GObject * object)
|
||||
{
|
||||
GstClapperPlaylistItem *self = GST_CLAPPER_PLAYLIST_ITEM (object);
|
||||
|
||||
g_free (self->owner_uuid);
|
||||
|
||||
g_free (self->uri);
|
||||
g_free (self->suburi);
|
||||
g_free (self->custom_title);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
item_activate_cb (GstClapperPlaylistItem * self, GParamSpec * pspec,
|
||||
GstClapperPlaylist * playlist)
|
||||
{
|
||||
gst_clapper_playlist_emit_item_activated (playlist, self);
|
||||
}
|
||||
|
||||
void
|
||||
gst_clapper_playlist_item_mark_added (GstClapperPlaylistItem * self,
|
||||
GstClapperPlaylist * playlist)
|
||||
{
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
self->owner_uuid = g_strdup (playlist->uuid);
|
||||
self->id = playlist->id_count;
|
||||
|
||||
self->activated_signal_id = g_signal_connect (self, "activated",
|
||||
G_CALLBACK (item_activate_cb), playlist);
|
||||
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_item_new:
|
||||
*
|
||||
* Creates a new #GstClapperPlaylistItem.
|
||||
*
|
||||
* Returns: (transfer full): a new #GstClapperPlaylistItem object.
|
||||
*/
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_item_new (const gchar * uri)
|
||||
{
|
||||
return g_object_new (GST_TYPE_CLAPPER_PLAYLIST_ITEM, "uri", uri, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_item_new_titled:
|
||||
* @uri: An URI pointing to media
|
||||
* @custom_title: A custom title for this item
|
||||
*
|
||||
* Creates a new #GstClapperPlaylistItem with a custom title.
|
||||
*
|
||||
* Normally item title is obtained from media info or local filename,
|
||||
* use this function for online sources where media title cannot be
|
||||
* determined or if you want to override original title for some reason.
|
||||
*
|
||||
* Returns: (transfer full): a new #GstClapperPlaylistItem object.
|
||||
*/
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_item_new_titled (const gchar * uri,
|
||||
const gchar * custom_title)
|
||||
{
|
||||
return g_object_new (GST_TYPE_CLAPPER_PLAYLIST_ITEM, "uri", uri,
|
||||
"custom_title", custom_title, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_item_copy:
|
||||
* @item: #GstClapperPlaylistItem
|
||||
*
|
||||
* Duplicates a #GstClapperPlaylistItem.
|
||||
*
|
||||
* Duplicated items do not belong to any playlist.
|
||||
* Use this function if you want to append the same
|
||||
* media into another #GstClapperPlaylist instance.
|
||||
*
|
||||
* Returns: (transfer full): a new #GstClapperPlaylistItem object.
|
||||
*/
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_item_copy (GstClapperPlaylistItem * source)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST_ITEM (source), NULL);
|
||||
|
||||
return g_object_new (GST_TYPE_CLAPPER_PLAYLIST_ITEM, "uri", source->uri,
|
||||
"suburi", source->suburi, "custom-title", source->custom_title, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_item_set_suburi:
|
||||
* @item: #GstClapperPlaylistItem
|
||||
* @suburi: subtitle URI
|
||||
*
|
||||
* Sets the external subtitle URI.
|
||||
*/
|
||||
void
|
||||
gst_clapper_playlist_item_set_suburi (GstClapperPlaylistItem * self,
|
||||
const gchar * suburi)
|
||||
{
|
||||
/* TODO: When setting this property for an item that is currently active,
|
||||
* it should be combined with a call to
|
||||
* gst_clapper_set_subtitle_track_enabled(Clapper, TRUE),
|
||||
* so the subtitles are actually rendered.
|
||||
*/
|
||||
g_return_if_fail (GST_IS_CLAPPER_PLAYLIST_ITEM (self));
|
||||
|
||||
g_object_set (self, "suburi", suburi, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_item_activate:
|
||||
* @item: #GstClapperPlaylistItem
|
||||
*
|
||||
* Activates the #GstClapperPlaylistItem.
|
||||
*/
|
||||
void
|
||||
gst_clapper_playlist_item_activate (GstClapperPlaylistItem * self)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CLAPPER_PLAYLIST_ITEM (self));
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0);
|
||||
}
|
62
lib/gst/clapper/gstclapper-playlist-item.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_CLAPPER_PLAYLIST_ITEM_H__
|
||||
#define __GST_CLAPPER_PLAYLIST_ITEM_H__
|
||||
|
||||
#include <gst/clapper/clapper-prelude.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstClapperPlaylistItem GstClapperPlaylistItem;
|
||||
typedef struct _GstClapperPlaylistItemClass GstClapperPlaylistItemClass;
|
||||
|
||||
#define GST_TYPE_CLAPPER_PLAYLIST_ITEM (gst_clapper_playlist_item_get_type ())
|
||||
#define GST_IS_CLAPPER_PLAYLIST_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_PLAYLIST_ITEM))
|
||||
#define GST_IS_CLAPPER_PLAYLIST_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_PLAYLIST_ITEM))
|
||||
#define GST_CLAPPER_PLAYLIST_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_PLAYLIST_ITEM, GstClapperPlaylistItemClass))
|
||||
#define GST_CLAPPER_PLAYLIST_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_PLAYLIST_ITEM, GstClapperPlaylistItem))
|
||||
#define GST_CLAPPER_PLAYLIST_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_PLAYLIST_ITEM, GstClapperPlaylistItemClass))
|
||||
#define GST_CLAPPER_PLAYLIST_ITEM_CAST(obj) ((GstClapperPlaylistItem*)(obj))
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstClapperPlaylistItem, gst_object_unref)
|
||||
#endif
|
||||
|
||||
GST_CLAPPER_API
|
||||
GType gst_clapper_playlist_item_get_type (void);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapperPlaylistItem * gst_clapper_playlist_item_new (const gchar *uri);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapperPlaylistItem * gst_clapper_playlist_item_new_titled (const gchar *uri, const gchar *custom_title);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapperPlaylistItem * gst_clapper_playlist_item_copy (GstClapperPlaylistItem *item);
|
||||
|
||||
GST_CLAPPER_API
|
||||
void gst_clapper_playlist_item_set_suburi (GstClapperPlaylistItem *item, const gchar *suburi);
|
||||
|
||||
GST_CLAPPER_API
|
||||
void gst_clapper_playlist_item_activate (GstClapperPlaylistItem *item);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_CLAPPER_PLAYLIST_ITEM_H__ */
|
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
@@ -19,11 +17,27 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_CLAPPER_GL_UTILS_H__
|
||||
#define __GST_CLAPPER_GL_UTILS_H__
|
||||
#ifndef __GST_CLAPPER_PLAYLIST_PRIVATE_H__
|
||||
#define __GST_CLAPPER_PLAYLIST_PRIVATE_H__
|
||||
|
||||
#include <gst/video/gstvideoaffinetransformationmeta.h>
|
||||
#include "gstclapper-playlist.h"
|
||||
|
||||
void gst_clapper_gl_get_affine_transformation_meta_as_ndc (GstVideoAffineTransformationMeta *meta, gfloat *matrix);
|
||||
struct _GstClapperPlaylist
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
#endif /* __GST_CLAPPER_GL_UTILS_H__ */
|
||||
gchar *uuid;
|
||||
gint id_count;
|
||||
GArray *items;
|
||||
gint active_index;
|
||||
};
|
||||
|
||||
struct _GstClapperPlaylistClass
|
||||
{
|
||||
GstObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gst_clapper_playlist_emit_item_activated (GstClapperPlaylist *playlist, GstClapperPlaylistItem *item);
|
||||
|
||||
#endif /* __GST_CLAPPER_PLAYLIST_PRIVATE_H__ */
|
275
lib/gst/clapper/gstclapper-playlist.c
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapper-playlist.h"
|
||||
#include "gstclapper-playlist-private.h"
|
||||
#include "gstclapper-playlist-item.h"
|
||||
#include "gstclapper-playlist-item-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_ITEM_ACTIVATED,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
#define parent_class gst_clapper_playlist_parent_class
|
||||
G_DEFINE_TYPE (GstClapperPlaylist, gst_clapper_playlist, GST_TYPE_OBJECT);
|
||||
|
||||
static guint signals[SIGNAL_LAST] = { 0, };
|
||||
|
||||
static void gst_clapper_playlist_dispose (GObject * object);
|
||||
static void gst_clapper_playlist_finalize (GObject * object);
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_init (GstClapperPlaylist * self)
|
||||
{
|
||||
self->uuid = g_uuid_string_random ();
|
||||
self->id_count = 0;
|
||||
self->items = g_array_new (FALSE, FALSE, sizeof (GstClapperPlaylistItem));
|
||||
self->active_index = -1;
|
||||
|
||||
g_array_set_clear_func (self->items, (GDestroyNotify) gst_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_class_init (GstClapperPlaylistClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
|
||||
gobject_class->dispose = gst_clapper_playlist_dispose;
|
||||
gobject_class->finalize = gst_clapper_playlist_finalize;
|
||||
|
||||
signals[SIGNAL_ITEM_ACTIVATED] =
|
||||
g_signal_new ("item-activated", 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, GST_TYPE_CLAPPER_PLAYLIST_ITEM);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_dispose (GObject * object)
|
||||
{
|
||||
GstClapperPlaylist *self = GST_CLAPPER_PLAYLIST (object);
|
||||
|
||||
/* FIXME: Need this for something? */
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_playlist_finalize (GObject * object)
|
||||
{
|
||||
GstClapperPlaylist *self = GST_CLAPPER_PLAYLIST (object);
|
||||
|
||||
g_free (self->uuid);
|
||||
g_array_unref (self->items);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
void
|
||||
gst_clapper_playlist_emit_item_activated (GstClapperPlaylist * self,
|
||||
GstClapperPlaylistItem * item)
|
||||
{
|
||||
g_signal_emit (self, signals[SIGNAL_ITEM_ACTIVATED], 0, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_new:
|
||||
*
|
||||
* Creates a new #GstClapperPlaylist.
|
||||
*
|
||||
* Returns: (transfer full): a new #GstClapperPlaylist instance.
|
||||
*/
|
||||
GstClapperPlaylist *
|
||||
gst_clapper_playlist_new (void)
|
||||
{
|
||||
return g_object_new (GST_TYPE_CLAPPER_PLAYLIST, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_append:
|
||||
* @playlist: #GstClapperPlaylist
|
||||
* @item: #GstClapperPlaylistItem to append
|
||||
*
|
||||
* Adds a new #GstClapperPlaylistItem to the end of playlist.
|
||||
*
|
||||
* Returns: %TRUE if the item was added successfully.
|
||||
*/
|
||||
gboolean
|
||||
gst_clapper_playlist_append (GstClapperPlaylist * self, GstClapperPlaylistItem * item)
|
||||
{
|
||||
gboolean added = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST (self), FALSE);
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST_ITEM (item), FALSE);
|
||||
g_return_val_if_fail (item->owner_uuid == NULL, FALSE);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
added = g_array_append_val (self->items, item) != NULL;
|
||||
if (added) {
|
||||
gst_clapper_playlist_item_mark_added (item, self);
|
||||
self->id_count++;
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_get_length:
|
||||
* @playlist: #GstClapperPlaylist
|
||||
*
|
||||
* Returns: Amount of items in playlist.
|
||||
*/
|
||||
guint
|
||||
gst_clapper_playlist_get_length (GstClapperPlaylist * self)
|
||||
{
|
||||
guint len;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST (self), 0);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
len = self->items->len;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_get_item_at_index:
|
||||
* @playlist: #GstClapperPlaylist
|
||||
*
|
||||
* Returns: (transfer none): A #GstClapperPlaylistItem at given index.
|
||||
*/
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_get_item_at_index (GstClapperPlaylist * self, gint index)
|
||||
{
|
||||
GstClapperPlaylistItem *item = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST (self), NULL);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
if (index < self->items->len)
|
||||
goto out;
|
||||
|
||||
item = &g_array_index (self->items, GstClapperPlaylistItem, index);
|
||||
|
||||
out:
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_get_active_item:
|
||||
* @playlist: #GstClapperPlaylist
|
||||
*
|
||||
* Returns: (transfer none): A #GstClapperPlaylistItem that is
|
||||
* currently playing.
|
||||
*/
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_get_active_item (GstClapperPlaylist * self)
|
||||
{
|
||||
gint active_index;
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
active_index = self->active_index;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return gst_clapper_playlist_get_item_at_index (self, active_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_remove_item_at_index:
|
||||
* @playlist: #GstClapperPlaylist
|
||||
* @index: Index of #GstClapperPlaylistItem to remove
|
||||
*
|
||||
* Removes item at given index from playlist.
|
||||
*
|
||||
* Returns: %TRUE if the item was removed successfully.
|
||||
*/
|
||||
gboolean
|
||||
gst_clapper_playlist_remove_item_at_index (GstClapperPlaylist * self, guint index)
|
||||
{
|
||||
gboolean removed = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST (self), FALSE);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
if (index >= self->items->len || index == self->active_index)
|
||||
goto out;
|
||||
|
||||
removed = g_array_remove_index (self->items, index) != NULL;
|
||||
|
||||
out:
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_playlist_remove_item:
|
||||
* @playlist: #GstClapperPlaylist
|
||||
* @item: #GstClapperPlaylistItem object to remove
|
||||
*
|
||||
* Removes given playlist item from playlist.
|
||||
*
|
||||
* Returns: %TRUE if the item was removed successfully.
|
||||
*/
|
||||
gboolean
|
||||
gst_clapper_playlist_remove_item (GstClapperPlaylist * self,
|
||||
GstClapperPlaylistItem * item)
|
||||
{
|
||||
gint i;
|
||||
gboolean removed = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST (self), FALSE);
|
||||
g_return_val_if_fail (GST_IS_CLAPPER_PLAYLIST_ITEM (item), FALSE);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
|
||||
if (strcmp (self->uuid, item->owner_uuid) != 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < self->items->len; i++) {
|
||||
GstClapperPlaylistItem *curr_item;
|
||||
|
||||
curr_item = &g_array_index (self->items, GstClapperPlaylistItem, i);
|
||||
if (!curr_item)
|
||||
goto out;
|
||||
|
||||
if (item->id == curr_item->id) {
|
||||
removed = g_array_remove_index (self->items, i) != NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return removed;
|
||||
}
|
71
lib/gst/clapper/gstclapper-playlist.h
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_CLAPPER_PLAYLIST_H__
|
||||
#define __GST_CLAPPER_PLAYLIST_H__
|
||||
|
||||
#include <gst/clapper/clapper-prelude.h>
|
||||
#include <gst/clapper/gstclapper-playlist-item.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstClapperPlaylist GstClapperPlaylist;
|
||||
typedef struct _GstClapperPlaylistClass GstClapperPlaylistClass;
|
||||
|
||||
#define GST_TYPE_CLAPPER_PLAYLIST (gst_clapper_playlist_get_type ())
|
||||
#define GST_IS_CLAPPER_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_PLAYLIST))
|
||||
#define GST_IS_CLAPPER_PLAYLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_PLAYLIST))
|
||||
#define GST_CLAPPER_PLAYLIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_PLAYLIST, GstClapperPlaylistClass))
|
||||
#define GST_CLAPPER_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_PLAYLIST, GstClapperPlaylist))
|
||||
#define GST_CLAPPER_PLAYLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_PLAYLIST, GstClapperPlaylistClass))
|
||||
#define GST_CLAPPER_PLAYLIST_CAST(obj) ((GstClapperPlaylist*)(obj))
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstClapperPlaylist, g_object_unref)
|
||||
#endif
|
||||
|
||||
GST_CLAPPER_API
|
||||
GType gst_clapper_playlist_get_type (void);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapperPlaylist * gst_clapper_playlist_new (void);
|
||||
|
||||
GST_CLAPPER_API
|
||||
gboolean gst_clapper_playlist_append (GstClapperPlaylist *playlist, GstClapperPlaylistItem *item);
|
||||
|
||||
GST_CLAPPER_API
|
||||
guint gst_clapper_playlist_get_length (GstClapperPlaylist *playlist);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_get_item_at_index (GstClapperPlaylist *playlist, gint index);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapperPlaylistItem *
|
||||
gst_clapper_playlist_get_active_item (GstClapperPlaylist *playlist);
|
||||
|
||||
GST_CLAPPER_API
|
||||
gboolean gst_clapper_playlist_remove_item_at_index (GstClapperPlaylist *playlist, guint index);
|
||||
|
||||
GST_CLAPPER_API
|
||||
gboolean gst_clapper_playlist_remove_item (GstClapperPlaylist *playlist, GstClapperPlaylistItem *item);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_CLAPPER_PLAYLIST_H__ */
|
893
lib/gst/clapper/gstclapper.c
vendored
16
lib/gst/clapper/gstclapper.h
vendored
@@ -30,6 +30,8 @@
|
||||
#include <gst/clapper/gstclapper-signal-dispatcher.h>
|
||||
#include <gst/clapper/gstclapper-video-renderer.h>
|
||||
#include <gst/clapper/gstclapper-media-info.h>
|
||||
#include <gst/clapper/gstclapper-playlist.h>
|
||||
#include <gst/clapper/gstclapper-playlist-item.h>
|
||||
#include <gst/clapper/gstclapper-mpris.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -153,9 +155,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstClapper, gst_object_unref)
|
||||
GST_CLAPPER_API
|
||||
GType gst_clapper_get_type (void);
|
||||
|
||||
GST_CLAPPER_API
|
||||
void gst_clapper_gst_init (int *argc, char **argv[]);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClapper * gst_clapper_new (GstClapperVideoRenderer *video_renderer, GstClapperSignalDispatcher *signal_dispatcher,
|
||||
GstClapperMpris *mpris);
|
||||
@@ -196,16 +195,7 @@ GST_CLAPPER_API
|
||||
gdouble gst_clapper_get_rate (GstClapper *clapper);
|
||||
|
||||
GST_CLAPPER_API
|
||||
gchar * gst_clapper_get_uri (GstClapper *clapper);
|
||||
|
||||
GST_CLAPPER_API
|
||||
void gst_clapper_set_uri (GstClapper *clapper, const gchar *uri);
|
||||
|
||||
GST_CLAPPER_API
|
||||
gchar * gst_clapper_get_subtitle_uri (GstClapper *clapper);
|
||||
|
||||
GST_CLAPPER_API
|
||||
void gst_clapper_set_subtitle_uri (GstClapper *clapper, const gchar *uri);
|
||||
void gst_clapper_set_playlist (GstClapper *clapper, GstClapperPlaylist *playlist);
|
||||
|
||||
GST_CLAPPER_API
|
||||
GstClockTime gst_clapper_get_position (GstClapper *clapper);
|
||||
|
@@ -37,27 +37,19 @@
|
||||
GST_DEBUG_CATEGORY (gst_debug_clapper_gl_sink);
|
||||
#define GST_CAT_DEFAULT gst_debug_clapper_gl_sink
|
||||
|
||||
#define GST_CLAPPER_GL_SINK_CAPS \
|
||||
"video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " \
|
||||
"format = (string) RGBA, " \
|
||||
"width = " GST_VIDEO_SIZE_RANGE ", " \
|
||||
"height = " GST_VIDEO_SIZE_RANGE ", " \
|
||||
"framerate = " GST_VIDEO_FPS_RANGE ", " \
|
||||
"texture-target = (string) { 2D, external-oes } " \
|
||||
" ; " \
|
||||
"video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "," \
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION "), " \
|
||||
"format = (string) RGBA, " \
|
||||
"width = " GST_VIDEO_SIZE_RANGE ", " \
|
||||
"height = " GST_VIDEO_SIZE_RANGE ", " \
|
||||
"framerate = " GST_VIDEO_FPS_RANGE ", " \
|
||||
"texture-target = (string) { 2D, external-oes } "
|
||||
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||
#define DEFAULT_PAR_N 0
|
||||
#define DEFAULT_PAR_D 1
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_gl_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (GST_CLAPPER_GL_SINK_CAPS));
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_GL_MEMORY, "RGBA") "; "
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||
(GST_CAPS_FEATURE_MEMORY_GL_MEMORY ", "
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, "RGBA")));
|
||||
|
||||
static void gst_clapper_gl_sink_finalize (GObject * object);
|
||||
static void gst_clapper_gl_sink_set_property (GObject * object, guint prop_id,
|
||||
@@ -70,7 +62,6 @@ static gboolean gst_clapper_gl_sink_propose_allocation (GstBaseSink * bsink,
|
||||
static gboolean gst_clapper_gl_sink_query (GstBaseSink * bsink, GstQuery * query);
|
||||
static gboolean gst_clapper_gl_sink_start (GstBaseSink * bsink);
|
||||
static gboolean gst_clapper_gl_sink_stop (GstBaseSink * bsink);
|
||||
static GstFlowReturn gst_clapper_gl_sink_wait_event (GstBaseSink * bsink, GstEvent * event);
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_clapper_gl_sink_change_state (GstElement * element,
|
||||
@@ -88,6 +79,14 @@ static GstFlowReturn gst_clapper_gl_sink_show_frame (GstVideoSink * bsink,
|
||||
static void
|
||||
gst_clapper_gl_sink_navigation_interface_init (GstNavigationInterface * iface);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_WIDGET,
|
||||
PROP_FORCE_ASPECT_RATIO,
|
||||
PROP_PIXEL_ASPECT_RATIO,
|
||||
};
|
||||
|
||||
#define gst_clapper_gl_sink_parent_class parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstClapperGLSink, gst_clapper_gl_sink,
|
||||
GST_TYPE_VIDEO_SINK,
|
||||
@@ -113,7 +112,6 @@ gst_clapper_gl_sink_class_init (GstClapperGLSinkClass * klass)
|
||||
|
||||
gobject_class->set_property = gst_clapper_gl_sink_set_property;
|
||||
gobject_class->get_property = gst_clapper_gl_sink_get_property;
|
||||
gobject_class->finalize = gst_clapper_gl_sink_finalize;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_WIDGET,
|
||||
g_param_spec_object ("widget", "GTK Widget",
|
||||
@@ -121,7 +119,19 @@ gst_clapper_gl_sink_class_init (GstClapperGLSinkClass * klass)
|
||||
"(must only be get from the GTK main thread)",
|
||||
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_gtk_install_shared_properties (gobject_class);
|
||||
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
|
||||
g_param_spec_boolean ("force-aspect-ratio",
|
||||
"Force aspect ratio",
|
||||
"When enabled, scaling will respect original aspect ratio",
|
||||
DEFAULT_FORCE_ASPECT_RATIO,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
|
||||
gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
|
||||
"The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
|
||||
G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gobject_class->finalize = gst_clapper_gl_sink_finalize;
|
||||
|
||||
gstelement_class->change_state = gst_clapper_gl_sink_change_state;
|
||||
|
||||
@@ -132,7 +142,6 @@ gst_clapper_gl_sink_class_init (GstClapperGLSinkClass * klass)
|
||||
gstbasesink_class->query = gst_clapper_gl_sink_query;
|
||||
gstbasesink_class->start = gst_clapper_gl_sink_start;
|
||||
gstbasesink_class->stop = gst_clapper_gl_sink_stop;
|
||||
gstbasesink_class->wait_event = gst_clapper_gl_sink_wait_event;
|
||||
|
||||
gstvideosink_class->show_frame = gst_clapper_gl_sink_show_frame;
|
||||
|
||||
@@ -157,9 +166,6 @@ gst_clapper_gl_sink_init (GstClapperGLSink * clapper_sink)
|
||||
clapper_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
|
||||
clapper_sink->par_n = DEFAULT_PAR_N;
|
||||
clapper_sink->par_d = DEFAULT_PAR_D;
|
||||
clapper_sink->keep_last_frame = DEFAULT_KEEP_LAST_FRAME;
|
||||
|
||||
clapper_sink->had_eos = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -222,12 +228,12 @@ gst_clapper_gl_sink_get_widget (GstClapperGLSink * clapper_sink)
|
||||
clapper_sink->widget = (GtkClapperGLWidget *)
|
||||
GST_CLAPPER_GL_SINK_GET_CLASS (clapper_sink)->create_widget ();
|
||||
|
||||
g_object_bind_property (clapper_sink, "force-aspect-ratio", clapper_sink->widget,
|
||||
clapper_sink->bind_aspect_ratio =
|
||||
g_object_bind_property (clapper_sink, "force-aspect-ratio", clapper_sink->widget,
|
||||
"force-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (clapper_sink, "pixel-aspect-ratio", clapper_sink->widget,
|
||||
clapper_sink->bind_pixel_aspect_ratio =
|
||||
g_object_bind_property (clapper_sink, "pixel-aspect-ratio", clapper_sink->widget,
|
||||
"pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (clapper_sink, "keep-last-frame", clapper_sink->widget,
|
||||
"keep-last-frame", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
|
||||
/* Take the floating ref, other wise the destruction of the container will
|
||||
* make this widget disappear possibly before we are done. */
|
||||
@@ -273,9 +279,6 @@ gst_clapper_gl_sink_get_property (GObject * object, guint prop_id,
|
||||
case PROP_PIXEL_ASPECT_RATIO:
|
||||
gst_value_set_fraction (value, clapper_sink->par_n, clapper_sink->par_d);
|
||||
break;
|
||||
case PROP_KEEP_LAST_FRAME:
|
||||
g_value_set_boolean (value, clapper_sink->keep_last_frame);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -296,9 +299,6 @@ gst_clapper_gl_sink_set_property (GObject * object, guint prop_id,
|
||||
clapper_sink->par_n = gst_value_get_fraction_numerator (value);
|
||||
clapper_sink->par_d = gst_value_get_fraction_denominator (value);
|
||||
break;
|
||||
case PROP_KEEP_LAST_FRAME:
|
||||
clapper_sink->keep_last_frame = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -372,10 +372,8 @@ gst_clapper_gl_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||
gst_buffer_pool_config_add_option (config,
|
||||
GST_BUFFER_POOL_OPTION_GL_SYNC_META);
|
||||
|
||||
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||
gst_object_unref (pool);
|
||||
if (!gst_buffer_pool_set_config (pool, config))
|
||||
goto config_failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need at least 2 buffer because we hold on to the last one */
|
||||
@@ -436,9 +434,12 @@ gst_clapper_gl_sink_query (GstBaseSink * bsink, GstQuery * query)
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CONTEXT:
|
||||
res = gst_gl_handle_context_query ((GstElement *) clapper_sink, query,
|
||||
clapper_sink->display, clapper_sink->context, clapper_sink->gtk_context);
|
||||
{
|
||||
if (gst_gl_handle_context_query ((GstElement *) clapper_sink, query,
|
||||
clapper_sink->display, clapper_sink->context, clapper_sink->gtk_context))
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = GST_BASE_SINK_CLASS (parent_class)->query (bsink, query);
|
||||
break;
|
||||
@@ -588,7 +589,6 @@ gst_clapper_gl_sink_change_state (GstElement * element, GstStateChange transitio
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
GST_OBJECT_LOCK (clapper_sink);
|
||||
clapper_sink->had_eos = FALSE;
|
||||
if (clapper_sink->widget) {
|
||||
GTK_CLAPPER_GL_WIDGET_LOCK (clapper_sink->widget);
|
||||
clapper_sink->widget->ignore_buffers = FALSE;
|
||||
@@ -614,8 +614,7 @@ gst_clapper_gl_sink_change_state (GstElement * element, GstStateChange transitio
|
||||
GST_OBJECT_LOCK (clapper_sink);
|
||||
if (clapper_sink->widget) {
|
||||
GTK_CLAPPER_GL_WIDGET_LOCK (clapper_sink->widget);
|
||||
clapper_sink->widget->ignore_buffers =
|
||||
!clapper_sink->had_eos || !clapper_sink->keep_last_frame;
|
||||
clapper_sink->widget->ignore_buffers = TRUE;
|
||||
GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_sink->widget);
|
||||
}
|
||||
GST_OBJECT_UNLOCK (clapper_sink);
|
||||
@@ -683,7 +682,6 @@ static gboolean
|
||||
gst_clapper_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||
{
|
||||
GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink);
|
||||
gboolean res = FALSE;
|
||||
|
||||
GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
|
||||
|
||||
@@ -703,34 +701,9 @@ gst_clapper_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||
GST_OBJECT_UNLOCK (clapper_sink);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = gtk_clapper_gl_widget_update_output_format (clapper_sink->widget, caps);
|
||||
GST_OBJECT_UNLOCK (clapper_sink);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_gl_sink_wait_event (GstBaseSink * bsink, GstEvent * event)
|
||||
{
|
||||
GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink);
|
||||
GstFlowReturn ret;
|
||||
|
||||
ret = GST_BASE_SINK_CLASS (parent_class)->wait_event (bsink, event);
|
||||
|
||||
switch (event->type) {
|
||||
case GST_EVENT_EOS:
|
||||
if (ret == GST_FLOW_OK) {
|
||||
GST_OBJECT_LOCK (clapper_sink);
|
||||
clapper_sink->had_eos = TRUE;
|
||||
GST_OBJECT_UNLOCK (clapper_sink);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
@@ -58,14 +58,15 @@ struct _GstClapperGLSink
|
||||
|
||||
GtkClapperGLWidget *widget;
|
||||
|
||||
gboolean had_eos;
|
||||
|
||||
/* properties */
|
||||
gboolean force_aspect_ratio;
|
||||
GBinding *bind_aspect_ratio;
|
||||
|
||||
gint par_n, par_d;
|
||||
gboolean keep_last_frame;
|
||||
GBinding *bind_pixel_aspect_ratio;
|
||||
|
||||
gboolean ignore_textures;
|
||||
GBinding *bind_ignore_textures;
|
||||
|
||||
GtkWidget *window;
|
||||
gulong widget_destroy_id;
|
||||
|
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
|
||||
* Copyright (C) 2015 Thibault Saunier <tsaunier@gnome.org>
|
||||
* Copyright (C) 2021 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* FIXME: remove these once their headers are public in gstreamer:
|
||||
* https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/804
|
||||
*/
|
||||
|
||||
#include "gstclapperglutils.h"
|
||||
|
||||
static const gfloat identity_matrix[] = {
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
static const gfloat from_ndc_matrix[] = {
|
||||
0.5, 0.0, 0.0, 0.0,
|
||||
0.0, 0.5, 0.0, 0.0,
|
||||
0.0, 0.0, 0.5, 0.0,
|
||||
0.5, 0.5, 0.5, 1.0,
|
||||
};
|
||||
|
||||
static const gfloat to_ndc_matrix[] = {
|
||||
2.0, 0.0, 0.0, 0.0,
|
||||
0.0, 2.0, 0.0, 0.0,
|
||||
0.0, 0.0, 2.0, 0.0,
|
||||
-1.0, -1.0, -1.0, 1.0,
|
||||
};
|
||||
|
||||
/* multiplies two 4x4 matrices, @a X @b, and stores the result in @result
|
||||
* https://en.wikipedia.org/wiki/Matrix_multiplication
|
||||
*/
|
||||
static void
|
||||
gst_gl_multiply_matrix4 (const gfloat * a, const gfloat * b, gfloat * result)
|
||||
{
|
||||
int i, j, k;
|
||||
gfloat tmp[16] = { 0.0f };
|
||||
|
||||
if (!a || !b || !result)
|
||||
return;
|
||||
for (i = 0; i < 4; i++) { /* column */
|
||||
for (j = 0; j < 4; j++) { /* row */
|
||||
for (k = 0; k < 4; k++) {
|
||||
tmp[j + (i * 4)] += a[k + (i * 4)] * b[j + (k * 4)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
result[i] = tmp[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* gst_clapper_gl_get_affine_transformation_meta_as_ndc:
|
||||
* @meta: (nullable): a #GstVideoAffineTransformationMeta
|
||||
* @matrix: (out): result of the 4x4 matrix
|
||||
*
|
||||
* Retrieves the stored 4x4 affine transformation matrix stored in @meta in
|
||||
* NDC coordinates. if @meta is NULL, an identity matrix is returned.
|
||||
*
|
||||
* NDC is a left-handed coordinate system
|
||||
* - x - [-1, 1] - +ve X moves right
|
||||
* - y - [-1, 1] - +ve Y moves up
|
||||
* - z - [-1, 1] - +ve Z moves into
|
||||
*/
|
||||
void
|
||||
gst_clapper_gl_get_affine_transformation_meta_as_ndc (GstVideoAffineTransformationMeta *
|
||||
meta, gfloat * matrix)
|
||||
{
|
||||
if (!meta) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
matrix[i] = identity_matrix[i];
|
||||
}
|
||||
} else {
|
||||
float tmp[16];
|
||||
|
||||
/* change of basis multiplications */
|
||||
gst_gl_multiply_matrix4 (from_ndc_matrix, meta->matrix, tmp);
|
||||
gst_gl_multiply_matrix4 (tmp, to_ndc_matrix, matrix);
|
||||
}
|
||||
}
|
@@ -19,7 +19,6 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
struct invoke_context
|
||||
@@ -70,26 +69,3 @@ gst_gtk_invoke_on_main (GThreadFunc func, gpointer data)
|
||||
|
||||
return info.res;
|
||||
}
|
||||
|
||||
void
|
||||
gst_gtk_install_shared_properties (GObjectClass *gobject_class)
|
||||
{
|
||||
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
|
||||
g_param_spec_boolean ("force-aspect-ratio",
|
||||
"Force aspect ratio",
|
||||
"When enabled, scaling will respect original aspect ratio",
|
||||
DEFAULT_FORCE_ASPECT_RATIO,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
|
||||
gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
|
||||
"The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
|
||||
G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_KEEP_LAST_FRAME,
|
||||
g_param_spec_boolean ("keep-last-frame",
|
||||
"Keep last frame",
|
||||
"Keep showing last video frame after playback instead of black screen",
|
||||
DEFAULT_KEEP_LAST_FRAME,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
@@ -22,25 +22,8 @@
|
||||
#ifndef __GST_GTK_UTILS_H__
|
||||
#define __GST_GTK_UTILS_H__
|
||||
|
||||
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||
#define DEFAULT_PAR_N 0
|
||||
#define DEFAULT_PAR_D 1
|
||||
#define DEFAULT_KEEP_LAST_FRAME FALSE
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_WIDGET,
|
||||
PROP_FORCE_ASPECT_RATIO,
|
||||
PROP_PIXEL_ASPECT_RATIO,
|
||||
PROP_KEEP_LAST_FRAME
|
||||
};
|
||||
|
||||
gpointer gst_gtk_invoke_on_main (GThreadFunc func, gpointer data);
|
||||
|
||||
void gst_gtk_install_shared_properties (GObjectClass *gobject_class);
|
||||
|
||||
#endif /* __GST_GTK_UTILS_H__ */
|
||||
|
@@ -26,11 +26,9 @@
|
||||
#include <stdio.h>
|
||||
#include <gst/gl/gstglfuncs.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/gstvideoaffinetransformationmeta.h>
|
||||
|
||||
#include "gtkclapperglwidget.h"
|
||||
#include "gstgtkutils.h"
|
||||
#include "gstclapperglutils.h"
|
||||
|
||||
#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11)
|
||||
#include <gdk/x11/gdkx.h>
|
||||
@@ -59,27 +57,24 @@
|
||||
GST_DEBUG_CATEGORY (gst_debug_clapper_gl_widget);
|
||||
#define GST_CAT_DEFAULT gst_debug_clapper_gl_widget
|
||||
|
||||
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||
#define DEFAULT_PAR_N 0
|
||||
#define DEFAULT_PAR_D 1
|
||||
|
||||
struct _GtkClapperGLWidgetPrivate
|
||||
{
|
||||
gboolean initiated;
|
||||
|
||||
GstGLDisplay *display;
|
||||
GdkGLContext *gdk_context;
|
||||
GstGLContext *other_context;
|
||||
GstGLContext *context;
|
||||
|
||||
GstGLTextureTarget texture_target;
|
||||
guint gl_target;
|
||||
|
||||
GstGLUpload *upload;
|
||||
GstGLShader *shader;
|
||||
|
||||
GLuint vao;
|
||||
GLuint vertex_buffer;
|
||||
GLint attr_position;
|
||||
GLint attr_texture;
|
||||
GLuint current_tex;
|
||||
|
||||
GstGLOverlayCompositor *overlay_compositor;
|
||||
};
|
||||
|
||||
@@ -99,6 +94,13 @@ G_DEFINE_TYPE_WITH_CODE (GtkClapperGLWidget, gtk_clapper_gl_widget, GTK_TYPE_GL_
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkclapperglwidget", 0,
|
||||
"GTK Clapper GL Widget"));
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FORCE_ASPECT_RATIO,
|
||||
PROP_PIXEL_ASPECT_RATIO,
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_clapper_gl_widget_get_preferred_width (GtkWidget * widget, gint * min,
|
||||
gint * natural)
|
||||
@@ -172,9 +174,6 @@ gtk_clapper_gl_widget_set_property (GObject * object, guint prop_id,
|
||||
clapper_widget->par_n = gst_value_get_fraction_numerator (value);
|
||||
clapper_widget->par_d = gst_value_get_fraction_denominator (value);
|
||||
break;
|
||||
case PROP_KEEP_LAST_FRAME:
|
||||
clapper_widget->keep_last_frame = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -194,9 +193,6 @@ gtk_clapper_gl_widget_get_property (GObject * object, guint prop_id,
|
||||
case PROP_PIXEL_ASPECT_RATIO:
|
||||
gst_value_set_fraction (value, clapper_widget->par_n, clapper_widget->par_d);
|
||||
break;
|
||||
case PROP_KEEP_LAST_FRAME:
|
||||
g_value_set_boolean (value, clapper_widget->keep_last_frame);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -320,22 +316,6 @@ _gdk_key_to_navigation_string (guint keyval)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_get_is_navigation_allowed (GstElement * element, GstState min_state)
|
||||
{
|
||||
if (GST_IS_NAVIGATION (element)) {
|
||||
GstState nav_state;
|
||||
|
||||
GST_OBJECT_LOCK (element);
|
||||
nav_state = element->current_state;
|
||||
GST_OBJECT_UNLOCK (element);
|
||||
|
||||
return nav_state >= min_state;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_clapper_gl_widget_key_event (GtkEventControllerKey * key_controller,
|
||||
guint keyval, guint keycode, GdkModifierType state)
|
||||
@@ -346,7 +326,7 @@ gtk_clapper_gl_widget_key_event (GtkEventControllerKey * key_controller,
|
||||
GstElement *element;
|
||||
|
||||
if ((element = g_weak_ref_get (&clapper_widget->element))) {
|
||||
if (_get_is_navigation_allowed (element, GST_STATE_PAUSED)) {
|
||||
if (GST_IS_NAVIGATION (element)) {
|
||||
GdkEvent *event = gtk_event_controller_get_current_event (controller);
|
||||
const gchar *str = _gdk_key_to_navigation_string (keyval);
|
||||
|
||||
@@ -435,11 +415,8 @@ gtk_clapper_gl_widget_button_event (GtkGestureClick * gesture,
|
||||
GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget);
|
||||
GstElement *element;
|
||||
|
||||
if (clapper_widget->display_width == 0 || clapper_widget->display_height == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((element = g_weak_ref_get (&clapper_widget->element))) {
|
||||
if (_get_is_navigation_allowed (element, GST_STATE_PLAYING)) {
|
||||
if (GST_IS_NAVIGATION (element)) {
|
||||
GdkEvent *event = gtk_event_controller_get_current_event (controller);
|
||||
const gchar *key_type =
|
||||
gdk_event_get_event_type (event) == GDK_BUTTON_PRESS
|
||||
@@ -468,12 +445,9 @@ gtk_clapper_gl_widget_motion_event (GtkEventControllerMotion * motion_controller
|
||||
GtkClapperGLWidget *clapper_widget = GTK_CLAPPER_GL_WIDGET (widget);
|
||||
GstElement *element;
|
||||
|
||||
if ((x == clapper_widget->last_pos_x && y == clapper_widget->last_pos_y) ||
|
||||
clapper_widget->display_width == 0 || clapper_widget->display_height == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((element = g_weak_ref_get (&clapper_widget->element))) {
|
||||
if (_get_is_navigation_allowed (element, GST_STATE_PLAYING)) {
|
||||
if (x != clapper_widget->last_pos_x && y != clapper_widget->last_pos_y &&
|
||||
(element = g_weak_ref_get (&clapper_widget->element))) {
|
||||
if (GST_IS_NAVIGATION (element)) {
|
||||
gdouble stream_x, stream_y;
|
||||
|
||||
clapper_widget->last_pos_x = x;
|
||||
@@ -534,42 +508,9 @@ gtk_clapper_gl_widget_init_redisplay (GtkClapperGLWidget * clapper_widget)
|
||||
GtkClapperGLWidgetPrivate *priv = clapper_widget->priv;
|
||||
const GstGLFuncs *gl = priv->context->gl_vtable;
|
||||
GError *error = NULL;
|
||||
GstGLSLStage *frag_stage, *vert_stage;
|
||||
|
||||
gst_gl_insert_debug_marker (priv->other_context, "initializing redisplay");
|
||||
|
||||
vert_stage = gst_glsl_stage_new_with_string (priv->context,
|
||||
GL_VERTEX_SHADER, GST_GLSL_VERSION_NONE,
|
||||
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
|
||||
gst_gl_shader_string_vertex_mat4_vertex_transform);
|
||||
if (priv->texture_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
|
||||
gchar *frag_str;
|
||||
|
||||
frag_str =
|
||||
gst_gl_shader_string_fragment_external_oes_get_default
|
||||
(priv->context, GST_GLSL_VERSION_NONE,
|
||||
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
|
||||
frag_stage = gst_glsl_stage_new_with_string (priv->context,
|
||||
GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE,
|
||||
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, frag_str);
|
||||
|
||||
g_free (frag_str);
|
||||
} else {
|
||||
frag_stage = gst_glsl_stage_new_default_fragment (priv->context);
|
||||
}
|
||||
|
||||
if (!vert_stage || !frag_stage) {
|
||||
GST_ERROR ("Failed to retrieve fragment shader for texture target");
|
||||
if (vert_stage)
|
||||
gst_object_unref (vert_stage);
|
||||
if (frag_stage)
|
||||
gst_object_unref (frag_stage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(priv->shader =
|
||||
gst_gl_shader_new_link_with_stages (priv->context, &error,
|
||||
vert_stage, frag_stage, NULL))) {
|
||||
if (!(priv->shader = gst_gl_shader_new_default (priv->context, &error))) {
|
||||
GST_ERROR ("Failed to initialize shader: %s", error->message);
|
||||
return;
|
||||
}
|
||||
@@ -596,9 +537,8 @@ gtk_clapper_gl_widget_init_redisplay (GtkClapperGLWidget * clapper_widget)
|
||||
|
||||
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
|
||||
if (!priv->overlay_compositor)
|
||||
priv->overlay_compositor =
|
||||
gst_gl_overlay_compositor_new (priv->other_context);
|
||||
priv->overlay_compositor =
|
||||
gst_gl_overlay_compositor_new (priv->other_context);
|
||||
|
||||
priv->initiated = TRUE;
|
||||
}
|
||||
@@ -629,9 +569,6 @@ gtk_clapper_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
|
||||
GtkClapperGLWidgetPrivate *priv = clapper_widget->priv;
|
||||
const GstGLFuncs *gl;
|
||||
|
||||
GstVideoAffineTransformationMeta *af_meta;
|
||||
gfloat matrix[16];
|
||||
|
||||
GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget);
|
||||
|
||||
/* Draw black with GDK context when priv is not available yet.
|
||||
@@ -719,15 +656,9 @@ gtk_clapper_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
|
||||
gtk_clapper_gl_widget_bind_buffer (clapper_widget);
|
||||
|
||||
gl->ActiveTexture (GL_TEXTURE0);
|
||||
gl->BindTexture (priv->gl_target, priv->current_tex);
|
||||
gl->BindTexture (GL_TEXTURE_2D, priv->current_tex);
|
||||
gst_gl_shader_set_uniform_1i (priv->shader, "tex", 0);
|
||||
|
||||
af_meta = gst_buffer_get_video_affine_transformation_meta (
|
||||
clapper_widget->buffer);
|
||||
gst_clapper_gl_get_affine_transformation_meta_as_ndc (af_meta, matrix);
|
||||
gst_gl_shader_set_uniform_matrix_4fv (priv->shader,
|
||||
"u_transformation", 1, FALSE, matrix);
|
||||
|
||||
gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
if (gl->BindVertexArray)
|
||||
@@ -735,7 +666,7 @@ gtk_clapper_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
|
||||
else
|
||||
gtk_clapper_gl_widget_unbind_buffer (clapper_widget);
|
||||
|
||||
gl->BindTexture (priv->gl_target, 0);
|
||||
gl->BindTexture (GL_TEXTURE_2D, 0);
|
||||
|
||||
/* Draw subtitles */
|
||||
gst_gl_overlay_compositor_draw_overlays (priv->overlay_compositor);
|
||||
@@ -749,67 +680,39 @@ done:
|
||||
}
|
||||
|
||||
static void
|
||||
_cleanup_gl_private (GtkClapperGLWidgetPrivate * priv)
|
||||
_reset_gl (GtkClapperGLWidget * clapper_widget)
|
||||
{
|
||||
GtkClapperGLWidgetPrivate *priv = clapper_widget->priv;
|
||||
const GstGLFuncs *gl = priv->other_context->gl_vtable;
|
||||
|
||||
if (!priv->gdk_context)
|
||||
priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (clapper_widget));
|
||||
|
||||
if (priv->gdk_context == NULL)
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (priv->gdk_context);
|
||||
gst_gl_context_activate (priv->other_context, TRUE);
|
||||
|
||||
if (priv->vao) {
|
||||
gl->DeleteVertexArrays (1, &priv->vao);
|
||||
priv->vao = 0;
|
||||
}
|
||||
|
||||
if (priv->vertex_buffer) {
|
||||
gl->DeleteBuffers (1, &priv->vertex_buffer);
|
||||
priv->vertex_buffer = 0;
|
||||
}
|
||||
|
||||
if (priv->upload) {
|
||||
gst_object_unref (priv->upload);
|
||||
priv->upload = NULL;
|
||||
}
|
||||
|
||||
if (priv->shader) {
|
||||
gst_object_unref (priv->shader);
|
||||
priv->shader = NULL;
|
||||
}
|
||||
if (priv->overlay_compositor)
|
||||
gst_gl_overlay_compositor_free_overlays (priv->overlay_compositor);
|
||||
}
|
||||
|
||||
static void
|
||||
_cleanup_gl_thread (GtkClapperGLWidget * clapper_widget)
|
||||
{
|
||||
GtkClapperGLWidgetPrivate *priv = clapper_widget->priv;
|
||||
|
||||
if (!priv->gdk_context)
|
||||
priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (clapper_widget));
|
||||
|
||||
if (priv->gdk_context == NULL)
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (priv->gdk_context);
|
||||
gst_gl_context_activate (priv->other_context, TRUE);
|
||||
|
||||
_cleanup_gl_private (priv);
|
||||
|
||||
gst_gl_context_activate (priv->other_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
priv->initiated = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_reset_gl (GtkClapperGLWidget * clapper_widget)
|
||||
{
|
||||
GtkClapperGLWidgetPrivate *priv = clapper_widget->priv;
|
||||
|
||||
if (!priv->gdk_context)
|
||||
priv->gdk_context = gtk_gl_area_get_context (GTK_GL_AREA (clapper_widget));
|
||||
|
||||
if (priv->gdk_context == NULL)
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (priv->gdk_context);
|
||||
gst_gl_context_activate (priv->other_context, TRUE);
|
||||
|
||||
_cleanup_gl_private (priv);
|
||||
|
||||
if (priv->overlay_compositor)
|
||||
gst_object_unref (priv->overlay_compositor);
|
||||
@@ -900,9 +803,8 @@ gtk_clapper_gl_widget_set_buffer (GtkClapperGLWidget * clapper_widget,
|
||||
GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_wrap_current_gl (GstGLDisplay * display, GstGLPlatform platform,
|
||||
GstGLContext ** other_context)
|
||||
static GstGLAPI
|
||||
_get_current_gl_api (GstGLPlatform platform)
|
||||
{
|
||||
GstGLAPI gl_api = GST_GL_API_NONE;
|
||||
guint gl_major = 0, gl_minor = 0;
|
||||
@@ -911,26 +813,11 @@ _wrap_current_gl (GstGLDisplay * display, GstGLPlatform platform,
|
||||
|
||||
if (gl_api) {
|
||||
const gboolean is_es = gl_api & (GST_GL_API_GLES1 | GST_GL_API_GLES2);
|
||||
gchar *gl_api_str = gst_gl_api_to_string (gl_api);
|
||||
guintptr gl_handle = 0;
|
||||
|
||||
GST_INFO ("Using GL API: %s, ver: %d.%d", gl_api_str, gl_major, gl_minor);
|
||||
g_free (gl_api_str);
|
||||
|
||||
if (is_es && platform == GST_GL_PLATFORM_EGL && !g_getenv ("GST_GL_API")) {
|
||||
GST_DEBUG ("No GST_GL_API env and GTK is using EGL GLES2, enforcing it");
|
||||
gst_gl_display_filter_gl_api (display, GST_GL_API_GLES2);
|
||||
}
|
||||
|
||||
gl_handle = gst_gl_context_get_current_gl_context (platform);
|
||||
if (gl_handle) {
|
||||
if ((*other_context = gst_gl_context_new_wrapped (display,
|
||||
gl_handle, platform, gl_api)))
|
||||
return TRUE;
|
||||
}
|
||||
GST_INFO ("Using OpenGL%s %d.%d", is_es ? " ES" : "", gl_major, gl_minor);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return gl_api;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -938,6 +825,8 @@ _get_gl_context (GtkClapperGLWidget * clapper_widget)
|
||||
{
|
||||
GtkClapperGLWidgetPrivate *priv = clapper_widget->priv;
|
||||
GstGLPlatform platform = GST_GL_PLATFORM_NONE;
|
||||
GstGLAPI gl_api = GST_GL_API_NONE;
|
||||
guintptr gl_handle = 0;
|
||||
|
||||
gtk_widget_realize (GTK_WIDGET (clapper_widget));
|
||||
|
||||
@@ -959,45 +848,53 @@ _get_gl_context (GtkClapperGLWidget * clapper_widget)
|
||||
}
|
||||
|
||||
g_object_ref (priv->gdk_context);
|
||||
|
||||
gdk_gl_context_make_current (priv->gdk_context);
|
||||
|
||||
#if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (GDK_WINDOWING_WAYLAND)
|
||||
if (GST_IS_GL_DISPLAY_WAYLAND (priv->display)) {
|
||||
platform = GST_GL_PLATFORM_EGL;
|
||||
GST_DEBUG ("Using EGL on Wayland");
|
||||
goto have_platform;
|
||||
}
|
||||
#endif
|
||||
#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11)
|
||||
#if GST_GL_HAVE_PLATFORM_EGL
|
||||
if (GST_IS_GL_DISPLAY_EGL (priv->display)) {
|
||||
platform = GST_GL_PLATFORM_EGL;
|
||||
GST_DEBUG ("Using EGL on x11");
|
||||
goto have_platform;
|
||||
gl_handle = gst_gl_context_get_current_gl_context (platform);
|
||||
}
|
||||
#endif
|
||||
#if GST_GL_HAVE_PLATFORM_GLX
|
||||
if (GST_IS_GL_DISPLAY_X11 (priv->display)) {
|
||||
if (!gl_handle && GST_IS_GL_DISPLAY_X11 (priv->display)) {
|
||||
platform = GST_GL_PLATFORM_GLX;
|
||||
GST_DEBUG ("Using GLX on x11");
|
||||
goto have_platform;
|
||||
gl_handle = gst_gl_context_get_current_gl_context (platform);
|
||||
}
|
||||
#endif
|
||||
if (gl_handle) {
|
||||
gl_api = _get_current_gl_api (platform);
|
||||
priv->other_context =
|
||||
gst_gl_context_new_wrapped (priv->display, gl_handle,
|
||||
platform, gl_api);
|
||||
}
|
||||
#endif
|
||||
#if GST_GL_HAVE_WINDOW_WAYLAND && GST_GL_HAVE_PLATFORM_EGL && defined (GDK_WINDOWING_WAYLAND)
|
||||
if (GST_IS_GL_DISPLAY_WAYLAND (priv->display)) {
|
||||
platform = GST_GL_PLATFORM_EGL;
|
||||
gl_api = _get_current_gl_api (platform);
|
||||
gl_handle = gst_gl_context_get_current_gl_context (platform);
|
||||
if (gl_handle)
|
||||
priv->other_context =
|
||||
gst_gl_context_new_wrapped (priv->display, gl_handle,
|
||||
platform, gl_api);
|
||||
}
|
||||
#endif
|
||||
|
||||
GST_ERROR ("Unknown GL platform");
|
||||
return;
|
||||
(void) platform;
|
||||
(void) gl_api;
|
||||
(void) gl_handle;
|
||||
|
||||
have_platform:
|
||||
|
||||
if (_wrap_current_gl (priv->display, platform, &priv->other_context)) {
|
||||
if (priv->other_context) {
|
||||
GError *error = NULL;
|
||||
|
||||
GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT,
|
||||
priv->other_context);
|
||||
gst_gl_context_activate (priv->other_context, TRUE);
|
||||
if (!gst_gl_context_fill_info (priv->other_context, &error)) {
|
||||
GST_ERROR ("Failed to retrieve gdk context info: %s", error->message);
|
||||
GST_ERROR ("failed to retrieve gdk context info: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
g_object_unref (priv->other_context);
|
||||
priv->other_context = NULL;
|
||||
@@ -1012,20 +909,30 @@ have_platform:
|
||||
static void
|
||||
gtk_clapper_gl_widget_class_init (GtkClapperGLWidgetClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
|
||||
GtkGLAreaClass *gl_area_class = (GtkGLAreaClass *) klass;
|
||||
GObjectClass *gobject_klass = (GObjectClass *) klass;
|
||||
GtkWidgetClass *widget_klass = (GtkWidgetClass *) klass;
|
||||
GtkGLAreaClass *gl_area_klass = (GtkGLAreaClass *) klass;
|
||||
|
||||
gobject_class->set_property = gtk_clapper_gl_widget_set_property;
|
||||
gobject_class->get_property = gtk_clapper_gl_widget_get_property;
|
||||
gobject_class->finalize = gtk_clapper_gl_widget_finalize;
|
||||
gobject_klass->set_property = gtk_clapper_gl_widget_set_property;
|
||||
gobject_klass->get_property = gtk_clapper_gl_widget_get_property;
|
||||
gobject_klass->finalize = gtk_clapper_gl_widget_finalize;
|
||||
|
||||
gst_gtk_install_shared_properties (gobject_class);
|
||||
g_object_class_install_property (gobject_klass, PROP_FORCE_ASPECT_RATIO,
|
||||
g_param_spec_boolean ("force-aspect-ratio",
|
||||
"Force aspect ratio",
|
||||
"When enabled, scaling will respect original aspect ratio",
|
||||
DEFAULT_FORCE_ASPECT_RATIO,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
widget_class->measure = gtk_clapper_gl_widget_measure;
|
||||
widget_class->size_allocate = gtk_clapper_gl_widget_size_allocate;
|
||||
g_object_class_install_property (gobject_klass, PROP_PIXEL_ASPECT_RATIO,
|
||||
gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
|
||||
"The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D,
|
||||
G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gl_area_class->render = gtk_clapper_gl_widget_render;
|
||||
widget_klass->measure = gtk_clapper_gl_widget_measure;
|
||||
widget_klass->size_allocate = gtk_clapper_gl_widget_size_allocate;
|
||||
|
||||
gl_area_klass->render = gtk_clapper_gl_widget_render;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1038,7 +945,6 @@ gtk_clapper_gl_widget_init (GtkClapperGLWidget * clapper_widget)
|
||||
clapper_widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
|
||||
clapper_widget->par_n = DEFAULT_PAR_N;
|
||||
clapper_widget->par_d = DEFAULT_PAR_D;
|
||||
clapper_widget->keep_last_frame = DEFAULT_KEEP_LAST_FRAME;
|
||||
clapper_widget->ignore_buffers = FALSE;
|
||||
clapper_widget->last_pos_x = 0;
|
||||
clapper_widget->last_pos_y = 0;
|
||||
@@ -1087,7 +993,7 @@ gtk_clapper_gl_widget_init (GtkClapperGLWidget * clapper_widget)
|
||||
#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11)
|
||||
if (GDK_IS_X11_DISPLAY (display)) {
|
||||
gpointer display_ptr;
|
||||
#if GST_GL_HAVE_PLATFORM_EGL && GTK_CHECK_VERSION(4,3,1)
|
||||
#if GST_GL_HAVE_PLATFORM_EGL && GTK_CHECK_VERSION(4,4,0)
|
||||
display_ptr = gdk_x11_display_get_egl_display (display);
|
||||
if (display_ptr)
|
||||
priv->display = (GstGLDisplay *)
|
||||
@@ -1118,9 +1024,6 @@ gtk_clapper_gl_widget_init (GtkClapperGLWidget * clapper_widget)
|
||||
|
||||
GST_INFO ("Created %" GST_PTR_FORMAT, priv->display);
|
||||
|
||||
priv->texture_target = GST_GL_TEXTURE_TARGET_NONE;
|
||||
priv->gl_target = 0;
|
||||
|
||||
gtk_gl_area_set_auto_render (GTK_GL_AREA (widget), FALSE);
|
||||
|
||||
g_signal_connect_swapped (gtk_widget_get_settings (widget), "notify",
|
||||
@@ -1205,44 +1108,3 @@ gtk_clapper_gl_widget_get_display (GtkClapperGLWidget * clapper_widget)
|
||||
|
||||
return gst_object_ref (clapper_widget->priv->display);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_clapper_gl_widget_update_output_format (GtkClapperGLWidget * clapper_widget,
|
||||
GstCaps * caps)
|
||||
{
|
||||
GtkClapperGLWidgetPrivate *priv;
|
||||
GstGLTextureTarget previous_target;
|
||||
GstStructure *structure;
|
||||
const gchar *target_str;
|
||||
gboolean cleanup_gl;
|
||||
|
||||
GTK_CLAPPER_GL_WIDGET_LOCK (clapper_widget);
|
||||
priv = clapper_widget->priv;
|
||||
|
||||
previous_target = priv->texture_target;
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
target_str = gst_structure_get_string (structure, "texture-target");
|
||||
|
||||
if (!target_str)
|
||||
target_str = GST_GL_TEXTURE_TARGET_2D_STR;
|
||||
|
||||
priv->texture_target = gst_gl_texture_target_from_string (target_str);
|
||||
if (!priv->texture_target)
|
||||
goto fail;
|
||||
|
||||
GST_DEBUG_OBJECT (clapper_widget, "Using texture-target: %s", target_str);
|
||||
priv->gl_target = gst_gl_texture_target_to_gl (priv->texture_target);
|
||||
|
||||
cleanup_gl = (previous_target != GST_GL_TEXTURE_TARGET_NONE &&
|
||||
priv->texture_target != previous_target);
|
||||
|
||||
GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget);
|
||||
if (cleanup_gl)
|
||||
gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _cleanup_gl_thread, clapper_widget);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_widget);
|
||||
return FALSE;
|
||||
}
|
||||
|
@@ -52,7 +52,6 @@ struct _GtkClapperGLWidget
|
||||
/* properties */
|
||||
gboolean force_aspect_ratio;
|
||||
gint par_n, par_d;
|
||||
gboolean keep_last_frame;
|
||||
|
||||
gint display_width;
|
||||
gint display_height;
|
||||
@@ -100,13 +99,12 @@ gboolean gtk_clapper_gl_widget_set_format (GtkClapperGLWidget *
|
||||
void gtk_clapper_gl_widget_set_buffer (GtkClapperGLWidget * widget, GstBuffer * buffer);
|
||||
void gtk_clapper_gl_widget_set_element (GtkClapperGLWidget * widget, GstElement * element);
|
||||
|
||||
GtkWidget * gtk_clapper_gl_widget_new (void);
|
||||
GtkWidget * gtk_clapper_gl_widget_new (void);
|
||||
|
||||
gboolean gtk_clapper_gl_widget_init_winsys (GtkClapperGLWidget * widget);
|
||||
GstGLDisplay * gtk_clapper_gl_widget_get_display (GtkClapperGLWidget * widget);
|
||||
GstGLContext * gtk_clapper_gl_widget_get_context (GtkClapperGLWidget * widget);
|
||||
GstGLContext * gtk_clapper_gl_widget_get_gtk_context (GtkClapperGLWidget * widget);
|
||||
gboolean gtk_clapper_gl_widget_update_output_format (GtkClapperGLWidget * widget, GstCaps * caps);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
74
lib/gst/clapper/meson.build
vendored
@@ -1,3 +1,5 @@
|
||||
gnome = import('gnome')
|
||||
|
||||
gstclapper_sources = [
|
||||
'gstclapper.c',
|
||||
'gstclapper-signal-dispatcher.c',
|
||||
@@ -6,13 +8,14 @@ gstclapper_sources = [
|
||||
'gstclapper-g-main-context-signal-dispatcher.c',
|
||||
'gstclapper-video-overlay-video-renderer.c',
|
||||
'gstclapper-visualization.c',
|
||||
'gstclapper-playlist.c',
|
||||
'gstclapper-playlist-item.c',
|
||||
'gstclapper-mpris.c',
|
||||
'gstclapper-gtk4-plugin.c',
|
||||
|
||||
'gtk4/gstclapperglsink.c',
|
||||
'gtk4/gstgtkutils.c',
|
||||
'gtk4/gtkclapperglwidget.c',
|
||||
'gtk4/gstclapperglutils.c',
|
||||
]
|
||||
gstclapper_headers = [
|
||||
'clapper.h',
|
||||
@@ -25,6 +28,8 @@ gstclapper_headers = [
|
||||
'gstclapper-g-main-context-signal-dispatcher.h',
|
||||
'gstclapper-video-overlay-video-renderer.h',
|
||||
'gstclapper-visualization.h',
|
||||
'gstclapper-playlist.h',
|
||||
'gstclapper-playlist-item.h',
|
||||
'gstclapper-mpris.h',
|
||||
'gstclapper-gtk4-plugin.h',
|
||||
]
|
||||
@@ -34,13 +39,36 @@ gstclapper_defines = [
|
||||
'-DGST_USE_UNSTABLE_API',
|
||||
'-DHAVE_GTK_GL',
|
||||
]
|
||||
gtk_deps = [gstgl_dep, gstglproto_dep]
|
||||
have_gtk_gl_windowing = false
|
||||
|
||||
if not get_option('lib')
|
||||
subdir_done()
|
||||
gtk4_dep = dependency('gtk4', required : true)
|
||||
|
||||
if not gtk4_dep.version().version_compare('>=4.0.0')
|
||||
error('GTK4 version on this system is too old')
|
||||
endif
|
||||
|
||||
if not gir.found()
|
||||
error('Clapper lib requires GI bindings to be compiled')
|
||||
if gst_gl_have_window_x11 and (gst_gl_have_platform_egl or gst_gl_have_platform_glx)
|
||||
gtk_x11_dep = dependency('gtk4-x11', required : false)
|
||||
if gtk_x11_dep.found()
|
||||
gtk_deps += gtk_x11_dep
|
||||
if gst_gl_have_platform_glx
|
||||
gtk_deps += gstglx11_dep
|
||||
endif
|
||||
have_gtk_gl_windowing = true
|
||||
endif
|
||||
endif
|
||||
|
||||
if gst_gl_have_window_wayland and gst_gl_have_platform_egl
|
||||
gtk_wayland_dep = dependency('gtk4-wayland', required : false)
|
||||
if gtk_wayland_dep.found()
|
||||
gtk_deps += [gtk_wayland_dep, gstglwayland_dep]
|
||||
have_gtk_gl_windowing = true
|
||||
endif
|
||||
endif
|
||||
|
||||
if gst_gl_have_platform_egl
|
||||
gtk_deps += gstglegl_dep
|
||||
endif
|
||||
|
||||
if not have_gtk_gl_windowing
|
||||
@@ -55,29 +83,29 @@ gstclapper_mpris_gdbus = gnome.gdbus_codegen('gstclapper-mpris-gdbus',
|
||||
|
||||
gstclapper = library('gstclapper-' + api_version,
|
||||
gstclapper_sources + gstclapper_mpris_gdbus,
|
||||
c_args: gstclapper_defines,
|
||||
link_args: noseh_link_args,
|
||||
include_directories: [configinc, libsinc],
|
||||
version: libversion,
|
||||
install: true,
|
||||
install_dir: pkglibdir,
|
||||
dependencies: [gtk4_dep, glib_dep, gio_dep, giounix_dep,
|
||||
c_args : gstclapper_defines,
|
||||
link_args : noseh_link_args,
|
||||
include_directories : [configinc, libsinc],
|
||||
version : libversion,
|
||||
install : true,
|
||||
install_dir : clapper_libdir,
|
||||
dependencies : [gtk4_dep, glib_dep, gio_dep,
|
||||
gstbase_dep, gstvideo_dep, gstaudio_dep,
|
||||
gsttag_dep, gstpbutils_dep, libm] + gtk_deps,
|
||||
)
|
||||
|
||||
clapper_gir = gnome.generate_gir(gstclapper,
|
||||
sources: gstclapper_sources + gstclapper_headers,
|
||||
namespace: 'GstClapper',
|
||||
nsversion: api_version,
|
||||
identifier_prefix: 'Gst',
|
||||
symbol_prefix: 'gst',
|
||||
export_packages: 'gstreamer-clapper-1.0',
|
||||
includes: ['Gst-1.0', 'GstPbutils-1.0', 'GstBase-1.0', 'GstVideo-1.0',
|
||||
sources : gstclapper_sources + gstclapper_headers,
|
||||
namespace : 'GstClapper',
|
||||
nsversion : api_version,
|
||||
identifier_prefix : 'Gst',
|
||||
symbol_prefix : 'gst',
|
||||
export_packages : 'gstreamer-clapper-1.0',
|
||||
includes : ['Gst-1.0', 'GstPbutils-1.0', 'GstBase-1.0', 'GstVideo-1.0',
|
||||
'GstAudio-1.0', 'GstTag-1.0'],
|
||||
install: true,
|
||||
install_dir_typelib: join_paths(pkglibdir, 'girepository-1.0'),
|
||||
extra_args: gir_init_section + ['-DGST_USE_UNSTABLE_API'],
|
||||
dependencies: [gstbase_dep, gstvideo_dep, gstaudio_dep,
|
||||
install : true,
|
||||
install_dir_typelib : join_paths(clapper_libdir, 'girepository-1.0'),
|
||||
extra_args : gir_init_section + ['-DGST_USE_UNSTABLE_API'],
|
||||
dependencies : [gstbase_dep, gstvideo_dep, gstaudio_dep,
|
||||
gsttag_dep, gstpbutils_dep]
|
||||
)
|
||||
|
1
lib/gst/meson.build
vendored
@@ -1,2 +1 @@
|
||||
subdir('clapper')
|
||||
subdir('plugin')
|
||||
|
374
lib/gst/plugin/gstclapperbaseimport.c
vendored
@@ -1,374 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapperbaseimport.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
#include "gstclappergdkbufferpool.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_base_import_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
#define parent_class gst_clapper_base_import_parent_class
|
||||
G_DEFINE_TYPE (GstClapperBaseImport, gst_clapper_base_import, GST_TYPE_BASE_TRANSFORM);
|
||||
|
||||
static void
|
||||
gst_clapper_base_import_init (GstClapperBaseImport *self)
|
||||
{
|
||||
g_mutex_init (&self->lock);
|
||||
|
||||
gst_video_info_init (&self->in_info);
|
||||
gst_video_info_init (&self->out_info);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_base_import_finalize (GObject *object)
|
||||
{
|
||||
GstClapperBaseImport *self = GST_CLAPPER_BASE_IMPORT_CAST (object);
|
||||
|
||||
GST_TRACE ("Finalize");
|
||||
g_mutex_clear (&self->lock);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_clapper_base_import_change_state (GstElement *element, GstStateChange transition)
|
||||
{
|
||||
GST_DEBUG_OBJECT (element, "Changing state: %s => %s",
|
||||
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
|
||||
gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
|
||||
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_base_import_start (GstBaseTransform *bt)
|
||||
{
|
||||
GST_INFO_OBJECT (bt, "Start");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_base_import_stop (GstBaseTransform *bt)
|
||||
{
|
||||
GST_INFO_OBJECT (bt, "Stop");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_clapper_base_import_transform_caps (GstBaseTransform *bt,
|
||||
GstPadDirection direction, GstCaps *caps, GstCaps *filter)
|
||||
{
|
||||
GstCaps *result, *tmp;
|
||||
|
||||
tmp = (direction == GST_PAD_SINK)
|
||||
? gst_pad_get_pad_template_caps (GST_BASE_TRANSFORM_SRC_PAD (bt))
|
||||
: gst_pad_get_pad_template_caps (GST_BASE_TRANSFORM_SINK_PAD (bt));
|
||||
|
||||
if (filter) {
|
||||
GST_DEBUG ("Intersecting with filter caps: %" GST_PTR_FORMAT, filter);
|
||||
result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (tmp);
|
||||
} else {
|
||||
result = tmp;
|
||||
}
|
||||
GST_DEBUG ("Returning %s caps: %" GST_PTR_FORMAT,
|
||||
(direction == GST_PAD_SINK) ? "src" : "sink", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_structure_filter_cb (GQuark field_id, GValue *value,
|
||||
G_GNUC_UNUSED gpointer user_data)
|
||||
{
|
||||
const gchar *str = g_quark_to_string (field_id);
|
||||
|
||||
if (!strcmp (str, "format")
|
||||
|| !strcmp (str, "width")
|
||||
|| !strcmp (str, "height")
|
||||
|| !strcmp (str, "pixel-aspect-ratio")
|
||||
|| !strcmp (str, "framerate"))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_clapper_base_import_fixate_caps (GstBaseTransform *bt,
|
||||
GstPadDirection direction, GstCaps *caps, GstCaps *othercaps)
|
||||
{
|
||||
GstCaps *fixated;
|
||||
|
||||
fixated = (!gst_caps_is_any (caps))
|
||||
? gst_caps_fixate (gst_caps_ref (caps))
|
||||
: gst_caps_copy (caps);
|
||||
|
||||
if (direction == GST_PAD_SINK) {
|
||||
guint i, n = gst_caps_get_size (fixated);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
GstCapsFeatures *features;
|
||||
GstStructure *structure;
|
||||
gboolean had_overlay_comp;
|
||||
|
||||
features = gst_caps_get_features (fixated, i);
|
||||
had_overlay_comp = gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
|
||||
|
||||
features = gst_caps_features_new (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY, NULL);
|
||||
if (had_overlay_comp)
|
||||
gst_caps_features_add (features, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
|
||||
|
||||
gst_caps_set_features (fixated, i, features);
|
||||
|
||||
/* Remove fields that do not apply to our memory */
|
||||
if ((structure = gst_caps_get_structure (fixated, i))) {
|
||||
gst_structure_filter_and_map_in_place (structure,
|
||||
(GstStructureFilterMapFunc) _structure_filter_cb, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
GST_DEBUG ("Fixated %s caps: %" GST_PTR_FORMAT,
|
||||
(direction == GST_PAD_SRC) ? "sink" : "src", fixated);
|
||||
|
||||
return fixated;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_base_import_set_caps (GstBaseTransform *bt,
|
||||
GstCaps *incaps, GstCaps *outcaps)
|
||||
{
|
||||
GstClapperBaseImport *self = GST_CLAPPER_BASE_IMPORT_CAST (bt);
|
||||
gboolean has_sink_info, has_src_info;
|
||||
|
||||
if ((has_sink_info = gst_video_info_from_caps (&self->in_info, incaps)))
|
||||
GST_INFO_OBJECT (self, "Set sink caps: %" GST_PTR_FORMAT, incaps);
|
||||
if ((has_src_info = gst_video_info_from_caps (&self->out_info, outcaps)))
|
||||
GST_INFO_OBJECT (self, "Set src caps: %" GST_PTR_FORMAT, outcaps);
|
||||
|
||||
return (has_sink_info && has_src_info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_base_import_import_propose_allocation (GstBaseTransform *bt,
|
||||
GstQuery *decide_query, GstQuery *query)
|
||||
{
|
||||
GstClapperBaseImport *self = GST_CLAPPER_BASE_IMPORT_CAST (bt);
|
||||
GstClapperBaseImportClass *bi_class = GST_CLAPPER_BASE_IMPORT_GET_CLASS (self);
|
||||
GstBufferPool *pool = NULL;
|
||||
GstCaps *caps;
|
||||
GstVideoInfo info;
|
||||
guint size;
|
||||
gboolean need_pool;
|
||||
|
||||
if (!GST_BASE_TRANSFORM_CLASS (parent_class)->propose_allocation (bt,
|
||||
decide_query, query))
|
||||
return FALSE;
|
||||
|
||||
/* Passthrough, nothing to do */
|
||||
if (!decide_query)
|
||||
return TRUE;
|
||||
|
||||
gst_query_parse_allocation (query, &caps, &need_pool);
|
||||
|
||||
if (!caps) {
|
||||
GST_DEBUG_OBJECT (self, "No caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_video_info_from_caps (&info, caps)) {
|
||||
GST_DEBUG_OBJECT (self, "Invalid caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Normal size of a frame */
|
||||
size = GST_VIDEO_INFO_SIZE (&info);
|
||||
|
||||
if (need_pool) {
|
||||
GstStructure *config = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Need to create upstream pool");
|
||||
pool = bi_class->create_upstream_pool (self, &config);
|
||||
|
||||
if (pool) {
|
||||
/* If we did not get config, use default one */
|
||||
if (!config)
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
|
||||
gst_buffer_pool_config_set_params (config, caps, size, 2, 0);
|
||||
|
||||
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||
gst_object_unref (pool);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Failed to set config");
|
||||
return FALSE;
|
||||
}
|
||||
} else if (config) {
|
||||
GST_WARNING_OBJECT (self, "Got pool config without a pool to apply it!");
|
||||
gst_structure_free (config);
|
||||
}
|
||||
}
|
||||
|
||||
gst_query_add_allocation_pool (query, pool, size, 2, 0);
|
||||
if (pool)
|
||||
gst_object_unref (pool);
|
||||
|
||||
gst_query_add_allocation_meta (query,
|
||||
GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_base_import_decide_allocation (GstBaseTransform *bt, GstQuery *query)
|
||||
{
|
||||
GstClapperBaseImport *self = GST_CLAPPER_BASE_IMPORT_CAST (bt);
|
||||
GstBufferPool *pool = NULL;
|
||||
GstCaps *caps;
|
||||
GstVideoInfo info;
|
||||
guint size = 0, min = 0, max = 0;
|
||||
gboolean update_pool, need_pool = TRUE;
|
||||
|
||||
gst_query_parse_allocation (query, &caps, NULL);
|
||||
|
||||
if (!caps) {
|
||||
GST_DEBUG_OBJECT (self, "No caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_video_info_from_caps (&info, caps)) {
|
||||
GST_DEBUG_OBJECT (self, "Invalid caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((update_pool = gst_query_get_n_allocation_pools (query) > 0)) {
|
||||
gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max);
|
||||
if (pool) {
|
||||
if ((need_pool = !GST_IS_CLAPPER_GDK_BUFFER_POOL (pool)))
|
||||
gst_clear_object (&pool);
|
||||
}
|
||||
} else {
|
||||
size = GST_VIDEO_INFO_SIZE (&info);
|
||||
}
|
||||
|
||||
if (need_pool) {
|
||||
GstStructure *config;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Creating new downstream pool");
|
||||
|
||||
pool = gst_clapper_gdk_buffer_pool_new ();
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
gst_buffer_pool_config_set_params (config, caps, size, min, max);
|
||||
|
||||
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||
gst_object_unref (pool);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Failed to set config");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_pool)
|
||||
gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max);
|
||||
else
|
||||
gst_query_add_allocation_pool (query, pool, size, min, max);
|
||||
|
||||
if (pool)
|
||||
gst_object_unref (pool);
|
||||
|
||||
return GST_BASE_TRANSFORM_CLASS (parent_class)->decide_allocation (bt, query);
|
||||
}
|
||||
|
||||
static GstBufferPool *
|
||||
gst_clapper_base_import_create_upstream_pool (GstClapperBaseImport *self, GstStructure **config)
|
||||
{
|
||||
GST_FIXME_OBJECT (self, "Need to create upstream buffer pool");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_base_import_class_init (GstClapperBaseImportClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GstBaseTransformClass *gstbasetransform_class = (GstBaseTransformClass *) klass;
|
||||
GstClapperBaseImportClass *bi_class = (GstClapperBaseImportClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperbaseimport", 0,
|
||||
"Clapper Base Import");
|
||||
|
||||
gobject_class->finalize = gst_clapper_base_import_finalize;
|
||||
|
||||
gstelement_class->change_state = gst_clapper_base_import_change_state;
|
||||
|
||||
gstbasetransform_class->passthrough_on_same_caps = TRUE;
|
||||
gstbasetransform_class->transform_ip_on_passthrough = FALSE;
|
||||
gstbasetransform_class->start = gst_clapper_base_import_start;
|
||||
gstbasetransform_class->stop = gst_clapper_base_import_stop;
|
||||
gstbasetransform_class->transform_caps = gst_clapper_base_import_transform_caps;
|
||||
gstbasetransform_class->fixate_caps = gst_clapper_base_import_fixate_caps;
|
||||
gstbasetransform_class->set_caps = gst_clapper_base_import_set_caps;
|
||||
gstbasetransform_class->propose_allocation = gst_clapper_base_import_import_propose_allocation;
|
||||
gstbasetransform_class->decide_allocation = gst_clapper_base_import_decide_allocation;
|
||||
|
||||
bi_class->create_upstream_pool = gst_clapper_base_import_create_upstream_pool;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maps input video frame and output memory from in/out buffers
|
||||
* using flags passed to this method.
|
||||
*
|
||||
* Remember to unmap both using `gst_video_frame_unmap` and
|
||||
* `gst_memory_unmap` when done with the data.
|
||||
*/
|
||||
gboolean
|
||||
gst_clapper_base_import_map_buffers (GstClapperBaseImport *self,
|
||||
GstBuffer *in_buf, GstBuffer *out_buf, GstMapFlags in_flags, GstMapFlags out_flags,
|
||||
GstVideoFrame *frame, GstMapInfo *info, GstMemory **mem)
|
||||
{
|
||||
GST_LOG_OBJECT (self, "Transforming from %" GST_PTR_FORMAT
|
||||
" into %" GST_PTR_FORMAT, in_buf, out_buf);
|
||||
|
||||
if (G_UNLIKELY (!gst_video_frame_map (frame, &self->in_info, in_buf, in_flags))) {
|
||||
GST_ERROR_OBJECT (self, "Could not map input buffer for reading");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*mem = gst_buffer_peek_memory (out_buf, 0);
|
||||
|
||||
if (G_UNLIKELY (!gst_memory_map (*mem, info, out_flags))) {
|
||||
GST_ERROR_OBJECT (self, "Could not map output memory for writing");
|
||||
gst_video_frame_unmap (frame);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
69
lib/gst/plugin/gstclapperbaseimport.h
vendored
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_BASE_IMPORT (gst_clapper_base_import_get_type())
|
||||
#define GST_IS_CLAPPER_BASE_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_BASE_IMPORT))
|
||||
#define GST_IS_CLAPPER_BASE_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_BASE_IMPORT))
|
||||
#define GST_CLAPPER_BASE_IMPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_BASE_IMPORT, GstClapperBaseImportClass))
|
||||
#define GST_CLAPPER_BASE_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_BASE_IMPORT, GstClapperBaseImport))
|
||||
#define GST_CLAPPER_BASE_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_BASE_IMPORT, GstClapperBaseImportClass))
|
||||
#define GST_CLAPPER_BASE_IMPORT_CAST(obj) ((GstClapperBaseImport *)(obj))
|
||||
|
||||
#define GST_CLAPPER_BASE_IMPORT_GET_LOCK(obj) (&GST_CLAPPER_BASE_IMPORT_CAST(obj)->lock)
|
||||
#define GST_CLAPPER_BASE_IMPORT_LOCK(obj) g_mutex_lock (GST_CLAPPER_BASE_IMPORT_GET_LOCK(obj))
|
||||
#define GST_CLAPPER_BASE_IMPORT_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_BASE_IMPORT_GET_LOCK(obj))
|
||||
|
||||
typedef struct _GstClapperBaseImport GstClapperBaseImport;
|
||||
typedef struct _GstClapperBaseImportClass GstClapperBaseImportClass;
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperBaseImport, gst_object_unref)
|
||||
#endif
|
||||
|
||||
struct _GstClapperBaseImport
|
||||
{
|
||||
GstBaseTransform parent;
|
||||
|
||||
GMutex lock;
|
||||
|
||||
GstVideoInfo in_info, out_info;
|
||||
};
|
||||
|
||||
struct _GstClapperBaseImportClass
|
||||
{
|
||||
GstBaseTransformClass parent_class;
|
||||
|
||||
GstBufferPool * (* create_upstream_pool) (GstClapperBaseImport *bi,
|
||||
GstStructure **config);
|
||||
};
|
||||
|
||||
GType gst_clapper_base_import_get_type (void);
|
||||
|
||||
gboolean gst_clapper_base_import_map_buffers (GstClapperBaseImport *bi,
|
||||
GstBuffer *in_buf, GstBuffer *out_buf, GstMapFlags in_flags, GstMapFlags out_flags,
|
||||
GstVideoFrame *frame, GstMapInfo *info, GstMemory **mem);
|
||||
|
||||
G_END_DECLS
|
464
lib/gst/plugin/gstclapperdmabufbaseimport.c
vendored
@@ -1,464 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
#include <gst/gl/egl/gsteglimage.h>
|
||||
|
||||
#include "gstclapperdmabufbaseimport.h"
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_dmabuf_base_import_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
static const GLfloat vertices[] = {
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 1.0f
|
||||
};
|
||||
static const GLushort indices[] = {
|
||||
0, 1, 2, 0, 2, 3
|
||||
};
|
||||
|
||||
/* GTK4 renders things upside down ¯\_(ツ)_/¯ */
|
||||
static const gfloat vertical_flip_matrix[] = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstClapperDmabufBaseImport *dmabuf_bi;
|
||||
GLuint id;
|
||||
guint width;
|
||||
guint height;
|
||||
} GstClapperDmabufTexData;
|
||||
|
||||
#define parent_class gst_clapper_dmabuf_base_import_parent_class
|
||||
G_DEFINE_TYPE (GstClapperDmabufBaseImport, gst_clapper_dmabuf_base_import, GST_TYPE_CLAPPER_GL_BASE_IMPORT);
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_base_import_init (GstClapperDmabufBaseImport *self)
|
||||
{
|
||||
g_mutex_init (&self->lock);
|
||||
|
||||
self->gst_tex_target = GST_GL_TEXTURE_TARGET_EXTERNAL_OES;
|
||||
self->gl_tex_target = gst_gl_texture_target_to_gl (self->gst_tex_target);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_base_import_finalize (GObject *object)
|
||||
{
|
||||
GstClapperDmabufBaseImport *self = GST_CLAPPER_DMABUF_BASE_IMPORT_CAST (object);
|
||||
|
||||
gst_clear_object (&self->shader);
|
||||
|
||||
g_mutex_clear (&self->lock);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_base_import_bind_buffer (GstClapperDmabufBaseImport *self)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (self);
|
||||
const GstGLFuncs *gl = gl_bi->gst_context->gl_vtable;
|
||||
|
||||
gl->BindBuffer (GL_ARRAY_BUFFER, self->vertex_buffer);
|
||||
|
||||
/* Load the vertex position */
|
||||
gl->VertexAttribPointer (self->attr_position, 3, GL_FLOAT, GL_FALSE,
|
||||
5 * sizeof (GLfloat), (void *) 0);
|
||||
|
||||
/* Load the texture coordinate */
|
||||
gl->VertexAttribPointer (self->attr_texture, 2, GL_FLOAT, GL_FALSE,
|
||||
5 * sizeof (GLfloat), (void *) (3 * sizeof (GLfloat)));
|
||||
|
||||
gl->EnableVertexAttribArray (self->attr_position);
|
||||
gl->EnableVertexAttribArray (self->attr_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_base_import_unbind_buffer (GstClapperDmabufBaseImport *self)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (self);
|
||||
const GstGLFuncs *gl = gl_bi->gst_context->gl_vtable;
|
||||
|
||||
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
gl->DisableVertexAttribArray (self->attr_position);
|
||||
gl->DisableVertexAttribArray (self->attr_texture);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
prepare_on_main (GstClapperDmabufBaseImport *self)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (self);
|
||||
GstGLSLStage *frag_stage, *vert_stage;
|
||||
GError *error = NULL;
|
||||
gchar *frag_str;
|
||||
const GstGLFuncs *gl;
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (gl_bi);
|
||||
|
||||
gdk_gl_context_make_current (gl_bi->gdk_context);
|
||||
gst_gl_context_activate (gl_bi->gst_context, TRUE);
|
||||
|
||||
if (!((vert_stage = gst_glsl_stage_new_with_string (gl_bi->gst_context,
|
||||
GL_VERTEX_SHADER, GST_GLSL_VERSION_NONE,
|
||||
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
|
||||
gst_gl_shader_string_vertex_mat4_vertex_transform)))) {
|
||||
gdk_gl_context_make_current (gl_bi->gdk_context);
|
||||
gst_gl_context_activate (gl_bi->gst_context, TRUE);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
GST_ERROR ("Failed to retrieve vertex shader for texture target");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
frag_str = gst_gl_shader_string_fragment_external_oes_get_default (
|
||||
gl_bi->gst_context, GST_GLSL_VERSION_NONE,
|
||||
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
|
||||
frag_stage = gst_glsl_stage_new_with_string (gl_bi->gst_context,
|
||||
GL_FRAGMENT_SHADER, GST_GLSL_VERSION_NONE,
|
||||
GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, frag_str);
|
||||
|
||||
g_free (frag_str);
|
||||
|
||||
if (!frag_stage) {
|
||||
gst_gl_context_activate (gl_bi->gst_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
GST_ERROR ("Failed to retrieve fragment shader for texture target");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_LOCK (self);
|
||||
|
||||
if (!((self->shader = gst_gl_shader_new_link_with_stages (gl_bi->gst_context,
|
||||
&error, vert_stage, frag_stage, NULL)))) {
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
gst_gl_context_activate (gl_bi->gst_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
|
||||
GST_ERROR ("Failed to initialize shader: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->attr_position =
|
||||
gst_gl_shader_get_attribute_location (self->shader, "a_position");
|
||||
self->attr_texture =
|
||||
gst_gl_shader_get_attribute_location (self->shader, "a_texcoord");
|
||||
|
||||
gl = gl_bi->gst_context->gl_vtable;
|
||||
|
||||
if (gl->GenVertexArrays) {
|
||||
gl->GenVertexArrays (1, &self->vao);
|
||||
gl->BindVertexArray (self->vao);
|
||||
}
|
||||
|
||||
gl->GenBuffers (1, &self->vertex_buffer);
|
||||
gl->BindBuffer (GL_ARRAY_BUFFER, self->vertex_buffer);
|
||||
gl->BufferData (GL_ARRAY_BUFFER, 4 * 5 * sizeof (GLfloat), vertices, GL_STATIC_DRAW);
|
||||
|
||||
if (gl->GenVertexArrays) {
|
||||
gst_clapper_dmabuf_base_import_bind_buffer (self);
|
||||
gl->BindVertexArray (0);
|
||||
}
|
||||
|
||||
gl->BindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
self->prepared = TRUE;
|
||||
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
gst_gl_context_activate (gl_bi->gst_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_prepared (GstClapperDmabufBaseImport *self)
|
||||
{
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_LOCK (self);
|
||||
|
||||
if (self->prepared) {
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (self->gst_tex_target != GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
|
||||
/* We do not need shaders if texture target is 2D */
|
||||
self->prepared = TRUE;
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_CLAPPER_DMABUF_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
if (!(! !gst_gtk_invoke_on_main (
|
||||
(GThreadFunc) (GCallback) prepare_on_main, self))) {
|
||||
GST_ERROR_OBJECT (self, "Could not ensure prepared");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_clapper_dmabuf_base_import_change_state (GstElement *element, GstStateChange transition)
|
||||
{
|
||||
GstClapperDmabufBaseImport *self = GST_CLAPPER_DMABUF_BASE_IMPORT_CAST (element);
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||
return ret;
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
if (!ensure_prepared (self))
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_dmabuf_into_texture (GstClapperDmabufBaseImport *self, gint *fds, GstVideoInfo *v_info,
|
||||
gsize *offsets, GstClapperDmabufTexData *tex_data)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (self);
|
||||
GstEGLImage *image;
|
||||
const GstGLFuncs *gl;
|
||||
|
||||
image = gst_egl_image_from_dmabuf_direct_target (gl_bi->gst_context,
|
||||
fds, offsets, v_info, self->gst_tex_target);
|
||||
|
||||
/* If HW colorspace conversion failed and there is only one
|
||||
* plane, we can just make it into single EGLImage as is */
|
||||
if (!image && GST_VIDEO_INFO_N_PLANES (v_info) == 1)
|
||||
image = gst_egl_image_from_dmabuf (gl_bi->gst_context,
|
||||
fds[0], v_info, 0, offsets[0]);
|
||||
|
||||
if (!image)
|
||||
return FALSE;
|
||||
|
||||
gl = gl_bi->gst_context->gl_vtable;
|
||||
|
||||
gl->GenTextures (1, &tex_data->id);
|
||||
tex_data->width = GST_VIDEO_INFO_WIDTH (v_info);
|
||||
tex_data->height = GST_VIDEO_INFO_HEIGHT (v_info);
|
||||
|
||||
gl->BindTexture (self->gl_tex_target, tex_data->id);
|
||||
|
||||
gl->TexParameteri (self->gl_tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
gl->TexParameteri (self->gl_tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
gl->TexParameteri (self->gl_tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
gl->TexParameteri (self->gl_tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
gl->EGLImageTargetTexture2D (self->gl_tex_target, gst_egl_image_get_image (image));
|
||||
|
||||
gl->BindTexture (GL_TEXTURE_2D, 0);
|
||||
gst_egl_image_unref (image);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_oes_texture_into_2d (GstClapperDmabufBaseImport *self, GstClapperDmabufTexData *tex_data)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (self);
|
||||
GLuint framebuffer, tex_id;
|
||||
GLenum status;
|
||||
const GstGLFuncs *gl;
|
||||
|
||||
gl = gl_bi->gst_context->gl_vtable;
|
||||
|
||||
gl->GenFramebuffers (1, &framebuffer);
|
||||
gl->BindFramebuffer (GL_FRAMEBUFFER, framebuffer);
|
||||
|
||||
gl->GenTextures (1, &tex_id);
|
||||
gl->BindTexture (GL_TEXTURE_2D, tex_id);
|
||||
|
||||
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, tex_data->width, tex_data->height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, tex_id, 0);
|
||||
|
||||
status = gl->CheckFramebufferStatus (GL_FRAMEBUFFER);
|
||||
if (G_UNLIKELY (status != GL_FRAMEBUFFER_COMPLETE)) {
|
||||
GST_ERROR ("Invalid framebuffer status: %u", status);
|
||||
|
||||
gl->BindTexture (GL_TEXTURE_2D, 0);
|
||||
gl->DeleteTextures (1, &tex_id);
|
||||
|
||||
gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
gl->DeleteFramebuffers (1, &framebuffer);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gl->Viewport (0, 0, tex_data->width, tex_data->height);
|
||||
|
||||
gst_gl_shader_use (self->shader);
|
||||
|
||||
if (gl->BindVertexArray)
|
||||
gl->BindVertexArray (self->vao);
|
||||
|
||||
gst_clapper_dmabuf_base_import_bind_buffer (self);
|
||||
|
||||
gl->ActiveTexture (GL_TEXTURE0);
|
||||
gl->BindTexture (self->gl_tex_target, tex_data->id);
|
||||
|
||||
gst_gl_shader_set_uniform_1i (self->shader, "tex", 0);
|
||||
gst_gl_shader_set_uniform_matrix_4fv (self->shader,
|
||||
"u_transformation", 1, FALSE, vertical_flip_matrix);
|
||||
|
||||
gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
if (gl->BindVertexArray)
|
||||
gl->BindVertexArray (0);
|
||||
else
|
||||
gst_clapper_dmabuf_base_import_unbind_buffer (self);
|
||||
|
||||
gl->BindTexture (self->gl_tex_target, 0);
|
||||
|
||||
/* Replace External OES texture with newly created 2D */
|
||||
gl->DeleteTextures (1, &tex_data->id);
|
||||
tex_data->id = tex_id;
|
||||
|
||||
gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
|
||||
gl->DeleteFramebuffers (1, &framebuffer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_tex_data_free (GstClapperDmabufTexData *tex_data)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (tex_data->dmabuf_bi);
|
||||
|
||||
if (G_LIKELY (tex_data->id > 0)) {
|
||||
const GstGLFuncs *gl;
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (gl_bi);
|
||||
|
||||
gl = gl_bi->gst_context->gl_vtable;
|
||||
|
||||
gdk_gl_context_make_current (gl_bi->gdk_context);
|
||||
gst_gl_context_activate (gl_bi->gst_context, TRUE);
|
||||
|
||||
gl->DeleteTextures (1, &tex_data->id);
|
||||
|
||||
gst_gl_context_activate (gl_bi->gst_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
}
|
||||
|
||||
gst_object_unref (tex_data->dmabuf_bi);
|
||||
g_slice_free (GstClapperDmabufTexData, tex_data);
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gst_clapper_dmabuf_base_import_fds_into_texture (GstClapperDmabufBaseImport *self, gint *fds, gsize *offsets)
|
||||
{
|
||||
GstClapperBaseImport *bi = GST_CLAPPER_BASE_IMPORT_CAST (self);
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (self);
|
||||
GdkTexture *texture = NULL;
|
||||
GstClapperDmabufTexData *tex_data;
|
||||
|
||||
tex_data = g_slice_new (GstClapperDmabufTexData);
|
||||
tex_data->dmabuf_bi = gst_object_ref (self);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (gl_bi);
|
||||
|
||||
gdk_gl_context_make_current (gl_bi->gdk_context);
|
||||
gst_gl_context_activate (gl_bi->gst_context, TRUE);
|
||||
|
||||
if (!_dmabuf_into_texture (self, fds, &bi->in_info, offsets, tex_data))
|
||||
goto finish;
|
||||
|
||||
/* GTK4 does not support External OES textures.
|
||||
* Make it into 2D using framebuffer + shader */
|
||||
if (self->gst_tex_target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) {
|
||||
if (G_UNLIKELY (!_oes_texture_into_2d (self, tex_data)))
|
||||
goto finish;
|
||||
}
|
||||
|
||||
texture = gdk_gl_texture_new (gl_bi->gdk_context,
|
||||
tex_data->id,
|
||||
tex_data->width,
|
||||
tex_data->height,
|
||||
(GDestroyNotify) _tex_data_free,
|
||||
tex_data);
|
||||
|
||||
finish:
|
||||
gst_gl_context_activate (gl_bi->gst_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_base_import_class_init (GstClapperDmabufBaseImportClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperdmabufbaseimport", 0,
|
||||
"Clapper DMABuf Base Import");
|
||||
|
||||
gobject_class->finalize = gst_clapper_dmabuf_base_import_finalize;
|
||||
|
||||
gstelement_class->change_state = gst_clapper_dmabuf_base_import_change_state;
|
||||
}
|
75
lib/gst/plugin/gstclapperdmabufbaseimport.h
vendored
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gl/gstglfuncs.h>
|
||||
|
||||
#include "gstclapperglbaseimport.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT (gst_clapper_dmabuf_base_import_get_type())
|
||||
#define GST_IS_CLAPPER_DMABUF_BASE_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT))
|
||||
#define GST_IS_CLAPPER_DMABUF_BASE_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT))
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT, GstClapperDmabufBaseImportClass))
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT, GstClapperDmabufBaseImport))
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT, GstClapperDmabufBaseImportClass))
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT_CAST(obj) ((GstClapperDmabufBaseImport *)(obj))
|
||||
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT_GET_LOCK(obj) (&GST_CLAPPER_DMABUF_BASE_IMPORT_CAST(obj)->lock)
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT_LOCK(obj) g_mutex_lock (GST_CLAPPER_DMABUF_BASE_IMPORT_GET_LOCK(obj))
|
||||
#define GST_CLAPPER_DMABUF_BASE_IMPORT_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_DMABUF_BASE_IMPORT_GET_LOCK(obj))
|
||||
|
||||
typedef struct _GstClapperDmabufBaseImport GstClapperDmabufBaseImport;
|
||||
typedef struct _GstClapperDmabufBaseImportClass GstClapperDmabufBaseImportClass;
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperDmabufBaseImport, gst_object_unref)
|
||||
#endif
|
||||
|
||||
struct _GstClapperDmabufBaseImport
|
||||
{
|
||||
GstClapperGLBaseImport parent;
|
||||
|
||||
GMutex lock;
|
||||
|
||||
gboolean prepared;
|
||||
|
||||
GstGLTextureTarget gst_tex_target;
|
||||
guint gl_tex_target;
|
||||
|
||||
GstGLShader *shader;
|
||||
|
||||
GLuint vao;
|
||||
GLuint vertex_buffer;
|
||||
GLint attr_position;
|
||||
GLint attr_texture;
|
||||
};
|
||||
|
||||
struct _GstClapperDmabufBaseImportClass
|
||||
{
|
||||
GstClapperGLBaseImportClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_clapper_dmabuf_base_import_get_type (void);
|
||||
|
||||
GdkTexture * gst_clapper_dmabuf_base_import_fds_into_texture (GstClapperDmabufBaseImport *dmabuf_bi, gint *fds, gsize *offsets);
|
||||
|
||||
G_END_DECLS
|
180
lib/gst/plugin/gstclapperdmabufimport.c
vendored
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
|
||||
#include "gstclapperdmabufimport.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_dmabuf_import_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
#ifndef GST_CAPS_FEATURE_MEMORY_DMABUF
|
||||
#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
|
||||
#endif
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_dmabuf_import_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS ", NV12 }")
|
||||
"; "
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF ", "
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS ", NV12 }")));
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_dmabuf_import_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS ", NV12 }")
|
||||
"; "
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY ", "
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS ", NV12 }")));
|
||||
|
||||
#define parent_class gst_clapper_dmabuf_import_parent_class
|
||||
G_DEFINE_TYPE (GstClapperDmabufImport, gst_clapper_dmabuf_import, GST_TYPE_CLAPPER_DMABUF_BASE_IMPORT);
|
||||
GST_ELEMENT_REGISTER_DEFINE (clapperdmabufimport, "clapperdmabufimport", GST_RANK_NONE,
|
||||
GST_TYPE_CLAPPER_DMABUF_IMPORT);
|
||||
|
||||
static gboolean
|
||||
verify_dmabuf_memory (GstBuffer *buffer, GstVideoInfo *info, gint *fds, gsize *offsets)
|
||||
{
|
||||
guint i, n_planes = GST_VIDEO_INFO_N_PLANES (info);
|
||||
|
||||
for (i = 0; i < n_planes; i++) {
|
||||
GstMemory *memory;
|
||||
gsize plane_size, mem_skip;
|
||||
guint mem_idx, length;
|
||||
|
||||
plane_size = gst_gl_get_plane_data_size (info, NULL, i);
|
||||
|
||||
if (!gst_buffer_find_memory (buffer,
|
||||
GST_VIDEO_INFO_PLANE_OFFSET (info, i),
|
||||
plane_size, &mem_idx, &length, &mem_skip)) {
|
||||
GST_DEBUG ("Could not find memory %u", i);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* We cannot have more then one DMABuf per plane */
|
||||
if (length != 1) {
|
||||
GST_DEBUG ("Data for plane %u spans %u memories", i, length);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memory = gst_buffer_peek_memory (buffer, mem_idx);
|
||||
|
||||
offsets[i] = memory->offset + mem_skip;
|
||||
fds[i] = gst_dmabuf_memory_get_fd (memory);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstBufferPool *
|
||||
gst_clapper_dmabuf_import_create_upstream_pool (GstClapperBaseImport *bi, GstStructure **config)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_dmabuf_import_transform (GstBaseTransform *bt,
|
||||
GstBuffer *in_buf, GstBuffer *out_buf)
|
||||
{
|
||||
GstClapperDmabufBaseImport *dmabuf_bi = GST_CLAPPER_DMABUF_BASE_IMPORT_CAST (bt);
|
||||
GstClapperBaseImport *bi = GST_CLAPPER_BASE_IMPORT_CAST (bt);
|
||||
GstMapInfo info;
|
||||
GstMemory *memory;
|
||||
GstVideoMeta *meta;
|
||||
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||
|
||||
GST_LOG_OBJECT (bt, "Transforming from %" GST_PTR_FORMAT
|
||||
" into %" GST_PTR_FORMAT, in_buf, out_buf);
|
||||
|
||||
if ((meta = gst_buffer_get_video_meta (in_buf))) {
|
||||
guint i;
|
||||
|
||||
GST_VIDEO_INFO_WIDTH (&bi->in_info) = meta->width;
|
||||
GST_VIDEO_INFO_HEIGHT (&bi->in_info) = meta->height;
|
||||
|
||||
for (i = 0; i < meta->n_planes; i++) {
|
||||
GST_VIDEO_INFO_PLANE_OFFSET (&bi->in_info, i) = meta->offset[i];
|
||||
GST_VIDEO_INFO_PLANE_STRIDE (&bi->in_info, i) = meta->stride[i];
|
||||
}
|
||||
}
|
||||
|
||||
memory = gst_buffer_peek_memory (out_buf, 0);
|
||||
|
||||
if (G_LIKELY (gst_memory_map (memory, &info, GST_MAP_WRITE))) {
|
||||
gint fds[GST_VIDEO_MAX_PLANES];
|
||||
gsize offsets[GST_VIDEO_MAX_PLANES];
|
||||
|
||||
if (verify_dmabuf_memory (in_buf, &bi->in_info, fds, offsets)) {
|
||||
GstClapperGdkMemory *clapper_memory = GST_CLAPPER_GDK_MEMORY_CAST (memory);
|
||||
|
||||
if (G_LIKELY ((clapper_memory->texture = gst_clapper_dmabuf_base_import_fds_into_texture (
|
||||
dmabuf_bi, fds, offsets))))
|
||||
ret = GST_FLOW_OK;
|
||||
}
|
||||
|
||||
gst_memory_unmap (memory, &info);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_import_init (GstClapperDmabufImport *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_dmabuf_import_class_init (GstClapperDmabufImportClass *klass)
|
||||
{
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GstBaseTransformClass *gstbasetransform_class = (GstBaseTransformClass *) klass;
|
||||
GstClapperBaseImportClass *bi_class = (GstClapperBaseImportClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperdmabufimport", 0,
|
||||
"Clapper DMABuf Import");
|
||||
|
||||
gstbasetransform_class->transform = gst_clapper_dmabuf_import_transform;
|
||||
|
||||
bi_class->create_upstream_pool = gst_clapper_dmabuf_import_create_upstream_pool;
|
||||
|
||||
gst_element_class_set_metadata (gstelement_class,
|
||||
"Clapper DMABuf import",
|
||||
"Filter/Video", "Imports DMABuf into ClapperGdkMemory",
|
||||
"Rafał Dzięgiel <rafostar.github@gmail.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_dmabuf_import_sink_template);
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_dmabuf_import_src_template);
|
||||
}
|
38
lib/gst/plugin/gstclapperdmabufimport.h
vendored
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gstclapperdmabufbaseimport.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_DMABUF_IMPORT (gst_clapper_dmabuf_import_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperDmabufImport, gst_clapper_dmabuf_import, GST, CLAPPER_DMABUF_IMPORT, GstClapperDmabufBaseImport)
|
||||
|
||||
#define GST_CLAPPER_DMABUF_IMPORT_CAST(obj) ((GstClapperDmabufImport *)(obj))
|
||||
|
||||
struct _GstClapperDmabufImport
|
||||
{
|
||||
GstClapperDmabufBaseImport parent;
|
||||
};
|
||||
|
||||
GST_ELEMENT_REGISTER_DECLARE (clapperdmabufimport);
|
||||
|
||||
G_END_DECLS
|
173
lib/gst/plugin/gstclappergdkbufferpool.c
vendored
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclappergdkbufferpool.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_gdk_buffer_pool_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
#define parent_class gst_clapper_gdk_buffer_pool_parent_class
|
||||
G_DEFINE_TYPE (GstClapperGdkBufferPool, gst_clapper_gdk_buffer_pool, GST_TYPE_BUFFER_POOL);
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_buffer_pool_init (GstClapperGdkBufferPool *pool)
|
||||
{
|
||||
}
|
||||
|
||||
static const gchar **
|
||||
gst_clapper_gdk_buffer_pool_get_options (GstBufferPool *pool)
|
||||
{
|
||||
static const gchar *options[] = {
|
||||
GST_BUFFER_POOL_OPTION_VIDEO_META,
|
||||
NULL
|
||||
};
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_gdk_buffer_pool_set_config (GstBufferPool *pool, GstStructure *config)
|
||||
{
|
||||
GstClapperGdkBufferPool *self = GST_CLAPPER_GDK_BUFFER_POOL_CAST (pool);
|
||||
GstCaps *caps = NULL;
|
||||
guint size, min_buffers, max_buffers;
|
||||
GstVideoInfo info;
|
||||
GstClapperGdkMemory *clapper_mem;
|
||||
|
||||
if (!gst_buffer_pool_config_get_params (config, &caps, &size,
|
||||
&min_buffers, &max_buffers)) {
|
||||
GST_WARNING_OBJECT (self, "Invalid buffer pool config");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!caps || !gst_video_info_from_caps (&info, caps)) {
|
||||
GST_WARNING_OBJECT (pool, "Could not parse caps into video info");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_clear_object (&self->allocator);
|
||||
self->allocator = GST_CLAPPER_GDK_ALLOCATOR_CAST (
|
||||
gst_allocator_find (GST_CLAPPER_GDK_MEMORY_TYPE_NAME));
|
||||
|
||||
if (G_UNLIKELY (!self->allocator)) {
|
||||
GST_ERROR_OBJECT (self, "ClapperGdkAllocator is unavailable");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clapper_mem = GST_CLAPPER_GDK_MEMORY_CAST (
|
||||
gst_clapper_gdk_allocator_alloc (self->allocator, &info));
|
||||
if (G_UNLIKELY (!clapper_mem)) {
|
||||
GST_ERROR_OBJECT (self, "Cannot create ClapperGdkMemory");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_buffer_pool_config_set_params (config, caps,
|
||||
GST_VIDEO_INFO_SIZE (&clapper_mem->info), min_buffers, max_buffers);
|
||||
gst_memory_unref (GST_MEMORY_CAST (clapper_mem));
|
||||
|
||||
self->info = info;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Set buffer pool config: %" GST_PTR_FORMAT, config);
|
||||
|
||||
return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_gdk_buffer_pool_alloc (GstBufferPool *pool, GstBuffer **buffer,
|
||||
GstBufferPoolAcquireParams *params)
|
||||
{
|
||||
GstClapperGdkBufferPool *self = GST_CLAPPER_GDK_BUFFER_POOL_CAST (pool);
|
||||
GstMemory *mem;
|
||||
GstClapperGdkMemory *clapper_mem;
|
||||
|
||||
mem = gst_clapper_gdk_allocator_alloc (self->allocator, &self->info);
|
||||
if (G_UNLIKELY (!mem)) {
|
||||
GST_ERROR_OBJECT (self, "Cannot create ClapperGdkMemory");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
clapper_mem = GST_CLAPPER_GDK_MEMORY_CAST (mem);
|
||||
|
||||
*buffer = gst_buffer_new ();
|
||||
gst_buffer_append_memory (*buffer, mem);
|
||||
|
||||
gst_buffer_add_video_meta_full (*buffer, GST_VIDEO_FRAME_FLAG_NONE,
|
||||
GST_VIDEO_INFO_FORMAT (&self->info), GST_VIDEO_INFO_WIDTH (&self->info),
|
||||
GST_VIDEO_INFO_HEIGHT (&self->info), GST_VIDEO_INFO_N_PLANES (&self->info),
|
||||
clapper_mem->info.offset, clapper_mem->info.stride);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Allocated %" GST_PTR_FORMAT, *buffer);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_buffer_reset_buffer (GstBufferPool *pool, GstBuffer *buffer)
|
||||
{
|
||||
GstClapperGdkMemory *clapper_mem;
|
||||
|
||||
GST_TRACE ("Reset %" GST_PTR_FORMAT, buffer);
|
||||
|
||||
clapper_mem = GST_CLAPPER_GDK_MEMORY_CAST (gst_buffer_peek_memory (buffer, 0));
|
||||
g_clear_object (&clapper_mem->texture);
|
||||
|
||||
return GST_BUFFER_POOL_CLASS (parent_class)->reset_buffer (pool, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_buffer_pool_dispose (GObject *object)
|
||||
{
|
||||
GstClapperGdkBufferPool *self = GST_CLAPPER_GDK_BUFFER_POOL_CAST (object);
|
||||
|
||||
gst_clear_object (&self->allocator);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_buffer_pool_class_init (GstClapperGdkBufferPoolClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstBufferPoolClass *bufferpool_class = (GstBufferPoolClass *) klass;
|
||||
|
||||
gobject_class->dispose = gst_clapper_gdk_buffer_pool_dispose;
|
||||
|
||||
bufferpool_class->get_options = gst_clapper_gdk_buffer_pool_get_options;
|
||||
bufferpool_class->set_config = gst_clapper_gdk_buffer_pool_set_config;
|
||||
bufferpool_class->alloc_buffer = gst_clapper_gdk_buffer_pool_alloc;
|
||||
bufferpool_class->reset_buffer = gst_clapper_gdk_buffer_reset_buffer;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergdkbufferpool", 0,
|
||||
"Clapper Gdk Buffer Pool");
|
||||
}
|
||||
|
||||
GstBufferPool *
|
||||
gst_clapper_gdk_buffer_pool_new (void)
|
||||
{
|
||||
GstClapperGdkBufferPool *self;
|
||||
|
||||
self = g_object_new (GST_TYPE_CLAPPER_GDK_BUFFER_POOL, NULL);
|
||||
gst_object_ref_sink (self);
|
||||
|
||||
return GST_BUFFER_POOL_CAST (self);
|
||||
}
|
44
lib/gst/plugin/gstclappergdkbufferpool.h
vendored
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gstbufferpool.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include "gstclappergdkmemory.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_GDK_BUFFER_POOL (gst_clapper_gdk_buffer_pool_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperGdkBufferPool, gst_clapper_gdk_buffer_pool, GST, CLAPPER_GDK_BUFFER_POOL, GstBufferPool)
|
||||
|
||||
#define GST_CLAPPER_GDK_BUFFER_POOL_CAST(obj) ((GstClapperGdkBufferPool *)(obj))
|
||||
|
||||
struct _GstClapperGdkBufferPool
|
||||
{
|
||||
GstBufferPool parent;
|
||||
|
||||
GstClapperGdkAllocator *allocator;
|
||||
GstVideoInfo info;
|
||||
};
|
||||
|
||||
GstBufferPool * gst_clapper_gdk_buffer_pool_new (void);
|
||||
|
||||
G_END_DECLS
|
141
lib/gst/plugin/gstclappergdkmemory.c
vendored
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclappergdkmemory.h"
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_gdk_allocator_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
static GstAllocator *_gst_clapper_gdk_allocator = NULL;
|
||||
|
||||
#define parent_class gst_clapper_gdk_allocator_parent_class
|
||||
G_DEFINE_TYPE (GstClapperGdkAllocator, gst_clapper_gdk_allocator, GST_TYPE_ALLOCATOR);
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_allocator_free (GstAllocator *self, GstMemory *memory)
|
||||
{
|
||||
GstClapperGdkMemory *mem = GST_CLAPPER_GDK_MEMORY_CAST (memory);
|
||||
|
||||
GST_TRACE_OBJECT (self, "Freeing ClapperGdkMemory: %" GST_PTR_FORMAT, mem);
|
||||
|
||||
g_clear_object (&mem->texture);
|
||||
g_free (mem);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gst_clapper_gdk_mem_map_full (GstMemory *memory, GstMapInfo *info, gsize maxsize)
|
||||
{
|
||||
GstClapperGdkMemory *mem = GST_CLAPPER_GDK_MEMORY_CAST (memory);
|
||||
|
||||
return &mem->texture;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_mem_unmap_full (GstMemory *memory, GstMapInfo *info)
|
||||
{
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
gst_clapper_gdk_mem_copy (GstMemory *memory, gssize offset, gssize size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
gst_clapper_gdk_mem_share (GstMemory *memory, gssize offset, gssize size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_gdk_mem_is_span (GstMemory *mem1, GstMemory *mem2, gsize *offset)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_allocator_init (GstClapperGdkAllocator *self)
|
||||
{
|
||||
GstAllocator *alloc = GST_ALLOCATOR_CAST (self);
|
||||
|
||||
alloc->mem_type = GST_CLAPPER_GDK_MEMORY_TYPE_NAME;
|
||||
alloc->mem_map_full = gst_clapper_gdk_mem_map_full;
|
||||
alloc->mem_unmap_full = gst_clapper_gdk_mem_unmap_full;
|
||||
alloc->mem_copy = gst_clapper_gdk_mem_copy;
|
||||
alloc->mem_share = gst_clapper_gdk_mem_share;
|
||||
alloc->mem_is_span = gst_clapper_gdk_mem_is_span;
|
||||
|
||||
GST_OBJECT_FLAG_SET (self, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_allocator_class_init (GstClapperGdkAllocatorClass *klass)
|
||||
{
|
||||
GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
|
||||
|
||||
allocator_class->alloc = NULL;
|
||||
allocator_class->free = GST_DEBUG_FUNCPTR (gst_clapper_gdk_allocator_free);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergdkallocator", 0,
|
||||
"Clapper Gdk Allocator");
|
||||
}
|
||||
|
||||
void
|
||||
gst_clapper_gdk_memory_init_once (void)
|
||||
{
|
||||
static gsize _alloc_init = 0;
|
||||
|
||||
if (g_once_init_enter (&_alloc_init)) {
|
||||
_gst_clapper_gdk_allocator = GST_ALLOCATOR_CAST (
|
||||
g_object_new (GST_TYPE_CLAPPER_GDK_ALLOCATOR, NULL));
|
||||
gst_object_ref_sink (_gst_clapper_gdk_allocator);
|
||||
|
||||
gst_allocator_register (GST_CLAPPER_GDK_MEMORY_TYPE_NAME, _gst_clapper_gdk_allocator);
|
||||
g_once_init_leave (&_alloc_init, 1);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_is_clapper_gdk_memory (GstMemory *memory)
|
||||
{
|
||||
return (memory != NULL && memory->allocator != NULL
|
||||
&& GST_IS_CLAPPER_GDK_ALLOCATOR (memory->allocator));
|
||||
}
|
||||
|
||||
GstMemory *
|
||||
gst_clapper_gdk_allocator_alloc (GstClapperGdkAllocator *self, const GstVideoInfo *info)
|
||||
{
|
||||
GstClapperGdkMemory *mem;
|
||||
|
||||
mem = g_new0 (GstClapperGdkMemory, 1);
|
||||
mem->info = *info;
|
||||
|
||||
gst_memory_init (GST_MEMORY_CAST (mem), 0, GST_ALLOCATOR_CAST (self),
|
||||
NULL, GST_VIDEO_INFO_SIZE (info), 0, 0, GST_VIDEO_INFO_SIZE (info));
|
||||
|
||||
GST_TRACE_OBJECT (self, "Allocated new ClapperGdkMemory: %" GST_PTR_FORMAT, mem);
|
||||
|
||||
return GST_MEMORY_CAST (mem);
|
||||
}
|
67
lib/gst/plugin/gstclappergdkmemory.h
vendored
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/gstmemory.h>
|
||||
#include <gst/gstallocator.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_GDK_ALLOCATOR (gst_clapper_gdk_allocator_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperGdkAllocator, gst_clapper_gdk_allocator, GST, CLAPPER_GDK_ALLOCATOR, GstAllocator)
|
||||
|
||||
#define GST_CLAPPER_GDK_ALLOCATOR_CAST(obj) ((GstClapperGdkAllocator *)(obj))
|
||||
#define GST_CLAPPER_GDK_MEMORY_CAST(mem) ((GstClapperGdkMemory *)(mem))
|
||||
|
||||
#define GST_CLAPPER_GDK_MEMORY_TYPE_NAME "gst.clapper.gdk.memory"
|
||||
|
||||
#define GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY "memory:ClapperGdkMemory"
|
||||
|
||||
#define GST_CLAPPER_GDK_MEMORY_FORMATS \
|
||||
"RGBA64_LE, RGBA64_BE, ABGR, BGRA, " \
|
||||
"ARGB, RGBA, BGRx, RGBx, BGR, RGB" \
|
||||
|
||||
/* Formats that `GdkGLTexture` supports */
|
||||
#define GST_CLAPPER_GDK_GL_TEXTURE_FORMATS \
|
||||
"RGBA64_LE, RGBA64_BE, RGBA, RGBx, RGB" \
|
||||
|
||||
typedef struct _GstClapperGdkMemory GstClapperGdkMemory;
|
||||
struct _GstClapperGdkMemory
|
||||
{
|
||||
GstMemory mem;
|
||||
|
||||
GdkTexture *texture;
|
||||
GstVideoInfo info;
|
||||
};
|
||||
|
||||
struct _GstClapperGdkAllocator
|
||||
{
|
||||
GstAllocator parent;
|
||||
};
|
||||
|
||||
void gst_clapper_gdk_memory_init_once (void);
|
||||
|
||||
gboolean gst_is_clapper_gdk_memory (GstMemory *memory);
|
||||
|
||||
GstMemory * gst_clapper_gdk_allocator_alloc (GstClapperGdkAllocator *allocator, const GstVideoInfo *info);
|
||||
|
||||
G_END_DECLS
|
414
lib/gst/plugin/gstclapperglbaseimport.c
vendored
@@ -1,414 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/gl/gstglfuncs.h>
|
||||
|
||||
#include "gstclapperglbaseimport.h"
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
#if GST_CLAPPER_GL_HAVE_WAYLAND
|
||||
#include <gdk/wayland/gdkwayland.h>
|
||||
#include <gst/gl/wayland/gstgldisplay_wayland.h>
|
||||
#endif
|
||||
|
||||
#if GST_CLAPPER_GL_HAVE_X11
|
||||
#include <gdk/x11/gdkx.h>
|
||||
#endif
|
||||
|
||||
#if GST_CLAPPER_GL_HAVE_X11_GLX
|
||||
#include <gst/gl/x11/gstgldisplay_x11.h>
|
||||
#endif
|
||||
#if GST_CLAPPER_GL_HAVE_X11_EGL
|
||||
#include <gst/gl/egl/gstgldisplay_egl.h>
|
||||
#endif
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_gl_base_import_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
#define parent_class gst_clapper_gl_base_import_parent_class
|
||||
G_DEFINE_TYPE (GstClapperGLBaseImport, gst_clapper_gl_base_import, GST_TYPE_CLAPPER_BASE_IMPORT);
|
||||
|
||||
static void
|
||||
gst_clapper_gl_base_import_init (GstClapperGLBaseImport *self)
|
||||
{
|
||||
g_mutex_init (&self->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gl_base_import_finalize (GObject *object)
|
||||
{
|
||||
GstClapperGLBaseImport *self = GST_CLAPPER_GL_BASE_IMPORT_CAST (object);
|
||||
|
||||
g_clear_object (&self->gdk_context);
|
||||
gst_clear_object (&self->gst_context);
|
||||
gst_clear_object (&self->wrapped_context);
|
||||
gst_clear_object (&self->gst_display);
|
||||
|
||||
g_mutex_clear (&self->lock);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
||||
}
|
||||
|
||||
static GstGLContext *
|
||||
wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platform)
|
||||
{
|
||||
GstGLAPI gst_gl_api = GST_GL_API_NONE;
|
||||
|
||||
switch (gdk_gl_api) {
|
||||
case GDK_GL_API_GL:
|
||||
gst_gl_api = GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
|
||||
break;
|
||||
case GDK_GL_API_GLES:
|
||||
gst_gl_api = GST_GL_API_GLES2;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (gst_gl_api != GST_GL_API_NONE) {
|
||||
guintptr gl_handle;
|
||||
|
||||
gst_gl_display_filter_gl_api (display, gst_gl_api);
|
||||
|
||||
if ((gl_handle = gst_gl_context_get_current_gl_context (platform)))
|
||||
return gst_gl_context_new_wrapped (display, gl_handle, platform, gst_gl_api);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
retrieve_gl_context_on_main (GstClapperGLBaseImport *self)
|
||||
{
|
||||
GstClapperGLBaseImportClass *gl_bi_class = GST_CLAPPER_GL_BASE_IMPORT_GET_CLASS (self);
|
||||
GdkDisplay *gdk_display;
|
||||
GdkGLContext *gdk_context;
|
||||
GError *error = NULL;
|
||||
GdkGLAPI gdk_gl_api;
|
||||
GstGLPlatform platform = GST_GL_PLATFORM_NONE;
|
||||
gint gl_major = 0, gl_minor = 0;
|
||||
|
||||
if (!gtk_init_check ()) {
|
||||
GST_ERROR_OBJECT (self, "Could not ensure GTK initialization");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_display = gdk_display_get_default ();
|
||||
|
||||
if (!(gdk_context = gdk_display_create_gl_context (gdk_display, &error))) {
|
||||
GST_ERROR_OBJECT (self, "Error creating Gdk GL context: %s",
|
||||
error ? error->message : "No error set by Gdk");
|
||||
g_clear_error (&error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gl_bi_class->gdk_context_realize (self, gdk_context)) {
|
||||
GST_ERROR_OBJECT (self, "Could not realize Gdk context: %" GST_PTR_FORMAT,
|
||||
gdk_context);
|
||||
g_object_unref (gdk_context);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
gdk_gl_api = gdk_gl_context_get_api (gdk_context);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (self);
|
||||
|
||||
self->gdk_context = gdk_context;
|
||||
|
||||
#if GST_CLAPPER_GL_HAVE_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
|
||||
struct wl_display *wayland_display =
|
||||
gdk_wayland_display_get_wl_display (gdk_display);
|
||||
self->gst_display = (GstGLDisplay *)
|
||||
gst_gl_display_wayland_new_with_display (wayland_display);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GST_CLAPPER_GL_HAVE_X11
|
||||
if (GDK_IS_X11_DISPLAY (gdk_display)) {
|
||||
gpointer display_ptr;
|
||||
#if GST_CLAPPER_GL_HAVE_X11_EGL
|
||||
display_ptr = gdk_x11_display_get_egl_display (gdk_display);
|
||||
if (display_ptr) {
|
||||
self->gst_display = (GstGLDisplay *)
|
||||
gst_gl_display_egl_new_with_egl_display (display_ptr);
|
||||
}
|
||||
#endif
|
||||
#if GST_CLAPPER_GL_HAVE_X11_GLX
|
||||
if (!self->gst_display) {
|
||||
display_ptr = gdk_x11_display_get_xdisplay (gdk_display);
|
||||
self->gst_display = (GstGLDisplay *)
|
||||
gst_gl_display_x11_new_with_display (display_ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Fallback to generic display */
|
||||
if (G_UNLIKELY (!self->gst_display)) {
|
||||
GST_WARNING_OBJECT (self, "Unknown Gdk display!");
|
||||
self->gst_display = gst_gl_display_new ();
|
||||
}
|
||||
|
||||
#if GST_CLAPPER_GL_HAVE_WAYLAND
|
||||
if (GST_IS_GL_DISPLAY_WAYLAND (self->gst_display)) {
|
||||
platform = GST_GL_PLATFORM_EGL;
|
||||
GST_INFO_OBJECT (self, "Using EGL on Wayland");
|
||||
goto have_display;
|
||||
}
|
||||
#endif
|
||||
#if GST_CLAPPER_GL_HAVE_X11_EGL
|
||||
if (GST_IS_GL_DISPLAY_EGL (self->gst_display)) {
|
||||
platform = GST_GL_PLATFORM_EGL;
|
||||
GST_INFO_OBJECT (self, "Using EGL on x11");
|
||||
goto have_display;
|
||||
}
|
||||
#endif
|
||||
#if GST_CLAPPER_GL_HAVE_X11_GLX
|
||||
if (GST_IS_GL_DISPLAY_X11 (self->gst_display)) {
|
||||
platform = GST_GL_PLATFORM_GLX;
|
||||
GST_INFO_OBJECT (self, "Using GLX on x11");
|
||||
goto have_display;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_clear_object (&self->gdk_context);
|
||||
gst_clear_object (&self->gst_display);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
GST_ERROR_OBJECT (self, "Unsupported GL platform");
|
||||
return FALSE;
|
||||
|
||||
have_display:
|
||||
gdk_gl_context_make_current (self->gdk_context);
|
||||
|
||||
self->wrapped_context = wrap_current_gl (self->gst_display, gdk_gl_api, platform);
|
||||
if (!self->wrapped_context) {
|
||||
GST_ERROR ("Could not retrieve Gdk OpenGL context");
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
g_clear_object (&self->gdk_context);
|
||||
gst_clear_object (&self->gst_display);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, self->wrapped_context);
|
||||
gst_gl_context_activate (self->wrapped_context, TRUE);
|
||||
|
||||
if (!gst_gl_context_fill_info (self->wrapped_context, &error)) {
|
||||
GST_ERROR ("Failed to fill Gdk context info: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
|
||||
gst_gl_context_activate (self->wrapped_context, FALSE);
|
||||
|
||||
gst_clear_object (&self->wrapped_context);
|
||||
g_clear_object (&self->gdk_context);
|
||||
gst_clear_object (&self->gst_display);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_gl_context_get_gl_version (self->wrapped_context, &gl_major, &gl_minor);
|
||||
GST_INFO ("Using OpenGL%s %i.%i", (gdk_gl_api == GDK_GL_API_GLES) ? " ES" : "",
|
||||
gl_major, gl_minor);
|
||||
|
||||
/* Deactivate in both places */
|
||||
gst_gl_context_activate (self->wrapped_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_gl_context (GstClapperGLBaseImport *self)
|
||||
{
|
||||
GstGLDisplay *gst_display = NULL;
|
||||
GstGLContext *gst_context = NULL;
|
||||
GError *error = NULL;
|
||||
gboolean has_gdk_contexts;
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (self);
|
||||
has_gdk_contexts = (self->gdk_context && self->wrapped_context);
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
if (!has_gdk_contexts) {
|
||||
if (!(! !gst_gtk_invoke_on_main (
|
||||
(GThreadFunc) (GCallback) retrieve_gl_context_on_main, self))) {
|
||||
GST_ERROR_OBJECT (self, "Could not retrieve Gdk GL context");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (self);
|
||||
|
||||
gst_display = gst_object_ref (self->gst_display);
|
||||
|
||||
/* GstGLDisplay operations require object lock to be held */
|
||||
GST_OBJECT_LOCK (gst_display);
|
||||
|
||||
if (!self->gst_context) {
|
||||
GST_TRACE_OBJECT (self, "Creating new GstGLContext");
|
||||
|
||||
if (!gst_gl_display_create_context (gst_display, self->wrapped_context,
|
||||
&self->gst_context, &error)) {
|
||||
GST_WARNING ("Could not create OpenGL context: %s",
|
||||
error ? error->message : "Unknown");
|
||||
g_clear_error (&error);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_context = gst_object_ref (self->gst_context);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
/* Calls `set_context` internally, so we cannot be locked here */
|
||||
gst_gl_display_add_context (gst_display, gst_context);
|
||||
gst_gl_element_propagate_display_context (GST_ELEMENT_CAST (self), gst_display);
|
||||
|
||||
GST_OBJECT_UNLOCK (gst_display);
|
||||
|
||||
gst_object_unref (gst_display);
|
||||
gst_object_unref (gst_context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gl_base_import_set_context (GstElement *element, GstContext *context)
|
||||
{
|
||||
GstClapperGLBaseImport *self = GST_CLAPPER_GL_BASE_IMPORT_CAST (element);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Set context");
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (self);
|
||||
gst_gl_handle_set_context (element, context, &self->gst_display,
|
||||
&self->wrapped_context);
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
|
||||
GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_clapper_gl_base_import_change_state (GstElement *element, GstStateChange transition)
|
||||
{
|
||||
GstClapperGLBaseImport *self = GST_CLAPPER_GL_BASE_IMPORT_CAST (element);
|
||||
GstStateChangeReturn ret;
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||
return ret;
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
if (!ensure_gl_context (self))
|
||||
return GST_STATE_CHANGE_FAILURE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_gl_base_import_query (GstBaseTransform *bt,
|
||||
GstPadDirection direction, GstQuery *query)
|
||||
{
|
||||
GstClapperGLBaseImport *self = GST_CLAPPER_GL_BASE_IMPORT_CAST (bt);
|
||||
gboolean res;
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_CONTEXT:
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (self);
|
||||
res = gst_gl_handle_context_query (GST_ELEMENT_CAST (self), query,
|
||||
self->gst_display, self->gst_context, self->wrapped_context);
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (self);
|
||||
break;
|
||||
default:
|
||||
res = GST_BASE_TRANSFORM_CLASS (parent_class)->query (bt, direction, query);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_gl_base_import_gdk_context_realize (GstClapperGLBaseImport *self, GdkGLContext *gdk_context)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean success;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Realizing GdkGLContext with default implementation");
|
||||
|
||||
gdk_gl_context_set_allowed_apis (gdk_context, GDK_GL_API_GLES);
|
||||
if (!(success = gdk_gl_context_realize (gdk_context, &error))) {
|
||||
GST_WARNING_OBJECT (self, "Could not realize Gdk context with GLES: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
if (!success) {
|
||||
gdk_gl_context_set_allowed_apis (gdk_context, GDK_GL_API_GL);
|
||||
if (!(success = gdk_gl_context_realize (gdk_context, &error))) {
|
||||
GST_WARNING_OBJECT (self, "Could not realize Gdk context with GL: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gl_base_import_class_init (GstClapperGLBaseImportClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GstBaseTransformClass *gstbasetransform_class = (GstBaseTransformClass *) klass;
|
||||
GstClapperGLBaseImportClass *gl_bi_class = (GstClapperGLBaseImportClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglbaseimport", 0,
|
||||
"Clapper GL Base Import");
|
||||
|
||||
gobject_class->finalize = gst_clapper_gl_base_import_finalize;
|
||||
|
||||
gstelement_class->set_context = gst_clapper_gl_base_import_set_context;
|
||||
gstelement_class->change_state = gst_clapper_gl_base_import_change_state;
|
||||
|
||||
gstbasetransform_class->query = gst_clapper_gl_base_import_query;
|
||||
|
||||
gl_bi_class->gdk_context_realize = gst_clapper_gl_base_import_gdk_context_realize;
|
||||
}
|
75
lib/gst/plugin/gstclapperglbaseimport.h
vendored
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gst/gl/gl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "gstclapperbaseimport.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_GL_BASE_IMPORT (gst_clapper_gl_base_import_get_type())
|
||||
#define GST_IS_CLAPPER_GL_BASE_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORT))
|
||||
#define GST_IS_CLAPPER_GL_BASE_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_GL_BASE_IMPORT))
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORT, GstClapperGLBaseImportClass))
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORT, GstClapperGLBaseImport))
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_GL_BASE_IMPORT, GstClapperGLBaseImportClass))
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT_CAST(obj) ((GstClapperGLBaseImport *)(obj))
|
||||
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT_GET_LOCK(obj) (&GST_CLAPPER_GL_BASE_IMPORT_CAST(obj)->lock)
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT_LOCK(obj) g_mutex_lock (GST_CLAPPER_GL_BASE_IMPORT_GET_LOCK(obj))
|
||||
#define GST_CLAPPER_GL_BASE_IMPORT_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_GL_BASE_IMPORT_GET_LOCK(obj))
|
||||
|
||||
#define GST_CLAPPER_GL_HAVE_WAYLAND (GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND))
|
||||
#define GST_CLAPPER_GL_HAVE_X11 (GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11))
|
||||
#define GST_CLAPPER_GL_HAVE_X11_GLX (GST_CLAPPER_GL_HAVE_X11 && GST_GL_HAVE_PLATFORM_GLX)
|
||||
#define GST_CLAPPER_GL_HAVE_X11_EGL (GST_CLAPPER_GL_HAVE_X11 && GST_GL_HAVE_PLATFORM_EGL)
|
||||
|
||||
typedef struct _GstClapperGLBaseImport GstClapperGLBaseImport;
|
||||
typedef struct _GstClapperGLBaseImportClass GstClapperGLBaseImportClass;
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperGLBaseImport, gst_object_unref)
|
||||
#endif
|
||||
|
||||
struct _GstClapperGLBaseImport
|
||||
{
|
||||
GstClapperBaseImport parent;
|
||||
|
||||
GMutex lock;
|
||||
|
||||
GdkGLContext *gdk_context;
|
||||
GstGLContext *gst_context;
|
||||
GstGLContext *wrapped_context;
|
||||
GstGLDisplay *gst_display;
|
||||
};
|
||||
|
||||
struct _GstClapperGLBaseImportClass
|
||||
{
|
||||
GstClapperBaseImportClass parent_class;
|
||||
|
||||
gboolean (* gdk_context_realize) (GstClapperGLBaseImport *gl_bi,
|
||||
GdkGLContext *gdk_context);
|
||||
};
|
||||
|
||||
GType gst_clapper_gl_base_import_get_type (void);
|
||||
|
||||
G_END_DECLS
|
178
lib/gst/plugin/gstclapperglimport.c
vendored
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapperglimport.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_gl_import_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_gl_import_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS " }") ", "
|
||||
"texture-target = (string) { " GST_GL_TEXTURE_TARGET_2D_STR " }"
|
||||
"; "
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY ", "
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS " }") ", "
|
||||
"texture-target = (string) { " GST_GL_TEXTURE_TARGET_2D_STR " }"));
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_gl_import_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS " }")
|
||||
"; "
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY ", "
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
|
||||
"{ " GST_CLAPPER_GDK_GL_TEXTURE_FORMATS " }")));
|
||||
|
||||
#define parent_class gst_clapper_gl_import_parent_class
|
||||
G_DEFINE_TYPE (GstClapperGLImport, gst_clapper_gl_import, GST_TYPE_CLAPPER_GL_BASE_IMPORT);
|
||||
GST_ELEMENT_REGISTER_DEFINE (clapperglimport, "clapperglimport", GST_RANK_NONE,
|
||||
GST_TYPE_CLAPPER_GL_IMPORT);
|
||||
|
||||
static GstBufferPool *
|
||||
gst_clapper_gl_import_create_upstream_pool (GstClapperBaseImport *bi, GstStructure **config)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (bi);
|
||||
GstBufferPool *pool;
|
||||
GstGLContext *context;
|
||||
|
||||
GST_DEBUG_OBJECT (bi, "Creating new pool");
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (gl_bi);
|
||||
context = gst_object_ref (gl_bi->gst_context);
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
|
||||
pool = gst_gl_buffer_pool_new (context);
|
||||
gst_object_unref (context);
|
||||
|
||||
*config = gst_buffer_pool_get_config (pool);
|
||||
|
||||
gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_GL_SYNC_META);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void
|
||||
video_frame_unmap_and_free (GstVideoFrame *frame)
|
||||
{
|
||||
gst_video_frame_unmap (frame);
|
||||
g_slice_free (GstVideoFrame, frame);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_gl_import_transform (GstBaseTransform *bt,
|
||||
GstBuffer *in_buf, GstBuffer *out_buf)
|
||||
{
|
||||
GstClapperGLBaseImport *gl_bi = GST_CLAPPER_GL_BASE_IMPORT_CAST (bt);
|
||||
GstClapperBaseImport *bi = GST_CLAPPER_BASE_IMPORT_CAST (bt);
|
||||
GstVideoFrame *frame;
|
||||
GstMapInfo info;
|
||||
GstMemory *memory;
|
||||
GstClapperGdkMemory *clapper_memory;
|
||||
GstGLSyncMeta *sync_meta;
|
||||
|
||||
frame = g_slice_new (GstVideoFrame);
|
||||
|
||||
if (!gst_clapper_base_import_map_buffers (bi, in_buf, out_buf,
|
||||
GST_MAP_READ | GST_MAP_GL, GST_MAP_WRITE, frame, &info, &memory)) {
|
||||
g_slice_free (GstVideoFrame, frame);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
clapper_memory = GST_CLAPPER_GDK_MEMORY_CAST (memory);
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_LOCK (gl_bi);
|
||||
|
||||
/* Must have context active here for both sync meta
|
||||
* and Gdk texture format auto-detection to work */
|
||||
gdk_gl_context_make_current (gl_bi->gdk_context);
|
||||
gst_gl_context_activate (gl_bi->wrapped_context, TRUE);
|
||||
|
||||
sync_meta = gst_buffer_get_gl_sync_meta (in_buf);
|
||||
|
||||
/* Wait for all previous OpenGL commands to complete,
|
||||
* before we start using the input texture */
|
||||
if (sync_meta) {
|
||||
gst_gl_sync_meta_set_sync_point (sync_meta, gl_bi->gst_context);
|
||||
gst_gl_sync_meta_wait (sync_meta, gl_bi->wrapped_context);
|
||||
}
|
||||
|
||||
/* Keep input data alive as long as necessary,
|
||||
* unmap only after texture is destroyed */
|
||||
clapper_memory->texture = gdk_gl_texture_new (
|
||||
gl_bi->gdk_context,
|
||||
*(guint *) GST_VIDEO_FRAME_PLANE_DATA (frame, 0),
|
||||
GST_VIDEO_FRAME_WIDTH (frame),
|
||||
GST_VIDEO_FRAME_HEIGHT (frame),
|
||||
(GDestroyNotify) video_frame_unmap_and_free,
|
||||
frame);
|
||||
|
||||
gst_gl_context_activate (gl_bi->wrapped_context, FALSE);
|
||||
gdk_gl_context_clear_current ();
|
||||
|
||||
GST_CLAPPER_GL_BASE_IMPORT_UNLOCK (gl_bi);
|
||||
|
||||
gst_memory_unmap (memory, &info);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gl_import_init (GstClapperGLImport *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_gl_import_class_init (GstClapperGLImportClass *klass)
|
||||
{
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GstBaseTransformClass *gstbasetransform_class = (GstBaseTransformClass *) klass;
|
||||
GstClapperBaseImportClass *bi_class = (GstClapperBaseImportClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglimport", 0,
|
||||
"Clapper GL Import");
|
||||
|
||||
gstbasetransform_class->transform = gst_clapper_gl_import_transform;
|
||||
|
||||
bi_class->create_upstream_pool = gst_clapper_gl_import_create_upstream_pool;
|
||||
|
||||
gst_element_class_set_metadata (gstelement_class,
|
||||
"Clapper GL import",
|
||||
"Filter/Video", "Imports GL memory into ClapperGdkMemory",
|
||||
"Rafał Dzięgiel <rafostar.github@gmail.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_gl_import_sink_template);
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_gl_import_src_template);
|
||||
}
|
38
lib/gst/plugin/gstclapperglimport.h
vendored
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gstclapperglbaseimport.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_GL_IMPORT (gst_clapper_gl_import_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperGLImport, gst_clapper_gl_import, GST, CLAPPER_GL_IMPORT, GstClapperGLBaseImport)
|
||||
|
||||
#define GST_CLAPPER_GL_IMPORT_CAST(obj) ((GstClapperGLImport *)(obj))
|
||||
|
||||
struct _GstClapperGLImport
|
||||
{
|
||||
GstClapperGLBaseImport parent;
|
||||
};
|
||||
|
||||
GST_ELEMENT_REGISTER_DECLARE (clapperglimport);
|
||||
|
||||
G_END_DECLS
|
128
lib/gst/plugin/gstclapperimport.c
vendored
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapperimport.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_import_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_import_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE ("{ " GST_CLAPPER_GDK_MEMORY_FORMATS " }")));
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_import_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY,
|
||||
"{ " GST_CLAPPER_GDK_MEMORY_FORMATS " }")));
|
||||
|
||||
#define parent_class gst_clapper_import_parent_class
|
||||
G_DEFINE_TYPE (GstClapperImport, gst_clapper_import, GST_TYPE_CLAPPER_BASE_IMPORT);
|
||||
GST_ELEMENT_REGISTER_DEFINE (clapperimport, "clapperimport", GST_RANK_NONE,
|
||||
GST_TYPE_CLAPPER_IMPORT);
|
||||
|
||||
static GstBufferPool *
|
||||
gst_clapper_import_create_upstream_pool (GstClapperBaseImport *bi, GstStructure **config)
|
||||
{
|
||||
GstClapperImport *self = GST_CLAPPER_IMPORT_CAST (bi);
|
||||
GstBufferPool *pool;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Creating new upstream pool");
|
||||
|
||||
pool = gst_video_buffer_pool_new ();
|
||||
*config = gst_buffer_pool_get_config (pool);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void
|
||||
video_frame_unmap_and_free (GstVideoFrame *frame)
|
||||
{
|
||||
gst_video_frame_unmap (frame);
|
||||
g_slice_free (GstVideoFrame, frame);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_import_transform (GstBaseTransform *bt,
|
||||
GstBuffer *in_buf, GstBuffer *out_buf)
|
||||
{
|
||||
GstClapperBaseImport *bi = GST_CLAPPER_BASE_IMPORT_CAST (bt);
|
||||
GstVideoFrame *frame;
|
||||
GstMapInfo info;
|
||||
GstMemory *memory;
|
||||
|
||||
frame = g_slice_new (GstVideoFrame);
|
||||
|
||||
if (!gst_clapper_base_import_map_buffers (bi, in_buf, out_buf,
|
||||
GST_MAP_READ, GST_MAP_WRITE, frame, &info, &memory)) {
|
||||
g_slice_free (GstVideoFrame, frame);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
/* Keep frame data alive as long as necessary,
|
||||
* unmap only after bytes are destroyed */
|
||||
GST_CLAPPER_GDK_MEMORY_CAST (memory)->texture = gst_video_frame_into_gdk_texture (
|
||||
frame, (GDestroyNotify) video_frame_unmap_and_free);
|
||||
|
||||
gst_memory_unmap (memory, &info);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_import_init (GstClapperImport *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_import_class_init (GstClapperImportClass *klass)
|
||||
{
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GstBaseTransformClass *gstbasetransform_class = (GstBaseTransformClass *) klass;
|
||||
GstClapperBaseImportClass *bi_class = (GstClapperBaseImportClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperimport", 0,
|
||||
"Clapper Import");
|
||||
|
||||
gstbasetransform_class->transform = gst_clapper_import_transform;
|
||||
|
||||
bi_class->create_upstream_pool = gst_clapper_import_create_upstream_pool;
|
||||
|
||||
gst_element_class_set_metadata (gstelement_class,
|
||||
"Clapper import",
|
||||
"Filter/Video", "Imports RAW video data into ClapperGdkMemory",
|
||||
"Rafał Dzięgiel <rafostar.github@gmail.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_import_sink_template);
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_import_src_template);
|
||||
}
|
38
lib/gst/plugin/gstclapperimport.h
vendored
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gstclapperbaseimport.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_IMPORT (gst_clapper_import_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperImport, gst_clapper_import, GST, CLAPPER_IMPORT, GstClapperBaseImport)
|
||||
|
||||
#define GST_CLAPPER_IMPORT_CAST(obj) ((GstClapperImport *)(obj))
|
||||
|
||||
struct _GstClapperImport
|
||||
{
|
||||
GstClapperBaseImport parent;
|
||||
};
|
||||
|
||||
GST_ELEMENT_REGISTER_DECLARE (clapperimport);
|
||||
|
||||
G_END_DECLS
|
635
lib/gst/plugin/gstclapperpaintable.c
vendored
@@ -1,635 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapperpaintable.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
#define DEFAULT_PAR_N 1
|
||||
#define DEFAULT_PAR_D 1
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_paintable_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GstVideoOverlayRectangle *rectangle;
|
||||
|
||||
gint x, y;
|
||||
guint width, height;
|
||||
|
||||
gboolean used;
|
||||
} GstClapperGdkOverlay;
|
||||
|
||||
static void
|
||||
gst_clapper_gdk_overlay_free (GstClapperGdkOverlay *overlay)
|
||||
{
|
||||
GST_TRACE ("Freeing overlay: %" GST_PTR_FORMAT, overlay);
|
||||
|
||||
g_object_unref (overlay->texture);
|
||||
gst_video_overlay_rectangle_unref (overlay->rectangle);
|
||||
g_slice_free (GstClapperGdkOverlay, overlay);
|
||||
}
|
||||
|
||||
static void gst_clapper_paintable_iface_init (GdkPaintableInterface *iface);
|
||||
static void gst_clapper_paintable_dispose (GObject *object);
|
||||
static void gst_clapper_paintable_finalize (GObject *object);
|
||||
|
||||
#define parent_class gst_clapper_paintable_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstClapperPaintable, gst_clapper_paintable, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gst_clapper_paintable_iface_init));
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_class_init (GstClapperPaintableClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperpaintable", 0,
|
||||
"Clapper Paintable");
|
||||
|
||||
gobject_class->dispose = gst_clapper_paintable_dispose;
|
||||
gobject_class->finalize = gst_clapper_paintable_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_init (GstClapperPaintable *self)
|
||||
{
|
||||
self->par_n = DEFAULT_PAR_N;
|
||||
self->par_d = DEFAULT_PAR_D;
|
||||
|
||||
g_mutex_init (&self->lock);
|
||||
gst_video_info_init (&self->v_info);
|
||||
g_weak_ref_init (&self->widget, NULL);
|
||||
|
||||
self->overlays = g_ptr_array_new_with_free_func (
|
||||
(GDestroyNotify) gst_clapper_gdk_overlay_free);
|
||||
|
||||
gdk_rgba_parse (&self->bg, "black");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_dispose (GObject *object)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE (object);
|
||||
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
if (self->draw_id > 0) {
|
||||
g_source_remove (self->draw_id);
|
||||
self->draw_id = 0;
|
||||
}
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_finalize (GObject *object)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE (object);
|
||||
|
||||
GST_TRACE ("Finalize");
|
||||
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
g_weak_ref_clear (&self->widget);
|
||||
|
||||
gst_clear_buffer (&self->pending_buffer);
|
||||
gst_clear_buffer (&self->buffer);
|
||||
|
||||
g_ptr_array_unref (self->overlays);
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
g_mutex_clear (&self->lock);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
calculate_display_par (GstClapperPaintable *self, GstVideoInfo *info)
|
||||
{
|
||||
gint width, height, par_n, par_d, req_par_n, req_par_d;
|
||||
gboolean success;
|
||||
|
||||
width = GST_VIDEO_INFO_WIDTH (info);
|
||||
height = GST_VIDEO_INFO_HEIGHT (info);
|
||||
|
||||
/* Cannot apply aspect ratio if there is no video */
|
||||
if (width == 0 || height == 0)
|
||||
return FALSE;
|
||||
|
||||
par_n = GST_VIDEO_INFO_PAR_N (info);
|
||||
par_d = GST_VIDEO_INFO_PAR_D (info);
|
||||
|
||||
req_par_n = self->par_n;
|
||||
req_par_d = self->par_d;
|
||||
|
||||
if (par_n == 0)
|
||||
par_n = 1;
|
||||
|
||||
/* Use defaults if user set zero */
|
||||
if (req_par_n == 0 || req_par_d == 0) {
|
||||
req_par_n = DEFAULT_PAR_N;
|
||||
req_par_d = DEFAULT_PAR_D;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (self, "PAR: %u/%u, DAR: %u/%u", par_n, par_d, req_par_n, req_par_d);
|
||||
|
||||
if (!(success = gst_video_calculate_display_ratio (&self->display_ratio_num,
|
||||
&self->display_ratio_den, width, height, par_n, par_d,
|
||||
req_par_n, req_par_d))) {
|
||||
GST_ERROR_OBJECT (self, "Could not calculate display ratio values");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
invalidate_paintable_size_internal (GstClapperPaintable *self)
|
||||
{
|
||||
gint video_width, video_height;
|
||||
guint display_ratio_num, display_ratio_den;
|
||||
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
video_width = GST_VIDEO_INFO_WIDTH (&self->v_info);
|
||||
video_height = GST_VIDEO_INFO_HEIGHT (&self->v_info);
|
||||
|
||||
display_ratio_num = self->display_ratio_num;
|
||||
display_ratio_den = self->display_ratio_den;
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
if (video_height % display_ratio_den == 0) {
|
||||
GST_LOG ("Keeping video height");
|
||||
|
||||
self->display_width = (guint)
|
||||
gst_util_uint64_scale_int (video_height, display_ratio_num, display_ratio_den);
|
||||
self->display_height = video_height;
|
||||
} else if (video_width % display_ratio_num == 0) {
|
||||
GST_LOG ("Keeping video width");
|
||||
|
||||
self->display_width = video_width;
|
||||
self->display_height = (guint)
|
||||
gst_util_uint64_scale_int (video_width, display_ratio_den, display_ratio_num);
|
||||
} else {
|
||||
GST_LOG ("Approximating while keeping video height");
|
||||
|
||||
self->display_width = (guint)
|
||||
gst_util_uint64_scale_int (video_height, display_ratio_num, display_ratio_den);
|
||||
self->display_height = video_height;
|
||||
}
|
||||
|
||||
self->display_aspect_ratio = ((gdouble) self->display_width
|
||||
/ (gdouble) self->display_height);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Invalidate paintable size, display: %dx%d",
|
||||
self->display_width, self->display_height);
|
||||
gdk_paintable_invalidate_size ((GdkPaintable *) self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
invalidate_paintable_size_on_main_cb (GstClapperPaintable *self)
|
||||
{
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
self->draw_id = 0;
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
invalidate_paintable_size_internal (self);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
comp_frame_unmap_and_free (GstVideoFrame *frame)
|
||||
{
|
||||
gst_video_frame_unmap (frame);
|
||||
g_slice_free (GstVideoFrame, frame);
|
||||
}
|
||||
|
||||
static GstClapperGdkOverlay *
|
||||
_get_cached_overlay (GPtrArray *overlays, GstVideoOverlayRectangle *rectangle, guint *index)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < overlays->len; i++) {
|
||||
GstClapperGdkOverlay *overlay = g_ptr_array_index (overlays, i);
|
||||
|
||||
if (overlay->rectangle != rectangle)
|
||||
continue;
|
||||
|
||||
*index = i;
|
||||
return overlay;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_prepare_overlays (GstClapperPaintable *self)
|
||||
{
|
||||
GstVideoOverlayCompositionMeta *comp_meta;
|
||||
guint num_overlays, i;
|
||||
|
||||
/* As long as this is called from main thread, no need to lock here */
|
||||
if (G_UNLIKELY (!self->buffer)
|
||||
|| !(comp_meta = gst_buffer_get_video_overlay_composition_meta (self->buffer))) {
|
||||
guint n_pending = self->overlays->len;
|
||||
|
||||
/* Remove all cached overlays if new buffer does not have any */
|
||||
if (n_pending > 0) {
|
||||
GST_TRACE ("No overlays in buffer, removing all cached ones");
|
||||
g_ptr_array_remove_range (self->overlays, 0, n_pending);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (self, "Preparing overlays...");
|
||||
|
||||
/* Mark all old overlays as unused */
|
||||
for (i = 0; i < self->overlays->len; i++) {
|
||||
GstClapperGdkOverlay *overlay = g_ptr_array_index (self->overlays, i);
|
||||
overlay->used = FALSE;
|
||||
}
|
||||
|
||||
num_overlays = gst_video_overlay_composition_n_rectangles (comp_meta->overlay);
|
||||
|
||||
for (i = 0; i < num_overlays; i++) {
|
||||
GdkTexture *texture;
|
||||
GstBuffer *comp_buffer;
|
||||
GstVideoFrame *comp_frame;
|
||||
GstVideoMeta *vmeta;
|
||||
GstVideoInfo vinfo;
|
||||
GstVideoOverlayRectangle *rectangle;
|
||||
GstClapperGdkOverlay *overlay;
|
||||
GstVideoOverlayFormatFlags flags, alpha_flags = 0;
|
||||
gint comp_x, comp_y;
|
||||
guint comp_width, comp_height, cached_index;
|
||||
|
||||
rectangle = gst_video_overlay_composition_get_rectangle (comp_meta->overlay, i);
|
||||
|
||||
if ((overlay = _get_cached_overlay (self->overlays, rectangle, &cached_index))) {
|
||||
overlay->used = TRUE;
|
||||
|
||||
/* Place overlay at expected position */
|
||||
if (i != cached_index) {
|
||||
GST_LOG ("Rearranging overlay position: %u => %u", cached_index, i);
|
||||
|
||||
overlay = g_ptr_array_steal_index_fast (self->overlays, cached_index);
|
||||
g_ptr_array_insert (self->overlays, i, overlay);
|
||||
}
|
||||
|
||||
GST_TRACE ("Reusing cached overlay: %" GST_PTR_FORMAT, overlay);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!gst_video_overlay_rectangle_get_render_rectangle (rectangle,
|
||||
&comp_x, &comp_y, &comp_width, &comp_height))) {
|
||||
GST_WARNING ("Invalid overlay rectangle dimensions: %" GST_PTR_FORMAT, rectangle);
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = gst_video_overlay_rectangle_get_flags (rectangle);
|
||||
|
||||
if (flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA)
|
||||
alpha_flags |= GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA;
|
||||
|
||||
comp_buffer = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rectangle, alpha_flags);
|
||||
comp_frame = g_slice_new (GstVideoFrame);
|
||||
|
||||
/* Update overlay video info from video meta */
|
||||
if ((vmeta = gst_buffer_get_video_meta (comp_buffer))) {
|
||||
gst_video_info_set_format (&vinfo, vmeta->format, vmeta->width, vmeta->height);
|
||||
vinfo.stride[0] = vmeta->stride[0];
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!gst_video_frame_map (comp_frame, &vinfo, comp_buffer, GST_MAP_READ))) {
|
||||
g_slice_free (GstVideoFrame, comp_frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((texture = gst_video_frame_into_gdk_texture (
|
||||
comp_frame, (GDestroyNotify) comp_frame_unmap_and_free))) {
|
||||
overlay = g_slice_new (GstClapperGdkOverlay);
|
||||
overlay->texture = texture;
|
||||
overlay->rectangle = gst_video_overlay_rectangle_ref (rectangle);
|
||||
overlay->x = comp_x;
|
||||
overlay->y = comp_y;
|
||||
overlay->width = comp_width;
|
||||
overlay->height = comp_height;
|
||||
overlay->used = TRUE;
|
||||
|
||||
GST_TRACE ("Created overlay: %"
|
||||
GST_PTR_FORMAT ", x: %i, y: %i, width: %u, height: %u",
|
||||
overlay, overlay->x, overlay->y, overlay->width, overlay->height);
|
||||
|
||||
g_ptr_array_insert (self->overlays, i, overlay);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all overlays that are not going to be used */
|
||||
for (i = self->overlays->len; i > 0; i--) {
|
||||
GstClapperGdkOverlay *overlay = g_ptr_array_index (self->overlays, i - 1);
|
||||
|
||||
if (!overlay->used) {
|
||||
GST_TRACE ("Removing unused cached overlay: %" GST_PTR_FORMAT, overlay);
|
||||
g_ptr_array_remove (self->overlays, overlay);
|
||||
}
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (num_overlays != self->overlays->len)) {
|
||||
GST_WARNING_OBJECT (self, "Some overlays could not be prepared, %u != %u",
|
||||
num_overlays, self->overlays->len);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (self, "Prepared overlays: %u", self->overlays->len);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_paintable_on_main_cb (GstClapperPaintable *self)
|
||||
{
|
||||
gboolean size_changed;
|
||||
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
/* Check if we will need to invalidate size */
|
||||
if ((size_changed = self->pending_resize))
|
||||
self->pending_resize = FALSE;
|
||||
|
||||
gst_clear_buffer (&self->buffer);
|
||||
self->buffer = self->pending_buffer;
|
||||
self->pending_buffer = NULL;
|
||||
|
||||
self->draw_id = 0;
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
gst_clapper_paintable_prepare_overlays (self);
|
||||
|
||||
if (size_changed)
|
||||
invalidate_paintable_size_internal (self);
|
||||
|
||||
GST_LOG_OBJECT (self, "Invalidate paintable contents");
|
||||
gdk_paintable_invalidate_contents ((GdkPaintable *) self);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
GstClapperPaintable *
|
||||
gst_clapper_paintable_new (void)
|
||||
{
|
||||
return g_object_new (GST_TYPE_CLAPPER_PAINTABLE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gst_clapper_paintable_set_widget (GstClapperPaintable *self, GtkWidget *widget)
|
||||
{
|
||||
g_weak_ref_set (&self->widget, widget);
|
||||
}
|
||||
|
||||
void
|
||||
gst_clapper_paintable_set_buffer (GstClapperPaintable *self, GstBuffer *buffer)
|
||||
{
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
if (self->draw_id > 0) {
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
GST_TRACE ("Already have pending buffer, skipping %" GST_PTR_FORMAT, buffer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gst_buffer_replace (&self->pending_buffer, buffer);
|
||||
self->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT,
|
||||
(GSourceFunc) update_paintable_on_main_cb, self, NULL);
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_clapper_paintable_set_video_info (GstClapperPaintable *self, GstVideoInfo *v_info)
|
||||
{
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
if (gst_video_info_is_equal (&self->v_info, v_info)) {
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Reject info if values would cause integer overflow */
|
||||
if (G_UNLIKELY (!calculate_display_par (self, v_info))) {
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->pending_resize = TRUE;
|
||||
self->v_info = *v_info;
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_clapper_paintable_set_pixel_aspect_ratio (GstClapperPaintable *self,
|
||||
gint par_n, gint par_d)
|
||||
{
|
||||
gboolean success;
|
||||
|
||||
GST_CLAPPER_PAINTABLE_LOCK (self);
|
||||
|
||||
/* No change */
|
||||
if (self->par_n == par_n && self->par_d == par_d) {
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
return;
|
||||
}
|
||||
|
||||
self->par_n = par_n;
|
||||
self->par_d = par_d;
|
||||
|
||||
/* Check if we can accept new values. This will update
|
||||
* display `ratio_num` and `ratio_den` only when successful */
|
||||
success = calculate_display_par (self, &self->v_info);
|
||||
|
||||
/* If paintable update is queued, wait for it, otherwise invalidate
|
||||
* size only for change to be applied even when paused */
|
||||
if (!success || self->draw_id > 0) {
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
return;
|
||||
}
|
||||
|
||||
self->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT,
|
||||
(GSourceFunc) invalidate_paintable_size_on_main_cb, self, NULL);
|
||||
|
||||
GST_CLAPPER_PAINTABLE_UNLOCK (self);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* GdkPaintableInterface
|
||||
*/
|
||||
static void
|
||||
gst_clapper_paintable_snapshot_internal (GstClapperPaintable *self,
|
||||
GdkSnapshot *snapshot, gdouble width, gdouble height,
|
||||
gint widget_width, gint widget_height)
|
||||
{
|
||||
GstMemory *memory;
|
||||
GstMapInfo info;
|
||||
gfloat scale_x, scale_y;
|
||||
guint i;
|
||||
|
||||
scale_x = (gfloat) width / self->display_width;
|
||||
scale_y = (gfloat) height / self->display_height;
|
||||
|
||||
/* Apply black borders when keeping aspect ratio */
|
||||
if (scale_x == scale_y || abs (scale_x - scale_y) <= FLT_EPSILON) {
|
||||
if (widget_height - height > 0) {
|
||||
gdouble bar_height = (widget_height - height) / 2;
|
||||
|
||||
gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (0, 0, width, -bar_height));
|
||||
gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (0, height, width, bar_height + 0.5));
|
||||
} else if (widget_width - width > 0) {
|
||||
gdouble bar_width = (widget_width - width) / 2;
|
||||
|
||||
gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (0, 0, -bar_width, height));
|
||||
gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (width, 0, bar_width + 0.5, height));
|
||||
}
|
||||
}
|
||||
|
||||
/* Buffer is accessed only from main thread, so no locking required */
|
||||
if (!self->buffer) {
|
||||
gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
return;
|
||||
}
|
||||
|
||||
GST_TRACE ("Snapshot %" GST_PTR_FORMAT, self->buffer);
|
||||
|
||||
memory = gst_buffer_peek_memory (self->buffer, 0);
|
||||
|
||||
/* If we cannot map, just draw black */
|
||||
if (G_UNLIKELY (!gst_memory_map (memory, &info, GST_MAP_READ))) {
|
||||
gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
GST_WARNING_OBJECT (self, "Could not map %" GST_PTR_FORMAT, self->buffer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_snapshot_append_texture (snapshot,
|
||||
GST_CLAPPER_GDK_MEMORY_CAST (memory)->texture,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gst_memory_unmap (memory, &info);
|
||||
|
||||
/* FIXME: Draw black BG here when import format has-alpha */
|
||||
//gtk_snapshot_append_color (snapshot, &self->bg, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
/* Finally append prepared overlays */
|
||||
for (i = 0; i < self->overlays->len; i++) {
|
||||
GstClapperGdkOverlay *overlay = g_ptr_array_index (self->overlays, i);
|
||||
|
||||
gtk_snapshot_append_texture (snapshot, overlay->texture,
|
||||
&GRAPHENE_RECT_INIT (overlay->x * scale_x, overlay->y * scale_y,
|
||||
overlay->width * scale_x, overlay->height * scale_y));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot, gdouble width, gdouble height)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE_CAST (paintable);
|
||||
GtkWidget *widget;
|
||||
gint widget_width = 0, widget_height = 0;
|
||||
|
||||
if ((widget = g_weak_ref_get (&self->widget))) {
|
||||
widget_width = gtk_widget_get_width (widget);
|
||||
widget_height = gtk_widget_get_height (widget);
|
||||
|
||||
g_object_unref (widget);
|
||||
}
|
||||
|
||||
gst_clapper_paintable_snapshot_internal (self, snapshot,
|
||||
width, height, widget_width, widget_height);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
gst_clapper_paintable_get_current_image (GdkPaintable *paintable)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE_CAST (paintable);
|
||||
|
||||
if (self->buffer) {
|
||||
GtkSnapshot *snapshot;
|
||||
GdkPaintable *ret;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
|
||||
/* Snapshot without widget size in order to get
|
||||
* paintable without black borders */
|
||||
gst_clapper_paintable_snapshot_internal (self, snapshot,
|
||||
self->display_width, self->display_height, 0, 0);
|
||||
|
||||
if ((ret = gtk_snapshot_free_to_paintable (snapshot, NULL)))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return gdk_paintable_new_empty (0, 0);
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_clapper_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE_CAST (paintable);
|
||||
|
||||
return self->display_width;
|
||||
}
|
||||
|
||||
static gint
|
||||
gst_clapper_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE_CAST (paintable);
|
||||
|
||||
return self->display_height;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
gst_clapper_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
|
||||
{
|
||||
GstClapperPaintable *self = GST_CLAPPER_PAINTABLE_CAST (paintable);
|
||||
|
||||
return self->display_aspect_ratio;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_paintable_iface_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gst_clapper_paintable_snapshot;
|
||||
iface->get_current_image = gst_clapper_paintable_get_current_image;
|
||||
iface->get_intrinsic_width = gst_clapper_paintable_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = gst_clapper_paintable_get_intrinsic_height;
|
||||
iface->get_intrinsic_aspect_ratio = gst_clapper_paintable_get_intrinsic_aspect_ratio;
|
||||
}
|
74
lib/gst/plugin/gstclapperpaintable.h
vendored
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_PAINTABLE (gst_clapper_paintable_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperPaintable, gst_clapper_paintable, GST, CLAPPER_PAINTABLE, GObject)
|
||||
|
||||
#define GST_CLAPPER_PAINTABLE_CAST(obj) ((GstClapperPaintable *)(obj))
|
||||
|
||||
#define GST_CLAPPER_PAINTABLE_GET_LOCK(obj) (&GST_CLAPPER_PAINTABLE_CAST(obj)->lock)
|
||||
#define GST_CLAPPER_PAINTABLE_LOCK(obj) g_mutex_lock (GST_CLAPPER_PAINTABLE_GET_LOCK(obj))
|
||||
#define GST_CLAPPER_PAINTABLE_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_PAINTABLE_GET_LOCK(obj))
|
||||
|
||||
struct _GstClapperPaintable
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
GMutex lock;
|
||||
|
||||
GstBuffer *pending_buffer, *buffer;
|
||||
GPtrArray *overlays;
|
||||
GstVideoInfo v_info;
|
||||
|
||||
GdkRGBA bg;
|
||||
|
||||
GWeakRef widget;
|
||||
|
||||
/* Sink properties */
|
||||
gint par_n, par_d;
|
||||
|
||||
/* Resize */
|
||||
gboolean pending_resize;
|
||||
guint display_ratio_num;
|
||||
guint display_ratio_den;
|
||||
|
||||
/* GdkPaintableInterface */
|
||||
gint display_width;
|
||||
gint display_height;
|
||||
gdouble display_aspect_ratio;
|
||||
|
||||
/* Pending draw signal id */
|
||||
guint draw_id;
|
||||
};
|
||||
|
||||
GstClapperPaintable * gst_clapper_paintable_new (void);
|
||||
void gst_clapper_paintable_set_widget (GstClapperPaintable *paintable, GtkWidget *widget);
|
||||
void gst_clapper_paintable_set_buffer (GstClapperPaintable *paintable, GstBuffer *buffer);
|
||||
gboolean gst_clapper_paintable_set_video_info (GstClapperPaintable *paintable, GstVideoInfo *v_info);
|
||||
void gst_clapper_paintable_set_pixel_aspect_ratio (GstClapperPaintable *paintable, gint par_n, gint par_d);
|
||||
|
||||
G_END_DECLS
|
838
lib/gst/plugin/gstclappersink.c
vendored
@@ -1,838 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclappersink.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
#include "gstclappergdkbufferpool.h"
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
||||
#define DEFAULT_PAR_N 1
|
||||
#define DEFAULT_PAR_D 1
|
||||
#define DEFAULT_KEEP_LAST_FRAME FALSE
|
||||
|
||||
#define WINDOW_CSS_CLASS_NAME "clappersinkwindow"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_WIDGET,
|
||||
PROP_FORCE_ASPECT_RATIO,
|
||||
PROP_PIXEL_ASPECT_RATIO,
|
||||
PROP_KEEP_LAST_FRAME,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
#define GST_CAT_DEFAULT gst_clapper_sink_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
static GstStaticPadTemplate gst_clapper_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY,
|
||||
"{ " GST_CLAPPER_GDK_MEMORY_FORMATS ", NV12 }")
|
||||
"; "
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_CLAPPER_GDK_MEMORY ", "
|
||||
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
|
||||
"{ " GST_CLAPPER_GDK_MEMORY_FORMATS ", NV12 }")));
|
||||
|
||||
static void gst_clapper_sink_navigation_interface_init (
|
||||
GstNavigationInterface *iface);
|
||||
|
||||
#define parent_class gst_clapper_sink_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstClapperSink, gst_clapper_sink, GST_TYPE_VIDEO_SINK,
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
|
||||
gst_clapper_sink_navigation_interface_init));
|
||||
GST_ELEMENT_REGISTER_DEFINE (clappersink, "clappersink", GST_RANK_NONE,
|
||||
GST_TYPE_CLAPPER_SINK);
|
||||
|
||||
static void
|
||||
window_clear_no_lock (GstClapperSink *self)
|
||||
{
|
||||
if (!self->window)
|
||||
return;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Window clear");
|
||||
|
||||
if (self->window_destroy_id) {
|
||||
g_signal_handler_disconnect (self->window, self->window_destroy_id);
|
||||
self->window_destroy_id = 0;
|
||||
}
|
||||
self->window = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
widget_clear_no_lock (GstClapperSink *self)
|
||||
{
|
||||
if (!self->widget)
|
||||
return;
|
||||
|
||||
GST_TRACE_OBJECT (self, "Widget clear");
|
||||
|
||||
if (self->widget_destroy_id) {
|
||||
g_signal_handler_disconnect (self->widget, self->widget_destroy_id);
|
||||
self->widget_destroy_id = 0;
|
||||
}
|
||||
g_clear_object (&self->widget);
|
||||
}
|
||||
|
||||
static void
|
||||
widget_destroy_cb (GtkWidget *widget, GstClapperSink *self)
|
||||
{
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
widget_clear_no_lock (self);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
}
|
||||
|
||||
static void
|
||||
window_destroy_cb (GtkWidget *window, GstClapperSink *self)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Window destroy");
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
widget_clear_no_lock (self);
|
||||
window_clear_no_lock (self);
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_stream_coords (GstClapperSink *self, GtkWidget *widget,
|
||||
gdouble x, gdouble y, gdouble *stream_x, gdouble *stream_y)
|
||||
{
|
||||
GstVideoRectangle result;
|
||||
gint scaled_width, scaled_height, scale_factor;
|
||||
gint video_width, video_height;
|
||||
gboolean force_aspect_ratio;
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
video_width = GST_VIDEO_INFO_WIDTH (&self->v_info);
|
||||
video_height = GST_VIDEO_INFO_HEIGHT (&self->v_info);
|
||||
force_aspect_ratio = self->force_aspect_ratio;
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
scale_factor = gtk_widget_get_scale_factor (widget);
|
||||
scaled_width = gtk_widget_get_width (widget) * scale_factor;
|
||||
scaled_height = gtk_widget_get_height (widget) * scale_factor;
|
||||
|
||||
if (force_aspect_ratio) {
|
||||
GstVideoRectangle src, dst;
|
||||
|
||||
src.x = 0;
|
||||
src.y = 0;
|
||||
src.w = gdk_paintable_get_intrinsic_width ((GdkPaintable *) self->paintable);
|
||||
src.h = gdk_paintable_get_intrinsic_height ((GdkPaintable *) self->paintable);
|
||||
|
||||
dst.x = 0;
|
||||
dst.y = 0;
|
||||
dst.w = scaled_width;
|
||||
dst.h = scaled_height;
|
||||
|
||||
gst_video_center_rect (&src, &dst, &result, TRUE);
|
||||
} else {
|
||||
result.x = 0;
|
||||
result.y = 0;
|
||||
result.w = scaled_width;
|
||||
result.h = scaled_height;
|
||||
}
|
||||
|
||||
/* Display coordinates to stream coordinates */
|
||||
*stream_x = (result.w > 0)
|
||||
? (x - result.x) / result.w * video_width
|
||||
: 0;
|
||||
*stream_y = (result.h > 0)
|
||||
? (y - result.y) / result.h * video_height
|
||||
: 0;
|
||||
|
||||
/* Clip to stream size */
|
||||
*stream_x = CLAMP (*stream_x, 0, video_width);
|
||||
*stream_y = CLAMP (*stream_y, 0, video_height);
|
||||
|
||||
GST_LOG ("Transform coords %fx%f => %fx%f", x, y, *stream_x, *stream_y);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_widget_motion_event (GtkEventControllerMotion *motion,
|
||||
gdouble x, gdouble y, GstClapperSink *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
gdouble stream_x, stream_y;
|
||||
|
||||
if ((x == self->last_pos_x && y == self->last_pos_y)
|
||||
|| GST_STATE (self) < GST_STATE_PLAYING)
|
||||
return;
|
||||
|
||||
self->last_pos_x = x;
|
||||
self->last_pos_y = y;
|
||||
|
||||
widget = gtk_event_controller_get_widget ((GtkEventController *) motion);
|
||||
calculate_stream_coords (self, widget, x, y, &stream_x, &stream_y);
|
||||
GST_LOG ("Event \"mouse-move\", x: %f, y: %f", stream_x, stream_y);
|
||||
|
||||
gst_navigation_send_mouse_event ((GstNavigation *) self, "mouse-move",
|
||||
0, stream_x, stream_y);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_widget_button_event (GtkGestureClick *click,
|
||||
gint n_press, gdouble x, gdouble y, GstClapperSink *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GdkEvent *event;
|
||||
gdouble stream_x, stream_y;
|
||||
GdkEventType event_type;
|
||||
const gchar *event_name;
|
||||
|
||||
if (GST_STATE (self) < GST_STATE_PLAYING)
|
||||
return;
|
||||
|
||||
event = gtk_event_controller_get_current_event ((GtkEventController *) click);
|
||||
event_type = gdk_event_get_event_type (event);
|
||||
|
||||
/* FIXME: Touchscreen handling should probably use new touch events from GStreamer 1.22 */
|
||||
event_name = (event_type == GDK_BUTTON_PRESS || event_type == GDK_TOUCH_BEGIN)
|
||||
? "mouse-button-press"
|
||||
: (event_type == GDK_BUTTON_RELEASE || event_type == GDK_TOUCH_END)
|
||||
? "mouse-button-release"
|
||||
: NULL;
|
||||
|
||||
/* Can be NULL on touch */
|
||||
if (!event_name)
|
||||
return;
|
||||
|
||||
widget = gtk_event_controller_get_widget ((GtkEventController *) click);
|
||||
calculate_stream_coords (self, widget, x, y, &stream_x, &stream_y);
|
||||
GST_LOG ("Event \"%s\", x: %f, y: %f", event_name, stream_x, stream_y);
|
||||
|
||||
/* Gesture is set to handle only primary button, so we do not have to check */
|
||||
gst_navigation_send_mouse_event ((GstNavigation *) self, event_name,
|
||||
1, stream_x, stream_y);
|
||||
}
|
||||
|
||||
/* Must call from main thread only with a lock */
|
||||
static GtkWidget *
|
||||
gst_clapper_sink_get_widget (GstClapperSink *self)
|
||||
{
|
||||
if (G_UNLIKELY (!self->widget)) {
|
||||
GtkEventController *controller;
|
||||
GtkGesture *gesture;
|
||||
|
||||
/* Make sure GTK is initialized */
|
||||
if (!gtk_init_check ()) {
|
||||
GST_ERROR_OBJECT (self, "Could not ensure GTK initialization");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->widget = gtk_picture_new ();
|
||||
|
||||
/* Otherwise widget in grid will appear as a 1x1px
|
||||
* video which might be misleading for users */
|
||||
gtk_widget_set_hexpand (self->widget, TRUE);
|
||||
gtk_widget_set_vexpand (self->widget, TRUE);
|
||||
|
||||
gtk_widget_set_focusable (self->widget, TRUE);
|
||||
gtk_widget_set_can_focus (self->widget, TRUE);
|
||||
|
||||
controller = gtk_event_controller_motion_new ();
|
||||
g_signal_connect (controller, "motion",
|
||||
G_CALLBACK (gst_clapper_sink_widget_motion_event), self);
|
||||
gtk_widget_add_controller (self->widget, controller);
|
||||
|
||||
gesture = gtk_gesture_click_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 1);
|
||||
g_signal_connect (gesture, "pressed",
|
||||
G_CALLBACK (gst_clapper_sink_widget_button_event), self);
|
||||
g_signal_connect (gesture, "released",
|
||||
G_CALLBACK (gst_clapper_sink_widget_button_event), self);
|
||||
gtk_widget_add_controller (self->widget, GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
/* TODO: Implement touch events once we depend on GStreamer 1.22 */
|
||||
|
||||
/* Take floating ref */
|
||||
g_object_ref_sink (self->widget);
|
||||
|
||||
/* Set back pointer */
|
||||
gst_clapper_paintable_set_widget (self->paintable, self->widget);
|
||||
|
||||
/* Set earlier remembered property */
|
||||
gtk_picture_set_keep_aspect_ratio (GTK_PICTURE (self->widget),
|
||||
self->force_aspect_ratio);
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (self->widget), GDK_PAINTABLE (self->paintable));
|
||||
|
||||
self->widget_destroy_id = g_signal_connect (self->widget,
|
||||
"destroy", G_CALLBACK (widget_destroy_cb), self);
|
||||
}
|
||||
|
||||
return self->widget;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
gst_clapper_sink_obtain_widget (GstClapperSink *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
widget = gst_clapper_sink_get_widget (self);
|
||||
if (widget)
|
||||
g_object_ref (widget);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (object);
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_WIDGET:
|
||||
if (self->widget) {
|
||||
g_value_set_object (value, self->widget);
|
||||
} else {
|
||||
GtkWidget *widget;
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
widget = gst_gtk_invoke_on_main ((GThreadFunc) gst_clapper_sink_obtain_widget, self);
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
g_value_set_object (value, widget);
|
||||
g_object_unref (widget);
|
||||
}
|
||||
break;
|
||||
case PROP_FORCE_ASPECT_RATIO:
|
||||
g_value_set_boolean (value, self->force_aspect_ratio);
|
||||
break;
|
||||
case PROP_PIXEL_ASPECT_RATIO:
|
||||
gst_value_set_fraction (value, self->par_n, self->par_d);
|
||||
break;
|
||||
case PROP_KEEP_LAST_FRAME:
|
||||
g_value_set_boolean (value, self->keep_last_frame);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (object);
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_FORCE_ASPECT_RATIO:
|
||||
self->force_aspect_ratio = g_value_get_boolean (value);
|
||||
|
||||
if (self->widget) {
|
||||
gtk_picture_set_keep_aspect_ratio (GTK_PICTURE (self->widget),
|
||||
self->force_aspect_ratio);
|
||||
}
|
||||
break;
|
||||
case PROP_PIXEL_ASPECT_RATIO:
|
||||
self->par_n = gst_value_get_fraction_numerator (value);
|
||||
self->par_d = gst_value_get_fraction_denominator (value);
|
||||
|
||||
gst_clapper_paintable_set_pixel_aspect_ratio (self->paintable,
|
||||
self->par_n, self->par_d);
|
||||
break;
|
||||
case PROP_KEEP_LAST_FRAME:
|
||||
self->keep_last_frame = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_navigation_send_event (GstNavigation *navigation,
|
||||
GstStructure *structure)
|
||||
{
|
||||
GstClapperSink *sink = GST_CLAPPER_SINK_CAST (navigation);
|
||||
GstEvent *event;
|
||||
|
||||
GST_TRACE_OBJECT (sink, "Navigation event: %" GST_PTR_FORMAT, structure);
|
||||
event = gst_event_new_navigation (structure);
|
||||
|
||||
if (G_LIKELY (event)) {
|
||||
GstPad *pad;
|
||||
|
||||
pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sink));
|
||||
|
||||
if (G_LIKELY (pad)) {
|
||||
if (!gst_pad_send_event (pad, gst_event_ref (event))) {
|
||||
/* If upstream didn't handle the event we'll post a message with it
|
||||
* for the application in case it wants to do something with it */
|
||||
gst_element_post_message (GST_ELEMENT_CAST (sink),
|
||||
gst_navigation_message_new_event (GST_OBJECT_CAST (sink), event));
|
||||
}
|
||||
gst_object_unref (pad);
|
||||
}
|
||||
gst_event_unref (event);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_sink_propose_allocation (GstBaseSink *bsink, GstQuery *query)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink);
|
||||
GstBufferPool *pool = NULL;
|
||||
GstCaps *caps;
|
||||
GstVideoInfo info;
|
||||
guint size;
|
||||
gboolean need_pool;
|
||||
|
||||
gst_query_parse_allocation (query, &caps, &need_pool);
|
||||
|
||||
if (!caps) {
|
||||
GST_DEBUG_OBJECT (self, "No caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gst_video_info_from_caps (&info, caps)) {
|
||||
GST_DEBUG_OBJECT (self, "Invalid caps specified");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Normal size of a frame */
|
||||
size = GST_VIDEO_INFO_SIZE (&info);
|
||||
|
||||
if (need_pool) {
|
||||
GstStructure *config;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Creating new pool");
|
||||
|
||||
pool = gst_clapper_gdk_buffer_pool_new ();
|
||||
config = gst_buffer_pool_get_config (pool);
|
||||
|
||||
gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
|
||||
gst_buffer_pool_config_set_params (config, caps, size, 2, 0);
|
||||
|
||||
if (!gst_buffer_pool_set_config (pool, config)) {
|
||||
gst_object_unref (pool);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Failed to set config");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gst_query_add_allocation_pool (query, pool, size, 2, 0);
|
||||
if (pool)
|
||||
gst_object_unref (pool);
|
||||
|
||||
gst_query_add_allocation_meta (query,
|
||||
GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
|
||||
|
||||
/* We also support various metadata */
|
||||
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_sink_start_on_main (GstClapperSink *self)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
/* Make sure widget is created */
|
||||
if (!(widget = gst_clapper_sink_get_widget (self))) {
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* When no toplevel window, make our own */
|
||||
if (G_UNLIKELY (!gtk_widget_get_root (widget) && !self->window)) {
|
||||
GtkWidget *toplevel, *parent;
|
||||
GtkCssProvider *provider;
|
||||
gchar *win_title;
|
||||
|
||||
if ((parent = gtk_widget_get_parent (widget))) {
|
||||
GtkWidget *temp_parent;
|
||||
|
||||
while ((temp_parent = gtk_widget_get_parent (parent)))
|
||||
parent = temp_parent;
|
||||
}
|
||||
toplevel = (parent) ? parent : widget;
|
||||
|
||||
self->window = (GtkWindow *) gtk_window_new ();
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self->window), WINDOW_CSS_CLASS_NAME);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_data (provider,
|
||||
"." WINDOW_CSS_CLASS_NAME " { background: none; }", -1);
|
||||
gtk_style_context_add_provider_for_display (
|
||||
gdk_display_get_default (), GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
g_object_unref (provider);
|
||||
|
||||
win_title = g_strdup_printf ("Clapper Sink - GTK %u.%u.%u Window",
|
||||
gtk_get_major_version (),
|
||||
gtk_get_minor_version (),
|
||||
gtk_get_micro_version ());
|
||||
|
||||
gtk_window_set_default_size (self->window, 640, 480);
|
||||
gtk_window_set_title (self->window, win_title);
|
||||
gtk_window_set_child (self->window, toplevel);
|
||||
|
||||
g_free (win_title);
|
||||
|
||||
self->window_destroy_id = g_signal_connect (self->window,
|
||||
"destroy", G_CALLBACK (window_destroy_cb), self);
|
||||
}
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_present_on_main_idle (GtkWindow *window)
|
||||
{
|
||||
GST_INFO ("Presenting window");
|
||||
gtk_window_present (window);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_sink_start (GstBaseSink *bsink)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink);
|
||||
|
||||
GST_INFO_OBJECT (self, "Start");
|
||||
|
||||
if (G_UNLIKELY (!(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback)
|
||||
gst_clapper_sink_start_on_main, self)))) {
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
("GtkWidget could not be created"), (NULL));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_sink_stop_on_main (GstClapperSink *self)
|
||||
{
|
||||
GtkWindow *window = NULL;
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
if (self->window)
|
||||
window = g_object_ref (self->window);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
if (window) {
|
||||
gtk_window_destroy (window);
|
||||
g_object_unref (window);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_sink_stop (GstBaseSink *bsink)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink);
|
||||
gboolean has_window;
|
||||
|
||||
GST_INFO_OBJECT (self, "Stop");
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
has_window = (self->window != NULL);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
if (G_UNLIKELY (has_window)) {
|
||||
return (! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback)
|
||||
gst_clapper_sink_stop_on_main, self));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_clapper_sink_change_state (GstElement *element, GstStateChange transition)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (element);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Changing state: %s => %s",
|
||||
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
|
||||
gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
if (!self->keep_last_frame)
|
||||
gst_clapper_paintable_set_buffer (self->paintable, NULL);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
if (G_UNLIKELY (self->window && !self->presented_window)) {
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT,
|
||||
(GSourceFunc) window_present_on_main_idle,
|
||||
g_object_ref (self->window), (GDestroyNotify) g_object_unref);
|
||||
self->presented_window = TRUE;
|
||||
}
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_get_times (GstBaseSink *bsink, GstBuffer *buffer,
|
||||
GstClockTime *start, GstClockTime *end)
|
||||
{
|
||||
if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
|
||||
return;
|
||||
|
||||
*start = GST_BUFFER_TIMESTAMP (buffer);
|
||||
|
||||
if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
|
||||
*end = *start + GST_BUFFER_DURATION (buffer);
|
||||
} else {
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink);
|
||||
gint fps_n, fps_d;
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
fps_n = GST_VIDEO_INFO_FPS_N (&self->v_info);
|
||||
fps_d = GST_VIDEO_INFO_FPS_D (&self->v_info);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
if (fps_n > 0)
|
||||
*end = *start + gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
|
||||
}
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_clapper_sink_get_caps (GstBaseSink *bsink, GstCaps *filter)
|
||||
{
|
||||
GstCaps *result, *tmp;
|
||||
|
||||
tmp = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (bsink));
|
||||
|
||||
if (filter) {
|
||||
GST_DEBUG ("Intersecting with filter caps: %" GST_PTR_FORMAT, filter);
|
||||
result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
|
||||
gst_caps_unref (tmp);
|
||||
} else {
|
||||
result = tmp;
|
||||
}
|
||||
GST_DEBUG ("Returning caps: %" GST_PTR_FORMAT, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_sink_set_caps (GstBaseSink *bsink, GstCaps *caps)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink);
|
||||
gboolean res;
|
||||
|
||||
GST_INFO_OBJECT (self, "Set caps: %" GST_PTR_FORMAT, caps);
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
if (!gst_video_info_from_caps (&self->v_info, caps)) {
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!self->widget)) {
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
("Output widget was destroyed"), (NULL));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = gst_clapper_paintable_set_video_info (self->paintable, &self->v_info);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_sink_show_frame (GstVideoSink *vsink, GstBuffer *buffer)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (vsink);
|
||||
|
||||
GST_TRACE ("Got %" GST_PTR_FORMAT, buffer);
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
if (G_UNLIKELY (!self->widget)) {
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
|
||||
("Output widget was destroyed"), (NULL));
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
gst_clapper_paintable_set_buffer (self->paintable, buffer);
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_init (GstClapperSink *self)
|
||||
{
|
||||
GObjectClass *gobject_class;
|
||||
|
||||
gobject_class = (GObjectClass *) GST_CLAPPER_SINK_GET_CLASS (self);
|
||||
|
||||
/* HACK: install here instead of class init to avoid GStreamer
|
||||
* plugin scanner GObject type conflicts with older GTK versions */
|
||||
if (!g_object_class_find_property (gobject_class, "widget")) {
|
||||
g_object_class_install_property (gobject_class, PROP_WIDGET,
|
||||
g_param_spec_object ("widget", "GTK Widget",
|
||||
"The GtkWidget to place in the widget hierarchy",
|
||||
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
self->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
|
||||
self->par_n = DEFAULT_PAR_N;
|
||||
self->par_d = DEFAULT_PAR_D;
|
||||
self->keep_last_frame = DEFAULT_KEEP_LAST_FRAME;
|
||||
|
||||
g_mutex_init (&self->lock);
|
||||
gst_video_info_init (&self->v_info);
|
||||
|
||||
self->paintable = gst_clapper_paintable_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_dispose (GObject *object)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (object);
|
||||
|
||||
GST_CLAPPER_SINK_LOCK (self);
|
||||
|
||||
window_clear_no_lock (self);
|
||||
widget_clear_no_lock (self);
|
||||
|
||||
g_clear_object (&self->paintable);
|
||||
|
||||
GST_CLAPPER_SINK_UNLOCK (self);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_finalize (GObject *object)
|
||||
{
|
||||
GstClapperSink *self = GST_CLAPPER_SINK_CAST (object);
|
||||
|
||||
GST_TRACE ("Finalize");
|
||||
|
||||
g_mutex_clear (&self->lock);
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_sink_class_init (GstClapperSinkClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
GstBaseSinkClass *gstbasesink_class = (GstBaseSinkClass *) klass;
|
||||
GstVideoSinkClass *gstvideosink_class = (GstVideoSinkClass *) klass;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappersink", 0,
|
||||
"Clapper Sink");
|
||||
|
||||
gobject_class->get_property = gst_clapper_sink_get_property;
|
||||
gobject_class->set_property = gst_clapper_sink_set_property;
|
||||
gobject_class->dispose = gst_clapper_sink_dispose;
|
||||
gobject_class->finalize = gst_clapper_sink_finalize;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
|
||||
g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
|
||||
"When enabled, scaling will respect original aspect ratio",
|
||||
DEFAULT_FORCE_ASPECT_RATIO,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
|
||||
gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio",
|
||||
"The pixel aspect ratio of the device",
|
||||
DEFAULT_PAR_N, DEFAULT_PAR_D,
|
||||
G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_KEEP_LAST_FRAME,
|
||||
g_param_spec_boolean ("keep-last-frame", "Keep last frame",
|
||||
"Keep showing last video frame after playback instead of black screen",
|
||||
DEFAULT_KEEP_LAST_FRAME,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstelement_class->change_state = gst_clapper_sink_change_state;
|
||||
|
||||
gstbasesink_class->get_caps = gst_clapper_sink_get_caps;
|
||||
gstbasesink_class->set_caps = gst_clapper_sink_set_caps;
|
||||
gstbasesink_class->get_times = gst_clapper_sink_get_times;
|
||||
gstbasesink_class->propose_allocation = gst_clapper_sink_propose_allocation;
|
||||
gstbasesink_class->start = gst_clapper_sink_start;
|
||||
gstbasesink_class->stop = gst_clapper_sink_stop;
|
||||
|
||||
gstvideosink_class->show_frame = gst_clapper_sink_show_frame;
|
||||
|
||||
gst_element_class_set_metadata (gstelement_class,
|
||||
"Clapper video sink",
|
||||
"Sink/Video", "A GTK4 video sink used by Clapper media player",
|
||||
"Rafał Dzięgiel <rafostar.github@gmail.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (gstelement_class,
|
||||
&gst_clapper_sink_template);
|
||||
}
|
||||
|
||||
/*
|
||||
* GstNavigationInterface
|
||||
*/
|
||||
static void
|
||||
gst_clapper_sink_navigation_interface_init (GstNavigationInterface *iface)
|
||||
{
|
||||
/* TODO: Port to "send_event_simple" once we depend on GStreamer 1.22 */
|
||||
iface->send_event = gst_clapper_sink_navigation_send_event;
|
||||
}
|
70
lib/gst/plugin/gstclappersink.h
vendored
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gst/video/gstvideosink.h>
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include "gstclapperpaintable.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_CLAPPER_SINK (gst_clapper_sink_get_type())
|
||||
G_DECLARE_FINAL_TYPE (GstClapperSink, gst_clapper_sink, GST, CLAPPER_SINK, GstVideoSink)
|
||||
|
||||
#define GST_CLAPPER_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_SINK, GstClapperSinkClass))
|
||||
#define GST_CLAPPER_SINK_CAST(obj) ((GstClapperSink *)(obj))
|
||||
|
||||
#define GST_CLAPPER_SINK_GET_LOCK(obj) (&GST_CLAPPER_SINK_CAST(obj)->lock)
|
||||
#define GST_CLAPPER_SINK_LOCK(obj) g_mutex_lock (GST_CLAPPER_SINK_GET_LOCK(obj))
|
||||
#define GST_CLAPPER_SINK_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_SINK_GET_LOCK(obj))
|
||||
|
||||
struct _GstClapperSink
|
||||
{
|
||||
GstVideoSink parent;
|
||||
|
||||
GMutex lock;
|
||||
|
||||
GstClapperPaintable *paintable;
|
||||
GstVideoInfo v_info;
|
||||
|
||||
GtkWidget *widget;
|
||||
GtkWindow *window;
|
||||
|
||||
gboolean presented_window;
|
||||
|
||||
/* Properties */
|
||||
gboolean force_aspect_ratio;
|
||||
gint par_n, par_d;
|
||||
gboolean keep_last_frame;
|
||||
|
||||
/* Position coords */
|
||||
gdouble last_pos_x;
|
||||
gdouble last_pos_y;
|
||||
|
||||
gulong widget_destroy_id;
|
||||
gulong window_destroy_id;
|
||||
};
|
||||
|
||||
GST_ELEMENT_REGISTER_DECLARE (clappersink);
|
||||
|
||||
G_END_DECLS
|
131
lib/gst/plugin/gstgtkutils.c
vendored
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* GStreamer
|
||||
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
|
||||
* Copyright (C) 2015 Thibault Saunier <tsaunier@gnome.org>
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "gstgtkutils.h"
|
||||
|
||||
struct invoke_context
|
||||
{
|
||||
GThreadFunc func;
|
||||
gpointer data;
|
||||
GMutex lock;
|
||||
GCond cond;
|
||||
gboolean fired;
|
||||
|
||||
gpointer res;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gst_gtk_invoke_func (struct invoke_context *info)
|
||||
{
|
||||
g_mutex_lock (&info->lock);
|
||||
info->res = info->func (info->data);
|
||||
info->fired = TRUE;
|
||||
g_cond_signal (&info->cond);
|
||||
g_mutex_unlock (&info->lock);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
gpointer
|
||||
gst_gtk_invoke_on_main (GThreadFunc func, gpointer data)
|
||||
{
|
||||
GMainContext *main_context = g_main_context_default ();
|
||||
struct invoke_context info;
|
||||
|
||||
g_mutex_init (&info.lock);
|
||||
g_cond_init (&info.cond);
|
||||
info.fired = FALSE;
|
||||
info.func = func;
|
||||
info.data = data;
|
||||
|
||||
g_main_context_invoke (main_context, (GSourceFunc) gst_gtk_invoke_func,
|
||||
&info);
|
||||
|
||||
g_mutex_lock (&info.lock);
|
||||
while (!info.fired)
|
||||
g_cond_wait (&info.cond, &info.lock);
|
||||
g_mutex_unlock (&info.lock);
|
||||
|
||||
g_mutex_clear (&info.lock);
|
||||
g_cond_clear (&info.cond);
|
||||
|
||||
return info.res;
|
||||
}
|
||||
|
||||
/* For use with `GdkMemoryTexture` only! */
|
||||
GdkMemoryFormat
|
||||
gst_video_format_to_gdk_memory_format (GstVideoFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case GST_VIDEO_FORMAT_RGBA64_LE:
|
||||
case GST_VIDEO_FORMAT_RGBA64_BE:
|
||||
return GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
case GST_VIDEO_FORMAT_RGBA:
|
||||
return GDK_MEMORY_R8G8B8A8;
|
||||
case GST_VIDEO_FORMAT_BGRA:
|
||||
return GDK_MEMORY_B8G8R8A8;
|
||||
case GST_VIDEO_FORMAT_ARGB:
|
||||
return GDK_MEMORY_A8R8G8B8;
|
||||
case GST_VIDEO_FORMAT_ABGR:
|
||||
return GDK_MEMORY_A8B8G8R8;
|
||||
case GST_VIDEO_FORMAT_RGBx:
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
case GST_VIDEO_FORMAT_BGRx:
|
||||
return GDK_MEMORY_B8G8R8A8_PREMULTIPLIED;
|
||||
case GST_VIDEO_FORMAT_RGB:
|
||||
return GDK_MEMORY_R8G8B8;
|
||||
case GST_VIDEO_FORMAT_BGR:
|
||||
return GDK_MEMORY_B8G8R8;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* This should never happen as long as above switch statement
|
||||
* is updated when new formats are added to caps */
|
||||
g_assert_not_reached ();
|
||||
|
||||
/* Fallback format */
|
||||
return GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gst_video_frame_into_gdk_texture (GstVideoFrame *frame, GDestroyNotify free_func)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_bytes_new_with_free_func (
|
||||
GST_VIDEO_FRAME_PLANE_DATA (frame, 0),
|
||||
GST_VIDEO_FRAME_HEIGHT (frame) * GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0),
|
||||
free_func, frame);
|
||||
|
||||
texture = gdk_memory_texture_new (
|
||||
GST_VIDEO_FRAME_WIDTH (frame),
|
||||
GST_VIDEO_FRAME_HEIGHT (frame),
|
||||
gst_video_format_to_gdk_memory_format (GST_VIDEO_FRAME_FORMAT (frame)),
|
||||
bytes,
|
||||
GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
48
lib/gst/plugin/gstplugin.c
vendored
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstclapperimport.h"
|
||||
#include "gstclapperglimport.h"
|
||||
#include "gstclapperdmabufimport.h"
|
||||
#include "gstclappersink.h"
|
||||
#include "gstclappergdkmemory.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin *plugin)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
|
||||
res |= GST_ELEMENT_REGISTER (clapperimport, plugin);
|
||||
res |= GST_ELEMENT_REGISTER (clapperglimport, plugin);
|
||||
res |= GST_ELEMENT_REGISTER (clapperdmabufimport, plugin);
|
||||
res |= GST_ELEMENT_REGISTER (clappersink, plugin);
|
||||
|
||||
if (res)
|
||||
gst_clapper_gdk_memory_init_once ();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
|
||||
clapper, "Clapper elements", plugin_init, VERSION, "LGPL",
|
||||
GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
71
lib/gst/plugin/meson.build
vendored
@@ -1,71 +0,0 @@
|
||||
gst_plugins_libdir = join_paths(prefix, libdir, 'gstreamer-1.0')
|
||||
|
||||
gst_clapper_plugin_args = [
|
||||
'-DHAVE_CONFIG_H',
|
||||
'-DGST_USE_UNSTABLE_API',
|
||||
]
|
||||
gst_clapper_plugin_deps = [
|
||||
gtk4_dep,
|
||||
gst_dep,
|
||||
gstbase_dep,
|
||||
gstvideo_dep,
|
||||
gstallocators_dep,
|
||||
]
|
||||
|
||||
if get_option('default_library') == 'static'
|
||||
gst_clapper_plugin_args += ['-DGST_STATIC_COMPILATION']
|
||||
endif
|
||||
|
||||
gst_clapper_plugin_option = get_option('gst-plugin')
|
||||
if gst_clapper_plugin_option.disabled()
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
foreach dep : gst_clapper_plugin_deps
|
||||
if not dep.found()
|
||||
if gst_clapper_plugin_option.enabled()
|
||||
error('GStreamer plugin was enabled, but required dependencies were not found')
|
||||
endif
|
||||
subdir_done()
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if not have_gtk_gl_windowing
|
||||
if gst_clapper_plugin_option.enabled()
|
||||
error('GTK4 widget requires GL windowing')
|
||||
else
|
||||
subdir_done()
|
||||
endif
|
||||
endif
|
||||
|
||||
if not gtk4_dep.version().version_compare('>=4.6.0')
|
||||
if gst_clapper_plugin_option.enabled()
|
||||
error('GTK4 version on this system is too old, plugin needs 4.6.0+')
|
||||
else
|
||||
subdir_done()
|
||||
endif
|
||||
endif
|
||||
|
||||
gst_clapper_plugin_sources = [
|
||||
'gstclappergdkmemory.c',
|
||||
'gstclappergdkbufferpool.c',
|
||||
'gstclapperbaseimport.c',
|
||||
'gstclapperglbaseimport.c',
|
||||
'gstclapperdmabufbaseimport.c',
|
||||
'gstclapperimport.c',
|
||||
'gstclapperglimport.c',
|
||||
'gstclapperdmabufimport.c',
|
||||
'gstclappersink.c',
|
||||
'gstclapperpaintable.c',
|
||||
'gstgtkutils.c',
|
||||
'gstplugin.c',
|
||||
]
|
||||
|
||||
library('gstclapper',
|
||||
gst_clapper_plugin_sources,
|
||||
c_args: gst_clapper_plugin_args,
|
||||
include_directories: configinc,
|
||||
dependencies: gst_clapper_plugin_deps + gtk_deps,
|
||||
install: true,
|
||||
install_dir: gst_plugins_libdir,
|
||||
)
|
123
lib/meson.build
vendored
@@ -1,5 +1,5 @@
|
||||
glib_req = '>= 2.56.0'
|
||||
gst_req = '>= 1.20.0'
|
||||
gst_req = '>= 1.18.0'
|
||||
|
||||
api_version = '1.0'
|
||||
libversion = meson.project_version()
|
||||
@@ -7,6 +7,10 @@ libversion = meson.project_version()
|
||||
cc = meson.get_compiler('c')
|
||||
cxx = meson.get_compiler('cpp')
|
||||
|
||||
clapper_libdir = join_paths(
|
||||
get_option('prefix'), get_option('libdir'), meson.project_name()
|
||||
)
|
||||
|
||||
cdata = configuration_data()
|
||||
|
||||
if cc.get_id() == 'msvc'
|
||||
@@ -36,7 +40,7 @@ else
|
||||
endif
|
||||
|
||||
if cc.has_link_argument('-Wl,-Bsymbolic-functions')
|
||||
add_project_link_arguments('-Wl,-Bsymbolic-functions', language: 'c')
|
||||
add_project_link_arguments('-Wl,-Bsymbolic-functions', language : 'c')
|
||||
endif
|
||||
|
||||
# Symbol visibility
|
||||
@@ -132,13 +136,13 @@ cdata.set('SIZEOF_SHORT', cc.sizeof('short'))
|
||||
cdata.set('SIZEOF_VOIDP', cc.sizeof('void*'))
|
||||
|
||||
cdata.set_quoted('VERSION', libversion)
|
||||
cdata.set_quoted('PACKAGE', 'clapper')
|
||||
cdata.set_quoted('PACKAGE', 'gst-plugins-clapper')
|
||||
cdata.set_quoted('PACKAGE_VERSION', libversion)
|
||||
cdata.set_quoted('PACKAGE_BUGREPORT', 'https://github.com/Rafostar/clapper/issues/new')
|
||||
cdata.set_quoted('PACKAGE_NAME', 'GStreamer Clapper Libs')
|
||||
cdata.set_quoted('GST_API_VERSION', api_version)
|
||||
cdata.set_quoted('GST_LICENSE', 'LGPL')
|
||||
cdata.set_quoted('LIBDIR', pkglibdir)
|
||||
cdata.set_quoted('LIBDIR', clapper_libdir)
|
||||
cdata.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir')))
|
||||
|
||||
warning_flags = [
|
||||
@@ -184,31 +188,29 @@ foreach extra_arg : warning_flags
|
||||
endif
|
||||
endforeach
|
||||
|
||||
cdata.set_quoted('GST_PACKAGE_NAME', 'gst-plugin-clapper')
|
||||
cdata.set_quoted('GST_PACKAGE_NAME', 'GStreamer Plugins Clapper')
|
||||
cdata.set_quoted('GST_PACKAGE_ORIGIN', 'https://github.com/Rafostar/clapper')
|
||||
|
||||
# Mandatory GST deps
|
||||
gst_dep = dependency('gstreamer-1.0', version: gst_req,
|
||||
fallback: ['gstreamer', 'gst_dep'])
|
||||
gstbase_dep = dependency('gstreamer-base-1.0', version: gst_req,
|
||||
fallback: ['gstreamer', 'gst_base_dep'])
|
||||
gstpbutils_dep = dependency('gstreamer-pbutils-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'pbutils_dep'])
|
||||
gstaudio_dep = dependency('gstreamer-audio-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'audio_dep'])
|
||||
gsttag_dep = dependency('gstreamer-tag-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'tag_dep'])
|
||||
gstvideo_dep = dependency('gstreamer-video-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'video_dep'])
|
||||
gstallocators_dep = dependency('gstreamer-allocators-1.0', version: gst_req,
|
||||
fallback : ['gst-plugins-base', 'allocators_dep'])
|
||||
gst_dep = dependency('gstreamer-1.0', version : gst_req,
|
||||
fallback : ['gstreamer', 'gst_dep'])
|
||||
gstbase_dep = dependency('gstreamer-base-1.0', version : gst_req,
|
||||
fallback : ['gstreamer', 'gst_base_dep'])
|
||||
gstpbutils_dep = dependency('gstreamer-pbutils-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'pbutils_dep'])
|
||||
gstaudio_dep = dependency('gstreamer-audio-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'audio_dep'])
|
||||
gsttag_dep = dependency('gstreamer-tag-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'tag_dep'])
|
||||
gstvideo_dep = dependency('gstreamer-video-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'video_dep'])
|
||||
|
||||
# GStreamer OpenGL
|
||||
gstgl_dep = dependency('gstreamer-gl-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'gstgl_dep'], required: true)
|
||||
gstglx11_dep = dependency('', required: false)
|
||||
gstglwayland_dep = dependency('', required: false)
|
||||
gstglegl_dep = dependency('', required: false)
|
||||
gstgl_dep = dependency('gstreamer-gl-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'gstgl_dep'], required: true)
|
||||
gstglx11_dep = dependency('', required : false)
|
||||
gstglwayland_dep = dependency('', required : false)
|
||||
gstglegl_dep = dependency('', required : false)
|
||||
|
||||
gst_gl_apis = gstgl_dep.get_pkgconfig_variable('gl_apis')
|
||||
gst_gl_winsys = gstgl_dep.get_pkgconfig_variable('gl_winsys')
|
||||
@@ -230,72 +232,53 @@ foreach api : ['gl', 'gles2']
|
||||
set_variable('gst_gl_have_api_@0@'.format(api), gst_gl_apis.contains(api))
|
||||
endforeach
|
||||
|
||||
gstglproto_dep = dependency('gstreamer-gl-prototypes-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'gstglproto_dep'], required: true)
|
||||
gstglproto_dep = dependency('gstreamer-gl-prototypes-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'gstglproto_dep'], required: true)
|
||||
if gst_gl_have_window_x11
|
||||
gstglx11_dep = dependency('gstreamer-gl-x11-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'gstglx11_dep'], required: true)
|
||||
gstglx11_dep = dependency('gstreamer-gl-x11-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'gstglx11_dep'], required: true)
|
||||
endif
|
||||
if gst_gl_have_window_wayland
|
||||
gstglwayland_dep = dependency('gstreamer-gl-wayland-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'gstglwayland_dep'], required: true)
|
||||
gstglwayland_dep = dependency('gstreamer-gl-wayland-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'gstglwayland_dep'], required: true)
|
||||
endif
|
||||
if gst_gl_have_platform_egl
|
||||
gstglegl_dep = dependency('gstreamer-gl-egl-1.0', version: gst_req,
|
||||
fallback: ['gst-plugins-base', 'gstglegl_dep'], required: true)
|
||||
gstglegl_dep = dependency('gstreamer-gl-egl-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'gstglegl_dep'], required: true)
|
||||
endif
|
||||
|
||||
libm = cc.find_library('m', required: false)
|
||||
glib_dep = dependency('glib-2.0', version: glib_req, fallback: ['glib', 'libglib_dep'])
|
||||
libm = cc.find_library('m', required : false)
|
||||
glib_dep = dependency('glib-2.0', version : glib_req, fallback: ['glib', 'libglib_dep'])
|
||||
gmodule_dep = dependency('gmodule-2.0', fallback: ['glib', 'libgmodule_dep'])
|
||||
gio_dep = dependency('gio-2.0', fallback: ['glib', 'libgio_dep'])
|
||||
giounix_dep = dependency('gio-unix-2.0', version: glib_req, fallback: ['glib', 'libgiounix_dep'])
|
||||
|
||||
cdata.set('DISABLE_ORC', 1)
|
||||
cdata.set('GST_ENABLE_EXTRA_CHECKS', get_option('devel-checks'))
|
||||
cdata.set_quoted('GST_PACKAGE_RELEASE_DATETIME', 'Unknown')
|
||||
|
||||
message('GStreamer debug system is disabled')
|
||||
if cc.has_argument('-Wno-unused')
|
||||
add_project_arguments('-Wno-unused', language: 'c')
|
||||
endif
|
||||
if cxx.has_argument ('-Wno-unused')
|
||||
add_project_arguments('-Wno-unused', language: 'cpp')
|
||||
endif
|
||||
|
||||
configinc = include_directories('.')
|
||||
libsinc = include_directories('gst')
|
||||
|
||||
gir = find_program('g-ir-scanner')
|
||||
gnome = import('gnome')
|
||||
gir = find_program('g-ir-scanner', required : true)
|
||||
|
||||
if not gir.found()
|
||||
error('Clapper requires GI bindings to be compiled')
|
||||
endif
|
||||
|
||||
gir_init_section = ['--add-init-section=extern void gst_init(gint*,gchar**);' + \
|
||||
'g_setenv("GST_REGISTRY_1.0", "@0@", TRUE);'.format(meson.current_build_dir() + '/gir_empty_registry.reg') + \
|
||||
'g_setenv("GST_PLUGIN_PATH_1_0", "", TRUE);' + \
|
||||
'g_setenv("GST_PLUGIN_SYSTEM_PATH_1_0", "", TRUE);' + \
|
||||
'gst_init(NULL,NULL);', '--quiet'
|
||||
]
|
||||
|
||||
gtk_deps = [gstgl_dep, gstglproto_dep]
|
||||
have_gtk_gl_windowing = false
|
||||
|
||||
gtk4_dep = dependency('gtk4', required: true)
|
||||
|
||||
if not gtk4_dep.version().version_compare('>=4.0.0')
|
||||
error('GTK4 version on this system is too old')
|
||||
endif
|
||||
|
||||
if gst_gl_have_window_x11 and (gst_gl_have_platform_egl or gst_gl_have_platform_glx)
|
||||
gtk_x11_dep = dependency('gtk4-x11', required: false)
|
||||
if gtk_x11_dep.found()
|
||||
gtk_deps += gtk_x11_dep
|
||||
if gst_gl_have_platform_glx
|
||||
gtk_deps += gstglx11_dep
|
||||
endif
|
||||
have_gtk_gl_windowing = true
|
||||
endif
|
||||
endif
|
||||
|
||||
if gst_gl_have_window_wayland and gst_gl_have_platform_egl
|
||||
gtk_wayland_dep = dependency('gtk4-wayland', required: false)
|
||||
if gtk_wayland_dep.found()
|
||||
gtk_deps += [gtk_wayland_dep, gstglwayland_dep]
|
||||
have_gtk_gl_windowing = true
|
||||
endif
|
||||
endif
|
||||
|
||||
if gst_gl_have_platform_egl
|
||||
gtk_deps += gstglegl_dep
|
||||
endif
|
||||
|
||||
subdir('gst')
|
||||
configure_file(output: 'config.h', configuration: cdata)
|
||||
configure_file(output : 'config.h', configuration : cdata)
|
||||
|
34
meson.build
@@ -1,41 +1,33 @@
|
||||
project('com.github.rafostar.Clapper', 'c', 'cpp',
|
||||
version: '0.4.1',
|
||||
version: '0.2.1',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPL-3.0-or-later',
|
||||
license: 'GPL3',
|
||||
default_options: [
|
||||
'warning_level=1',
|
||||
'buildtype=debugoptimized'
|
||||
]
|
||||
)
|
||||
|
||||
gnome = import('gnome')
|
||||
i18n = import('i18n')
|
||||
python = import('python')
|
||||
python_bin = python.find_installation('python3')
|
||||
|
||||
bindir = join_paths(get_option('prefix'), get_option('bindir'))
|
||||
libdir = join_paths(get_option('prefix'), get_option('libdir'))
|
||||
datadir = join_paths(get_option('prefix'), get_option('datadir'))
|
||||
if not python_bin.found()
|
||||
error('No valid python3 binary found')
|
||||
endif
|
||||
|
||||
pkglibdir = join_paths(libdir, meson.project_name())
|
||||
pkgdatadir = join_paths(datadir, meson.project_name())
|
||||
|
||||
if get_option('lib') or not get_option('gst-plugin').disabled()
|
||||
if get_option('clapper-lib')
|
||||
subdir('lib')
|
||||
endif
|
||||
|
||||
if get_option('player')
|
||||
if get_option('clapper-player')
|
||||
subdir('bin')
|
||||
subdir('data')
|
||||
subdir('po')
|
||||
|
||||
install_subdir('src', install_dir: pkgdatadir)
|
||||
install_subdir('extras', install_dir: pkgdatadir)
|
||||
install_subdir('css', install_dir: pkgdatadir)
|
||||
install_subdir('ui', install_dir: pkgdatadir)
|
||||
installdir = join_paths(get_option('prefix'), 'share', meson.project_name())
|
||||
install_subdir('src', install_dir : installdir)
|
||||
install_subdir('extras', install_dir : installdir)
|
||||
install_subdir('css', install_dir : installdir)
|
||||
install_subdir('ui', install_dir : installdir)
|
||||
|
||||
python_bin = python.find_installation('python3')
|
||||
if not python_bin.found()
|
||||
error('No valid python3 binary found')
|
||||
endif
|
||||
meson.add_install_script('build-aux/meson/postinstall.py')
|
||||
endif
|
||||
|
@@ -1,25 +1,20 @@
|
||||
option('player',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
option('clapper-player',
|
||||
type : 'boolean',
|
||||
value : true,
|
||||
description: 'Build Clapper player'
|
||||
)
|
||||
option('lib',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
description: 'Build GstClapper lib'
|
||||
)
|
||||
option('gst-plugin',
|
||||
type: 'feature',
|
||||
value: 'enabled',
|
||||
description: 'Build GStreamer plugin (includes GTK video sink element)'
|
||||
option('clapper-lib',
|
||||
type : 'boolean',
|
||||
value : true,
|
||||
description: 'Build Clapper libs (including API)'
|
||||
)
|
||||
option('devel-checks',
|
||||
type: 'boolean',
|
||||
value: false,
|
||||
type : 'boolean',
|
||||
value : false,
|
||||
description: 'GStreamer GLib checks and asserts such as API guards (disable for stable releases)'
|
||||
)
|
||||
option('deprecated-glib-api',
|
||||
type: 'boolean',
|
||||
value: true,
|
||||
type : 'boolean',
|
||||
value : true,
|
||||
description: 'Allow using of deprecated GLib API'
|
||||
)
|
||||
|
29
pkgs/arch/.SRCINFO
Normal file
@@ -0,0 +1,29 @@
|
||||
pkgbase = clapper-git
|
||||
pkgdesc = A GNOME media player built using GJS with GTK4 toolkit and powered by GStreamer with OpenGL rendering.
|
||||
pkgver = r393.bf04af2
|
||||
pkgrel = 1
|
||||
url = https://github.com/Rafostar/clapper
|
||||
arch = any
|
||||
license = GPL-3.0
|
||||
makedepends = meson>=0.50
|
||||
makedepends = git
|
||||
depends = gtk4
|
||||
depends = gjs
|
||||
depends = glib2>=2.56.0
|
||||
depends = gobject-introspection
|
||||
depends = wayland-protocols
|
||||
depends = hicolor-icon-theme
|
||||
depends = gstreamer>=1.18.0
|
||||
depends = gst-plugins-base-libs>=1.18.0
|
||||
depends = gst-plugins-good>=1.18.0
|
||||
depends = gst-plugins-bad-libs>=1.18.0
|
||||
optdepends = gst-libav>=1.18.0: Popular video decoders
|
||||
optdepends = gstreamer-vaapi>=1.18.0: Intel/AMD video acceleration
|
||||
provides = clapper
|
||||
conflicts = clapper
|
||||
replaces = clapper
|
||||
source = clapper::git+https://github.com/Rafostar/clapper.git
|
||||
md5sums = SKIP
|
||||
|
||||
pkgname = clapper-git
|
||||
|
4
pkgs/arch/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
clapper-*/
|
||||
clapper-*.pkg.tar.*
|
||||
pkg/
|
||||
src/
|
74
pkgs/arch/PKGBUILD
Normal file
@@ -0,0 +1,74 @@
|
||||
#
|
||||
# PKGBUILD file for package clapper
|
||||
#
|
||||
# Copyright (C) 2020/21 sp1rit
|
||||
# Copyright (C) 2020 Rafostar
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# Maintainer: sp1rit <sp1ritCS@protonmail.com>
|
||||
|
||||
_basename=clapper
|
||||
pkgname="${_basename}-git"
|
||||
pkgver=r393.bf04af2
|
||||
pkgrel=1
|
||||
pkgdesc="A GNOME media player built using GJS with GTK4 toolkit and powered by GStreamer with OpenGL rendering."
|
||||
arch=(any)
|
||||
url="https://github.com/Rafostar/clapper"
|
||||
license=("GPL-3.0")
|
||||
depends=(
|
||||
"gtk4"
|
||||
"gjs"
|
||||
"glib2>=2.56.0" # glib-2.0, gmodule-2.0, gio-2.0
|
||||
"gobject-introspection" # /usr/sbin/g-ir-scanner
|
||||
"wayland-protocols" # gtk4 non-default runtime dep
|
||||
"hicolor-icon-theme"
|
||||
"gstreamer>=1.18.0" # gstreamer-1.0, gstreamer-base-1.0
|
||||
"gst-plugins-base-libs>=1.18.0" # gstreamer-pbutils-1.0, gstreamer-audio-1.0, gstreamer-tag-1.0, gstreamer-video-1.0, gstreamer-gl-1.0, gstreamer-gl-prototypes-1.0, gstreamer-gl-x11-1.0, gstreamer-gl-wayland-1.0, gstreamer-gl-egl-1.0,
|
||||
"gst-plugins-good>=1.18.0"
|
||||
"gst-plugins-bad-libs>=1.18.0"
|
||||
)
|
||||
makedepends=(
|
||||
"meson>=0.50"
|
||||
"git"
|
||||
)
|
||||
optdepends=(
|
||||
"gst-libav>=1.18.0: Popular video decoders"
|
||||
"gstreamer-vaapi>=1.18.0: Intel/AMD video acceleration"
|
||||
)
|
||||
source=("${_basename}::git+https://github.com/Rafostar/${_basename}.git")
|
||||
provides=("${_basename}")
|
||||
replaces=("${_basename}")
|
||||
conflicts=("${_basename}")
|
||||
md5sums=("SKIP")
|
||||
|
||||
pkgver() {
|
||||
cd "${srcdir}/${_basename}"
|
||||
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "${srcdir}/${_basename}"
|
||||
arch-meson . _build
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${_basename}"
|
||||
ninja -C _build
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/${_basename}"
|
||||
DESTDIR="$pkgdir" meson install -C _build/
|
||||
}
|
28
pkgs/deb/clapper.dsc
Normal file
@@ -0,0 +1,28 @@
|
||||
Format: 3.0 (quilt)
|
||||
Source: clapper
|
||||
Binary: clapper
|
||||
Architecture: any
|
||||
Version: 0.2.1
|
||||
Maintainer: Rafostar <rafostar.github@gmail.com>
|
||||
Build-Depends: debhelper (>= 10),
|
||||
meson (>= 0.50),
|
||||
gjs,
|
||||
gobject-introspection,
|
||||
libgtk-4-dev (>= 4.0.0),
|
||||
libgstreamer1.0-dev (>= 1.18),
|
||||
libgstreamer-plugins-base1.0-dev (>= 1.18),
|
||||
libgstreamer-gl1.0-0 (>= 1.18),
|
||||
libgles-dev,
|
||||
libglib2.0-dev,
|
||||
libglib2.0-bin,
|
||||
desktop-file-utils,
|
||||
hicolor-icon-theme,
|
||||
brz,
|
||||
libfontconfig1-dev,
|
||||
libpam-systemd
|
||||
Package-List:
|
||||
clapper deb gnome optional arch=any
|
||||
Files:
|
||||
0 0 debian.tar.xz
|
||||
Description: Simple and modern GNOME media player
|
||||
A GNOME media player built using GJS with GTK4 toolkit and powered by GStreamer with OpenGL rendering.
|
5
pkgs/deb/debian/changelog
Normal file
@@ -0,0 +1,5 @@
|
||||
clapper (0.2.1) unstable; urgency=low
|
||||
|
||||
* New version
|
||||
|
||||
-- Rafostar <rafostar.github@gmail.com> Mon, 19 Apr 2021 09:39:00 +0100
|
1
pkgs/deb/debian/compat
Normal file
@@ -0,0 +1 @@
|
||||
10
|
37
pkgs/deb/debian/control
Normal file
@@ -0,0 +1,37 @@
|
||||
Source: clapper
|
||||
Section: gnome
|
||||
Priority: optional
|
||||
Maintainer: Rafostar <rafostar.github@gmail.com>
|
||||
Standards-Version: 4.4.0
|
||||
Build-Depends: debhelper (>= 10),
|
||||
meson (>= 0.50),
|
||||
gjs,
|
||||
gobject-introspection,
|
||||
libgtk-4-dev (>= 4.0.0),
|
||||
libgstreamer1.0-dev (>= 1.18),
|
||||
libgstreamer-plugins-base1.0-dev (>= 1.18),
|
||||
libgstreamer-gl1.0-0 (>= 1.18),
|
||||
libgles-dev,
|
||||
libglib2.0-dev,
|
||||
libglib2.0-bin,
|
||||
desktop-file-utils,
|
||||
hicolor-icon-theme
|
||||
|
||||
Package: clapper
|
||||
Architecture: any
|
||||
Depends: gjs,
|
||||
gir1.2-gtk-4.0 (>= 4.0.0),
|
||||
hicolor-icon-theme,
|
||||
libgstreamer1.0-0 (>= 1.18),
|
||||
gstreamer1.0-plugins-base (>= 1.18),
|
||||
gstreamer1.0-plugins-good (>= 1.18),
|
||||
gstreamer1.0-plugins-bad (>= 1.18),
|
||||
gstreamer1.0-gl (>= 1.18)
|
||||
Recommends: gstreamer1.0-libav,
|
||||
gstreamer1.0-pulseaudio
|
||||
Suggests: gstreamer1.0-plugins-ugly,
|
||||
gstreamer1.0-vaapi
|
||||
Description: Simple and modern GNOME media player
|
||||
A GNOME media player built using GJS with GTK4 toolkit and powered by GStreamer with OpenGL rendering.
|
||||
.
|
||||
More codecs/features and video acceleration can be enabled by installing the suggested packages.
|
27
pkgs/deb/debian/copyright
Normal file
@@ -0,0 +1,27 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: clapper
|
||||
Source: https://github.com/Rafostar/clapper
|
||||
|
||||
Files: *
|
||||
Copyright: 2020 Rafostar <rafostar.github@gmail.com>
|
||||
License: GPL-3.0+
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2020 Rafostar <rafostar.github@gmail.com>
|
||||
License: GPL-3.0+
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General Public License
|
||||
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
|
4
pkgs/deb/debian/rules
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@
|
1
pkgs/deb/debian/source/format
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
@@ -1,60 +0,0 @@
|
||||
{
|
||||
"app-id": "com.github.rafostar.Clapper",
|
||||
"runtime": "org.gnome.Platform",
|
||||
"runtime-version": "master",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.rust-nightly",
|
||||
"org.freedesktop.Sdk.Extension.llvm13"
|
||||
],
|
||||
"command": "com.github.rafostar.Clapper",
|
||||
"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",
|
||||
"--own-name=org.mpris.MediaPlayer2.Clapper",
|
||||
"--talk-name=org.gnome.Shell",
|
||||
"--env=GST_PLUGIN_SYSTEM_PATH=/app/lib/gstreamer-1.0",
|
||||
"--env=GST_VAAPI_ALL_DRIVERS=1"
|
||||
],
|
||||
"build-options": {
|
||||
"append-path": "/usr/lib/sdk/rust-nightly/bin:/usr/lib/sdk/llvm13/bin",
|
||||
"prepend-ld-library-path": "/usr/lib/sdk/llvm13/lib"
|
||||
},
|
||||
"modules": [
|
||||
"flathub/shared-modules/gudev/gudev.json",
|
||||
"flathub/lib/libsass.json",
|
||||
"flathub/lib/sassc.json",
|
||||
"flathub/lib/libadwaita.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/ffmpeg.json",
|
||||
"testing/gstreamer.json",
|
||||
"testing/gst-plugins-rs.json",
|
||||
"testing/gtuber.json",
|
||||
{
|
||||
"name": "clapper",
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "dir",
|
||||
"path": "../../."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cleanup-commands": [
|
||||
"ln -s /lib/$FLATPAK_ARCH-linux-*/gstreamer-1.0/libgstpipewire.so /app/lib/gstreamer-1.0/"
|
||||
]
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"app-id": "com.github.rafostar.Clapper",
|
||||
"runtime": "org.gnome.Platform",
|
||||
"runtime-version": "42",
|
||||
"runtime-version": "40",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"command": "com.github.rafostar.Clapper",
|
||||
"finish-args": [
|
||||
@@ -12,7 +12,6 @@
|
||||
"--socket=pulseaudio",
|
||||
"--share=network",
|
||||
"--device=all",
|
||||
"--filesystem=xdg-run/pipewire-0:ro",
|
||||
"--filesystem=xdg-videos",
|
||||
"--own-name=org.mpris.MediaPlayer2.Clapper",
|
||||
"--talk-name=org.gnome.Shell",
|
||||
@@ -20,13 +19,14 @@
|
||||
"--env=GST_VAAPI_ALL_DRIVERS=1"
|
||||
],
|
||||
"modules": [
|
||||
"flathub/lib/glib-networking.json",
|
||||
"flathub/shared-modules/gudev/gudev.json",
|
||||
"flathub/lib/pango.json",
|
||||
"flathub/lib/libsass.json",
|
||||
"flathub/lib/sassc.json",
|
||||
"flathub/lib/gtk4.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",
|
||||
@@ -34,9 +34,12 @@
|
||||
"flathub/lib/ffmpeg.json",
|
||||
"flathub/lib/uchardet.json",
|
||||
"flathub/gstreamer-1.0/gstreamer.json",
|
||||
"testing/gtk4.json",
|
||||
"flathub/lib/libadwaita.json",
|
||||
"testing/gtuber.json",
|
||||
"flathub/gstreamer-1.0/gst-plugins-base.json",
|
||||
"flathub/gstreamer-1.0/gst-plugins-good.json",
|
||||
"flathub/gstreamer-1.0/gst-plugins-bad.json",
|
||||
"flathub/gstreamer-1.0/gst-plugins-ugly.json",
|
||||
"flathub/gstreamer-1.0/gst-libav.json",
|
||||
"flathub/gstreamer-1.0/gstreamer-vaapi.json",
|
||||
{
|
||||
"name": "clapper",
|
||||
"buildsystem": "meson",
|
||||
@@ -47,8 +50,5 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cleanup-commands": [
|
||||
"ln -s /lib/$FLATPAK_ARCH-linux-*/gstreamer-1.0/libgstpipewire.so /app/lib/gstreamer-1.0/"
|
||||
]
|
||||
}
|
||||
|
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "gst-plugins-rs",
|
||||
"buildsystem": "simple",
|
||||
"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"
|
||||
]
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
From b413ee2c7d458c7005d3d3d1da8822cd86893ac0 Mon Sep 17 00:00:00 2001
|
||||
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
|
||||
Date: Fri, 4 Dec 2020 19:25:34 +0100
|
||||
Subject: [PATCH] popover: Call unrealize on hide
|
||||
|
||||
When popover is shown "realize" method is called which creates a new
|
||||
surface for popup. Unfortunately this causes performance drop on Wayland until that
|
||||
surface is destroyed what happens inside "unrealize" method during popover destruction.
|
||||
|
||||
This commit changes default behavior in a way that surface will be destroyed
|
||||
when popover is closed and app will ragain the performance it lost when
|
||||
popover was shown.
|
||||
---
|
||||
gtk/gtkpopover.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
|
||||
index 504dcd6cc1..a7a764d483 100644
|
||||
--- a/gtk/gtkpopover.c
|
||||
+++ b/gtk/gtkpopover.c
|
||||
@@ -951,6 +951,7 @@ gtk_popover_hide (GtkWidget *widget)
|
||||
|
||||
gtk_popover_set_mnemonics_visible (GTK_POPOVER (widget), FALSE);
|
||||
_gtk_widget_set_visible_flag (widget, FALSE);
|
||||
+ gtk_widget_unrealize (widget);
|
||||
gtk_widget_unmap (widget);
|
||||
g_signal_emit (widget, signals[CLOSED], 0);
|
||||
}
|
||||
--
|
||||
GitLab
|
||||
|
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"name": "gtk",
|
||||
"buildsystem": "meson",
|
||||
"build-options": {
|
||||
"build-args": [
|
||||
"--share=network"
|
||||
]
|
||||
},
|
||||
"config-opts": [
|
||||
"--buildtype=release",
|
||||
|
||||
"-Dwin32-backend=false",
|
||||
"-Dmacos-backend=false",
|
||||
"-Dmedia-ffmpeg=disabled",
|
||||
"-Dprint-cups=disabled",
|
||||
"-Dintrospection=enabled",
|
||||
"-Ddemos=false",
|
||||
"-Dbuild-examples=false",
|
||||
"-Dbuild-tests=false"
|
||||
],
|
||||
"cleanup": [
|
||||
"/bin/gtk4-builder-tool",
|
||||
"/bin/gtk4-encode-symbolic-svg"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.gnome.org/GNOME/gtk.git",
|
||||
"tag": "4.6.2",
|
||||
"commit": "aec7ca82007dbe07faee6be084d20758ebac2b91"
|
||||
},
|
||||
{
|
||||
"type": "patch",
|
||||
"path": "gtk4-popover-unrealize.patch"
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"name": "gtuber",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": [
|
||||
"-Dintrospection=disabled",
|
||||
"-Dvapi=disabled",
|
||||
"-Dgst-gtuber=enabled"
|
||||
],
|
||||
"cleanup": [
|
||||
"/include",
|
||||
"/lib/pkgconfig"
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/Rafostar/gtuber.git",
|
||||
"branch": "main"
|
||||
}
|
||||
]
|
||||
}
|
3
pkgs/rpm/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.osc/
|
||||
clapper/
|
||||
.lock
|
1
pkgs/rpm/clapper.rpmlintrc
Normal file
@@ -0,0 +1 @@
|
||||
addFilter("explicit-lib-dependency")
|
166
pkgs/rpm/clapper.spec
Normal file
@@ -0,0 +1,166 @@
|
||||
#
|
||||
# spec file for package clapper
|
||||
#
|
||||
# Copyright (C) 2020 sp1rit
|
||||
# Copyright (C) 2020-21 Rafostar
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
%global appname com.github.rafostar.Clapper
|
||||
%global gst_version 1.18.0
|
||||
%global gtk4_version 4.0.0
|
||||
%global meson_version 0.50
|
||||
%global glib2_version 2.56.0
|
||||
|
||||
Name: clapper
|
||||
Version: 0.2.1
|
||||
Release: 1%{?dist}
|
||||
Summary: Simple and modern GNOME media player
|
||||
|
||||
License: GPL-3.0
|
||||
URL: https://github.com/Rafostar/clapper
|
||||
BuildRoot: %{_builddir}/%{name}-%{version}-build
|
||||
Source0: _service
|
||||
|
||||
BuildRequires: meson >= %{meson_version}
|
||||
BuildRequires: gtk4-devel >= %{gtk4_version}
|
||||
BuildRequires: glib2-devel >= %{glib2_version}
|
||||
BuildRequires: gobject-introspection-devel
|
||||
BuildRequires: gjs
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: hicolor-icon-theme
|
||||
|
||||
Requires: gjs
|
||||
Requires: gtk4 >= %{gtk4_version}
|
||||
Requires: hicolor-icon-theme
|
||||
|
||||
%if 0%{?suse_version}
|
||||
# SUSE recommends group tag, while Fedora discourages their use
|
||||
Group: Productivity/Multimedia/Video/Players
|
||||
|
||||
BuildRequires: update-desktop-files
|
||||
BuildRequires: gstreamer-devel >= %{gst_version}
|
||||
BuildRequires: gstreamer-plugins-base-devel >= %{gst_version}
|
||||
BuildRequires: Mesa-libGLESv2-devel
|
||||
BuildRequires: Mesa-libGLESv3-devel
|
||||
|
||||
Requires: gstreamer >= %{gst_version}
|
||||
Requires: gstreamer-plugins-base >= %{gst_version}
|
||||
Requires: gstreamer-plugins-good >= %{gst_version}
|
||||
Requires: gstreamer-plugins-bad >= %{gst_version}
|
||||
|
||||
# Popular video decoders
|
||||
Recommends: gstreamer-plugins-libav >= %{gst_version}
|
||||
|
||||
# CD Playback
|
||||
Suggests: gstreamer-plugins-ugly
|
||||
# Intel/AMD video acceleration
|
||||
Suggests: gstreamer-plugins-vaapi
|
||||
%else
|
||||
BuildRequires: glibc-all-langpacks
|
||||
BuildRequires: gstreamer1-devel >= %{gst_version}
|
||||
BuildRequires: gstreamer1-plugins-base-devel >= %{gst_version}
|
||||
BuildRequires: mesa-libGL-devel
|
||||
BuildRequires: mesa-libGLES-devel
|
||||
BuildRequires: mesa-libGLU-devel
|
||||
BuildRequires: mesa-libEGL-devel
|
||||
|
||||
Requires: gstreamer1 >= %{gst_version}
|
||||
Requires: gstreamer1-plugins-base >= %{gst_version}
|
||||
Requires: gstreamer1-plugins-good >= %{gst_version}
|
||||
Requires: gstreamer1-plugins-bad-free >= %{gst_version}
|
||||
|
||||
# ASS subtitles (assrender)
|
||||
Recommends: gstreamer1-plugins-bad-free-extras >= %{gst_version}
|
||||
|
||||
# CD Playback
|
||||
Suggests: gstreamer1-plugins-ugly-free
|
||||
# Intel/AMD video acceleration
|
||||
Suggests: gstreamer1-vaapi
|
||||
%endif
|
||||
|
||||
%description
|
||||
A GNOME media player built using GJS with GTK4 toolkit and powered by GStreamer with OpenGL rendering.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{_sourcedir}/%{name}-%{version} -T -D
|
||||
|
||||
%build
|
||||
%meson
|
||||
%meson_build
|
||||
|
||||
%install
|
||||
%meson_install
|
||||
%if 0%{?suse_version}
|
||||
%suse_update_desktop_file %{appname}
|
||||
%endif
|
||||
|
||||
%check
|
||||
desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
|
||||
|
||||
%files
|
||||
%license COPYING
|
||||
%doc README.md
|
||||
%{_bindir}/%{appname}*
|
||||
%{_datadir}/%{appname}/
|
||||
%{_datadir}/icons/hicolor/*/apps/*.svg
|
||||
%{_datadir}/glib-2.0/schemas/%{appname}.gschema.xml
|
||||
%{_datadir}/mime/packages/%{appname}.xml
|
||||
%{_datadir}/applications/*.desktop
|
||||
%{_datadir}/metainfo/*.metainfo.xml
|
||||
%{_datadir}/gir-1.0/GstClapper-1.0.gir
|
||||
%{_libdir}/%{appname}/
|
||||
|
||||
%changelog
|
||||
* Mon Apr 19 2021 Rafostar <rafostar.github@gmail.com> - 0.2.1-1
|
||||
- New version
|
||||
|
||||
* Tue Apr 13 2021 Rafostar <rafostar.github@gmail.com> - 0.2.0-1
|
||||
- New version
|
||||
|
||||
* Fri Feb 25 2021 Rafostar <rafostar.github@gmail.com> - 0.1.0-1
|
||||
- New version
|
||||
|
||||
* Sun Feb 7 2021 Rafostar <rafostar.github@gmail.com> - 0.0.0-10
|
||||
- Install gstclapper libs to app named subdirectory
|
||||
|
||||
* Fri Feb 5 2021 Rafostar <rafostar.github@gmail.com> - 0.0.0-9
|
||||
- Update build with gstclapper libs support
|
||||
|
||||
* Thu Jan 21 2021 Rafostar <rafostar.github@gmail.com> - 0.0.0-8
|
||||
- Use metainfo instead of deprecated appdata
|
||||
|
||||
* Mon Jan 18 2021 Rafostar <rafostar.github@gmail.com> - 0.0.0-7
|
||||
- Remove gjs-1.0 files
|
||||
|
||||
* Sun Dec 20 2020 Rafostar <rafostar.github@gmail.com> - 0.0.0-6
|
||||
- Include additional app binaries
|
||||
|
||||
* Sat Oct 31 2020 Rafostar <rafostar.github@gmail.com> - 0.0.0-5
|
||||
- Added metainfo
|
||||
|
||||
* Sun Oct 25 2020 Rafostar <rafostar.github@gmail.com> - 0.0.0-4
|
||||
- Added gschema
|
||||
|
||||
* Wed Oct 14 2020 Rafostar <rafostar.github@gmail.com> - 0.0.0-3
|
||||
- Update to GTK4
|
||||
|
||||
* Sat Sep 19 22:02:00 CEST 2020 sp1rit - 0.0.0-2
|
||||
- Added suse_update_desktop_file macro for SuSE packages
|
||||
|
||||
* Fri Sep 18 2020 Rafostar <rafostar.github@gmail.com> - 0.0.0-1
|
||||
- Initial package
|
@@ -1 +0,0 @@
|
||||
ca cs de es fr hu it nl pl pt pt_BR ru sv zh_CN
|
10
po/POTFILES
@@ -1,10 +0,0 @@
|
||||
ui/clapper.ui
|
||||
ui/elapsed-time-button.ui
|
||||
ui/help-overlay.ui
|
||||
ui/preferences-plugin-ranking-subpage.ui
|
||||
ui/preferences-window.ui
|
||||
|
||||
src/buttons.js
|
||||
src/dialogs.js
|
||||
src/revealers.js
|
||||
src/widget.js
|
459
po/af.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 15:25\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/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
459
po/ar.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 15:25\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/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
459
po/ca.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 16:21\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/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr "Obre fitxers…"
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr "Obre l'URI…"
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr "Preferències"
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr "Dreceres"
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr "Quant al Clapper"
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr "Velocitat"
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr "Normal"
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr "Mostra les dreceres"
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr "Commuta la pantalla completa"
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr "Prem dues vegades | Doble clic"
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr "Surt de la pantalla completa"
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr "Mostra l'OSD (només pantalla completa)"
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr "Toca"
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr "Surt"
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr "Mèdia"
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr "Obre fitxers"
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr "Obre l'URI"
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr "Llista de reproducció"
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr "Element següent"
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr "Prem dues vegades (part dreta)"
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr "Element anterior"
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr "Prem dues vegades (part esquerra)"
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr "Canvia el mode de repetició"
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr "Exporta a un fitxer"
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr "Reproducció"
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr "Commuta la reproducció"
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr "Prem llarga | Clic dret"
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr "Avança"
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr "Llisca el dit a la dreta | Desplaça a la dreta"
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr "Retrocedeix"
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr "Llisca el dit a l'esquerra | Desplaça a l'esquerra"
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr "Apuja el volum"
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr "Llisca el dit cap amunt | Desplaça amunt"
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr "Baixa el volum"
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr "Llisca el dit cap avall | Desplaça cap avall"
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr "Commuta el silenci"
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr "Capítol següent"
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr "Capítol anterior"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr "Descodificadors"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr "Torna a les preferències"
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr "Comportament"
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr "Pantalla completa automàtica"
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr "Entra a pantalla completa quan se substitueix la llista de reproducció excepte el mode flotant"
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr "Pregunta per reprendre recents"
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr "Flota en tots els espais de treball"
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr "Aquesta opció només funciona amb el GNOME"
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr "Després de la reproducció"
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr "No facis res"
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr "Congela l'últim fotograma"
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr "Surt de l'aplicació"
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr "Volum"
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr "Valor inicial personalitzat"
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr "Estableix el volum personalitzat a l'inici en lloc de restaurar-lo"
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr "Percentatge de volum"
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr "Cerca"
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr "Mode"
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr "Acurat"
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr "Ràpid"
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr "Unitat"
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr "Segon"
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr "Minut"
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr "Percentatge"
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr "Àudio"
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr "Desplaçament en mil·lisegons"
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr "Només formats d'àudio natius"
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr "Subtítols"
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr "Tipus de lletra per defecte"
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr "Xarxa"
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr "Client"
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr "Memòria intermèdia de baixada progressiva"
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr "Servidor"
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr "Controla el reproductor remotament"
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr "Port d'escolta"
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr "Executa l'aplicació web en segon pla"
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr "Requereix el GTK compilat amb el backend Broadway"
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr "Port de l'aplicació web"
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr "Prefereix la transmissió adaptativa"
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr "Qualitat màxima"
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr "Ajustaments"
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr "Aparença"
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr "Tema fosc"
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr "Renderitza les ombres de la finestra"
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr "Inhabilita per augmentar el rendiment en mode finestra"
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr "Classificació dels connectors"
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr "Altera els rangs predeterminats dels connectors del GStreamer"
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr "Usa playbin3"
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr "Requereix reiniciar el reproductor"
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr "Experimental"
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr "Usa PipeWire per la sortida d'àudio"
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr "Descodificador: %s"
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr "Escriu o deixa anar una URI aquí"
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr "Obre"
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr "Títol"
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr "Completat"
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr "Reprèn la reproducció?"
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr "Versió del GTK: %s"
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr "Versió del Adwaita: %s"
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr "Versió del GStreamer: %s"
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr "Versió del GJS: %s"
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr "Un reproductor multimèdia del GNOME que usa GStreamer"
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr "Ícar Nin Solana <icar.nin@protonmail.com>, 2021"
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr "Acaba a la/les %s"
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr "Sense determinar"
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr "Canals"
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr "Deshabilitat"
|
||||
|
@@ -1,458 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the com.github.rafostar.Clapper package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.github.rafostar.Clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\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=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
459
po/cs.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-19 20:57\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/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr "Otevřít soubory…"
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr "Otevřít URI…"
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr "Předvolby"
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr "Klávesové zkratky"
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr "O aplikaci Clapper"
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr "Rychlost"
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr "Normální"
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr "Obecné"
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr "Zobrazit klávesové zkratky"
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr "Celá obrazovka"
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr "Dvojitým poklepáním | Dvojitým kliknutím"
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr "Opustit režim celé obrazovky"
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr "Odhalit OSD (pouze při zobrazení na celou obrazovku)"
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr "Klepnutím"
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr "Ukončit"
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr "Média"
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr "Otevřít soubory"
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr "Otevřít URI"
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr "Playlisty"
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr "Další položka"
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr "Dvojité poklepání (pravá strana)"
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr "Předchozí položka"
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr "Dvojité poklepání (levá strana)"
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr "Změnit režim opakování"
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr "Exportovat do souboru"
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr "Přehrávání"
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr "Přepnout přehrávání"
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr "Dlouhým stisknutím | Klepnutím pravým tlačítkem"
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr "Přetočit vpřed"
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr "Přejetím vpravo | Scrollováním vpravo"
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr "Přetočit zpět"
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr "Přejetím vlevo | Scrollováním vlevo"
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr "Zesílit"
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr "Přejetím nahoru | Scrollováním nahoru"
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr "Zeslabit"
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr "Přejetím dolů | Scrollováním dolů"
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr "Vypnout/zapnout zvuk"
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr "Další kapitola"
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr "Předchozí kapitola"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr "Dekodéry"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr "Zpět do předvoleb"
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr "Chování"
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr "Automaticky na celou obrazovku"
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr "Přejít do režimu na celou obrazovku při nahrazení seznamu skladeb s výjimkou plovoucího režimu"
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr "Zeptat se na obnovení nedávných médií"
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr "Plovoucí režim na všech pracovních plochách"
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr "Tato možnost funguje pouze na GNOME"
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr "Po skončení přehrávání"
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr "Nedělat nic"
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr "Zůstat na posledním snímku"
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr "Zavřít aplikaci"
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr "Hlasitost"
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr "Vlastní počáteční hodnota"
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr "Nastavit vlastní hlasitost při spuštění namísto obnovení předchozí hodnoty"
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr "Procento hlasitosti"
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr "Přetáčení"
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr "Režim"
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr "Přesný"
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr "Rychlý"
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr "Jednotka"
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr "Sekundy"
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr "Minuty"
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr "Procenta"
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr "Hodnota"
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr "Zvuk"
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr "Posunutí v milisekundách"
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr "Pouze nativní formáty zvuku"
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr "Titulky"
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr "Výchozí styl písma"
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr "Síť"
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr "Klient"
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr "Postupné stahování do vyrovnávací paměti"
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr "Server"
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr "Vzdáleně ovládat přehrávač"
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr "Naslouchat na portu"
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr "Spustit webovou aplikaci na pozadí"
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr "Vyžaduje GTK kompilovaný s Broadway backendem"
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr "Port webové aplikace"
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr "Preferovat adaptivní streamování"
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr "Maximální kvalita"
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr "Vylepšení"
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr "Vzhled"
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr "Tmavý motiv"
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr "Vykreslovat stíny okna"
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr "Zakázat pro zvýšení výkonu"
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr "Pořadí pluginů"
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr "Změna výchozího pořadí zásuvných modulů GStreameru"
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr "Použít playbin3"
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr "Vyžaduje restart přehrávače"
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr "Experimentální"
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr "Použít PipeWire pro zvukový výstup"
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr "Dekodér: %s"
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr "Zde zadejte nebo přetáhněte URI"
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr "Zrušit"
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr "Otevřít"
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr "Název"
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr "Přehráno"
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr "Pokračovat v přehrávání?"
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr "Verze GTK: %s"
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr "Verze Adwaita: %s"
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr "Verze GStreameru: %s"
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr "Verze GJS: %s"
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr "Přehrávač médií pro GNOME postavený na GStreameru"
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr "Vojtěch Perník <translations@pervoj.cz>"
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr "Končí v: %s"
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr "Neurčeno"
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr "Kanály"
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr "Vypnuto"
|
||||
|
459
po/da.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 15:25\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/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
459
po/de.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 15:25\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/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr "Dateien öffnen…"
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr "Webquelle öffnen…"
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr "Tastenkombinationen"
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr "Über Clapper"
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr "Wiedergabegeschwindigkeit"
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr "Normal"
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr "Allgemein"
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr "Tastenkombinationen zeigen"
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr "In Vollbildmodus wechseln"
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr "Doppelt tippen bzw. klicken"
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr "Vollbildmodus beenden"
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr "OSD zeigen (nur im Vollbildmodus)"
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr "Tippen"
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr "Clapper beenden"
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr "Medien"
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr "Dateien öffnen"
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr "Webquelle öffnen"
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr "Wiedergabeliste"
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr "Nächster Titel"
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr "Doppelt auf der rechten Seite tippen"
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr "Vorheriger Titel"
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr "Doppelt auf der linken Seite tippen"
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr "Wiederholmodus ändern"
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr "Als Datei exportieren"
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr "Wiedergabe"
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr "Wiedergabe umschalten"
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr "Lange Bildschirm berühren oder Rechtsklick"
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr "Vorwärts springen"
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr "Nach rechts wischen bzw. scrollen"
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr "Rückwärts springen"
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr "Nach links wischen bzw. scrollen"
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr "Lautstärke erhöhen"
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr "Nach oben wischen bzw. scrollen"
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr "Lautstärke verringern"
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr "Nach unten wischen bzw. scrollen"
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr "In Vollbildmodus wechseln"
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr "Nächstes Kapitel"
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr "Vorheriges Kapitel"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr "Decodierer"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr "Zurück zu den Einstellungen"
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr "Verhalten"
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr "Automatischer Vollbildmodus"
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr "Vollbildmodus betreten, wenn Wiedergabeliste ersetzt wird. (Außer Clapper befindet sich im Schwebemodus)"
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr "Nachfragen ob kürzlich wiedergegebene Medien weitergespielt werden sollen"
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr "Schwebemodus auf allen Arbeitsflächen"
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr "Diese Option funktioniert nur auf GNOME"
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr "Nach Wiedergabe"
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr "Nichts tun"
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr "Letztes Bild einfrieren"
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr "Anwendung beenden"
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr "Lautstärke"
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr "Benutzerdefinierter Anfangswert"
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr "Lautstärke auf einen fixierten Wert beim Start setzen, anstelle ihn wiederherzustellen."
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr "Lautstärke (in Prozent)"
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr "Springen"
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr "Modus"
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr "Genau"
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr "Schnell"
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr "Einheit"
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr "Sekunden"
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr "Minuten"
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr "Prozentsatz"
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr "Wert"
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr "Audio"
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr "Verschiebung in Millisekunden"
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr "Nur systemeigene Audioformate"
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr "Untertitel"
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr "Standartschriftart"
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr "Netzwerk"
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr "Client"
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr "Fortschreitender Download-Puffer"
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr "Server"
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr "Clapper fernsteuern"
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr "Empfangsport"
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr "Webanwendung im Hintergrund starten"
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr "Benötigt, dass GTK mit Broadway Unterstützung kompiliert wurde"
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr "Webanwendungsport"
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr "Bevorzuge adaptives Streaming"
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr "Höchste Qualität"
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr "Optimierungen"
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr "Erscheinungsbild"
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr "Dunkler Modus"
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr "Fensterschatten darstellen"
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr "Deaktivieren, um Performance im Fenstermodus zu verbessern"
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr "Plugin-Reihenfolge"
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr "Standard GStreamer Reihenfolge verändern"
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr "Playbin3 benutzen"
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr "Benötigt Neustart von Clapper"
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr "Experimentell"
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr "PipeWire für Audioausgabe verwenden"
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr "Decodierer: %s"
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr "URI hier einfügen"
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr "Öffnen"
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr "Abgespielt"
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr "Wiedergabe fortfahren?"
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr "GTK Version: %s"
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr "Adwaita Version: %s"
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr "GStreamer Version: %s"
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr "GJS Version: %s"
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr "Ein von GStreamer betriebener GNOME Multimedia-Player"
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr "Ended um %s"
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr "Unbestimmet"
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr "Audio-Kanäle"
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr "Deaktiviert"
|
||||
|
459
po/el.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 15:25\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Greek\n"
|
||||
"Language: el_GR\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: el\n"
|
||||
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
459
po/es.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2022-01-16 16:58\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Language: es_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: es-ES\n"
|
||||
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr "Abrir archivos…"
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr "Abrir URI…"
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr "Preferencias"
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr "Atajos"
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr "Acerca de Clapper"
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr "Velocidad"
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr "Normal"
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr "Mostrar atajos"
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr "Fijar a pantalla completa"
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr "Doble toque | Doble clic "
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr "Salir de pantalla completa"
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr "Revelar OSD (solo pantalla completa)"
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr "Tocar"
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr "Renunciar"
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr "Media"
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr "Abrir archivos"
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr "Abrir URI"
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr "Lista de reproducción"
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr "Elemento siguiente"
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr "Tocar doble (lado derecho)"
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr "Elemento anterior"
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr "Tocar doble (lado izquierdo)"
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr "Cambiar a modo repetir"
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr "Exportar a archivo"
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr "Reproducir"
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr "Fijar a reproducir"
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr "Pulsación larga | Clic derecho"
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr "Buscar siguiente"
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr "Deslizar a derecha | Desplazar a derecha"
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr "Buscar anterior"
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr "Deslizar a izquierda | Desplazar a izquierda"
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr "Volumen +"
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr "Deslizar + | Desplazar +"
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr "Volumen -"
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr "Deslizar - | Desplazar -"
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr "Fijar a mudo"
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr "Capítulo siguiente"
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr "Capítulo anterior"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr "Decodificadores"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr "Regresar a preferencias"
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr "Configuraciones"
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr "Pantalla completa automática"
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr "Entra a pantalla completa cuando se reemplaza la lista de reproducción, excepto en modo flotante"
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr "Preguntar al reanudar los medios recientes"
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr "Flotar todos los espacios de trabajo"
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr "Esta opción solo funciona en GNOME"
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr "Después de reproducción "
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr "Nada por hacer"
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr "Detener último fotograma"
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr "Cerrar la aplicación"
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr "Volumen"
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr "Valor inicial personalizado"
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr "Establece un volumen personalizado al inicio en lugar de restaurarlo"
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr "Porcentaje de volumen"
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr "Buscando"
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr "Modo"
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr "Precisión"
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr "Rápido"
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr "Unidad"
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr "Segundo"
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr "Minuto"
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr "Porcentaje"
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr "Audio"
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr "Compensación en milisegundos"
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr "Solo formatos de audio nativos"
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr "Subtítulos"
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr "Fuente por defecto"
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr "Red"
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr "Cliente"
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr "Bajada progresiva de búfer"
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr "Servidor"
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr "Controlar el reproductor remotamente"
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr "Puerto de escucha"
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr "Ejecutar la aplicación web en modo demonio"
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr "Requiere GTK compilado con el backend de Broadway"
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr "Puerto de la aplicación web"
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr "Preferir la transmisión adaptativa "
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr "Calidad máxima"
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr "Retoques"
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr "Apariencia"
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr "Tema oscuro"
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr "Renderizar sombras de ventana"
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr "Deshabilitado aumenta el rendimiento cuando se abre en ventana"
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr "Rango de enchufes"
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr "Altera los rangos predeterminados de los enchufes de GStreamer"
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr "Usar Playbin3"
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr "Require reiniciar el reproductor"
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr "Experimental"
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr "Usar PipeWire"
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr "Decodificador: %s"
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr "Introducir la URI"
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr "Abrir"
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr "Título"
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr "Completado"
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr "Resumir el reproductor?"
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr "Versión GTK: %s"
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr "Versión LibAdwaita: %s"
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr "Versión GStreamer: %s"
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr "Versión GJS: %s"
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr "Un reproductor multimedia de GNOME impulsado por GStreamer"
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr "carlosgonz"
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr "Termina en: %s"
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr "Indeterminado"
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr "Canales"
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr "Deshabilitar"
|
||||
|
459
po/eu.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2022-01-16 16:58\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Basque\n"
|
||||
"Language: eu_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: eu\n"
|
||||
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
459
po/fi.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2021-09-14 15:25\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Finnish\n"
|
||||
"Language: fi_FI\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: clapper\n"
|
||||
"X-Crowdin-Project-ID: 473374\n"
|
||||
"X-Crowdin-Language: fi\n"
|
||||
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr ""
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr ""
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr ""
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr ""
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr ""
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
459
po/fr.po
@@ -1,459 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: clapper\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-14 16:35+0200\n"
|
||||
"PO-Revision-Date: 2022-01-18 20:57\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"Language: fr_FR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Crowdin-Project: clapper\n"
|
||||
"X-Crowdin-Project-ID: 473374\n"
|
||||
"X-Crowdin-Language: fr\n"
|
||||
"X-Crowdin-File: /master/po/com.github.rafostar.Clapper.pot\n"
|
||||
"X-Crowdin-File-ID: 31\n"
|
||||
|
||||
#: ui/clapper.ui:6
|
||||
msgid "Open Files…"
|
||||
msgstr "Ouvrir un fichier…"
|
||||
|
||||
#: ui/clapper.ui:10
|
||||
msgid "Open URI…"
|
||||
msgstr "Ouvrir une URL…"
|
||||
|
||||
#: ui/clapper.ui:16 ui/preferences-window.ui:4
|
||||
msgid "Preferences"
|
||||
msgstr "Préférences"
|
||||
|
||||
#: ui/clapper.ui:20
|
||||
msgid "Shortcuts"
|
||||
msgstr "Raccourcis clavier"
|
||||
|
||||
#: ui/clapper.ui:26
|
||||
msgid "About Clapper"
|
||||
msgstr "Á propos de Clapper"
|
||||
|
||||
#: ui/elapsed-time-button.ui:27
|
||||
msgid "Speed"
|
||||
msgstr "Vitesse"
|
||||
|
||||
#: ui/elapsed-time-button.ui:41 ui/preferences-window.ui:83
|
||||
#: ui/preferences-window.ui:215
|
||||
msgid "Normal"
|
||||
msgstr "Normal"
|
||||
|
||||
#: ui/help-overlay.ui:10 ui/preferences-window.ui:12
|
||||
msgid "General"
|
||||
msgstr "Général"
|
||||
|
||||
#: ui/help-overlay.ui:13
|
||||
msgid "Show shortcuts"
|
||||
msgstr "Montrer les raccourcis"
|
||||
|
||||
#: ui/help-overlay.ui:19
|
||||
msgid "Toggle fullscreen"
|
||||
msgstr "Basculer en plein écran"
|
||||
|
||||
#: ui/help-overlay.ui:20
|
||||
msgid "Double tap | Double click"
|
||||
msgstr "Tapoter/cliquer deux fois"
|
||||
|
||||
#: ui/help-overlay.ui:26
|
||||
msgid "Leave fullscreen"
|
||||
msgstr "Sortir du plein écran"
|
||||
|
||||
#: ui/help-overlay.ui:32
|
||||
msgid "Reveal OSD (fullscreen only)"
|
||||
msgstr "Afficher les commandes de lecture (seulement en plein écran)"
|
||||
|
||||
#: ui/help-overlay.ui:33
|
||||
msgid "Tap"
|
||||
msgstr "Taper"
|
||||
|
||||
#: ui/help-overlay.ui:39
|
||||
msgid "Quit"
|
||||
msgstr "Quitter"
|
||||
|
||||
#: ui/help-overlay.ui:47
|
||||
msgid "Media"
|
||||
msgstr "Média"
|
||||
|
||||
#: ui/help-overlay.ui:50
|
||||
msgid "Open files"
|
||||
msgstr "Ouvrir un fichier"
|
||||
|
||||
#: ui/help-overlay.ui:56 src/dialogs.js:137
|
||||
msgid "Open URI"
|
||||
msgstr "Ouvrir une URL"
|
||||
|
||||
#: ui/help-overlay.ui:64
|
||||
msgid "Playlist"
|
||||
msgstr "Playlist"
|
||||
|
||||
#: ui/help-overlay.ui:67
|
||||
msgid "Next item"
|
||||
msgstr "Prochain média"
|
||||
|
||||
#: ui/help-overlay.ui:68
|
||||
msgid "Double tap (right side)"
|
||||
msgstr "Tapoter deux fois (côté droit)"
|
||||
|
||||
#: ui/help-overlay.ui:74
|
||||
msgid "Previous item"
|
||||
msgstr "Média précédent"
|
||||
|
||||
#: ui/help-overlay.ui:75
|
||||
msgid "Double tap (left side)"
|
||||
msgstr "Tapoter deux fois (côté gauche)"
|
||||
|
||||
#: ui/help-overlay.ui:81
|
||||
msgid "Change repeat mode"
|
||||
msgstr "Changer le mode de répétition"
|
||||
|
||||
#: ui/help-overlay.ui:87
|
||||
msgid "Export to file"
|
||||
msgstr "Exporter vers un fichier"
|
||||
|
||||
#: ui/help-overlay.ui:95 ui/preferences-window.ui:119
|
||||
msgid "Playback"
|
||||
msgstr "Lecture"
|
||||
|
||||
#: ui/help-overlay.ui:98
|
||||
msgid "Toggle play"
|
||||
msgstr "Relancer/stopper la lecture"
|
||||
|
||||
#: ui/help-overlay.ui:99
|
||||
msgid "Long press | Right click"
|
||||
msgstr "Longue pression | Clic droit"
|
||||
|
||||
#: ui/help-overlay.ui:105
|
||||
msgid "Seek forward"
|
||||
msgstr "Avancer dans la lecture"
|
||||
|
||||
#: ui/help-overlay.ui:106
|
||||
msgid "Swipe right | Scroll right"
|
||||
msgstr "Glisser/Faire défiler vers la droite"
|
||||
|
||||
#: ui/help-overlay.ui:112
|
||||
msgid "Seek backward"
|
||||
msgstr "Reculer dans la lecture"
|
||||
|
||||
#: ui/help-overlay.ui:113
|
||||
msgid "Swipe left | Scroll left"
|
||||
msgstr "Glisser/Faire défiler vers la gauche"
|
||||
|
||||
#: ui/help-overlay.ui:119
|
||||
msgid "Volume up"
|
||||
msgstr "Augmenter le volume"
|
||||
|
||||
#: ui/help-overlay.ui:120
|
||||
msgid "Swipe up | Scroll up"
|
||||
msgstr "Glisser/Défiler vers le haut"
|
||||
|
||||
#: ui/help-overlay.ui:126
|
||||
msgid "Volume down"
|
||||
msgstr "Baisser le volume"
|
||||
|
||||
#: ui/help-overlay.ui:127
|
||||
msgid "Swipe down | Scroll down"
|
||||
msgstr "Glisser/Défiler vers le bas"
|
||||
|
||||
#: ui/help-overlay.ui:133
|
||||
msgid "Toggle mute"
|
||||
msgstr "Basculer le mode silencieux"
|
||||
|
||||
#: ui/help-overlay.ui:139
|
||||
msgid "Next chapter"
|
||||
msgstr "Prochain chapitre"
|
||||
|
||||
#: ui/help-overlay.ui:145
|
||||
msgid "Previous chapter"
|
||||
msgstr "Chapitre précédent"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:11
|
||||
msgid "Decoders"
|
||||
msgstr "Décodeurs"
|
||||
|
||||
#: ui/preferences-plugin-ranking-subpage.ui:18
|
||||
msgid "Return to the preferences"
|
||||
msgstr "Retourner aux préférences"
|
||||
|
||||
#: ui/preferences-window.ui:16
|
||||
msgid "Behavior"
|
||||
msgstr "Comportement"
|
||||
|
||||
#: ui/preferences-window.ui:19
|
||||
msgid "Auto fullscreen"
|
||||
msgstr "Lecture automatique en plein écran"
|
||||
|
||||
#: ui/preferences-window.ui:20
|
||||
msgid "Enter fullscreen when playlist is replaced except floating mode"
|
||||
msgstr "Basculer en plein écran quand la playlisyt est remplacée sauf si le mode flottant est activé"
|
||||
|
||||
#: ui/preferences-window.ui:26
|
||||
msgid "Ask to resume recent media"
|
||||
msgstr "Demander pour reprendre à la position des médias récents"
|
||||
|
||||
#: ui/preferences-window.ui:32
|
||||
msgid "Float on all workspaces"
|
||||
msgstr "Flotter sur tous les bureaux virtuels"
|
||||
|
||||
#: ui/preferences-window.ui:33
|
||||
msgid "This option only works on GNOME"
|
||||
msgstr "Cette option ne marche qu'avec GNOME"
|
||||
|
||||
#: ui/preferences-window.ui:39
|
||||
msgid "After playback"
|
||||
msgstr "Après la lecture"
|
||||
|
||||
#: ui/preferences-window.ui:44
|
||||
msgid "Do nothing"
|
||||
msgstr "Ne rien faire"
|
||||
|
||||
#: ui/preferences-window.ui:45
|
||||
msgid "Freeze last frame"
|
||||
msgstr "Geler la dernière image"
|
||||
|
||||
#: ui/preferences-window.ui:46
|
||||
msgid "Close the app"
|
||||
msgstr "Fermer l'application"
|
||||
|
||||
#: ui/preferences-window.ui:56
|
||||
msgid "Volume"
|
||||
msgstr "Volume"
|
||||
|
||||
#: ui/preferences-window.ui:59
|
||||
msgid "Custom initial value"
|
||||
msgstr "Valeur initiale personnalisée"
|
||||
|
||||
#: ui/preferences-window.ui:60
|
||||
msgid "Set custom volume at startup instead of restoring it"
|
||||
msgstr "Régler une valeur personnalisée du volume au démarrage au lien de restorer la valeur précédente"
|
||||
|
||||
#: ui/preferences-window.ui:64
|
||||
msgid "Volume percentage"
|
||||
msgstr "Pourcentage du volume"
|
||||
|
||||
#: ui/preferences-window.ui:75
|
||||
msgid "Seeking"
|
||||
msgstr "Avancement"
|
||||
|
||||
#: ui/preferences-window.ui:78
|
||||
msgid "Mode"
|
||||
msgstr "Comportement"
|
||||
|
||||
#: ui/preferences-window.ui:84
|
||||
msgid "Accurate"
|
||||
msgstr "Précis"
|
||||
|
||||
#: ui/preferences-window.ui:85
|
||||
msgid "Fast"
|
||||
msgstr "Rapide"
|
||||
|
||||
#: ui/preferences-window.ui:93
|
||||
msgid "Unit"
|
||||
msgstr "Unité des sauts"
|
||||
|
||||
#: ui/preferences-window.ui:98
|
||||
msgid "Second"
|
||||
msgstr "Seconde"
|
||||
|
||||
#: ui/preferences-window.ui:99
|
||||
msgid "Minute"
|
||||
msgstr "Minute"
|
||||
|
||||
#: ui/preferences-window.ui:100
|
||||
msgid "Percentage"
|
||||
msgstr "Pourcentage"
|
||||
|
||||
#: ui/preferences-window.ui:108
|
||||
msgid "Value"
|
||||
msgstr "Longueur du saut"
|
||||
|
||||
#: ui/preferences-window.ui:123
|
||||
msgid "Audio"
|
||||
msgstr "Audio"
|
||||
|
||||
#: ui/preferences-window.ui:126
|
||||
msgid "Offset in milliseconds"
|
||||
msgstr "Décalage en millisecondes"
|
||||
|
||||
#: ui/preferences-window.ui:133
|
||||
msgid "Only native audio formats"
|
||||
msgstr "Seulement des formats audios natifs"
|
||||
|
||||
#: ui/preferences-window.ui:141
|
||||
msgid "Subtitles"
|
||||
msgstr "Sous-titres"
|
||||
|
||||
#: ui/preferences-window.ui:144
|
||||
msgid "Default font"
|
||||
msgstr "Police par défaut"
|
||||
|
||||
#: ui/preferences-window.ui:154
|
||||
msgid "Network"
|
||||
msgstr "Réseau"
|
||||
|
||||
#: ui/preferences-window.ui:158
|
||||
msgid "Client"
|
||||
msgstr "Client"
|
||||
|
||||
#: ui/preferences-window.ui:161
|
||||
msgid "Progressive download buffering"
|
||||
msgstr "Téléchargement progressif dans le tampon"
|
||||
|
||||
#: ui/preferences-window.ui:169
|
||||
msgid "Server"
|
||||
msgstr "Serveur"
|
||||
|
||||
#: ui/preferences-window.ui:172
|
||||
msgid "Control player remotely"
|
||||
msgstr "Controler le lecteur à distance"
|
||||
|
||||
#: ui/preferences-window.ui:176
|
||||
msgid "Listening port"
|
||||
msgstr "Écouter sur le port"
|
||||
|
||||
#: ui/preferences-window.ui:183
|
||||
msgid "Run web application in background"
|
||||
msgstr "Lancer l'application web en arrière plan"
|
||||
|
||||
#: ui/preferences-window.ui:184
|
||||
msgid "Requires GTK compiled with Broadway backend"
|
||||
msgstr "Requiert GTK compilé avec l'interface Broadway"
|
||||
|
||||
#: ui/preferences-window.ui:190
|
||||
msgid "Web application port"
|
||||
msgstr "Port de l'application web"
|
||||
|
||||
#: ui/preferences-window.ui:204
|
||||
msgid "Prefer adaptive streaming"
|
||||
msgstr "Préférer le streaming adaptatif"
|
||||
|
||||
#: ui/preferences-window.ui:210
|
||||
msgid "Max quality"
|
||||
msgstr "Qualité maximale"
|
||||
|
||||
#: ui/preferences-window.ui:228
|
||||
msgid "Tweaks"
|
||||
msgstr "Réglages"
|
||||
|
||||
#: ui/preferences-window.ui:232
|
||||
msgid "Appearance"
|
||||
msgstr "Apparence"
|
||||
|
||||
#: ui/preferences-window.ui:235
|
||||
msgid "Dark theme"
|
||||
msgstr "Thème sombre"
|
||||
|
||||
#: ui/preferences-window.ui:241
|
||||
msgid "Render window shadows"
|
||||
msgstr "Afficher les ombres de la fenêtre"
|
||||
|
||||
#: ui/preferences-window.ui:242
|
||||
msgid "Disable to increase performance when windowed"
|
||||
msgstr "Désactiver pour améliorer les performances quand fenêtré"
|
||||
|
||||
#: ui/preferences-window.ui:253
|
||||
msgid "Plugin ranking"
|
||||
msgstr "Liste des plugins"
|
||||
|
||||
#: ui/preferences-window.ui:254
|
||||
msgid "Alter default ranks of GStreamer plugins"
|
||||
msgstr "Changer les options par défaut de plugins GStreamer"
|
||||
|
||||
#: ui/preferences-window.ui:259
|
||||
msgid "Use playbin3"
|
||||
msgstr "Utiliser playbin3"
|
||||
|
||||
#: ui/preferences-window.ui:260 ui/preferences-window.ui:269
|
||||
msgid "Requires player restart"
|
||||
msgstr "Requiert le redémarrage du lecteur"
|
||||
|
||||
#: ui/preferences-window.ui:262 ui/preferences-window.ui:271
|
||||
msgid "Experimental"
|
||||
msgstr "Expérimental"
|
||||
|
||||
#: ui/preferences-window.ui:268
|
||||
msgid "Use PipeWire for audio output"
|
||||
msgstr "Utiliser PipeWire pour la sortie audio"
|
||||
|
||||
#: src/buttons.js:201
|
||||
#, javascript-format
|
||||
msgid "Decoder: %s"
|
||||
msgstr "Décodeur: %s"
|
||||
|
||||
#: src/dialogs.js:152
|
||||
msgid "Enter or drop URI here"
|
||||
msgstr "Entrer ou déposer une URL ici"
|
||||
|
||||
#: src/dialogs.js:157
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: src/dialogs.js:158
|
||||
msgid "Open"
|
||||
msgstr "Ouvrir"
|
||||
|
||||
#: src/dialogs.js:226
|
||||
msgid "Title"
|
||||
msgstr "Titre"
|
||||
|
||||
#: src/dialogs.js:227
|
||||
msgid "Completed"
|
||||
msgstr "Terminé"
|
||||
|
||||
#: src/dialogs.js:235
|
||||
msgid "Resume playback?"
|
||||
msgstr "Reprendre la lecture?"
|
||||
|
||||
#: src/dialogs.js:289
|
||||
#, javascript-format
|
||||
msgid "GTK version: %s"
|
||||
msgstr "Version de GTK: %s"
|
||||
|
||||
#: src/dialogs.js:290
|
||||
#, javascript-format
|
||||
msgid "Adwaita version: %s"
|
||||
msgstr "Version d'Adwaita: %s"
|
||||
|
||||
#: src/dialogs.js:291
|
||||
#, javascript-format
|
||||
msgid "GStreamer version: %s"
|
||||
msgstr "Version de GStreamer: %s"
|
||||
|
||||
#: src/dialogs.js:292
|
||||
#, javascript-format
|
||||
msgid "GJS version: %s"
|
||||
msgstr "Version de GJS: %s"
|
||||
|
||||
#: src/dialogs.js:300
|
||||
msgid "A GNOME media player powered by GStreamer"
|
||||
msgstr "Un lecteur multimédia pour GNOME propulsé par GStreamer"
|
||||
|
||||
#. TRANSLATORS: Put your name(s) here for credits or leave untranslated
|
||||
#: src/dialogs.js:305
|
||||
msgid "translator-credits"
|
||||
msgstr "Robin Verdenal-Tallieux"
|
||||
|
||||
#: src/revealers.js:170
|
||||
#, javascript-format
|
||||
msgid "Ends at: %s"
|
||||
msgstr "Finit à: %s"
|
||||
|
||||
#: src/widget.js:227 src/widget.js:236 src/widget.js:242 src/widget.js:248
|
||||
msgid "Undetermined"
|
||||
msgstr "Indéterminé"
|
||||
|
||||
#: src/widget.js:243
|
||||
msgid "Channels"
|
||||
msgstr "Chaines"
|
||||
|
||||
#: src/widget.js:261
|
||||
msgid "Disabled"
|
||||
msgstr "Désactivé"
|
||||
|