mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 23:32:04 +02:00
Compare commits
63 Commits
configurab
...
c21e1c1c6a
Author | SHA1 | Date | |
---|---|---|---|
|
c21e1c1c6a | ||
|
92e0e22e8b | ||
|
4d5519b42d | ||
|
4a34fb3484 | ||
|
d8ea220aad | ||
|
dc56cb201a | ||
|
07f944fb31 | ||
|
b2e6533c30 | ||
|
7a56fbfff8 | ||
|
7457ffda13 | ||
|
bee2e08fb1 | ||
|
0c1d291006 | ||
|
4002a63e3a | ||
|
ff054743e6 | ||
|
9432156aec | ||
|
47d3ebe693 | ||
|
5f8270f0e8 | ||
|
54f059aaa3 | ||
|
f63e13ed39 | ||
|
daadabba8d | ||
|
225e665aff | ||
|
31564b568b | ||
|
1c376612b8 | ||
|
c4afd8bea1 | ||
|
266c588db9 | ||
|
1c0049ec2b | ||
|
7f326e6875 | ||
|
16430c4c66 | ||
|
9f1102bafd | ||
|
7b4a19659b | ||
|
8fe46d315c | ||
|
b5cc171803 | ||
|
0f929014d5 | ||
|
f3b120f451 | ||
|
c354d31436 | ||
|
c0b360dc0f | ||
|
a6ca0b726c | ||
|
976bcc338f | ||
|
6273446817 | ||
|
72ab32d4ef | ||
|
e9d0d8f345 | ||
|
0b8d359844 | ||
|
4a93bea203 | ||
|
5e2c1a8e30 | ||
|
72c8e4ab84 | ||
|
db61b9c773 | ||
|
682ad6c3c8 | ||
|
749796a12f | ||
|
c557c11e86 | ||
|
a2f67a9bc0 | ||
|
ddc0a4d8f9 | ||
|
92e3e686db | ||
|
9fd87dbbb9 | ||
|
ca15f4760a | ||
|
6ddb53252a | ||
|
b30d53d8ce | ||
|
1527873bcc | ||
|
e23f2acb3e | ||
|
1dfcb218ac | ||
|
b05f0f2b30 | ||
|
dad0d46196 | ||
|
147d94088c | ||
|
c7790d9f7b |
31
COPYING-LGPL
31
COPYING-LGPL
@@ -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!
|
||||
|
@@ -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('.')
|
||||
|
Submodule pkgs/flatpak/flathub updated: f58477c356...3a672be190
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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 ());
|
||||
|
@@ -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'),
|
||||
]
|
||||
)
|
||||
|
@@ -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);
|
||||
|
@@ -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')
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -176,7 +176,6 @@ if build_gir
|
||||
clappergtk_enums,
|
||||
],
|
||||
extra_args: [
|
||||
gir_init_section,
|
||||
'--quiet',
|
||||
'--warn-all',
|
||||
'-DCLAPPER_GTK_COMPILATION',
|
||||
|
@@ -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);
|
||||
|
@@ -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))
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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");
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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)
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
Reference in New Issue
Block a user