Compare commits

63 Commits

Author SHA1 Message Date
Rafał Dzięgiel
c21e1c1c6a Merge pull request #578 from City-busz/window-group
Put each main window into its own group
2025-08-01 16:09:41 +02:00
Balló György
92e0e22e8b Put each main window into its own group
This fixes the problem that a main window cannot be used if a modal dialog
is opened in another main window.
2025-07-31 19:15:29 +02:00
Rafał Dzięgiel
4d5519b42d Merge pull request #575 from Rafostar/playlistable
Expandable playlists support
2025-07-26 18:10:29 +02:00
Rafał Dzięgiel
4a34fb3484 clapper: discoverer: Skip items that already have tags
When tags are populated elsewhere, do not run discovery on them again.
It is possible they were discovered in more efficient maner
(e.g. from playlist data itself).

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

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

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

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

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

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

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

This also works nicely with Clapper discoverer feature.
Making queued items be fetched and cached ahead of playback.
2025-05-20 18:56:28 +02:00
Rafał Dzięgiel
b30d53d8ce clapper: Add ability to set harvest expiration date 2025-05-20 17:18:20 +02:00
Rafał Dzięgiel
1527873bcc clapper: Fix missing unref of mapped file
In case where enhancer plugin version did not match
an unref was missing of read file.
2025-05-19 20:42:32 +02:00
Rafał Dzięgiel
e23f2acb3e meson: Remove unused "config.h" variable 2025-05-18 13:24:51 +02:00
Rafał Dzięgiel
1dfcb218ac meson: Bump min required libadwaita version
Since URI dialog was ported to use AdwAlertDialog,
a minimal Adw version has to be changed to 1.5.
2025-05-17 18:55:31 +02:00
Rafał Dzięgiel
b05f0f2b30 meson: Remove GIR init section
Clapper GStreamer plugin is not part of GObject Introspection,
so no need to init GStreamer when compiling bindings.
2025-05-17 18:20:33 +02:00
Rafał Dzięgiel
dad0d46196 Merge pull request #546 from Rafostar/configurable-enhancers
Make Clapper Enhancers configurable
2025-05-16 18:30:05 +02:00
Rafał Dzięgiel
147d94088c Merge pull request #548 from ximion/master
Use modern appstream, instead of appstream-util for validation
2025-05-03 15:42:28 +02:00
Matthias Klumpp
c7790d9f7b Use modern appstream, instead of appstream-util for validation 2025-05-03 01:56:53 +02:00
188 changed files with 4983 additions and 1494 deletions

View File

@@ -2,7 +2,7 @@
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
@@ -111,7 +111,7 @@ modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -158,7 +158,7 @@ Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
@@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
@@ -267,7 +267,7 @@ Library will still fall under Section 6.)
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
@@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
@@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
@@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
@@ -456,7 +456,7 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
@@ -484,9 +484,7 @@ convey the exclusion of warranty; and each file should have at least the
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
License along with this library; if not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@@ -495,10 +493,9 @@ school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
<signature of Moe Ghoul>, 1 April 1990
Moe Ghoul, President of Vice
That's all there is to it!

View File

@@ -1,5 +1,5 @@
project('clapper', 'c',
version: '0.9.0',
version: '0.9.1',
meson_version: '>= 0.64.0',
license: 'LGPL-2.1-or-later AND GPL-3.0-or-later', # LGPL-2.1+ for libs and gst-plugin, GPL-3.0+ for app
default_options: [
@@ -11,7 +11,7 @@ project('clapper', 'c',
glib_req = '>= 2.76.0'
gst_req = '>= 1.24.0'
gtk4_req = '>= 4.10.0'
adw_req = '>= 1.4.0'
adw_req = '>= 1.5.0'
clapper_version = meson.project_version().split('-')[0]
version_array = clapper_version.split('.')

View File

@@ -642,18 +642,6 @@ clapper_app_application_command_line (GApplication *app, GApplicationCommandLine
return EXIT_SUCCESS;
}
static gboolean
_is_claps_file (GFile *file)
{
gchar *basename = g_file_get_basename (file);
gboolean is_claps;
is_claps = (basename && g_str_has_suffix (basename, ".claps"));
g_free (basename);
return is_claps;
}
static void
add_item_from_file (GFile *file, ClapperQueue *queue)
{
@@ -666,51 +654,6 @@ add_item_from_file (GFile *file, ClapperQueue *queue)
gst_object_unref (item);
}
static void
add_items_from_claps_file (GFile *file, ClapperQueue *queue)
{
GDataInputStream *dstream = NULL;
GFileInputStream *stream;
GError *error = NULL;
gchar *line;
if (!(stream = g_file_read (file, NULL, &error)))
goto finish;
dstream = g_data_input_stream_new (G_INPUT_STREAM (stream));
while ((line = g_data_input_stream_read_line (
dstream, NULL, NULL, &error))) {
g_strstrip (line);
if (strlen (line) > 0) {
GFile *tmp_file = gst_uri_is_valid (line)
? g_file_new_for_uri (line)
: g_file_new_for_path (line);
if (_is_claps_file (tmp_file))
add_items_from_claps_file (tmp_file, queue);
else
add_item_from_file (tmp_file, queue);
g_object_unref (tmp_file);
}
g_free (line);
}
finish:
if (error) {
GST_ERROR ("Could not read \".claps\" file, reason: %s", error->message);
g_error_free (error);
}
if (stream) {
g_input_stream_close (G_INPUT_STREAM (stream), NULL, NULL);
g_object_unref (stream);
}
g_clear_object (&dstream);
}
static void
add_item_with_subtitles (GFile *media_file,
GFile *subs_file, ClapperQueue *queue)
@@ -779,12 +722,8 @@ clapper_app_application_open (GApplication *app,
if (!handled) {
gint i;
for (i = 0; i < n_files; ++i) {
if (_is_claps_file (files[i]))
add_items_from_claps_file (files[i], queue);
else
add_item_from_file (files[i], queue);
}
for (i = 0; i < n_files; ++i)
add_item_from_file (files[i], queue);
}
add_only = (g_strcmp0 (hint, "add-only") == 0);

View File

@@ -582,7 +582,7 @@ _create_pipeline_svg_file_in_thread (GTask *task, GObject *source G_GNUC_UNUSED,
GVC_t *gvc;
gchar *path, *template = NULL, *dot_data = NULL, *img_data = NULL;
gint fd;
guint size = 0;
gsize size = 0;
if (!(tmp_subdir = _create_tmp_subdir ("pipelines", cancellable, &error)))
goto finish;
@@ -610,7 +610,16 @@ _create_pipeline_svg_file_in_thread (GTask *task, GObject *source G_GNUC_UNUSED,
gvc = gvContext ();
gvLayout (gvc, graph, "dot");
#ifdef HAVE_GVC_13
gvRenderData (gvc, graph, "svg", &img_data, &size);
#else
{
guint tmp_size = 0; // Temporary uint to satisfy older API
gvRenderData (gvc, graph, "svg", &img_data, &tmp_size);
size = tmp_size;
}
#endif
agclose (graph);
gvFreeContext (gvc);

View File

@@ -86,9 +86,7 @@ typedef struct
gint64 last_tick;
} ClapperAppWindowResizeData;
#if CLAPPER_HAVE_MPRIS
static guint16 instance_count = 0;
#endif
static inline GQuark
clapper_app_window_extra_options_get_quark (void)
@@ -1200,6 +1198,7 @@ clapper_app_window_init (ClapperAppWindow *self)
GtkSettings *settings;
GtkWidget *dummy_titlebar;
gint distance = 0;
GtkWindowGroup *group;
gtk_widget_set_size_request (GTK_WIDGET (self),
MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
@@ -1231,6 +1230,11 @@ clapper_app_window_init (ClapperAppWindow *self)
gtk_drop_target_set_gtypes (self->drop_target,
(GType[3]) { GDK_TYPE_FILE_LIST, G_TYPE_FILE, G_TYPE_STRING }, 3);
/* Add to window group */
group = gtk_window_group_new ();
gtk_window_group_add_window (group, GTK_WINDOW (self));
g_object_unref (group);
}
static void
@@ -1239,6 +1243,8 @@ clapper_app_window_constructed (GObject *object)
ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (object);
ClapperPlayer *player = clapper_app_window_get_player (self);
ClapperQueue *queue = clapper_player_get_queue (player);
ClapperEnhancerProxyList *proxies = clapper_player_get_enhancer_proxies (player);
ClapperEnhancerProxy *proxy;
ClapperGtkExtraMenuButton *button;
AdwStyleManager *manager;
@@ -1252,22 +1258,30 @@ clapper_app_window_constructed (GObject *object)
#if (CLAPPER_HAVE_MPRIS || CLAPPER_HAVE_SERVER || CLAPPER_HAVE_DISCOVERER)
ClapperFeature *feature = NULL;
#endif
#if CLAPPER_HAVE_MPRIS
gchar mpris_name[45];
g_snprintf (mpris_name, sizeof (mpris_name),
"org.mpris.MediaPlayer2.Clapper.instance%" G_GUINT16_FORMAT, instance_count++);
#endif
self->settings = g_settings_new (CLAPPER_APP_ID);
self->last_volume = PERCENTAGE_ROUND (g_settings_get_double (self->settings, "volume"));
if ((proxy = clapper_enhancer_proxy_list_get_proxy_by_module (proxies, "clapper-mpris"))) {
clapper_enhancer_proxy_set_locally (proxy,
"own-name", mpris_name,
"identity", CLAPPER_APP_NAME,
"desktop-entry", CLAPPER_APP_ID,
"queue-controllable", TRUE, NULL);
gst_object_unref (proxy);
} else {
#if CLAPPER_HAVE_MPRIS
feature = CLAPPER_FEATURE (clapper_mpris_new (
mpris_name, CLAPPER_APP_NAME, CLAPPER_APP_ID));
clapper_mpris_set_queue_controllable (CLAPPER_MPRIS (feature), TRUE);
clapper_player_add_feature (player, feature);
gst_object_unref (feature);
feature = CLAPPER_FEATURE (clapper_mpris_new (
mpris_name, CLAPPER_APP_NAME, CLAPPER_APP_ID));
clapper_mpris_set_queue_controllable (CLAPPER_MPRIS (feature), TRUE);
clapper_player_add_feature (player, feature);
gst_object_unref (feature);
#endif
}
#if CLAPPER_HAVE_SERVER
feature = CLAPPER_FEATURE (clapper_server_new ());

View File

@@ -1,10 +1,11 @@
appstream_util = find_program('appstream-util', required: false)
if appstream_util.found()
appstream_cli = find_program('appstreamcli', required: false)
if appstream_cli.found()
test('Validate appstream file',
appstream_util,
appstream_cli,
args: [
'validate-relax',
'--nonet',
'validate',
'--no-net',
'--explain',
join_paths(meson.current_source_dir(), 'metainfo', 'com.github.rafostar.Clapper.metainfo.xml'),
]
)

View File

@@ -31,8 +31,10 @@
gint
main (gint argc, gchar **argv)
{
const gchar *clapper_ldir;
GApplication *application;
ClapperEnhancerProxyList *proxies;
const gchar *clapper_ldir;
guint i, n_proxies;
gint status;
#ifdef G_OS_WIN32
@@ -64,6 +66,15 @@ main (gint argc, gchar **argv)
resolution = clapper_app_utils_win_hi_res_clock_start ();
#endif
proxies = clapper_get_global_enhancer_proxies ();
n_proxies = clapper_enhancer_proxy_list_get_n_proxies (proxies);
/* Allow usage of all enhancers */
for (i = 0; i < n_proxies; ++i) {
ClapperEnhancerProxy *proxy = clapper_enhancer_proxy_list_peek_proxy (proxies, i);
clapper_enhancer_proxy_set_target_creation_allowed (proxy, TRUE);
}
application = clapper_app_application_new ();
status = g_application_run (application, argc, argv);

View File

@@ -105,6 +105,9 @@ if not pp_option.disabled()
if cgraph_dep.found() and gvc_dep.found()
clapperapp_c_args += ['-DHAVE_GRAPHVIZ']
clapperapp_deps += [cgraph_dep, gvc_dep]
if gvc_dep.version().version_compare('>= 13.0.0')
clapperapp_c_args += ['-DHAVE_GVC_13']
endif
clapperapp_available_functionalities += 'pipeline-preview'
elif pp_option.enabled()
error('pipeline-preview option was enabled, but required dependencies were not found')

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include <clapper/clapper.h>

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "clapper-gtk-buffering-paintable-private.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include <clapper/clapper.h>

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -396,6 +395,47 @@ _update_duration_label (ClapperGtkSeekBar *self, gdouble duration)
gtk_adjustment_set_upper (adjustment, duration);
}
static gboolean
_find_marks_in_widget (GtkWidget *widget, GtkWidget **top_marks, GtkWidget **bottom_marks)
{
GtkWidget *child;
if (g_strcmp0 (gtk_widget_get_css_name (widget), "marks") == 0) {
if (gtk_widget_has_css_class (widget, "top"))
*top_marks = widget;
else if (gtk_widget_has_css_class (widget, "bottom"))
*bottom_marks = widget;
/* Its unexpected to have marks within marks,
* so do not iterate children of marks widget */
return (*top_marks && *bottom_marks);
}
child = gtk_widget_get_first_child (widget);
while (child != NULL) {
if (_find_marks_in_widget (child, top_marks, bottom_marks))
return TRUE;
child = gtk_widget_get_next_sibling (child);
}
return FALSE;
}
static gboolean
_find_last_mark_in_marks (GtkWidget *marks, GtkWidget **last_mark)
{
GtkWidget *widget = gtk_widget_get_last_child (marks);
if (widget && g_strcmp0 (gtk_widget_get_css_name (widget), "mark") == 0) {
*last_mark = widget;
return TRUE;
}
return FALSE;
}
static void
_update_scale_marks (ClapperGtkSeekBar *self, ClapperTimeline *timeline)
{
@@ -424,11 +464,43 @@ _update_scale_marks (ClapperGtkSeekBar *self, ClapperTimeline *timeline)
for (i = 0; i < n_markers; ++i) {
ClapperMarker *marker = clapper_timeline_get_marker (timeline, i);
ClapperMarkerType marker_type = clapper_marker_get_marker_type (marker);
gdouble start = clapper_marker_get_start (marker);
gtk_scale_add_mark (GTK_SCALE (self->scale), start, GTK_POS_TOP, NULL);
gtk_scale_add_mark (GTK_SCALE (self->scale), start, GTK_POS_BOTTOM, NULL);
if (marker_type >= CLAPPER_MARKER_TYPE_CUSTOM_1) {
GtkWidget *top_marks = NULL, *bottom_marks = NULL;
GtkWidget *top_mark = NULL, *bottom_mark = NULL;
if (_find_marks_in_widget (self->scale, &top_marks, &bottom_marks)
&& _find_last_mark_in_marks (top_marks, &top_mark)
&& _find_last_mark_in_marks (bottom_marks, &bottom_mark)) {
const gchar *custom_name;
switch (marker_type) {
case CLAPPER_MARKER_TYPE_CUSTOM_1:
custom_name = "custom1";
break;
case CLAPPER_MARKER_TYPE_CUSTOM_2:
custom_name = "custom2";
break;
case CLAPPER_MARKER_TYPE_CUSTOM_3:
custom_name = "custom3";
break;
default:
custom_name = NULL;
break;
}
if (G_LIKELY (custom_name != NULL)) {
gtk_widget_add_css_class (top_mark, custom_name);
gtk_widget_add_css_class (bottom_mark, custom_name);
}
}
}
gst_object_unref (marker);
}

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -129,6 +129,15 @@ clapper-gtk-seek-bar label {
margin-left: 2px;
margin-right: 2px;
}
clapper-gtk-seek-bar scale marks .custom1 indicator {
color: tomato;
}
clapper-gtk-seek-bar scale marks .custom2 indicator {
color: goldenrod;
}
clapper-gtk-seek-bar scale marks .custom3 indicator {
color: limegreen;
}
clapper-gtk-extra-menu-button popover .spinsidebutton {
min-width: 28px;

View File

@@ -176,7 +176,6 @@ if build_gir
clappergtk_enums,
],
extra_args: [
gir_init_section,
'--quiet',
'--warn-all',
'-DCLAPPER_GTK_COMPILATION',

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -45,6 +44,8 @@ void clapper_app_bus_post_refresh_streams (ClapperAppBus *app_bus, GstObject *sr
void clapper_app_bus_post_refresh_timeline (ClapperAppBus *app_bus, GstObject *src);
void clapper_app_bus_post_insert_playlist (ClapperAppBus *app_bus, GstObject *src, GstObject *playlist_item, GObject *playlist);
void clapper_app_bus_post_simple_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id);
void clapper_app_bus_post_object_desc_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GstObject *object, const gchar *desc);

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include <gio/gio.h>
@@ -22,6 +21,7 @@
#include "clapper-bus-private.h"
#include "clapper-app-bus-private.h"
#include "clapper-player-private.h"
#include "clapper-queue-private.h"
#include "clapper-media-item-private.h"
#include "clapper-timeline-private.h"
@@ -42,6 +42,7 @@ enum
CLAPPER_APP_BUS_STRUCTURE_PROP_NOTIFY,
CLAPPER_APP_BUS_STRUCTURE_REFRESH_STREAMS,
CLAPPER_APP_BUS_STRUCTURE_REFRESH_TIMELINE,
CLAPPER_APP_BUS_STRUCTURE_INSERT_PLAYLIST,
CLAPPER_APP_BUS_STRUCTURE_SIMPLE_SIGNAL,
CLAPPER_APP_BUS_STRUCTURE_OBJECT_DESC_SIGNAL,
CLAPPER_APP_BUS_STRUCTURE_DESC_WITH_DETAILS_SIGNAL,
@@ -53,6 +54,7 @@ static ClapperBusQuark _structure_quarks[] = {
{"prop-notify", 0},
{"refresh-streams", 0},
{"refresh-timeline", 0},
{"insert-playlist", 0},
{"simple-signal", 0},
{"object-desc-signal", 0},
{"desc-with-details-signal", 0},
@@ -66,6 +68,7 @@ enum
CLAPPER_APP_BUS_FIELD_PSPEC,
CLAPPER_APP_BUS_FIELD_SIGNAL_ID,
CLAPPER_APP_BUS_FIELD_OBJECT,
CLAPPER_APP_BUS_FIELD_OTHER_OBJECT,
CLAPPER_APP_BUS_FIELD_DESC,
CLAPPER_APP_BUS_FIELD_DETAILS,
CLAPPER_APP_BUS_FIELD_ERROR,
@@ -77,6 +80,7 @@ static ClapperBusQuark _field_quarks[] = {
{"pspec", 0},
{"signal-id", 0},
{"object", 0},
{"other-object", 0},
{"desc", 0},
{"details", 0},
{"error", 0},
@@ -161,6 +165,36 @@ _handle_refresh_timeline_msg (GstMessage *msg, const GstStructure *structure)
clapper_timeline_refresh (timeline);
}
void
clapper_app_bus_post_insert_playlist (ClapperAppBus *self, GstObject *src,
GstObject *playlist_item, GObject *playlist)
{
GstStructure *structure = gst_structure_new_id (_STRUCTURE_QUARK (INSERT_PLAYLIST),
_FIELD_QUARK (OBJECT), GST_TYPE_OBJECT, playlist_item,
_FIELD_QUARK (OTHER_OBJECT), G_TYPE_OBJECT, playlist,
NULL);
gst_bus_post (GST_BUS_CAST (self), gst_message_new_application (src, structure));
}
static inline void
_handle_insert_playlist_msg (GstMessage *msg, const GstStructure *structure)
{
ClapperPlayer *player = CLAPPER_PLAYER_CAST (GST_MESSAGE_SRC (msg));
ClapperQueue *queue = clapper_player_get_queue (player);
GstObject *playlist_item;
GObject *playlist;
gst_structure_id_get (structure,
_FIELD_QUARK (OBJECT), GST_TYPE_OBJECT, &playlist_item,
_FIELD_QUARK (OTHER_OBJECT), G_TYPE_OBJECT, &playlist,
NULL);
clapper_queue_handle_playlist (queue,
CLAPPER_MEDIA_ITEM (playlist_item), G_LIST_STORE (playlist));
gst_object_unref (playlist_item);
g_object_unref (playlist);
}
void
clapper_app_bus_post_simple_signal (ClapperAppBus *self, GstObject *src, guint signal_id)
{
@@ -286,6 +320,8 @@ clapper_app_bus_message_func (GstBus *bus, GstMessage *msg, gpointer user_data G
_handle_refresh_streams_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (REFRESH_TIMELINE))
_handle_refresh_timeline_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (INSERT_PLAYLIST))
_handle_insert_playlist_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (SIMPLE_SIGNAL))
_handle_simple_signal_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (OBJECT_DESC_SIGNAL))

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
@@ -29,6 +28,7 @@
#include "clapper-app-bus-private.h"
#include "clapper-features-bus-private.h"
#include "clapper-enhancer-proxy-list-private.h"
#include "clapper-reactables-manager-private.h"
#include "gst/clapper-plugin-private.h"
#include "clapper-functionalities-availability.h"
@@ -56,6 +56,7 @@ clapper_init_check_internal (int *argc, char **argv[])
clapper_playbin_bus_initialize ();
clapper_app_bus_initialize ();
clapper_features_bus_initialize ();
clapper_reactables_manager_initialize ();
_proxies = clapper_enhancer_proxy_list_new_named ("global-proxy-list");

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -27,6 +26,9 @@ G_BEGIN_DECLS
G_GNUC_INTERNAL
void clapper_cache_initialize (void);
G_GNUC_INTERNAL
gboolean clapper_cache_is_disabled (void);
G_GNUC_INTERNAL
GMappedFile * clapper_cache_open (const gchar *filename, const gchar **data, GError **error);
@@ -39,12 +41,18 @@ gint clapper_cache_read_int (const gchar **data);
G_GNUC_INTERNAL
guint clapper_cache_read_uint (const gchar **data);
G_GNUC_INTERNAL
gint64 clapper_cache_read_int64 (const gchar **data);
G_GNUC_INTERNAL
gdouble clapper_cache_read_double (const gchar **data);
G_GNUC_INTERNAL
const gchar * clapper_cache_read_string (const gchar **data);
G_GNUC_INTERNAL
const guint8 * clapper_cache_read_data (const gchar **data, gsize *size);
G_GNUC_INTERNAL
GType clapper_cache_read_enum (const gchar **data);
@@ -69,12 +77,18 @@ void clapper_cache_store_int (GByteArray *bytes, gint val);
G_GNUC_INTERNAL
void clapper_cache_store_uint (GByteArray *bytes, guint val);
G_GNUC_INTERNAL
void clapper_cache_store_int64 (GByteArray *bytes, gint64 val);
G_GNUC_INTERNAL
void clapper_cache_store_double (GByteArray *bytes, gdouble val);
G_GNUC_INTERNAL
void clapper_cache_store_string (GByteArray *bytes, const gchar *val);
G_GNUC_INTERNAL
void clapper_cache_store_data (GByteArray *bytes, const guint8 *val, gsize val_size);
G_GNUC_INTERNAL
void clapper_cache_store_enum (GByteArray *bytes, GType enum_type);

View File

@@ -12,20 +12,24 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "clapper-cache-private.h"
#include "clapper-version.h"
#include "clapper-extractable.h"
#include "clapper-playlistable.h"
#include "clapper-reactable.h"
#define CLAPPER_CACHE_HEADER "CLAPPER"
typedef enum
{
CLAPPER_CACHE_IFACE_EXTRACTABLE = 1,
CLAPPER_CACHE_IFACE_PLAYLISTABLE,
CLAPPER_CACHE_IFACE_REACTABLE,
} ClapperCacheIfaces;
static GArray *enum_registry = NULL;
@@ -45,6 +49,12 @@ clapper_cache_initialize (void)
}
}
gboolean
clapper_cache_is_disabled (void)
{
return cache_disabled;
}
GMappedFile *
clapper_cache_open (const gchar *filename, const gchar **data, GError **error)
{
@@ -111,6 +121,15 @@ clapper_cache_read_uint (const gchar **data)
return val;
}
inline gint64
clapper_cache_read_int64 (const gchar **data)
{
gint64 val = *(const gint64 *) *data;
*data += sizeof (gint64);
return val;
}
inline gdouble
clapper_cache_read_double (const gchar **data)
{
@@ -134,6 +153,22 @@ clapper_cache_read_string (const gchar **data)
return str;
}
inline const guint8 *
clapper_cache_read_data (const gchar **data, gsize *size)
{
const guint8 *val = NULL;
*size = *(const gsize *) *data;
*data += sizeof (gsize);
if (G_LIKELY (*size > 0)) {
val = (const guint8 *) *data;
*data += *size;
}
return val;
}
inline GType
clapper_cache_read_enum (const gchar **data)
{
@@ -212,6 +247,10 @@ clapper_cache_read_iface (const gchar **data)
switch (iface_id) {
case CLAPPER_CACHE_IFACE_EXTRACTABLE:
return CLAPPER_TYPE_EXTRACTABLE;
case CLAPPER_CACHE_IFACE_PLAYLISTABLE:
return CLAPPER_TYPE_PLAYLISTABLE;
case CLAPPER_CACHE_IFACE_REACTABLE:
return CLAPPER_TYPE_REACTABLE;
default:
return 0;
}
@@ -332,6 +371,12 @@ clapper_cache_store_uint (GByteArray *bytes, guint val)
g_byte_array_append (bytes, (const guint8 *) &val, sizeof (guint));
}
inline void
clapper_cache_store_int64 (GByteArray *bytes, gint64 val)
{
g_byte_array_append (bytes, (const guint8 *) &val, sizeof (gint64));
}
inline void
clapper_cache_store_double (GByteArray *bytes, gdouble val)
{
@@ -349,6 +394,14 @@ clapper_cache_store_string (GByteArray *bytes, const gchar *val)
g_byte_array_append (bytes, (const guint8 *) val, strlen (val) + 1);
}
inline void
clapper_cache_store_data (GByteArray *bytes, const guint8 *val, gsize val_size)
{
g_byte_array_append (bytes, (const guint8 *) &val_size, sizeof (gsize));
if (G_LIKELY (val_size > 0))
g_byte_array_append (bytes, val, val_size);
}
inline void
clapper_cache_store_enum (GByteArray *bytes, GType enum_type)
{
@@ -388,6 +441,10 @@ clapper_cache_store_iface (GByteArray *bytes, GType iface)
if (iface == CLAPPER_TYPE_EXTRACTABLE)
iface_id = CLAPPER_CACHE_IFACE_EXTRACTABLE;
else if (iface == CLAPPER_TYPE_PLAYLISTABLE)
iface_id = CLAPPER_CACHE_IFACE_PLAYLISTABLE;
else if (iface == CLAPPER_TYPE_REACTABLE)
iface_id = CLAPPER_CACHE_IFACE_REACTABLE;
else
return FALSE;

View File

@@ -12,14 +12,14 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include "clapper-enhancer-proxy-list.h"
#include "clapper-enhancer-proxy.h"
@@ -38,4 +38,7 @@ void clapper_enhancer_proxy_list_fill_from_global_proxies (ClapperEnhancerProxyL
G_GNUC_INTERNAL
void clapper_enhancer_proxy_list_sort (ClapperEnhancerProxyList *list);
G_GNUC_INTERNAL
gboolean clapper_enhancer_proxy_list_has_proxy_with_interface (ClapperEnhancerProxyList *list, GType iface_type);
G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -161,6 +160,29 @@ clapper_enhancer_proxy_list_sort (ClapperEnhancerProxyList *self)
g_ptr_array_sort_values (self->proxies, (GCompareFunc) _sort_values_by_name);
}
/*
* clapper_enhancer_proxy_list_has_proxy_with_interface:
* @iface_type: an interface #GType
*
* Check if any enhancer implementing given interface type is available.
*
* Returns: whether any enhancer proxy was found.
*/
gboolean
clapper_enhancer_proxy_list_has_proxy_with_interface (ClapperEnhancerProxyList *self, GType iface_type)
{
guint i;
for (i = 0; i < self->proxies->len; ++i) {
ClapperEnhancerProxy *proxy = clapper_enhancer_proxy_list_peek_proxy (self, i);
if (clapper_enhancer_proxy_target_has_interface (proxy, iface_type))
return TRUE;
}
return FALSE;
}
/**
* clapper_enhancer_proxy_list_get_proxy:
* @list: a #ClapperEnhancerProxyList

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,15 +12,15 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <glib.h>
#include <glib-object.h>
#include <gst/gst.h>
#include "clapper-enhancer-proxy.h"
@@ -45,6 +45,12 @@ G_GNUC_INTERNAL
GObject * clapper_enhancer_proxy_get_peas_info (ClapperEnhancerProxy *proxy);
G_GNUC_INTERNAL
void clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *proxy, GObject *enhancer);
gboolean clapper_enhancer_proxy_has_locally_set (ClapperEnhancerProxy *proxy, const gchar *property_name);
G_GNUC_INTERNAL
GstStructure * clapper_enhancer_proxy_make_current_config (ClapperEnhancerProxy *proxy);
G_GNUC_INTERNAL
void clapper_enhancer_proxy_apply_config_to_enhancer (ClapperEnhancerProxy *proxy, const GstStructure *config, GObject *enhancer);
G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -47,9 +46,14 @@
#include "clapper-enhancer-proxy-list.h"
#include "clapper-basic-functions.h"
#include "clapper-cache-private.h"
#include "clapper-extractable.h"
#include "clapper-player-private.h"
#include "clapper-utils-private.h"
#include "clapper-enums.h"
#include "clapper-extractable.h"
#include "clapper-playlistable.h"
#include "clapper-reactable.h"
#include "clapper-functionalities-availability.h"
#if CLAPPER_WITH_ENHANCERS_LOADER
@@ -84,6 +88,8 @@ struct _ClapperEnhancerProxy
ClapperEnhancerParamFlags scope;
GstStructure *local_config;
gboolean allowed;
/* GSettings are not thread-safe,
* so store schema instead */
GSettingsSchema *schema;
@@ -98,6 +104,7 @@ enum
PROP_MODULE_DIR,
PROP_DESCRIPTION,
PROP_VERSION,
PROP_TARGET_CREATION_ALLOWED,
PROP_LAST
};
@@ -213,7 +220,7 @@ clapper_enhancer_proxy_copy (ClapperEnhancerProxy *src_proxy, const gchar *copy_
copy->pspecs = g_new (GParamSpec *, copy->n_pspecs);
for (i = 0; i < src_proxy->n_pspecs; ++i)
copy->pspecs[i] = src_proxy->pspecs[i];
copy->pspecs[i] = g_param_spec_ref (src_proxy->pspecs[i]);
copy->scope = CLAPPER_ENHANCER_PARAM_LOCAL;
@@ -227,6 +234,8 @@ clapper_enhancer_proxy_copy (ClapperEnhancerProxy *src_proxy, const gchar *copy_
if (src_proxy->local_config)
copy->local_config = gst_structure_copy (src_proxy->local_config);
copy->allowed = src_proxy->allowed;
GST_OBJECT_UNLOCK (src_proxy);
gst_object_ref_sink (copy);
@@ -345,8 +354,10 @@ clapper_enhancer_proxy_fill_from_cache (ClapperEnhancerProxy *self)
}
/* Plugin version check */
if (g_strcmp0 (clapper_cache_read_string (&data), self->version) != 0)
if (g_strcmp0 (clapper_cache_read_string (&data), self->version) != 0) {
g_mapped_file_unref (mapped_file);
return FALSE; // not an error
}
/* Restore Interfaces */
if ((self->n_ifaces = clapper_cache_read_uint (&data)) > 0) {
@@ -355,6 +366,8 @@ clapper_enhancer_proxy_fill_from_cache (ClapperEnhancerProxy *self)
if (G_UNLIKELY ((self->ifaces[i] = clapper_cache_read_iface (&data)) == 0))
goto abort_reading;
}
/* Reactable type is always last */
self->allowed = (self->ifaces[self->n_ifaces - 1] != CLAPPER_TYPE_REACTABLE);
}
/* Restore ParamSpecs */
@@ -452,7 +465,8 @@ clapper_enhancer_proxy_export_to_cache (ClapperEnhancerProxy *self)
gboolean
clapper_enhancer_proxy_fill_from_instance (ClapperEnhancerProxy *self, GObject *enhancer)
{
GType enhancer_types[1] = { CLAPPER_TYPE_EXTRACTABLE };
/* NOTE: REACTABLE must be last for "allowed" to work as expected */
const GType enhancer_types[] = { CLAPPER_TYPE_EXTRACTABLE, CLAPPER_TYPE_PLAYLISTABLE, CLAPPER_TYPE_REACTABLE };
GType *ifaces;
GParamSpec **pspecs;
GParamFlags enhancer_flags;
@@ -461,9 +475,12 @@ clapper_enhancer_proxy_fill_from_instance (ClapperEnhancerProxy *self, GObject *
/* Filter to only Clapper interfaces */
ifaces = g_type_interfaces (G_OBJECT_TYPE (enhancer), &n);
for (i = 0; i < n; ++i) {
for (j = 0; j < G_N_ELEMENTS (enhancer_types); ++j) {
const guint n_types = G_N_ELEMENTS (enhancer_types);
for (j = 0; j < n_types; ++j) {
if (ifaces[i] == enhancer_types[j]) {
ifaces[write_index++] = ifaces[i];
self->allowed = (j < n_types - 1);
break; // match found, do next iface
}
}
@@ -498,6 +515,18 @@ clapper_enhancer_proxy_get_peas_info (ClapperEnhancerProxy *self)
return self->peas_info;
}
gboolean
clapper_enhancer_proxy_has_locally_set (ClapperEnhancerProxy *self, const gchar *property_name)
{
gboolean has_field;
GST_OBJECT_LOCK (self);
has_field = (self->local_config && gst_structure_has_field (self->local_config, property_name));
GST_OBJECT_UNLOCK (self);
return has_field;
}
static gboolean
_apply_config_cb (GQuark field_id, const GValue *value, GObject *enhancer)
{
@@ -505,15 +534,18 @@ _apply_config_cb (GQuark field_id, const GValue *value, GObject *enhancer)
return TRUE;
}
void
clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *self, GObject *enhancer)
/*
* clapper_enhancer_proxy_make_current_config:
*
* Returns: (transfer full) (nullable): Current merged global and local config as #GstStructure.
*/
GstStructure *
clapper_enhancer_proxy_make_current_config (ClapperEnhancerProxy *self)
{
GSettings *settings = clapper_enhancer_proxy_get_settings (self);
GstStructure *merged_config = NULL;
guint i;
GST_DEBUG_OBJECT (self, "Applying config to enhancer");
/* Lock here to ensure consistent local config */
GST_OBJECT_LOCK (self);
@@ -522,6 +554,7 @@ clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *s
/* Using "has_field", as set value might be %NULL */
if ((pspec->flags & CLAPPER_ENHANCER_PARAM_LOCAL)
&& self->local_config
&& gst_structure_has_field (self->local_config, pspec->name)) {
if (!merged_config)
merged_config = gst_structure_new_empty (CONFIG_STRUCTURE_NAME);
@@ -535,44 +568,13 @@ clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *s
GVariant *def = g_settings_get_default_value (settings, pspec->name);
if (!g_variant_equal (val, def)) {
if (!merged_config)
merged_config = gst_structure_new_empty (CONFIG_STRUCTURE_NAME);
GValue value = G_VALUE_INIT;
switch (pspec->value_type) {
case G_TYPE_BOOLEAN:
gst_structure_set (merged_config, pspec->name,
pspec->value_type, g_variant_get_boolean (val), NULL);
break;
case G_TYPE_INT:
gst_structure_set (merged_config, pspec->name,
pspec->value_type, g_variant_get_int32 (val), NULL);
break;
case G_TYPE_UINT:
gst_structure_set (merged_config, pspec->name,
pspec->value_type, g_variant_get_uint32 (val), NULL);
break;
case G_TYPE_DOUBLE:
gst_structure_set (merged_config, pspec->name,
pspec->value_type, g_variant_get_double (val), NULL);
break;
case G_TYPE_STRING:
gst_structure_set (merged_config, pspec->name,
pspec->value_type, g_variant_get_string (val, NULL), NULL);
break;
default:{
if (G_IS_PARAM_SPEC_ENUM (pspec)) {
gst_structure_set (merged_config, pspec->name,
G_TYPE_INT, g_variant_get_int32 (val), NULL);
break;
} else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
gst_structure_set (merged_config, pspec->name,
G_TYPE_UINT, g_variant_get_uint32 (val), NULL);
break;
}
GST_ERROR_OBJECT (self, "Unsupported enhancer \"%s\" setting type: %s",
pspec->name, g_type_name (pspec->value_type));
break;
}
if (G_LIKELY (clapper_utils_set_value_from_variant (&value, val))) {
if (!merged_config)
merged_config = gst_structure_new_empty (CONFIG_STRUCTURE_NAME);
gst_structure_take_value (merged_config, pspec->name, &value);
}
}
@@ -585,13 +587,14 @@ clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *s
g_clear_object (&settings);
/* Nothing if no configurable properties
* or all have default values */
if (merged_config) {
gst_structure_foreach (merged_config, (GstStructureForeachFunc) _apply_config_cb, enhancer);
gst_structure_free (merged_config);
}
return merged_config;
}
void
clapper_enhancer_proxy_apply_config_to_enhancer (ClapperEnhancerProxy *self, const GstStructure *config, GObject *enhancer)
{
GST_DEBUG_OBJECT (self, "Applying config to enhancer");
gst_structure_foreach (config, (GstStructureForeachFunc) _apply_config_cb, enhancer);
GST_DEBUG_OBJECT (self, "Enhancer config applied");
}
@@ -700,7 +703,7 @@ clapper_enhancer_proxy_get_version (ClapperEnhancerProxy *self)
*
* Get extra data from enhancer plugin info file specified by @key.
*
* External data in the plugin info file is prefixed with `X-`.
* Extra data in the plugin info file is prefixed with `X-`.
* For example `X-Schemes=https`.
*
* Returns: (nullable): extra data value of the proxied enhancer.
@@ -734,6 +737,10 @@ clapper_enhancer_proxy_get_extra_data (ClapperEnhancerProxy *self, const gchar *
* calling this function with "X-Schemes" as key and "http" as value will
* return %TRUE.
*
* It is also safe to call this function when there is no such @key
* in plugin info file. Use [method@Clapper.EnhancerProxy.get_extra_data]
* if you need to know whether key exists.
*
* Returns: whether list named with @key existed and contained @value.
*
* Since: 0.10
@@ -937,6 +944,20 @@ _structure_take_value_by_pspec (ClapperEnhancerProxy *self,
return FALSE;
}
static void
_trigger_reactable_configure_take (ClapperEnhancerProxy *self, GstStructure *structure)
{
ClapperPlayer *player = clapper_player_get_from_ancestor (GST_OBJECT_CAST (self));
if (G_LIKELY (player != NULL)) {
clapper_reactables_manager_trigger_configure_take_config (
player->reactables_manager, self, structure);
gst_object_unref (player);
} else {
gst_structure_free (structure);
}
}
/**
* clapper_enhancer_proxy_set_locally:
* @proxy: a #ClapperEnhancerProxy
@@ -1007,10 +1028,10 @@ clapper_enhancer_proxy_set_locally (ClapperEnhancerProxy *self, const gchar *fir
_update_local_config_from_structure (self, structure);
/* TODO: _post_local_config instead of free if managed
* (for when managed interfaces are implemented) */
gst_structure_free (structure);
if (clapper_enhancer_proxy_target_has_interface (self, CLAPPER_TYPE_REACTABLE))
_trigger_reactable_configure_take (self, structure);
else
gst_structure_free (structure);
}
/**
@@ -1074,10 +1095,62 @@ clapper_enhancer_proxy_set_locally_with_table (ClapperEnhancerProxy *self, GHash
_update_local_config_from_structure (self, structure);
/* TODO: _post_local_config instead of free if managed
* (for when managed interfaces are implemented) */
if (clapper_enhancer_proxy_target_has_interface (self, CLAPPER_TYPE_REACTABLE))
_trigger_reactable_configure_take (self, structure);
else
gst_structure_free (structure);
}
gst_structure_free (structure);
/**
* clapper_enhancer_proxy_set_target_creation_allowed:
* @proxy: a #ClapperEnhancerProxy
* @allowed: whether allowed
*
* Set whether to allow instances of proxy target to be created.
*
* See [property@Clapper.EnhancerProxy:target-creation-allowed] for
* detailed descripton what this does.
*
* Since: 0.10
*/
void
clapper_enhancer_proxy_set_target_creation_allowed (ClapperEnhancerProxy *self, gboolean allowed)
{
gboolean changed;
g_return_if_fail (CLAPPER_IS_ENHANCER_PROXY (self));
GST_OBJECT_LOCK (self);
if ((changed = self->allowed != allowed))
self->allowed = allowed;
GST_OBJECT_UNLOCK (self);
if (changed)
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_TARGET_CREATION_ALLOWED]);
}
/**
* clapper_enhancer_proxy_get_target_creation_allowed:
* @proxy: a #ClapperEnhancerProxy
*
* Get whether it is allowed to create instances of enhancer that this proxy targets.
*
* Returns: whether target creation is allowed.
*
* Since: 0.10
*/
gboolean
clapper_enhancer_proxy_get_target_creation_allowed (ClapperEnhancerProxy *self)
{
gboolean allowed;
g_return_val_if_fail (CLAPPER_IS_ENHANCER_PROXY (self), FALSE);
GST_OBJECT_LOCK (self);
allowed = self->allowed;
GST_OBJECT_UNLOCK (self);
return allowed;
}
static void
@@ -1129,6 +1202,25 @@ clapper_enhancer_proxy_get_property (GObject *object, guint prop_id,
case PROP_VERSION:
g_value_set_string (value, clapper_enhancer_proxy_get_version (self));
break;
case PROP_TARGET_CREATION_ALLOWED:
g_value_set_boolean (value, clapper_enhancer_proxy_get_target_creation_allowed (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_enhancer_proxy_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperEnhancerProxy *self = CLAPPER_ENHANCER_PROXY_CAST (object);
switch (prop_id) {
case PROP_TARGET_CREATION_ALLOWED:
clapper_enhancer_proxy_set_target_creation_allowed (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1144,6 +1236,7 @@ clapper_enhancer_proxy_class_init (ClapperEnhancerProxyClass *klass)
"Clapper Enhancer Proxy");
gobject_class->get_property = clapper_enhancer_proxy_get_property;
gobject_class->set_property = clapper_enhancer_proxy_set_property;
gobject_class->finalize = clapper_enhancer_proxy_finalize;
/**
@@ -1201,5 +1294,29 @@ clapper_enhancer_proxy_class_init (ClapperEnhancerProxyClass *klass)
NULL, NULL, NULL,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* ClapperEnhancerProxy:target-creation-allowed:
*
* Whether to allow instances of proxy target to be created.
*
* This effectively means whether the given enhancer can be used.
*
* By default all enhancers that work on-demand ([iface@Clapper.Extractable], [iface@Clapper.Playlistable])
* are allowed while enhancers implementing [iface@Clapper.Reactable] are not.
*
* Value of this property from a `GLOBAL` [class@Clapper.EnhancerProxyList] will carry
* over to all newly created [class@Clapper.Player] objects, while altering this on
* `LOCAL` proxy list will only influence given player instance that list belongs to.
*
* Changing this property will not remove already created enhancer instances, thus
* it is usually best practice to allow/disallow creation of given enhancer plugin
* right after [class@Clapper.Player] is created (before it or its queue are used).
*
* Since: 0.10
*/
param_specs[PROP_TARGET_CREATION_ALLOWED] = g_param_spec_boolean ("target-creation-allowed",
NULL, NULL, FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
}

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -77,4 +76,10 @@ void clapper_enhancer_proxy_set_locally (ClapperEnhancerProxy *proxy, const gcha
CLAPPER_API
void clapper_enhancer_proxy_set_locally_with_table (ClapperEnhancerProxy *proxy, GHashTable *table);
CLAPPER_API
void clapper_enhancer_proxy_set_target_creation_allowed (ClapperEnhancerProxy *proxy, gboolean allowed);
CLAPPER_API
gboolean clapper_enhancer_proxy_get_target_creation_allowed (ClapperEnhancerProxy *proxy);
G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
@@ -33,6 +32,8 @@ static HMODULE _enhancers_dll_handle = NULL;
// Supported interfaces
#include "clapper-extractable.h"
#include "clapper-playlistable.h"
#include "clapper-reactable.h"
#define GST_CAT_DEFAULT clapper_enhancers_loader_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -52,6 +53,28 @@ _import_enhancers (const gchar *enhancers_path)
g_strfreev (dir_paths);
}
static GObject *
_force_create_enhancer (ClapperEnhancerProxy *proxy, GType iface_type)
{
GObject *enhancer = NULL;
PeasPluginInfo *info = (PeasPluginInfo *) clapper_enhancer_proxy_get_peas_info (proxy);
g_mutex_lock (&load_lock);
if (!peas_plugin_info_is_loaded (info) && !peas_engine_load_plugin (_engine, info)) {
GST_ERROR ("Could not load enhancer: %s", peas_plugin_info_get_module_name (info));
} else if (!peas_engine_provides_extension (_engine, info, iface_type)) {
GST_LOG ("No \"%s\" enhancer in module: %s", g_type_name (iface_type),
peas_plugin_info_get_module_name (info));
} else {
enhancer = peas_engine_create_extension (_engine, info, iface_type, NULL);
}
g_mutex_unlock (&load_lock);
return enhancer;
}
/*
* clapper_enhancers_loader_initialize:
*
@@ -118,12 +141,12 @@ clapper_enhancers_loader_initialize (ClapperEnhancerProxyList *proxies)
* Otherwise make an instance and fill missing data from it (slow). */
if (!(filled = clapper_enhancer_proxy_fill_from_cache (proxy))) {
GObject *enhancer;
GType main_types[1] = { CLAPPER_TYPE_EXTRACTABLE };
const GType main_types[] = { CLAPPER_TYPE_EXTRACTABLE, CLAPPER_TYPE_PLAYLISTABLE, CLAPPER_TYPE_REACTABLE };
guint j;
/* We cannot ask libpeas for "any" of our main interfaces, so try each one until found */
for (j = 0; j < G_N_ELEMENTS (main_types); ++j) {
if ((enhancer = clapper_enhancers_loader_create_enhancer (proxy, main_types[j]))) {
if ((enhancer = _force_create_enhancer (proxy, main_types[j]))) {
filled = clapper_enhancer_proxy_fill_from_instance (proxy, enhancer);
g_object_unref (enhancer);
@@ -168,21 +191,8 @@ clapper_enhancers_loader_initialize (ClapperEnhancerProxyList *proxies)
GObject *
clapper_enhancers_loader_create_enhancer (ClapperEnhancerProxy *proxy, GType iface_type)
{
GObject *enhancer = NULL;
PeasPluginInfo *info = (PeasPluginInfo *) clapper_enhancer_proxy_get_peas_info (proxy);
if (!clapper_enhancer_proxy_get_target_creation_allowed (proxy))
return NULL;
g_mutex_lock (&load_lock);
if (!peas_plugin_info_is_loaded (info) && !peas_engine_load_plugin (_engine, info)) {
GST_ERROR ("Could not load enhancer: %s", peas_plugin_info_get_module_name (info));
} else if (!peas_engine_provides_extension (_engine, info, iface_type)) {
GST_LOG ("No \"%s\" enhancer in module: %s", g_type_name (iface_type),
peas_plugin_info_get_module_name (info));
} else {
enhancer = peas_engine_create_extension (_engine, info, iface_type, NULL);
}
g_mutex_unlock (&load_lock);
return enhancer;
return _force_create_enhancer (proxy, iface_type);
}

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -151,4 +150,23 @@ typedef enum
CLAPPER_ENHANCER_PARAM_DIRPATH = 1 << 20,
} ClapperEnhancerParamFlags;
/**
* ClapperReactableItemUpdatedFlags:
* @CLAPPER_REACTABLE_ITEM_UPDATED_TITLE: Media item title was updated.
* @CLAPPER_REACTABLE_ITEM_UPDATED_DURATION: Media item duration was updated.
* @CLAPPER_REACTABLE_ITEM_UPDATED_TIMELINE: Media item timeline was updated.
* @CLAPPER_REACTABLE_ITEM_UPDATED_TAGS: Media item tags were updated.
*
* Flags informing which properties were updated within [class@Clapper.MediaItem].
*
* Since: 0.10
*/
typedef enum
{
CLAPPER_REACTABLE_ITEM_UPDATED_TITLE = 1 << 0,
CLAPPER_REACTABLE_ITEM_UPDATED_DURATION = 1 << 1,
CLAPPER_REACTABLE_ITEM_UPDATED_TIMELINE = 1 << 2,
CLAPPER_REACTABLE_ITEM_UPDATED_TAGS = 1 << 3,
} ClapperReactableItemUpdatedFlags;
G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -30,6 +29,8 @@
* virtual functions logic, while for controlling playback implementation
* may call [method@Gst.Object.get_parent] to acquire a weak reference on
* a parent [class@Clapper.Player] object feature was added to.
*
* Deprecated: 0.10: Use [iface@Clapper.Reactable] instead.
*/
#include "clapper-feature.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -37,7 +36,7 @@ G_BEGIN_DECLS
#define CLAPPER_TYPE_FEATURE (clapper_feature_get_type())
#define CLAPPER_FEATURE_CAST(obj) ((ClapperFeature *)(obj))
CLAPPER_API
CLAPPER_DEPRECATED_FOR(ClapperReactable)
G_DECLARE_DERIVABLE_TYPE (ClapperFeature, clapper_feature, CLAPPER, FEATURE, GstObject)
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "clapper-bus-private.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include "clapper-features-manager-private.h"

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -23,13 +22,23 @@
#include <gst/tag/tag.h>
#include "clapper-harvest.h"
#include "clapper-enhancer-proxy.h"
G_BEGIN_DECLS
G_GNUC_INTERNAL
ClapperHarvest * clapper_harvest_new (void);
G_GNUC_INTERNAL
void clapper_harvest_set_enhancer_in_caps (ClapperHarvest *harvest, ClapperEnhancerProxy *proxy);
G_GNUC_INTERNAL
gboolean clapper_harvest_unpack (ClapperHarvest *harvest, GstBuffer **buffer, gsize *buf_size, GstCaps **caps, GstTagList **tags, GstToc **toc, GstStructure **headers);
G_GNUC_INTERNAL
gboolean clapper_harvest_fill_from_cache (ClapperHarvest *harvest, ClapperEnhancerProxy *proxy, const GstStructure *config, GUri *uri);
G_GNUC_INTERNAL
void clapper_harvest_export_to_cache (ClapperHarvest *harvest, ClapperEnhancerProxy *proxy, const GstStructure *config, GUri *uri);
G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -31,7 +30,11 @@
* https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2867
*/
#include "config.h"
#include "clapper-harvest-private.h"
#include "clapper-cache-private.h"
#include "clapper-utils.h"
#define GST_CAT_DEFAULT clapper_harvest_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -50,6 +53,8 @@ struct _ClapperHarvest
guint16 n_chapters;
guint16 n_tracks;
gint64 exp_epoch;
};
#define parent_class clapper_harvest_parent_class
@@ -89,6 +94,13 @@ clapper_harvest_new (void)
return harvest;
}
void
clapper_harvest_set_enhancer_in_caps (ClapperHarvest *self, ClapperEnhancerProxy *proxy)
{
gst_caps_set_simple (self->caps, "enhancer", G_TYPE_STRING,
clapper_enhancer_proxy_get_module_name (proxy), NULL);
}
gboolean
clapper_harvest_unpack (ClapperHarvest *self,
GstBuffer **buffer, gsize *buf_size, GstCaps **caps,
@@ -119,6 +131,304 @@ clapper_harvest_unpack (ClapperHarvest *self,
return TRUE;
}
/* Custom implementation due to the lack of TOC serialization in GStreamer */
static void
_harvest_fill_toc_from_cache (ClapperHarvest *self, const gchar **data)
{
guint i, n_entries;
n_entries = clapper_cache_read_uint (data);
for (i = 0; i < n_entries; ++i) {
guint j, n_subentries;
n_subentries = clapper_cache_read_uint (data);
for (j = 0; j < n_subentries; ++j) {
GstTocEntryType type;
const gchar *title;
gdouble start, end;
type = (GstTocEntryType) clapper_cache_read_int (data);
title = clapper_cache_read_string (data);
start = clapper_cache_read_double (data);
end = clapper_cache_read_double (data);
clapper_harvest_toc_add (self, type, title, start, end);
}
}
}
static void
_harvest_store_toc_to_cache (ClapperHarvest *self, GByteArray *bytes)
{
GList *list = NULL, *el;
guint n_entries = 0;
if (self->toc) {
list = gst_toc_get_entries (self->toc);
n_entries = g_list_length (list);
}
clapper_cache_store_uint (bytes, n_entries);
for (el = list; el; el = g_list_next (el)) {
const GstTocEntry *entry = (const GstTocEntry *) el->data;
GList *subentries, *sub_el;
guint n_subentries;
subentries = gst_toc_entry_get_sub_entries (entry);
n_subentries = g_list_length (subentries);
clapper_cache_store_uint (bytes, n_subentries);
for (sub_el = subentries; sub_el; sub_el = g_list_next (sub_el)) {
const GstTocEntry *subentry = (const GstTocEntry *) sub_el->data;
GstTagList *tags;
gint64 start = 0, end = 0;
gdouble start_dbl, end_dbl;
const gchar *title = NULL;
clapper_cache_store_int (bytes, (gint) gst_toc_entry_get_entry_type (subentry));
if ((tags = gst_toc_entry_get_tags (subentry)))
gst_tag_list_peek_string_index (tags, GST_TAG_TITLE, 0, &title);
clapper_cache_store_string (bytes, title);
gst_toc_entry_get_start_stop_times (subentry, &start, &end);
start_dbl = ((gdouble) start) / GST_SECOND;
end_dbl = (end >= 0) ? ((gdouble) end) / GST_SECOND : -1;
clapper_cache_store_double (bytes, start_dbl);
clapper_cache_store_double (bytes, end_dbl);
}
}
}
static inline gchar *
_build_cache_filename (ClapperEnhancerProxy *proxy, GUri *uri)
{
gchar *uri_str = g_uri_to_string (uri);
gchar name[15];
g_snprintf (name, sizeof (name), "%u.bin", g_str_hash (uri_str));
g_free (uri_str);
return g_build_filename (g_get_user_cache_dir (), CLAPPER_API_NAME,
"enhancers", clapper_enhancer_proxy_get_module_name (proxy),
"harvests", name, NULL);
}
/* NOTE: On failure, this function must not modify harvest! */
gboolean
clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *proxy,
const GstStructure *config, GUri *uri)
{
GMappedFile *mapped_file;
GstStructure *config_cached = NULL;
GError *error = NULL;
gchar *filename;
const gchar *data, *read_str;
const guint8 *buf_data;
gsize buf_size;
gint64 epoch_cached, epoch_now = 0;
gdouble exp_seconds;
gboolean changed, read_ok = FALSE;
filename = _build_cache_filename (proxy, uri);
GST_DEBUG_OBJECT (self, "Importing harvest from cache file: \"%s\"", filename);
mapped_file = clapper_cache_open (filename, &data, &error);
g_free (filename);
if (!mapped_file) {
/* No error if cache disabled or version mismatch */
if (error) {
if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)
GST_DEBUG_OBJECT (self, "No cached harvest found");
else
GST_ERROR_OBJECT (self, "Could not use cached harvest, reason: %s", error->message);
g_error_free (error);
}
return FALSE;
}
/* Plugin version check */
if (g_strcmp0 (clapper_cache_read_string (&data),
clapper_enhancer_proxy_get_version (proxy)) != 0)
goto finish; // no error printing here
if (G_LIKELY ((epoch_cached = clapper_cache_read_int64 (&data)) > 0)) {
GDateTime *date = g_date_time_new_now_utc ();
epoch_now = g_date_time_to_unix (date);
g_date_time_unref (date);
}
/* Check if expired */
if ((exp_seconds = (gdouble) (epoch_cached - epoch_now)) <= 0) {
GST_DEBUG_OBJECT (self, "Cached harvest expired"); // expiration is not an error
goto finish;
}
GST_DEBUG_OBJECT (self, "Cached harvest expiration in %" CLAPPER_TIME_FORMAT,
CLAPPER_TIME_ARGS (exp_seconds));
/* Read last used config to generate cache data */
if ((read_str = clapper_cache_read_string (&data)))
config_cached = gst_structure_from_string (read_str, NULL);
/* Compare used config when cache was generated to the current one */
changed = (config_cached && config)
? !gst_structure_is_equal (config_cached, config)
: (config_cached != config);
gst_clear_structure (&config_cached);
if (changed) {
GST_DEBUG_OBJECT (self, "Enhancer config differs from the last time");
goto finish;
}
/* Read caps */
read_str = clapper_cache_read_string (&data);
if (G_UNLIKELY (read_str == NULL)) {
GST_ERROR_OBJECT (self, "Could not read caps from cache file");
goto finish;
}
/* Read buffer data */
buf_data = clapper_cache_read_data (&data, &buf_size);
if (G_UNLIKELY (buf_data == NULL)) {
GST_ERROR_OBJECT (self, "Could not read buffer data from cache");
goto finish;
}
/* Fill harvest */
if (!(self->caps = gst_caps_from_string (read_str))) {
GST_ERROR_OBJECT (self, "Could not construct caps from cache");
goto finish;
}
self->buffer = gst_buffer_new_memdup (buf_data, buf_size);
self->buf_size = buf_size;
/* Read tags */
read_str = clapper_cache_read_string (&data);
if (read_str && (self->tags = gst_tag_list_new_from_string (read_str))) {
GST_LOG_OBJECT (self, "Read %s", read_str);
gst_tag_list_set_scope (self->tags, GST_TAG_SCOPE_GLOBAL);
}
/* Read TOC */
_harvest_fill_toc_from_cache (self, &data);
/* Read headers */
read_str = clapper_cache_read_string (&data);
if (read_str && (self->headers = gst_structure_from_string (read_str, NULL)))
GST_LOG_OBJECT (self, "Read %s", read_str);
read_ok = TRUE;
finish:
g_mapped_file_unref (mapped_file);
if (!read_ok)
return FALSE;
GST_DEBUG_OBJECT (self, "Filled harvest from cache");
return TRUE;
}
void
clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *proxy,
const GstStructure *config, GUri *uri)
{
GByteArray *bytes;
gchar *filename, *temp_str = NULL;
gboolean data_ok = TRUE;
/* No caching if no expiration date set */
if (self->exp_epoch <= 0)
return;
/* Might happen if extractor extract function implementation
* returns %TRUE without filling harvest properly */
if (G_UNLIKELY (self->caps == NULL || self->buffer == NULL))
return; // no data to cache
bytes = clapper_cache_create ();
/* If cache disabled */
if (G_UNLIKELY (bytes == NULL))
return;
filename = _build_cache_filename (proxy, uri);
GST_DEBUG_OBJECT (self, "Exporting harvest to cache file: \"%s\"", filename);
/* Store enhancer version that generated harvest */
clapper_cache_store_string (bytes, clapper_enhancer_proxy_get_version (proxy));
/* Store expiration date */
clapper_cache_store_int64 (bytes, self->exp_epoch);
/* Store config used to generate harvest */
if (config)
temp_str = gst_structure_to_string (config);
clapper_cache_store_string (bytes, temp_str); // NULL when no config
g_clear_pointer (&temp_str, g_free);
/* Store caps */
temp_str = gst_caps_to_string (self->caps);
if (G_LIKELY (temp_str != NULL)) {
clapper_cache_store_string (bytes, temp_str);
g_clear_pointer (&temp_str, g_free);
} else {
GST_ERROR_OBJECT (self, "Cannot cache caps");
data_ok = FALSE;
}
if (G_LIKELY (data_ok)) {
GstMemory *mem;
GstMapInfo map_info;
/* Store buffer data */
mem = gst_buffer_peek_memory (self->buffer, 0);
if (G_LIKELY (gst_memory_map (mem, &map_info, GST_MAP_READ))) {
clapper_cache_store_data (bytes, map_info.data, map_info.size);
gst_memory_unmap (mem, &map_info);
} else {
GST_ERROR_OBJECT (self, "Could not map harvest buffer for reading");
data_ok = FALSE;
}
}
if (G_LIKELY (data_ok)) {
GError *error = NULL;
/* Store tags */
if (self->tags)
temp_str = gst_tag_list_to_string (self->tags);
clapper_cache_store_string (bytes, temp_str);
g_clear_pointer (&temp_str, g_free);
/* Store TOC */
_harvest_store_toc_to_cache (self, bytes);
/* Store headers */
if (self->headers)
temp_str = gst_structure_to_string (self->headers);
clapper_cache_store_string (bytes, temp_str);
g_clear_pointer (&temp_str, g_free);
if (clapper_cache_write (filename, bytes, &error)) {
GST_DEBUG_OBJECT (self, "Successfully exported harvest to cache file");
} else if (error) {
GST_ERROR_OBJECT (self, "Could not cache harvest, reason: %s", error->message);
g_error_free (error);
}
}
g_free (filename);
g_byte_array_free (bytes, TRUE);
}
/**
* clapper_harvest_fill:
* @harvest: a #ClapperHarvest
@@ -133,11 +443,15 @@ clapper_harvest_unpack (ClapperHarvest *self,
*
* Commonly used media types are:
*
* * `application/dash+xml`
* * `application/dash+xml` - DASH manifest
*
* * `application/x-hls`
* * `application/x-hls` - HLS manifest
*
* * `text/uri-list`
* * `text/x-uri` - direct media URI
*
* * `text/uri-list` - playlist of URIs
*
* * `application/clapper-playlist` - custom playlist format
*
* Returns: %TRUE when filled successfully, %FALSE if taken data was empty.
*
@@ -155,9 +469,10 @@ clapper_harvest_fill (ClapperHarvest *self, const gchar *media_type, gpointer da
return FALSE;
}
if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_DEBUG) {
if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG) {
gboolean is_printable = (strcmp (media_type, "application/dash+xml") == 0)
|| (strcmp (media_type, "application/x-hls") == 0)
|| (strcmp (media_type, "text/x-uri") == 0)
|| (strcmp (media_type, "text/uri-list") == 0);
if (is_printable) {
@@ -166,7 +481,7 @@ clapper_harvest_fill (ClapperHarvest *self, const gchar *media_type, gpointer da
data_str = g_new0 (gchar, size + 1);
memcpy (data_str, data, size);
GST_DEBUG_OBJECT (self, "Filled with data:\n%s", data_str);
GST_LOG_OBJECT (self, "Filled with data:\n%s", data_str);
g_free (data_str);
}
@@ -328,7 +643,7 @@ clapper_harvest_toc_add (ClapperHarvest *self, GstTocEntryType type,
g_snprintf (edition, sizeof (edition), "0%i", type);
g_snprintf (id, sizeof (id), "%s.%" G_GUINT16_FORMAT, id_prefix, nth_entry);
GST_DEBUG_OBJECT (self, "Inserting TOC %s: \"%s\""
GST_LOG_OBJECT (self, "Inserting TOC %s: \"%s\""
" (%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ")",
id, title, start_time, end_time);
@@ -380,7 +695,7 @@ clapper_harvest_headers_set (ClapperHarvest *self, const gchar *key, ...)
while (key != NULL) {
const gchar *val = va_arg (args, const gchar *);
GST_DEBUG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, val);
GST_LOG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, val);
gst_structure_set (self->headers, key, G_TYPE_STRING, val, NULL);
key = va_arg (args, const gchar *);
}
@@ -409,10 +724,70 @@ clapper_harvest_headers_set_value (ClapperHarvest *self, const gchar *key, const
_ensure_headers (self);
GST_DEBUG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, g_value_get_string (value));
GST_LOG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, g_value_get_string (value));
gst_structure_set_value (self->headers, key, value);
}
/**
* clapper_harvest_set_expiration_date_utc:
* @harvest: a #ClapperHarvest
* @date_utc: a #GDateTime in UTC time
*
* Set date in UTC time until harvested content is expected
* to stay alive.
*
* This is used for harvest caching, so next time user requests to
* play the same URI, recently harvested data can be reused without
* the need to run [vfunc@Clapper.Extractable.extract] again.
*
* Since: 0.10
*/
void
clapper_harvest_set_expiration_date_utc (ClapperHarvest *self, GDateTime *date_utc)
{
g_return_if_fail (CLAPPER_IS_HARVEST (self));
g_return_if_fail (date_utc != NULL);
self->exp_epoch = g_date_time_to_unix (date_utc);
GST_LOG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch);
}
/**
* clapper_harvest_set_expiration_seconds:
* @harvest: a #ClapperHarvest
* @seconds: time in seconds until expiration
*
* Set amount of seconds for how long harvested content is
* expected to stay alive.
*
* Alternative function to [method@Clapper.Harvest.set_expiration_date_utc],
* but takes time as number in seconds from now.
*
* It is safe to pass zero or negative number to this function in
* case when calculating time manually and it already expired.
*
* Since: 0.10
*/
void
clapper_harvest_set_expiration_seconds (ClapperHarvest *self, gdouble seconds)
{
GDateTime *date, *date_epoch;
g_return_if_fail (CLAPPER_IS_HARVEST (self));
GST_LOG_OBJECT (self, "Set expiration in %" CLAPPER_TIME_FORMAT,
CLAPPER_TIME_ARGS (seconds));
date = g_date_time_new_now_utc ();
date_epoch = g_date_time_add_seconds (date, seconds);
g_date_time_unref (date);
self->exp_epoch = g_date_time_to_unix (date_epoch);
g_date_time_unref (date_epoch);
GST_LOG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch);
}
static void
clapper_harvest_init (ClapperHarvest *self)
{

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -61,4 +60,10 @@ void clapper_harvest_headers_set (ClapperHarvest *harvest, const gchar *key, ...
CLAPPER_API
void clapper_harvest_headers_set_value (ClapperHarvest *harvest, const gchar *key, const GValue *value);
CLAPPER_API
void clapper_harvest_set_expiration_date_utc (ClapperHarvest *harvest, GDateTime *date_utc);
CLAPPER_API
void clapper_harvest_set_expiration_seconds (ClapperHarvest *harvest, gdouble seconds);
G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -23,7 +22,7 @@
#include <gst/pbutils/pbutils.h>
#include "clapper-media-item.h"
#include "clapper-player-private.h"
#include "clapper-player.h"
#include "clapper-app-bus-private.h"
G_BEGIN_DECLS
@@ -34,6 +33,9 @@ void clapper_media_item_update_from_tag_list (ClapperMediaItem *item, const GstT
G_GNUC_INTERNAL
void clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDiscovererInfo *info);
G_GNUC_INTERNAL
gboolean clapper_media_item_update_from_item (ClapperMediaItem *item, ClapperMediaItem *other_item, ClapperPlayer *player);
G_GNUC_INTERNAL
gboolean clapper_media_item_set_duration (ClapperMediaItem *item, gdouble duration, ClapperAppBus *app_bus);

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -30,6 +29,7 @@
#include "clapper-timeline-private.h"
#include "clapper-player-private.h"
#include "clapper-playbin-bus-private.h"
#include "clapper-reactables-manager-private.h"
#include "clapper-features-manager-private.h"
#include "clapper-utils-private.h"
@@ -43,6 +43,7 @@ struct _ClapperMediaItem
gchar *uri;
gchar *suburi;
GstTagList *tags;
ClapperTimeline *timeline;
guint id;
@@ -50,12 +51,23 @@ struct _ClapperMediaItem
gchar *container_format;
gdouble duration;
/* Whether using title from URI */
gboolean title_is_parsed;
GSList *redirects;
gchar *cache_uri;
/* For shuffle */
gboolean used;
};
typedef struct
{
ClapperMediaItem *item;
gboolean changed;
gboolean from_user;
} ClapperMediaItemTagIterData;
enum
{
PROP_0,
@@ -63,6 +75,7 @@ enum
PROP_URI,
PROP_SUBURI,
PROP_CACHE_LOCATION,
PROP_TAGS,
PROP_TITLE,
PROP_CONTAINER_FORMAT,
PROP_DURATION,
@@ -111,8 +124,8 @@ clapper_media_item_new (const gchar *uri)
/* FIXME: Set initial container format from file extension parsing */
GST_TRACE_OBJECT (item, "New media item, ID: %u, URI: %s, title: %s",
item->id, item->uri, item->title);
GST_TRACE_OBJECT (item, "New media item, ID: %u, URI: \"%s\", title: \"%s\"",
item->id, item->uri, GST_STR_NULL (item->title));
return item;
}
@@ -189,6 +202,12 @@ clapper_media_item_get_id (ClapperMediaItem *self)
return self->id;
}
/* FIXME: 1.0:
* Consider change to be transfer-full and just return latest data from redirects
* list (alternatively expose redirect URI). This should make it possible to work
* with enhancers that would benefit from knowledge about URI changes
* (e.g "Recall" could read actual media instead of playlist file).
*/
/**
* clapper_media_item_get_uri:
* @item: a #ClapperMediaItem
@@ -258,27 +277,6 @@ clapper_media_item_get_suburi (ClapperMediaItem *self)
return suburi;
}
static gboolean
clapper_media_item_take_title (ClapperMediaItem *self, gchar *title,
ClapperAppBus *app_bus)
{
gboolean changed;
GST_OBJECT_LOCK (self);
if ((changed = g_strcmp0 (self->title, title) != 0)) {
g_free (self->title);
self->title = title;
}
GST_OBJECT_UNLOCK (self);
if (changed)
clapper_app_bus_post_prop_notify (app_bus, GST_OBJECT_CAST (self), param_specs[PROP_TITLE]);
else
g_free (title);
return changed;
}
/**
* clapper_media_item_get_title:
* @item: a #ClapperMediaItem
@@ -305,25 +303,24 @@ clapper_media_item_get_title (ClapperMediaItem *self)
return title;
}
static gboolean
clapper_media_item_take_container_format (ClapperMediaItem *self, gchar *container_format,
ClapperAppBus *app_bus)
static inline gboolean
_refresh_tag_prop_unlocked (ClapperMediaItem *self, const gchar *tag,
gboolean allow_overwrite, gchar **tag_ptr)
{
gboolean changed;
const gchar *string;
GST_OBJECT_LOCK (self);
if ((changed = g_strcmp0 (self->container_format, container_format) != 0)) {
g_free (self->container_format);
self->container_format = container_format;
}
GST_OBJECT_UNLOCK (self);
if ((*tag_ptr && !allow_overwrite)
|| !gst_tag_list_peek_string_index (self->tags, tag, 0, &string) // guarantees non-empty string
|| (g_strcmp0 (*tag_ptr, string) == 0))
return FALSE;
if (changed)
clapper_app_bus_post_prop_notify (app_bus, GST_OBJECT_CAST (self), param_specs[PROP_CONTAINER_FORMAT]);
else
g_free (container_format);
GST_LOG_OBJECT (self, "Tag prop \"%s\" update: \"%s\" -> \"%s\"",
tag, GST_STR_NULL (*tag_ptr), string);
return changed;
g_free (*tag_ptr);
*tag_ptr = g_strdup (string);
return TRUE;
}
/**
@@ -333,6 +330,8 @@ clapper_media_item_take_container_format (ClapperMediaItem *self, gchar *contain
* Get media item container format.
*
* Returns: (transfer full) (nullable): media container format.
*
* Deprecated: 0.10: Get `container-format` from [property@Clapper.MediaItem:tags] instead.
*/
gchar *
clapper_media_item_get_container_format (ClapperMediaItem *self)
@@ -389,11 +388,215 @@ clapper_media_item_get_duration (ClapperMediaItem *self)
return duration;
}
/**
* clapper_media_item_get_tags:
* @item: a #ClapperMediaItem
*
* Get readable list of tags stored in media item.
*
* Returns: (transfer full): a #GstTagList.
*
* Since: 0.10
*/
GstTagList *
clapper_media_item_get_tags (ClapperMediaItem *self)
{
GstTagList *tags = NULL;
g_return_val_if_fail (CLAPPER_IS_MEDIA_ITEM (self), NULL);
GST_OBJECT_LOCK (self);
tags = gst_tag_list_ref (self->tags);
GST_OBJECT_UNLOCK (self);
return tags;
}
static void
_tags_replace_func (const GstTagList *tags, const gchar *tag, ClapperMediaItemTagIterData *data)
{
ClapperMediaItem *self = data->item;
guint index = 0;
gboolean replace = FALSE;
while (TRUE) {
const GValue *old_value = gst_tag_list_get_value_index (self->tags, tag, index);
const GValue *new_value = gst_tag_list_get_value_index (tags, tag, index);
/* Number of old values is the same or greater and
* all values until this iteration were the same */
if (!new_value)
break;
/* A wild new tag appeared */
if (!old_value) {
replace = TRUE;
break;
}
/* Users can only set non-existing tags */
if (data->from_user)
break;
/* Check with tolerance for doubles */
if (G_VALUE_TYPE (old_value) == G_TYPE_DOUBLE
&& G_VALUE_TYPE (new_value) == G_TYPE_DOUBLE) {
gdouble old_dbl, new_dbl;
old_dbl = g_value_get_double (old_value);
new_dbl = g_value_get_double (new_value);
if ((replace = !G_APPROX_VALUE (old_dbl, new_dbl, FLT_EPSILON)))
break;
} else if (gst_value_compare (old_value, new_value) != GST_VALUE_EQUAL) {
replace = TRUE;
break;
}
++index;
}
if (replace) {
const GValue *value;
index = 0;
GST_LOG_OBJECT (self, "Replacing \"%s\" tag value", tag);
/* Ensure writable, but only when replacing something */
if (!data->changed) {
self->tags = gst_tag_list_make_writable (self->tags);
data->changed = TRUE;
}
/* Replace first tag value (so it becomes sole member) */
value = gst_tag_list_get_value_index (tags, tag, index);
gst_tag_list_add_value (self->tags, GST_TAG_MERGE_REPLACE, tag, value);
/* Append any remaining tags (so next time we iterate indexes will match) */
while ((value = gst_tag_list_get_value_index (tags, tag, ++index)))
gst_tag_list_add_value (self->tags, GST_TAG_MERGE_APPEND, tag, value);
}
}
static gboolean
clapper_media_item_insert_tags_internal (ClapperMediaItem *self, const GstTagList *tags,
ClapperAppBus *app_bus, gboolean from_user, ClapperReactableItemUpdatedFlags *flags)
{
ClapperMediaItemTagIterData data;
gboolean title_changed = FALSE, cont_changed = FALSE;
GST_OBJECT_LOCK (self);
data.item = self;
data.changed = FALSE;
data.from_user = from_user;
if (G_LIKELY (tags != self->tags))
gst_tag_list_foreach (tags, (GstTagForeachFunc) _tags_replace_func, &data);
if (data.changed) {
*flags |= CLAPPER_REACTABLE_ITEM_UPDATED_TAGS;
if ((title_changed = _refresh_tag_prop_unlocked (self, GST_TAG_TITLE,
(!from_user || self->title_is_parsed), &self->title))) {
self->title_is_parsed = FALSE;
*flags |= CLAPPER_REACTABLE_ITEM_UPDATED_TITLE;
}
cont_changed = _refresh_tag_prop_unlocked (self, GST_TAG_CONTAINER_FORMAT,
!from_user, &self->container_format);
}
GST_OBJECT_UNLOCK (self);
if (!data.changed)
return FALSE;
if (app_bus) {
GstObject *src = GST_OBJECT_CAST (self);
clapper_app_bus_post_prop_notify (app_bus, src, param_specs[PROP_TAGS]);
if (title_changed)
clapper_app_bus_post_prop_notify (app_bus, src, param_specs[PROP_TITLE]);
if (cont_changed)
clapper_app_bus_post_prop_notify (app_bus, src, param_specs[PROP_CONTAINER_FORMAT]);
} else {
GObject *src = G_OBJECT (self);
clapper_utils_prop_notify_on_main_sync (src, param_specs[PROP_TAGS]);
if (title_changed)
clapper_utils_prop_notify_on_main_sync (src, param_specs[PROP_TITLE]);
if (cont_changed)
clapper_utils_prop_notify_on_main_sync (src, param_specs[PROP_CONTAINER_FORMAT]);
}
return TRUE;
}
/**
* clapper_media_item_populate_tags:
* @item: a #ClapperMediaItem
* @tags: a #GstTagList of GLOBAL scope
*
* Populate non-existing tags in @item tag list.
*
* Passed @tags must use [enum@Gst.TagScope.GLOBAL] scope.
*
* Note that tags are automatically determined during media playback
* and those take precedence. This function can be useful if an app can
* determine some tags that are not in media metadata or for filling
* item with some initial/cached tags to display in UI before playback.
*
* When a tag already exists in the tag list (was populated) this
* function will not overwrite it. If you really need to permanently
* override some tags in media, you can use `taginject` element as
* player video/audio filter instead.
*
* Returns: whether at least one tag got updated.
*
* Since: 0.10
*/
gboolean
clapper_media_item_populate_tags (ClapperMediaItem *self, const GstTagList *tags)
{
ClapperPlayer *player;
ClapperAppBus *app_bus = NULL;
ClapperReactableItemUpdatedFlags flags = 0;
gboolean changed;
g_return_val_if_fail (CLAPPER_IS_MEDIA_ITEM (self), FALSE);
g_return_val_if_fail (tags != NULL, FALSE);
if (G_UNLIKELY (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_GLOBAL)) {
g_warning ("Cannot populate media item tags using a list with non-global tag scope");
return FALSE;
}
if ((player = clapper_player_get_from_ancestor (GST_OBJECT_CAST (self))))
app_bus = player->app_bus;
changed = clapper_media_item_insert_tags_internal (self, tags, app_bus, TRUE, &flags);
if (changed && player) {
ClapperFeaturesManager *features_manager;
if (player->reactables_manager)
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, self);
}
gst_clear_object (&player);
return changed;
}
/**
* clapper_media_item_get_timeline:
* @item: a #ClapperMediaItem
*
* Get the [class@Clapper.Timeline] assosiated with @item.
* Get the [class@Clapper.Timeline] associated with @item.
*
* Returns: (transfer none): a #ClapperTimeline of item.
*/
@@ -405,21 +608,6 @@ clapper_media_item_get_timeline (ClapperMediaItem *self)
return self->timeline;
}
static gboolean
clapper_media_item_update_from_container_tags (ClapperMediaItem *self, const GstTagList *tags,
ClapperAppBus *app_bus)
{
gchar *string = NULL;
gboolean changed = FALSE;
if (gst_tag_list_get_string (tags, GST_TAG_CONTAINER_FORMAT, &string))
changed |= clapper_media_item_take_container_format (self, string, app_bus);
if (gst_tag_list_get_string (tags, GST_TAG_TITLE, &string))
changed |= clapper_media_item_take_title (self, string, app_bus);
return changed;
}
void
clapper_media_item_update_from_tag_list (ClapperMediaItem *self, const GstTagList *tags,
ClapperPlayer *player)
@@ -427,11 +615,14 @@ clapper_media_item_update_from_tag_list (ClapperMediaItem *self, const GstTagLis
GstTagScope scope = gst_tag_list_get_scope (tags);
if (scope == GST_TAG_SCOPE_GLOBAL) {
gboolean changed = clapper_media_item_update_from_container_tags (self, tags, player->app_bus);
ClapperReactableItemUpdatedFlags flags = 0;
gboolean changed = clapper_media_item_insert_tags_internal (self, tags, player->app_bus, FALSE, &flags);
if (changed) {
ClapperFeaturesManager *features_manager;
if (player->reactables_manager)
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, self);
}
@@ -444,6 +635,7 @@ clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDisco
ClapperPlayer *player;
GstDiscovererStreamInfo *sinfo;
GstClockTime duration;
ClapperReactableItemUpdatedFlags flags = 0;
gdouble val_dbl;
gboolean changed = FALSE;
@@ -459,7 +651,7 @@ clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDisco
GstDiscovererContainerInfo *cinfo = (GstDiscovererContainerInfo *) sinfo;
if ((tags = gst_discoverer_container_info_get_tags (cinfo)))
changed |= clapper_media_item_update_from_container_tags (self, tags, player->app_bus);
changed |= clapper_media_item_insert_tags_internal (self, tags, player->app_bus, FALSE, &flags);
}
gst_discoverer_stream_info_unref (sinfo);
}
@@ -470,11 +662,16 @@ clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDisco
duration = 0;
val_dbl = (gdouble) duration / GST_SECOND;
changed |= clapper_media_item_set_duration (self, val_dbl, player->app_bus);
if (clapper_media_item_set_duration (self, val_dbl, player->app_bus)) {
changed = TRUE;
flags |= CLAPPER_REACTABLE_ITEM_UPDATED_DURATION;
}
if (changed) {
ClapperFeaturesManager *features_manager;
if (player->reactables_manager)
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, self);
}
@@ -482,6 +679,61 @@ clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDisco
gst_object_unref (player);
}
/* XXX: Must be set from player thread */
static inline gboolean
clapper_media_item_set_redirect_uri (ClapperMediaItem *self, const gchar *redirect_uri)
{
/* Check if we did not already redirect into that URI (prevent endless loop) */
if (!redirect_uri || g_slist_find_custom (self->redirects, redirect_uri, (GCompareFunc) strcmp))
return FALSE;
self->redirects = g_slist_prepend (self->redirects, g_strdup (redirect_uri));
GST_DEBUG_OBJECT (self, "Set redirect URI: \"%s\"", (gchar *) self->redirects->data);
return TRUE;
}
gboolean
clapper_media_item_update_from_item (ClapperMediaItem *self, ClapperMediaItem *other_item,
ClapperPlayer *player)
{
gboolean title_changed = FALSE;
if (!clapper_media_item_set_redirect_uri (self, clapper_media_item_get_uri (other_item)))
return FALSE;
GST_OBJECT_LOCK (other_item);
if (other_item->tags)
clapper_media_item_update_from_tag_list (self, other_item->tags, player);
/* Since its redirect now, we have to update title to describe new file instead of
* being a playlist title. If other item had parsed title, it also means that tags
* did not contain it, thus we have to manually update it and notify. */
if (other_item->title_is_parsed) {
GST_OBJECT_LOCK (self);
title_changed = g_set_str (&self->title, other_item->title);
self->title_is_parsed = TRUE;
GST_OBJECT_UNLOCK (self);
}
GST_OBJECT_UNLOCK (other_item);
if (title_changed) {
ClapperReactableItemUpdatedFlags flags = CLAPPER_REACTABLE_ITEM_UPDATED_TITLE;
ClapperFeaturesManager *features_manager;
clapper_app_bus_post_prop_notify (player->app_bus, GST_OBJECT_CAST (self), param_specs[PROP_TITLE]);
if (player->reactables_manager)
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, self, flags);
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, self);
}
return TRUE;
}
/* XXX: Must be set from player thread or upon construction */
void
clapper_media_item_set_cache_location (ClapperMediaItem *self, const gchar *location)
@@ -496,7 +748,7 @@ clapper_media_item_set_cache_location (ClapperMediaItem *self, const gchar *loca
}
/* XXX: Can only be read from player thread.
* Returns cache URI if available, item URI otherwise. */
* Returns cache URI if available, otherwise redirect or item URI. */
inline const gchar *
clapper_media_item_get_playback_uri (ClapperMediaItem *self)
{
@@ -516,6 +768,9 @@ clapper_media_item_get_playback_uri (ClapperMediaItem *self)
clapper_media_item_set_cache_location (self, NULL);
}
if (self->redirects)
return self->redirects->data;
return self->uri;
}
@@ -542,6 +797,9 @@ clapper_media_item_get_used (ClapperMediaItem *self)
static void
clapper_media_item_init (ClapperMediaItem *self)
{
self->tags = gst_tag_list_new_empty ();
gst_tag_list_set_scope (self->tags, GST_TAG_SCOPE_GLOBAL);
self->timeline = clapper_timeline_new ();
gst_object_set_parent (GST_OBJECT_CAST (self->timeline), GST_OBJECT_CAST (self));
}
@@ -556,6 +814,7 @@ clapper_media_item_constructed (GObject *object)
self->uri = g_strdup ("file://");
self->title = clapper_utils_title_from_uri (self->uri);
self->title_is_parsed = (self->title != NULL);
G_OBJECT_CLASS (parent_class)->constructed (object);
}
@@ -571,9 +830,12 @@ clapper_media_item_finalize (GObject *object)
g_free (self->title);
g_free (self->container_format);
gst_tag_list_unref (self->tags);
gst_object_unparent (GST_OBJECT_CAST (self->timeline));
gst_object_unref (self->timeline);
g_slist_free_full (self->redirects, g_free);
g_free (self->cache_uri);
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -617,6 +879,9 @@ clapper_media_item_get_property (GObject *object, guint prop_id,
case PROP_SUBURI:
g_value_take_string (value, clapper_media_item_get_suburi (self));
break;
case PROP_TAGS:
g_value_take_boxed (value, clapper_media_item_get_tags (self));
break;
case PROP_TITLE:
g_value_take_string (value, clapper_media_item_get_title (self));
break;
@@ -686,10 +951,28 @@ clapper_media_item_class_init (ClapperMediaItemClass *klass)
NULL, NULL, NULL,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* ClapperMediaItem:tags:
*
* A readable list of tags stored in media item.
*
* Since: 0.10
*/
param_specs[PROP_TAGS] = g_param_spec_boxed ("tags",
NULL, NULL, GST_TYPE_TAG_LIST,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/* FIXME: 1.0: Consider rename to e.g. "(menu/display)-title"
* and also make it non-nullable (return URI as final fallback).
* NOTE: It would probably need to work with redirect URI */
/**
* ClapperMediaItem:title:
*
* Media title.
*
* This might be a different string compared to `title` from
* [property@Clapper.MediaItem:tags], as this gives parsed
* title from file name/URI as fallback when no `title` tag.
*/
param_specs[PROP_TITLE] = g_param_spec_string ("title",
NULL, NULL, NULL,
@@ -699,15 +982,21 @@ clapper_media_item_class_init (ClapperMediaItemClass *klass)
* ClapperMediaItem:container-format:
*
* Media container format.
*
* Deprecated: 0.10: Get `container-format` from [property@Clapper.MediaItem:tags] instead.
*/
param_specs[PROP_CONTAINER_FORMAT] = g_param_spec_string ("container-format",
NULL, NULL, NULL,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED);
/**
* ClapperMediaItem:duration:
*
* Media duration as a decimal number in seconds.
*
* This might be a different value compared to `duration` from
* [property@Clapper.MediaItem:tags], as this value is updated
* during decoding instead of being a fixed value from metadata.
*/
param_specs[PROP_DURATION] = g_param_spec_double ("duration",
NULL, NULL, 0, G_MAXDOUBLE, 0,

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -27,6 +26,7 @@
#include <glib-object.h>
#include <gio/gio.h>
#include <gst/gst.h>
#include <gst/tag/tag.h>
#include <clapper/clapper-visibility.h>
#include <clapper/clapper-timeline.h>
@@ -63,12 +63,18 @@ gchar * clapper_media_item_get_suburi (ClapperMediaItem *item);
CLAPPER_API
gchar * clapper_media_item_get_title (ClapperMediaItem *item);
CLAPPER_API
CLAPPER_DEPRECATED_FOR(clapper_media_item_get_tags)
gchar * clapper_media_item_get_container_format (ClapperMediaItem *item);
CLAPPER_API
gdouble clapper_media_item_get_duration (ClapperMediaItem *item);
CLAPPER_API
GstTagList * clapper_media_item_get_tags (ClapperMediaItem *item);
CLAPPER_API
gboolean clapper_media_item_populate_tags (ClapperMediaItem *item, const GstTagList *tags);
CLAPPER_API
ClapperTimeline * clapper_media_item_get_timeline (ClapperMediaItem *item);

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#include <gst/pbutils/pbutils.h>
@@ -29,12 +28,7 @@
#include "clapper-timeline-private.h"
#include "clapper-stream-private.h"
#include "clapper-stream-list-private.h"
#include "clapper-functionalities-availability.h"
#if CLAPPER_WITH_ENHANCERS_LOADER
#include "gst/clapper-enhancer-src-private.h"
#endif
#include "gst/clapper-extractable-src-private.h"
#define GST_CAT_DEFAULT clapper_playbin_bus_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -178,6 +172,10 @@ _update_current_duration (ClapperPlayer *player)
if (clapper_media_item_set_duration (player->played_item, duration_dbl, player->app_bus)) {
ClapperFeaturesManager *features_manager;
if (player->reactables_manager) {
clapper_reactables_manager_trigger_item_updated (player->reactables_manager, player->played_item,
CLAPPER_REACTABLE_ITEM_UPDATED_DURATION);
}
if ((features_manager = clapper_player_get_features_manager (player)))
clapper_features_manager_trigger_item_updated (features_manager, player->played_item);
}
@@ -833,6 +831,71 @@ _handle_element_msg (GstMessage *msg, ClapperPlayer *player)
g_free (name);
g_free (details);
} else if (gst_message_has_name (msg, "ClapperPlaylistParsed")) {
ClapperMediaItem *playlist_item = NULL;
GListStore *playlist = NULL;
const GstStructure *structure = gst_message_get_structure (msg);
guint n_items;
/* If message contains item, use that.
* Otherwise assume pending item was parsed. */
if (gst_structure_has_field (structure, "item")) {
gst_structure_get (structure,
"item", CLAPPER_TYPE_MEDIA_ITEM, &playlist_item, NULL);
} else {
GST_OBJECT_LOCK (player);
/* Playlist is always parsed before playback starts */
if (player->pending_item)
playlist_item = gst_object_ref (player->pending_item);
GST_OBJECT_UNLOCK (player);
}
if (G_UNLIKELY (playlist_item == NULL)) {
GST_WARNING_OBJECT (player, "Playlist parsed without media item set");
return;
}
GST_INFO_OBJECT (player, "Received parsed playlist of %" GST_PTR_FORMAT
"(%s)", playlist_item, clapper_media_item_get_uri (playlist_item));
gst_structure_get (structure,
"playlist", G_TYPE_LIST_STORE, &playlist, NULL);
n_items = g_list_model_get_n_items (G_LIST_MODEL (playlist));
if (G_LIKELY (n_items > 0)) {
ClapperMediaItem *active_item = g_list_model_get_item (G_LIST_MODEL (playlist), 0);
gboolean updated;
/* Update redirect URI (must be done from player thread) */
updated = clapper_media_item_update_from_item (playlist_item, active_item, player);
gst_object_unref (active_item);
if (!updated) {
GstMessage *msg;
GError *error;
error = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
"Detected infinite redirection in playlist");
msg = gst_message_new_error (GST_OBJECT (player), error, NULL);
_handle_error_msg (msg, player);
g_error_free (error);
gst_message_unref (msg);
} else if (n_items > 1) {
/* Forward to append remaining items (must be done from main thread) */
clapper_app_bus_post_insert_playlist (player->app_bus,
GST_OBJECT_CAST (player),
GST_OBJECT_CAST (playlist_item),
G_OBJECT (playlist));
}
}
gst_object_unref (playlist_item);
g_object_unref (playlist);
} else if (gst_message_has_name (msg, "GstCacheDownloadComplete")) {
ClapperMediaItem *downloaded_item = NULL;
const GstStructure *structure;
@@ -875,7 +938,6 @@ _handle_tag_msg (GstMessage *msg, ClapperPlayer *player)
{
GstObject *src = GST_MESSAGE_SRC (msg);
GstTagList *tags = NULL;
gboolean from_enhancer_src;
/* Tag messages should only be posted by sink elements */
if (G_UNLIKELY (!src))
@@ -886,14 +948,8 @@ _handle_tag_msg (GstMessage *msg, ClapperPlayer *player)
GST_LOG_OBJECT (player, "Got tags from element: %s: %" GST_PTR_FORMAT,
GST_OBJECT_NAME (src), tags);
#if CLAPPER_WITH_ENHANCERS_LOADER
from_enhancer_src = CLAPPER_IS_ENHANCER_SRC (src);
#else
from_enhancer_src = FALSE;
#endif
/* ClapperEnhancerSrc determines tags before stream start */
if (from_enhancer_src) {
/* ClapperExtractableSrc determines tags before stream start */
if (CLAPPER_IS_EXTRACTABLE_SRC (src)) {
if (player->pending_tags) {
gst_tag_list_unref (player->pending_tags);
}
@@ -910,7 +966,7 @@ _handle_toc_msg (GstMessage *msg, ClapperPlayer *player)
{
GstObject *src = GST_MESSAGE_SRC (msg);
GstToc *toc = NULL;
gboolean from_enhancer_src, updated = FALSE;
gboolean updated = FALSE;
/* TOC messages should only be posted by sink elements */
if (G_UNLIKELY (!src))
@@ -923,14 +979,8 @@ _handle_toc_msg (GstMessage *msg, ClapperPlayer *player)
" from element: %s, updated: %s",
toc, GST_OBJECT_NAME (src), (updated) ? "yes" : "no");
#if CLAPPER_WITH_ENHANCERS_LOADER
from_enhancer_src = CLAPPER_IS_ENHANCER_SRC (src);
#else
from_enhancer_src = FALSE;
#endif
/* ClapperEnhancerSrc determines TOC before stream start */
if (from_enhancer_src) {
/* ClapperExtractableSrc determines TOC before stream start */
if (CLAPPER_IS_EXTRACTABLE_SRC (src)) {
if (player->pending_toc) {
gst_toc_unref (player->pending_toc);
}
@@ -1064,6 +1114,8 @@ _handle_stream_start_msg (GstMessage *msg, ClapperPlayer *player)
if (G_LIKELY (changed)) {
clapper_queue_handle_played_item_changed (player->queue, player->played_item, player->app_bus);
if (player->reactables_manager)
clapper_reactables_manager_trigger_played_item_changed (player->reactables_manager, player->played_item);
if (clapper_player_get_have_features (player))
clapper_features_manager_trigger_played_item_changed (player->features_manager, player->played_item);
}

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
@@ -27,6 +26,7 @@
#include "clapper-app-bus-private.h"
#include "clapper-features-manager-private.h"
#include "clapper-reactables-manager-private.h"
G_BEGIN_DECLS
@@ -47,6 +47,8 @@ struct _ClapperPlayer
ClapperFeaturesManager *features_manager;
gint have_features; // atomic integer
ClapperReactablesManager *reactables_manager;
ClapperEnhancerProxyList *enhancer_proxies;
/* This is different from queue current item as it is used/changed only

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
@@ -50,6 +49,7 @@
#include "clapper-audio-stream-private.h"
#include "clapper-subtitle-stream-private.h"
#include "clapper-enhancer-proxy-list-private.h"
#include "clapper-reactable.h"
#include "clapper-enums-private.h"
#include "clapper-utils-private.h"
#include "../shared/clapper-shared-utils-private.h"
@@ -159,6 +159,8 @@ clapper_player_refresh_position (ClapperPlayer *self)
clapper_app_bus_post_prop_notify (self->app_bus,
GST_OBJECT_CAST (self), param_specs[PROP_POSITION]);
if (self->reactables_manager)
clapper_reactables_manager_trigger_position_changed (self->reactables_manager, position_dbl);
if (clapper_player_get_have_features (self))
clapper_features_manager_trigger_position_changed (self->features_manager, position_dbl);
}
@@ -225,6 +227,8 @@ clapper_player_handle_playbin_state_changed (ClapperPlayer *self)
clapper_app_bus_post_prop_notify (self->app_bus,
GST_OBJECT_CAST (self), param_specs[PROP_STATE]);
if (self->reactables_manager)
clapper_reactables_manager_trigger_state_changed (self->reactables_manager, state);
if (clapper_player_get_have_features (self))
clapper_features_manager_trigger_state_changed (self->features_manager, state);
}
@@ -256,6 +260,8 @@ clapper_player_handle_playbin_volume_changed (ClapperPlayer *self, const GValue
clapper_app_bus_post_prop_notify (self->app_bus,
GST_OBJECT_CAST (self), param_specs[PROP_VOLUME]);
if (self->reactables_manager)
clapper_reactables_manager_trigger_volume_changed (self->reactables_manager, volume);
if (clapper_player_get_have_features (self))
clapper_features_manager_trigger_volume_changed (self->features_manager, volume);
}
@@ -280,6 +286,8 @@ clapper_player_handle_playbin_mute_changed (ClapperPlayer *self, const GValue *v
clapper_app_bus_post_prop_notify (self->app_bus,
GST_OBJECT_CAST (self), param_specs[PROP_MUTE]);
if (self->reactables_manager)
clapper_reactables_manager_trigger_mute_changed (self->reactables_manager, mute);
if (clapper_player_get_have_features (self))
clapper_features_manager_trigger_mute_changed (self->features_manager, mute);
}
@@ -400,6 +408,8 @@ clapper_player_handle_playbin_rate_changed (ClapperPlayer *self, gdouble speed)
clapper_app_bus_post_prop_notify (self->app_bus,
GST_OBJECT_CAST (self), param_specs[PROP_SPEED]);
if (self->reactables_manager)
clapper_reactables_manager_trigger_speed_changed (self->reactables_manager, speed);
if (clapper_player_get_have_features (self))
clapper_features_manager_trigger_speed_changed (self->features_manager, speed);
}
@@ -816,7 +826,8 @@ _element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self
factory_name = g_intern_static_string (GST_OBJECT_NAME (factory));
GST_INFO_OBJECT (self, "Element setup: %s", factory_name);
if (factory_name == g_intern_static_string ("clapperenhancersrc")) {
if (factory_name == g_intern_static_string ("clapperextractablesrc")
|| factory_name == g_intern_static_string ("clapperplaylistdemux")) {
g_object_set (element,
"enhancer-proxies", self->enhancer_proxies,
NULL);
@@ -2326,6 +2337,11 @@ clapper_player_init (ClapperPlayer *self)
clapper_enhancer_proxy_list_fill_from_global_proxies (self->enhancer_proxies);
if (clapper_enhancer_proxy_list_has_proxy_with_interface (self->enhancer_proxies, CLAPPER_TYPE_REACTABLE)) {
self->reactables_manager = clapper_reactables_manager_new ();
gst_object_set_parent (GST_OBJECT_CAST (self->reactables_manager), GST_OBJECT_CAST (self));
}
self->position_query = gst_query_new_position (GST_FORMAT_TIME);
self->current_state = GST_STATE_NULL;
@@ -2392,6 +2408,11 @@ clapper_player_finalize (GObject *object)
gst_object_unparent (GST_OBJECT_CAST (self->subtitle_streams));
gst_object_unref (self->subtitle_streams);
if (self->reactables_manager) {
gst_object_unparent (GST_OBJECT_CAST (self->reactables_manager));
gst_object_unref (self->reactables_manager);
}
gst_object_unparent (GST_OBJECT_CAST (self->enhancer_proxies));
gst_object_unref (self->enhancer_proxies);
@@ -2833,7 +2854,7 @@ clapper_player_class_init (ClapperPlayerClass *klass)
* An initial bitrate (bits/s) to select during
* starting adaptive streaming such as DASH or HLS.
*
* If value is higher than lowest available bitrate in streaming
* If value is lower than the lowest available bitrate in streaming
* manifest, then lowest possible bitrate will be selected.
*
* Since: 0.8

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