mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
Compare commits
1 Commits
0.3.0
...
gstplaylis
Author | SHA1 | Date | |
---|---|---|---|
|
f64f438f1e |
6
TODO.md
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,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 |
@@ -14,10 +14,6 @@
|
||||
<default>100</default>
|
||||
<summary>Custom initial volume value in percentage after startup</summary>
|
||||
</key>
|
||||
<key name="keep-last-frame" type="b">
|
||||
<default>false</default>
|
||||
<summary>Keep showing last video frame after playback finishes</summary>
|
||||
</key>
|
||||
<key name="close-auto" type="b">
|
||||
<default>false</default>
|
||||
<summary>Automatically close the app after playback finishes</summary>
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<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 H.264 videos.
|
||||
for reduced CPU and GPU usage on standard (8-bit) H.264 videos.
|
||||
</p>
|
||||
</description>
|
||||
<developer_name>Rafał Dzięgiel</developer_name>
|
||||
@@ -52,26 +52,6 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<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>
|
||||
|
@@ -4,9 +4,6 @@ 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(sharedir, 'glib-2.0', 'schemas')
|
||||
)
|
||||
|
2
lib/gst/clapper/clapper.h
vendored
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>
|
||||
|
||||
|
@@ -392,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;
|
||||
@@ -771,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;
|
||||
}
|
||||
|
49
lib/gst/clapper/gstclapper-playlist-item-private.h
vendored
Normal file
49
lib/gst/clapper/gstclapper-playlist-item-private.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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_PRIVATE_H__
|
||||
#define __GST_CLAPPER_PLAYLIST_ITEM_PRIVATE_H__
|
||||
|
||||
#include "gstclapper-playlist.h"
|
||||
|
||||
struct _GstClapperPlaylistItem
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
/* ID of the playlist this item belongs to */
|
||||
gchar *owner_uuid;
|
||||
gint id;
|
||||
|
||||
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
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
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__ */
|
43
lib/gst/clapper/gstclapper-playlist-private.h
vendored
Normal file
43
lib/gst/clapper/gstclapper-playlist-private.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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_PRIVATE_H__
|
||||
#define __GST_CLAPPER_PLAYLIST_PRIVATE_H__
|
||||
|
||||
#include "gstclapper-playlist.h"
|
||||
|
||||
struct _GstClapperPlaylist
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
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
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
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__ */
|
290
lib/gst/clapper/gstclapper.c
vendored
290
lib/gst/clapper/gstclapper.c
vendored
@@ -46,6 +46,7 @@
|
||||
#include "gstclapper-signal-dispatcher-private.h"
|
||||
#include "gstclapper-video-renderer-private.h"
|
||||
#include "gstclapper-media-info-private.h"
|
||||
#include "gstclapper-playlist-item-private.h"
|
||||
#include "gstclapper-mpris-private.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_clapper_debug);
|
||||
@@ -79,8 +80,7 @@ enum
|
||||
PROP_SIGNAL_DISPATCHER,
|
||||
PROP_MPRIS,
|
||||
PROP_STATE,
|
||||
PROP_URI,
|
||||
PROP_SUBURI,
|
||||
PROP_PLAYLIST,
|
||||
PROP_POSITION,
|
||||
PROP_DURATION,
|
||||
PROP_MEDIA_INFO,
|
||||
@@ -134,6 +134,7 @@ struct _GstClapper
|
||||
gchar *uri;
|
||||
gchar *redirect_uri;
|
||||
gchar *suburi;
|
||||
gchar *custom_title;
|
||||
|
||||
GThread *thread;
|
||||
GMutex lock;
|
||||
@@ -188,6 +189,12 @@ struct _GstClapper
|
||||
gchar *audio_sid;
|
||||
gchar *subtitle_sid;
|
||||
gulong stream_notify_id;
|
||||
|
||||
/* For playlist */
|
||||
GstClapperPlaylist *playlist;
|
||||
GstClapperPlaylistItem *active_item;
|
||||
gulong item_activated_id;
|
||||
gulong suburi_notify_id;
|
||||
};
|
||||
|
||||
struct _GstClapperClass
|
||||
@@ -320,12 +327,8 @@ gst_clapper_class_init (GstClapperClass * klass)
|
||||
GST_TYPE_CLAPPER_STATE, DEFAULT_STATE, G_PARAM_READABLE |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_URI] = g_param_spec_string ("uri", "URI", "Current URI",
|
||||
DEFAULT_URI, G_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_SUBURI] = g_param_spec_string ("suburi", "Subtitle URI",
|
||||
"Current Subtitle URI", NULL, G_PARAM_READWRITE |
|
||||
param_specs[PROP_PLAYLIST] = g_param_spec_string ("playlist", "Playlist",
|
||||
"Current Playlist", NULL, G_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_POSITION] =
|
||||
@@ -519,6 +522,8 @@ gst_clapper_finalize (GObject * object)
|
||||
g_object_unref (self->signal_dispatcher);
|
||||
if (self->mpris)
|
||||
g_object_unref (self->mpris);
|
||||
if (self->playlist)
|
||||
gst_object_unref (self->playlist);
|
||||
if (self->current_vis_element)
|
||||
gst_object_unref (self->current_vis_element);
|
||||
if (self->collection)
|
||||
@@ -567,35 +572,6 @@ uri_loaded_signal_data_free (UriLoadedSignalData * data)
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_set_uri_internal (gpointer user_data)
|
||||
{
|
||||
GstClapper *self = user_data;
|
||||
|
||||
gst_clapper_stop_internal (self, FALSE);
|
||||
|
||||
g_mutex_lock (&self->lock);
|
||||
GST_DEBUG_OBJECT (self, "Changing URI to '%s'", GST_STR_NULL (self->uri));
|
||||
g_object_set (self->playbin, "uri", self->uri, NULL);
|
||||
g_object_set (self->playbin, "suburi", NULL, NULL);
|
||||
self->can_start = TRUE;
|
||||
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_URI_LOADED], 0, NULL, NULL, NULL) != 0) {
|
||||
UriLoadedSignalData *data = g_new (UriLoadedSignalData, 1);
|
||||
|
||||
data->clapper = g_object_ref (self);
|
||||
data->uri = g_strdup (self->uri);
|
||||
gst_clapper_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
uri_loaded_dispatch, data,
|
||||
(GDestroyNotify) uri_loaded_signal_data_free);
|
||||
}
|
||||
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_set_suburi_internal (gpointer user_data)
|
||||
{
|
||||
@@ -628,6 +604,100 @@ gst_clapper_set_suburi_internal (gpointer user_data)
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
suburi_notify_cb (GstClapperPlaylistItem * item, GParamSpec * pspec,
|
||||
GstClapper * self)
|
||||
{
|
||||
g_mutex_lock (&self->lock);
|
||||
g_free (self->suburi);
|
||||
self->suburi = g_strdup (item->suburi);
|
||||
GST_DEBUG_OBJECT (self, "Set suburi: %s", self->suburi);
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT + 1,
|
||||
gst_clapper_set_suburi_internal, self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_set_playlist_item_locked (GstClapper * self,
|
||||
GstClapperPlaylistItem * item)
|
||||
{
|
||||
if (self->suburi_notify_id)
|
||||
g_signal_handler_disconnect (self->active_item, self->suburi_notify_id);
|
||||
|
||||
gst_object_replace ((GstObject **) & self->active_item,
|
||||
(GstObject *) item);
|
||||
|
||||
g_free (self->uri);
|
||||
self->uri = g_strdup (self->active_item->uri);
|
||||
|
||||
g_free (self->redirect_uri);
|
||||
self->redirect_uri = NULL;
|
||||
|
||||
g_free (self->suburi);
|
||||
self->suburi = g_strdup (self->active_item->suburi);
|
||||
|
||||
g_free (self->custom_title);
|
||||
self->custom_title = g_strdup (self->active_item->custom_title);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Changing URI to '%s'",
|
||||
GST_STR_NULL (self->uri));
|
||||
g_object_set (self->playbin, "uri", self->uri, NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Changing SUBURI to '%s'",
|
||||
GST_STR_NULL (self->suburi));
|
||||
g_object_set (self->playbin, "suburi", self->suburi, NULL);
|
||||
|
||||
self->suburi_notify_id = g_signal_connect (self->active_item,
|
||||
"notify::suburi", G_CALLBACK (suburi_notify_cb), self);
|
||||
|
||||
self->can_start = TRUE;
|
||||
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_URI_LOADED], 0, NULL, NULL, NULL) != 0) {
|
||||
UriLoadedSignalData *data = g_new (UriLoadedSignalData, 1);
|
||||
|
||||
data->clapper = g_object_ref (self);
|
||||
data->uri = g_strdup (self->uri);
|
||||
gst_clapper_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
uri_loaded_dispatch, data,
|
||||
(GDestroyNotify) uri_loaded_signal_data_free);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_clapper_set_playlist_internal (gpointer user_data)
|
||||
{
|
||||
GstClapper *self = user_data;
|
||||
GstClapperPlaylistItem *item;
|
||||
|
||||
gst_clapper_stop_internal (self, FALSE);
|
||||
|
||||
g_mutex_lock (&self->lock);
|
||||
item = gst_clapper_playlist_get_item_at_index (self->playlist, 0);
|
||||
if (!item) {
|
||||
GST_DEBUG_OBJECT (self, "Set empty playlist");
|
||||
goto out;
|
||||
}
|
||||
gst_clapper_set_playlist_item_locked (self, item);
|
||||
|
||||
out:
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
item_activated_cb (G_GNUC_UNUSED GstClapperPlaylist * playlist,
|
||||
GstClapperPlaylistItem * item, gpointer user_data)
|
||||
{
|
||||
GstClapper *self = GST_CLAPPER (user_data);
|
||||
|
||||
g_mutex_lock (&self->lock);
|
||||
gst_clapper_set_playlist_item_locked (self, item);
|
||||
g_mutex_unlock (&self->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_clapper_set_rate_internal (GstClapper * self)
|
||||
{
|
||||
@@ -664,35 +734,21 @@ gst_clapper_set_property (GObject * object, guint prop_id,
|
||||
case PROP_MPRIS:
|
||||
self->mpris = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_URI:{
|
||||
case PROP_PLAYLIST:
|
||||
g_mutex_lock (&self->lock);
|
||||
g_free (self->uri);
|
||||
g_free (self->redirect_uri);
|
||||
self->redirect_uri = NULL;
|
||||
|
||||
g_free (self->suburi);
|
||||
self->suburi = NULL;
|
||||
|
||||
self->uri = g_value_dup_string (value);
|
||||
GST_DEBUG_OBJECT (self, "Set uri=%s", self->uri);
|
||||
if (self->playlist) {
|
||||
if (self->item_activated_id)
|
||||
g_signal_handler_disconnect (self->playlist, self->item_activated_id);
|
||||
gst_object_unref (self->playlist);
|
||||
}
|
||||
self->playlist = g_value_dup_object (value);
|
||||
self->item_activated_id = g_signal_connect (self->playlist, "item-activated",
|
||||
G_CALLBACK (item_activated_cb), self);
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
|
||||
gst_clapper_set_uri_internal, self, NULL);
|
||||
gst_clapper_set_playlist_internal, self, NULL);
|
||||
break;
|
||||
}
|
||||
case PROP_SUBURI:{
|
||||
g_mutex_lock (&self->lock);
|
||||
g_free (self->suburi);
|
||||
|
||||
self->suburi = g_value_dup_string (value);
|
||||
GST_DEBUG_OBJECT (self, "Set suburi=%s", self->suburi);
|
||||
g_mutex_unlock (&self->lock);
|
||||
|
||||
g_main_context_invoke_full (self->context, G_PRIORITY_DEFAULT,
|
||||
gst_clapper_set_suburi_internal, self, NULL);
|
||||
break;
|
||||
}
|
||||
case PROP_VOLUME: {
|
||||
GValue volume_linear = G_VALUE_INIT;
|
||||
gdouble volume = g_value_get_double (value);
|
||||
@@ -757,27 +813,13 @@ gst_clapper_get_property (GObject * object, guint prop_id,
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_MPRIS:
|
||||
g_mutex_lock (&self->lock);
|
||||
g_value_set_object (value, self->mpris);
|
||||
g_mutex_unlock (&self->lock);
|
||||
break;
|
||||
case PROP_STATE:
|
||||
g_mutex_lock (&self->lock);
|
||||
g_value_set_enum (value, self->app_state);
|
||||
g_mutex_unlock (&self->lock);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_mutex_lock (&self->lock);
|
||||
g_value_set_string (value, self->uri);
|
||||
g_mutex_unlock (&self->lock);
|
||||
break;
|
||||
case PROP_SUBURI:
|
||||
g_mutex_lock (&self->lock);
|
||||
g_value_set_string (value, self->suburi);
|
||||
g_mutex_unlock (&self->lock);
|
||||
GST_DEBUG_OBJECT (self, "Returning suburi=%s",
|
||||
g_value_get_string (value));
|
||||
break;
|
||||
case PROP_POSITION:{
|
||||
gint64 position = GST_CLOCK_TIME_NONE;
|
||||
|
||||
@@ -787,12 +829,11 @@ gst_clapper_get_property (GObject * object, guint prop_id,
|
||||
GST_TIME_ARGS (g_value_get_uint64 (value)));
|
||||
break;
|
||||
}
|
||||
case PROP_DURATION:{
|
||||
case PROP_DURATION:
|
||||
g_value_set_uint64 (value, self->cached_duration);
|
||||
GST_TRACE_OBJECT (self, "Returning duration=%" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (g_value_get_uint64 (value)));
|
||||
break;
|
||||
}
|
||||
case PROP_MEDIA_INFO:{
|
||||
GstClapperMediaInfo *media_info = gst_clapper_get_media_info (self);
|
||||
g_value_take_object (value, media_info);
|
||||
@@ -839,20 +880,18 @@ gst_clapper_get_property (GObject * object, guint prop_id,
|
||||
case PROP_PIPELINE:
|
||||
g_value_set_object (value, self->playbin);
|
||||
break;
|
||||
case PROP_VIDEO_MULTIVIEW_MODE:{
|
||||
case PROP_VIDEO_MULTIVIEW_MODE:
|
||||
g_object_get_property (G_OBJECT (self->playbin), "video-multiview-mode",
|
||||
value);
|
||||
GST_TRACE_OBJECT (self, "Return multiview mode=%d",
|
||||
g_value_get_enum (value));
|
||||
break;
|
||||
}
|
||||
case PROP_VIDEO_MULTIVIEW_FLAGS:{
|
||||
case PROP_VIDEO_MULTIVIEW_FLAGS:
|
||||
g_object_get_property (G_OBJECT (self->playbin), "video-multiview-flags",
|
||||
value);
|
||||
GST_TRACE_OBJECT (self, "Return multiview flags=%x",
|
||||
g_value_get_flags (value));
|
||||
break;
|
||||
}
|
||||
case PROP_AUDIO_VIDEO_OFFSET:
|
||||
g_object_get_property (G_OBJECT (self->playbin), "av-offset", value);
|
||||
break;
|
||||
@@ -1618,7 +1657,7 @@ static void
|
||||
emit_duration_changed (GstClapper * self, GstClockTime duration)
|
||||
{
|
||||
if (self->cached_duration == duration
|
||||
|| self->cached_duration / (250 * GST_MSECOND) == duration / (250 * GST_MSECOND))
|
||||
|| self->cached_duration / GST_MSECOND == duration / GST_MSECOND)
|
||||
return;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Duration changed %" GST_TIME_FORMAT,
|
||||
@@ -1806,11 +1845,13 @@ request_state_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
|
||||
static void
|
||||
media_info_update (GstClapper * self, GstClapperMediaInfo * info)
|
||||
{
|
||||
/* Update title from new tags or leave the title from URI */
|
||||
gchar *tags_title = get_from_tags (self, info, get_title);
|
||||
if (tags_title) {
|
||||
g_free (info->title);
|
||||
info->title = tags_title;
|
||||
if (!self->custom_title) {
|
||||
/* Update title from new tags or leave the title from URI */
|
||||
gchar *tags_title = get_from_tags (self, info, get_title);
|
||||
if (tags_title) {
|
||||
g_free (info->title);
|
||||
info->title = tags_title;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (info->container);
|
||||
@@ -2819,7 +2860,10 @@ gst_clapper_media_info_create (GstClapper * self)
|
||||
GST_TYPE_CLAPPER_SUBTITLE_INFO);
|
||||
}
|
||||
|
||||
media_info->title = get_from_tags (self, media_info, get_title);
|
||||
if (self->custom_title)
|
||||
media_info->title = g_strdup (self->custom_title);
|
||||
if (!media_info->title)
|
||||
media_info->title = get_from_tags (self, media_info, get_title);
|
||||
if (!media_info->title)
|
||||
media_info->title = get_title_from_uri (self->uri);
|
||||
|
||||
@@ -3632,77 +3676,19 @@ gst_clapper_get_state (GstClapper * self)
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_get_uri:
|
||||
* gst_clapper_set_playlist:
|
||||
* @clapper: #GstClapper instance
|
||||
* @playlist: #GstClapperPlaylist instance
|
||||
*
|
||||
* Gets the URI of the currently-playing stream.
|
||||
*
|
||||
* Returns: (transfer full): a string containing the URI of the
|
||||
* currently-playing stream. g_free() after usage.
|
||||
*/
|
||||
gchar *
|
||||
gst_clapper_get_uri (GstClapper * self)
|
||||
{
|
||||
gchar *val;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER (self), DEFAULT_URI);
|
||||
|
||||
g_object_get (self, "uri", &val, NULL);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_set_uri:
|
||||
* @clapper: #GstClapper instance
|
||||
* @uri: next URI to play.
|
||||
*
|
||||
* Sets the next URI to play.
|
||||
* Sets the new #GstClapperPlaylist
|
||||
*/
|
||||
void
|
||||
gst_clapper_set_uri (GstClapper * self, const gchar * val)
|
||||
gst_clapper_set_playlist (GstClapper * self, GstClapperPlaylist * val)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CLAPPER (self));
|
||||
g_return_if_fail (GST_IS_CLAPPER_PLAYLIST (val));
|
||||
|
||||
g_object_set (self, "uri", val, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_set_subtitle_uri:
|
||||
* @clapper: #GstClapper instance
|
||||
* @uri: subtitle URI
|
||||
*
|
||||
* Sets the external subtitle URI. This should be combined with a call to
|
||||
* gst_clapper_set_subtitle_track_enabled(@clapper, TRUE) so the subtitles are actually
|
||||
* rendered.
|
||||
*/
|
||||
void
|
||||
gst_clapper_set_subtitle_uri (GstClapper * self, const gchar * suburi)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CLAPPER (self));
|
||||
|
||||
g_object_set (self, "suburi", suburi, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_clapper_get_subtitle_uri:
|
||||
* @clapper: #GstClapper instance
|
||||
*
|
||||
* current subtitle URI
|
||||
*
|
||||
* Returns: (transfer full): URI of the current external subtitle.
|
||||
* g_free() after usage.
|
||||
*/
|
||||
gchar *
|
||||
gst_clapper_get_subtitle_uri (GstClapper * self)
|
||||
{
|
||||
gchar *val = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CLAPPER (self), NULL);
|
||||
|
||||
g_object_get (self, "suburi", &val, NULL);
|
||||
|
||||
return val;
|
||||
g_object_set (self, "playlist", val, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
13
lib/gst/clapper/gstclapper.h
vendored
13
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
|
||||
@@ -193,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,6 +37,10 @@
|
||||
GST_DEBUG_CATEGORY (gst_debug_clapper_gl_sink);
|
||||
#define GST_CAT_DEFAULT gst_debug_clapper_gl_sink
|
||||
|
||||
#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,
|
||||
@@ -58,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,
|
||||
@@ -76,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,
|
||||
@@ -101,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",
|
||||
@@ -109,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;
|
||||
|
||||
@@ -120,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;
|
||||
|
||||
@@ -145,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
|
||||
@@ -210,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. */
|
||||
@@ -261,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;
|
||||
@@ -284,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;
|
||||
@@ -577,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;
|
||||
@@ -603,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);
|
||||
@@ -696,29 +706,6 @@ gst_clapper_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_clapper_gl_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -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__ */
|
||||
|
@@ -57,6 +57,10 @@
|
||||
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;
|
||||
@@ -90,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)
|
||||
@@ -163,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;
|
||||
@@ -185,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;
|
||||
@@ -904,20 +909,30 @@ _get_gl_context (GtkClapperGLWidget * clapper_widget)
|
||||
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
|
||||
@@ -930,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;
|
||||
@@ -979,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 *)
|
||||
|
@@ -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;
|
||||
|
4
lib/gst/clapper/meson.build
vendored
4
lib/gst/clapper/meson.build
vendored
@@ -8,6 +8,8 @@ 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',
|
||||
|
||||
@@ -26,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',
|
||||
]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('com.github.rafostar.Clapper', 'c', 'cpp',
|
||||
version: '0.3.0',
|
||||
version: '0.2.1',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPL3',
|
||||
default_options: [
|
||||
|
@@ -2,7 +2,7 @@ Format: 3.0 (quilt)
|
||||
Source: clapper
|
||||
Binary: clapper
|
||||
Architecture: any
|
||||
Version: 0.3.0
|
||||
Version: 0.2.1
|
||||
Maintainer: Rafostar <rafostar.github@gmail.com>
|
||||
Build-Depends: debhelper (>= 10),
|
||||
meson (>= 0.50),
|
||||
|
@@ -1,5 +1,5 @@
|
||||
clapper (0.3.0) unstable; urgency=low
|
||||
clapper (0.2.1) unstable; urgency=low
|
||||
|
||||
* New version
|
||||
|
||||
-- Rafostar <rafostar.github@gmail.com> Fri, 18 Jun 2021 09:39:00 +0100
|
||||
-- Rafostar <rafostar.github@gmail.com> Mon, 19 Apr 2021 09:39:00 +0100
|
||||
|
@@ -26,7 +26,7 @@
|
||||
%global glib2_version 2.56.0
|
||||
|
||||
Name: clapper
|
||||
Version: 0.3.0
|
||||
Version: 0.2.1
|
||||
Release: 1%{?dist}
|
||||
Summary: Simple and modern GNOME media player
|
||||
|
||||
@@ -126,9 +126,6 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
|
||||
%{_libdir}/%{appname}/
|
||||
|
||||
%changelog
|
||||
* Fri Jun 18 2021 Rafostar <rafostar.github@gmail.com> - 0.3.0-1
|
||||
- New version
|
||||
|
||||
* Mon Apr 19 2021 Rafostar <rafostar.github@gmail.com> - 0.2.1-1
|
||||
- New version
|
||||
|
||||
|
@@ -81,8 +81,7 @@ class ClapperPlayer extends GstClapper.Clapper
|
||||
this._onSettingsKeyChanged(settings, key);
|
||||
|
||||
const flag = Gio.SettingsBindFlags.GET;
|
||||
settings.bind('keep-last-frame', this.widget, 'keep-last-frame', flag);
|
||||
settings.bind('subtitle-font', this.pipeline, 'subtitle-font-desc', flag);
|
||||
settings.bind('subtitle-font', this.pipeline, 'subtitle_font_desc', flag);
|
||||
}
|
||||
|
||||
set_initial_config()
|
||||
|
@@ -41,7 +41,6 @@ class ClapperGeneralPage extends PrefsBase.Grid
|
||||
comboBox.connect('changed', this._onVolumeInitialChanged.bind(this, spinButton));
|
||||
|
||||
this.addTitle('Finish');
|
||||
this.addCheckButton('Keep showing last frame', 'keep-last-frame');
|
||||
this.addCheckButton('Close after playback', 'close-auto');
|
||||
}
|
||||
|
||||
|
@@ -38,7 +38,7 @@ var YouTubeClient = GObject.registerClass({
|
||||
|
||||
this.lastInfo = null;
|
||||
this.postInfo = {
|
||||
clientVersion: "2.20210605.09.00",
|
||||
clientVersion: null,
|
||||
visitorData: "",
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user