43 Commits

Author SHA1 Message Date
Rafał Dzięgiel
d9c8534bb7 Merge pull request #579 from Rafostar/audio
clapper-gtk: Add audio widget
2025-08-03 14:23:20 +02:00
Rafał Dzięgiel
292b339e8a clapper-app: Use actions from AV widget
Replace all usage of "video" actions with "av" as the former one is deprecated
2025-08-03 13:36:34 +02:00
Rafał Dzięgiel
ddfedddce5 clapper-app: Use player from AV widget
Replace all usage of "clapper_gtk_video_get_player" with
"clapper_gtk_av_get_player" as the former one is deprecated
2025-08-02 20:57:03 +02:00
Rafał Dzięgiel
743097060e gst: sink: Remove unused posting of navigation messages
We only need to post events in the pipeline for navigation to work.
This was never used for anything and it generates a lot of noise
in the pipeline bus when cursor is moving over video.
2025-08-02 20:50:26 +02:00
Rafał Dzięgiel
b0b15cec5c clapper: Add "message" signal to the player
A detailed signal that allows for applications to receive element
messages posted on the pipeline bus. Useful if app cares about
some custom message that player normally does not handle.

For example audio player might want to read "level" messages in
order to show current audio level or implement visualizations.
2025-08-02 20:50:24 +02:00
Rafał Dzięgiel
b9a8b28a1f examples: Add audio player python example
A simple audio player made using "ClapperGtkAudio"
widget with python3 GI bindings
2025-08-02 20:50:22 +02:00
Rafał Dzięgiel
4c8c76c8f7 clapper-gtk: Introduce "ClapperGtkAudio" widget
A widget similar to video but for audio playback only. Widgets from
ClapperGtk library like buttons, seek bar, etc. can be used in it
for building an audio player with ease.
2025-08-02 20:50:20 +02:00
Rafał Dzięgiel
a5db6f701d clapper-gtk: Use AV widget actions directly
Actions of video widget are being deprecated in favour of
the same actions in the recently added AV base class
2025-08-02 20:50:18 +02:00
Rafał Dzięgiel
4301a9a9fa clapper-gtk: video: Split code into subclass
Create a base class called "ClapperGtkAv" and subclass it into "ClapperGtkVideo".
This allows to have player and session inhibit logic in base class and share it
with other subclassed widgets.
2025-08-02 20:50:10 +02:00
Rafał Dzięgiel
c21e1c1c6a Merge pull request #578 from City-busz/window-group
Put each main window into its own group
2025-08-01 16:09:41 +02:00
Balló György
92e0e22e8b Put each main window into its own group
This fixes the problem that a main window cannot be used if a modal dialog
is opened in another main window.
2025-07-31 19:15:29 +02:00
Rafał Dzięgiel
4d5519b42d Merge pull request #575 from Rafostar/playlistable
Expandable playlists support
2025-07-26 18:10:29 +02:00
Rafał Dzięgiel
4a34fb3484 clapper: discoverer: Skip items that already have tags
When tags are populated elsewhere, do not run discovery on them again.
It is possible they were discovered in more efficient maner
(e.g. from playlist data itself).

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

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

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

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

View File

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

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env python3
import gi
gi.require_version('Adw', '1')
gi.require_version('Clapper', '0.0')
gi.require_version('ClapperGtk', '0.0')
gi.require_version('Gtk', '4.0')
from gi.repository import Adw, Clapper, ClapperGtk, Gtk
Clapper.init(None)
def on_activate(app):
# Create our widgets.
win = Gtk.ApplicationWindow(application=app, title='Clapper Audio', default_width=640, default_height=96)
audio = ClapperGtk.Audio()
box = Gtk.Box(valign=Gtk.Align.CENTER, margin_start=8, margin_end=8, spacing=4)
prev_btn = ClapperGtk.PreviousItemButton()
play_btn = ClapperGtk.TogglePlayButton()
next_btn = ClapperGtk.NextItemButton()
seek_bar = ClapperGtk.SeekBar()
# Add media for playback. First media item in queue will be automatically selected.
item = Clapper.MediaItem(uri='https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3')
audio.props.player.props.queue.add_item(item)
item = Clapper.MediaItem(uri='https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3')
audio.props.player.props.queue.add_item(item)
# Assemble window.
box.append(prev_btn)
box.append(play_btn)
box.append(next_btn)
box.append(seek_bar)
audio.set_child(box)
win.set_child(audio)
win.present()
# Not too loud. Mind the ears.
audio.props.player.props.volume = 0.7
# Start playback.
audio.props.player.play()
# Create a new application.
app = Adw.Application(application_id='com.example.ClapperAudio')
app.connect('activate', on_activate)
# Run the application.
app.run(None)

View File

@@ -1,5 +1,5 @@
project('clapper', 'c', project('clapper', 'c',
version: '0.9.0', version: '0.9.1',
meson_version: '>= 0.64.0', 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 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: [ default_options: [

View File

@@ -642,18 +642,6 @@ clapper_app_application_command_line (GApplication *app, GApplicationCommandLine
return EXIT_SUCCESS; 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 static void
add_item_from_file (GFile *file, ClapperQueue *queue) add_item_from_file (GFile *file, ClapperQueue *queue)
{ {
@@ -666,51 +654,6 @@ add_item_from_file (GFile *file, ClapperQueue *queue)
gst_object_unref (item); 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 static void
add_item_with_subtitles (GFile *media_file, add_item_with_subtitles (GFile *media_file,
GFile *subs_file, ClapperQueue *queue) GFile *subs_file, ClapperQueue *queue)
@@ -779,12 +722,8 @@ clapper_app_application_open (GApplication *app,
if (!handled) { if (!handled) {
gint i; gint i;
for (i = 0; i < n_files; ++i) { for (i = 0; i < n_files; ++i)
if (_is_claps_file (files[i])) add_item_from_file (files[i], queue);
add_items_from_claps_file (files[i], queue);
else
add_item_from_file (files[i], queue);
}
} }
add_only = (g_strcmp0 (hint, "add-only") == 0); add_only = (g_strcmp0 (hint, "add-only") == 0);

View File

@@ -582,7 +582,7 @@ _create_pipeline_svg_file_in_thread (GTask *task, GObject *source G_GNUC_UNUSED,
GVC_t *gvc; GVC_t *gvc;
gchar *path, *template = NULL, *dot_data = NULL, *img_data = NULL; gchar *path, *template = NULL, *dot_data = NULL, *img_data = NULL;
gint fd; gint fd;
guint size = 0; gsize size = 0;
if (!(tmp_subdir = _create_tmp_subdir ("pipelines", cancellable, &error))) if (!(tmp_subdir = _create_tmp_subdir ("pipelines", cancellable, &error)))
goto finish; goto finish;
@@ -610,7 +610,16 @@ _create_pipeline_svg_file_in_thread (GTask *task, GObject *source G_GNUC_UNUSED,
gvc = gvContext (); gvc = gvContext ();
gvLayout (gvc, graph, "dot"); gvLayout (gvc, graph, "dot");
#ifdef HAVE_GVC_13
gvRenderData (gvc, graph, "svg", &img_data, &size); 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); agclose (graph);
gvFreeContext (gvc); gvFreeContext (gvc);

View File

@@ -231,7 +231,7 @@ video_map_cb (GtkWidget *widget, ClapperAppWindow *self)
GST_TRACE_OBJECT (self, "Video map"); GST_TRACE_OBJECT (self, "Video map");
player = clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (self->video)); player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self->video));
g_signal_connect (player, "notify::volume", g_signal_connect (player, "notify::volume",
G_CALLBACK (_player_volume_changed_cb), self); G_CALLBACK (_player_volume_changed_cb), self);
@@ -252,7 +252,7 @@ video_unmap_cb (GtkWidget *widget, ClapperAppWindow *self)
GST_TRACE_OBJECT (self, "Video unmap"); GST_TRACE_OBJECT (self, "Video unmap");
player = clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (self->video)); player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self->video));
g_signal_handlers_disconnect_by_func (player, _player_volume_changed_cb, self); g_signal_handlers_disconnect_by_func (player, _player_volume_changed_cb, self);
g_signal_handlers_disconnect_by_func (player, _player_speed_changed_cb, self); g_signal_handlers_disconnect_by_func (player, _player_speed_changed_cb, self);
@@ -524,7 +524,7 @@ drag_update_cb (GtkGestureDrag *drag,
static inline void static inline void
_alter_volume (ClapperAppWindow *self, gdouble dy) _alter_volume (ClapperAppWindow *self, gdouble dy)
{ {
ClapperPlayer *player = clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (self->video)); ClapperPlayer *player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self->video));
gdouble volume = clapper_player_get_volume (player); gdouble volume = clapper_player_get_volume (player);
/* We do not want for volume to change too suddenly */ /* We do not want for volume to change too suddenly */
@@ -547,7 +547,7 @@ _alter_volume (ClapperAppWindow *self, gdouble dy)
static inline void static inline void
_alter_speed (ClapperAppWindow *self, gdouble dx) _alter_speed (ClapperAppWindow *self, gdouble dx)
{ {
ClapperPlayer *player = clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (self->video)); ClapperPlayer *player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self->video));
gdouble speed = clapper_player_get_speed (player); gdouble speed = clapper_player_get_speed (player);
speed -= dx * 0.02; speed -= dx * 0.02;
@@ -571,8 +571,7 @@ _begin_seek_operation (ClapperAppWindow *self)
if (self->seeking) if (self->seeking)
return FALSE; return FALSE;
player = clapper_gtk_video_get_player ( player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self->video));
CLAPPER_GTK_VIDEO_CAST (self->video));
queue = clapper_player_get_queue (player); queue = clapper_player_get_queue (player);
current_item = clapper_queue_get_current_item (queue); current_item = clapper_queue_get_current_item (queue);
@@ -600,8 +599,8 @@ static void
_end_seek_operation (ClapperAppWindow *self) _end_seek_operation (ClapperAppWindow *self)
{ {
if (self->seeking && self->current_duration > 0) { if (self->seeking && self->current_duration > 0) {
ClapperPlayer *player = clapper_gtk_video_get_player ( ClapperPlayer *player = clapper_gtk_av_get_player (
CLAPPER_GTK_VIDEO_CAST (self->video)); CLAPPER_GTK_AV_CAST (self->video));
clapper_player_seek_custom (player, self->pending_position, clapper_player_seek_custom (player, self->pending_position,
g_settings_get_int (self->settings, "seek-method")); g_settings_get_int (self->settings, "seek-method"));
@@ -764,8 +763,8 @@ _handle_seek_key_press (ClapperAppWindow *self, gboolean forward)
static void static void
_handle_chapter_key_press (ClapperAppWindow *self, gboolean forward) _handle_chapter_key_press (ClapperAppWindow *self, gboolean forward)
{ {
ClapperPlayer *player = clapper_gtk_video_get_player ( ClapperPlayer *player = clapper_gtk_av_get_player (
CLAPPER_GTK_VIDEO_CAST (self->video)); CLAPPER_GTK_AV_CAST (self->video));
ClapperQueue *queue = clapper_player_get_queue (player); ClapperQueue *queue = clapper_player_get_queue (player);
ClapperMediaItem *current_item = clapper_queue_get_current_item (queue); ClapperMediaItem *current_item = clapper_queue_get_current_item (queue);
ClapperTimeline *timeline; ClapperTimeline *timeline;
@@ -855,8 +854,8 @@ _handle_chapter_key_press (ClapperAppWindow *self, gboolean forward)
static void static void
_handle_item_key_press (ClapperAppWindow *self, gboolean forward) _handle_item_key_press (ClapperAppWindow *self, gboolean forward)
{ {
ClapperPlayer *player = clapper_gtk_video_get_player ( ClapperPlayer *player = clapper_gtk_av_get_player (
CLAPPER_GTK_VIDEO_CAST (self->video)); CLAPPER_GTK_AV_CAST (self->video));
ClapperQueue *queue = clapper_player_get_queue (player); ClapperQueue *queue = clapper_player_get_queue (player);
guint prev_index, index; guint prev_index, index;
@@ -864,7 +863,7 @@ _handle_item_key_press (ClapperAppWindow *self, gboolean forward)
prev_index = clapper_queue_get_current_index (queue); prev_index = clapper_queue_get_current_index (queue);
gtk_widget_activate_action (self->video, gtk_widget_activate_action (self->video,
(forward) ? "video.next-item" : "video.previous-item", NULL); (forward) ? "av.next-item" : "av.previous-item", NULL);
index = clapper_queue_get_current_index (queue); index = clapper_queue_get_current_index (queue);
/* Notify only when changed */ /* Notify only when changed */
@@ -881,14 +880,14 @@ _handle_speed_key_press (ClapperAppWindow *self, gboolean forward)
forward ^= (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL); forward ^= (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
gtk_widget_activate_action (self->video, gtk_widget_activate_action (self->video,
(forward) ? "video.speed-up" : "video.speed-down", NULL); (forward) ? "av.speed-up" : "av.speed-down", NULL);
} }
static inline void static inline void
_handle_progression_key_press (ClapperAppWindow *self) _handle_progression_key_press (ClapperAppWindow *self)
{ {
ClapperPlayer *player = clapper_gtk_video_get_player ( ClapperPlayer *player = clapper_gtk_av_get_player (
CLAPPER_GTK_VIDEO_CAST (self->video)); CLAPPER_GTK_AV_CAST (self->video));
ClapperQueue *queue = clapper_player_get_queue (player); ClapperQueue *queue = clapper_player_get_queue (player);
ClapperQueueProgressionMode mode; ClapperQueueProgressionMode mode;
const gchar *icon = NULL, *label = NULL; const gchar *icon = NULL, *label = NULL;
@@ -908,11 +907,11 @@ key_pressed_cb (GtkEventControllerKey *controller, guint keyval,
switch (keyval) { switch (keyval) {
case GDK_KEY_Up: case GDK_KEY_Up:
if ((state & GDK_MODIFIER_MASK) == 0) if ((state & GDK_MODIFIER_MASK) == 0)
gtk_widget_activate_action (self->video, "video.volume-up", NULL); gtk_widget_activate_action (self->video, "av.volume-up", NULL);
break; break;
case GDK_KEY_Down: case GDK_KEY_Down:
if ((state & GDK_MODIFIER_MASK) == 0) if ((state & GDK_MODIFIER_MASK) == 0)
gtk_widget_activate_action (self->video, "video.volume-down", NULL); gtk_widget_activate_action (self->video, "av.volume-down", NULL);
break; break;
case GDK_KEY_Left: case GDK_KEY_Left:
if ((state & GDK_MODIFIER_MASK) == 0) { if ((state & GDK_MODIFIER_MASK) == 0) {
@@ -943,7 +942,7 @@ key_pressed_cb (GtkEventControllerKey *controller, guint keyval,
case GDK_KEY_space: case GDK_KEY_space:
case GDK_KEY_k: case GDK_KEY_k:
if (!self->key_held && (state & GDK_MODIFIER_MASK) == 0) if (!self->key_held && (state & GDK_MODIFIER_MASK) == 0)
gtk_widget_activate_action (self->video, "video.toggle-play", NULL); gtk_widget_activate_action (self->video, "av.toggle-play", NULL);
break; break;
case GDK_KEY_less: case GDK_KEY_less:
if (!self->key_held) // Needs seek (action is slow) if (!self->key_held) // Needs seek (action is slow)
@@ -955,7 +954,7 @@ key_pressed_cb (GtkEventControllerKey *controller, guint keyval,
break; break;
case GDK_KEY_m: case GDK_KEY_m:
if (!self->key_held && (state & GDK_MODIFIER_MASK) == 0) if (!self->key_held && (state & GDK_MODIFIER_MASK) == 0)
gtk_widget_activate_action (self->video, "video.toggle-mute", NULL); gtk_widget_activate_action (self->video, "av.toggle-mute", NULL);
break; break;
case GDK_KEY_p: case GDK_KEY_p:
if (!self->key_held && (state & GDK_MODIFIER_MASK) == 0) if (!self->key_held && (state & GDK_MODIFIER_MASK) == 0)
@@ -1123,7 +1122,7 @@ clapper_app_window_get_video (ClapperAppWindow *self)
ClapperPlayer * ClapperPlayer *
clapper_app_window_get_player (ClapperAppWindow *self) clapper_app_window_get_player (ClapperAppWindow *self)
{ {
return clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (self->video)); return clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self->video));
} }
ClapperAppWindowExtraOptions * ClapperAppWindowExtraOptions *
@@ -1198,6 +1197,7 @@ clapper_app_window_init (ClapperAppWindow *self)
GtkSettings *settings; GtkSettings *settings;
GtkWidget *dummy_titlebar; GtkWidget *dummy_titlebar;
gint distance = 0; gint distance = 0;
GtkWindowGroup *group;
gtk_widget_set_size_request (GTK_WIDGET (self), gtk_widget_set_size_request (GTK_WIDGET (self),
MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT); MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
@@ -1229,6 +1229,11 @@ clapper_app_window_init (ClapperAppWindow *self)
gtk_drop_target_set_gtypes (self->drop_target, gtk_drop_target_set_gtypes (self->drop_target,
(GType[3]) { GDK_TYPE_FILE_LIST, G_TYPE_FILE, G_TYPE_STRING }, 3); (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 static void
@@ -1237,6 +1242,8 @@ clapper_app_window_constructed (GObject *object)
ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (object); ClapperAppWindow *self = CLAPPER_APP_WINDOW_CAST (object);
ClapperPlayer *player = clapper_app_window_get_player (self); ClapperPlayer *player = clapper_app_window_get_player (self);
ClapperQueue *queue = clapper_player_get_queue (player); ClapperQueue *queue = clapper_player_get_queue (player);
ClapperEnhancerProxyList *proxies = clapper_player_get_enhancer_proxies (player);
ClapperEnhancerProxy *proxy;
ClapperGtkExtraMenuButton *button; ClapperGtkExtraMenuButton *button;
AdwStyleManager *manager; AdwStyleManager *manager;
@@ -1250,10 +1257,6 @@ clapper_app_window_constructed (GObject *object)
#if (CLAPPER_HAVE_MPRIS || CLAPPER_HAVE_SERVER || CLAPPER_HAVE_DISCOVERER) #if (CLAPPER_HAVE_MPRIS || CLAPPER_HAVE_SERVER || CLAPPER_HAVE_DISCOVERER)
ClapperFeature *feature = NULL; ClapperFeature *feature = NULL;
#endif #endif
#if (!CLAPPER_HAVE_MPRIS || !CLAPPER_HAVE_SERVER || !CLAPPER_HAVE_DISCOVERER)
ClapperEnhancerProxyList *proxies = clapper_player_get_enhancer_proxies (player);
ClapperEnhancerProxy *proxy;
#endif
gchar mpris_name[45]; gchar mpris_name[45];
g_snprintf (mpris_name, sizeof (mpris_name), g_snprintf (mpris_name, sizeof (mpris_name),
@@ -1262,7 +1265,6 @@ clapper_app_window_constructed (GObject *object)
self->settings = g_settings_new (CLAPPER_APP_ID); self->settings = g_settings_new (CLAPPER_APP_ID);
self->last_volume = PERCENTAGE_ROUND (g_settings_get_double (self->settings, "volume")); self->last_volume = PERCENTAGE_ROUND (g_settings_get_double (self->settings, "volume"));
#if !CLAPPER_HAVE_MPRIS
if ((proxy = clapper_enhancer_proxy_list_get_proxy_by_module (proxies, "clapper-mpris"))) { if ((proxy = clapper_enhancer_proxy_list_get_proxy_by_module (proxies, "clapper-mpris"))) {
clapper_enhancer_proxy_set_locally (proxy, clapper_enhancer_proxy_set_locally (proxy,
"own-name", mpris_name, "own-name", mpris_name,
@@ -1270,14 +1272,15 @@ clapper_app_window_constructed (GObject *object)
"desktop-entry", CLAPPER_APP_ID, "desktop-entry", CLAPPER_APP_ID,
"queue-controllable", TRUE, NULL); "queue-controllable", TRUE, NULL);
gst_object_unref (proxy); gst_object_unref (proxy);
} } else {
#else #if CLAPPER_HAVE_MPRIS
feature = CLAPPER_FEATURE (clapper_mpris_new ( feature = CLAPPER_FEATURE (clapper_mpris_new (
mpris_name, CLAPPER_APP_NAME, CLAPPER_APP_ID)); mpris_name, CLAPPER_APP_NAME, CLAPPER_APP_ID));
clapper_mpris_set_queue_controllable (CLAPPER_MPRIS (feature), TRUE); clapper_mpris_set_queue_controllable (CLAPPER_MPRIS (feature), TRUE);
clapper_player_add_feature (player, feature); clapper_player_add_feature (player, feature);
gst_object_unref (feature); gst_object_unref (feature);
#endif #endif
}
#if CLAPPER_HAVE_SERVER #if CLAPPER_HAVE_SERVER
feature = CLAPPER_FEATURE (clapper_server_new ()); feature = CLAPPER_FEATURE (clapper_server_new ());

View File

@@ -31,8 +31,10 @@
gint gint
main (gint argc, gchar **argv) main (gint argc, gchar **argv)
{ {
const gchar *clapper_ldir;
GApplication *application; GApplication *application;
ClapperEnhancerProxyList *proxies;
const gchar *clapper_ldir;
guint i, n_proxies;
gint status; gint status;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@@ -64,6 +66,15 @@ main (gint argc, gchar **argv)
resolution = clapper_app_utils_win_hi_res_clock_start (); resolution = clapper_app_utils_win_hi_res_clock_start ();
#endif #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 (); application = clapper_app_application_new ();
status = g_application_run (application, argc, argv); status = g_application_run (application, argc, argv);

View File

@@ -105,6 +105,9 @@ if not pp_option.disabled()
if cgraph_dep.found() and gvc_dep.found() if cgraph_dep.found() and gvc_dep.found()
clapperapp_c_args += ['-DHAVE_GRAPHVIZ'] clapperapp_c_args += ['-DHAVE_GRAPHVIZ']
clapperapp_deps += [cgraph_dep, gvc_dep] 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' clapperapp_available_functionalities += 'pipeline-preview'
elif pp_option.enabled() elif pp_option.enabled()
error('pipeline-preview option was enabled, but required dependencies were not found') error('pipeline-preview option was enabled, but required dependencies were not found')

View File

@@ -0,0 +1,268 @@
/* Clapper GTK Integration Library
* Copyright (C) 2025 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
* ClapperGtkAudio:
*
* A GTK widget for audio playback with Clapper API.
*
* #ClapperGtkAudio is a widget meant for integrating audio playback
* within GTK application. It exposes [class@Clapper.Player] through its
* base class [property@ClapperGtk.Av:player] property.
*
* Other widgets (buttons, seek bar, etc.) provided by `ClapperGtk` library, once placed
* anywhere inside audio container (including nesting within another widget like [class@Gtk.Box])
* will automatically control #ClapperGtkAudio they are within. This allows to freely create
* custom UI best suited for specific application.
*
* # Basic usage
*
* A typical use case is to embed audio widget as part of your app where audio playback
* is needed (can be even the very first child of the window). Get the [class@Clapper.Player]
* belonging to the AV widget and start adding new [class@Clapper.MediaItem] items to the
* [class@Clapper.Queue] for playback. For more information please refer to the Clapper
* playback library documentation.
*
* # Actions
*
* You can use built-in actions of parent [class@ClapperGtk.Av].
* See its documentation for the list of available ones.
*
* # ClapperGtkAudio as GtkBuildable
*
* #ClapperGtkAudio implementation of the [iface@Gtk.Buildable] interface supports
* placing a single widget (which might then hold multiple widgets) as `<child>` element.
*
* ```xml
* <object class="ClapperGtkAudio" id="audio">
* <child>
* <object class="GtkBox">
* <property name="orientation">horizontal</property>
* <child>
* <object class="ClapperGtkPreviousItemButton">
* </child>
* <child>
* <object class="ClapperGtkTogglePlayButton">
* </child>
* <child>
* <object class="ClapperGtkNextItemButton">
* </child>
* </object>
* </child>
* </object>
* ```
*
* Since: 0.10
*/
#include "config.h"
#include "clapper-gtk-audio.h"
#define GST_CAT_DEFAULT clapper_gtk_audio_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperGtkAudio
{
ClapperGtkAv parent;
GtkWidget *child;
};
static void
clapper_gtk_audio_add_child (GtkBuildable *buildable,
GtkBuilder *builder, GObject *child, const char *type)
{
if (GTK_IS_WIDGET (child)) {
clapper_gtk_audio_set_child (CLAPPER_GTK_AUDIO (buildable), GTK_WIDGET (child));
} else {
GtkBuildableIface *parent_iface = g_type_interface_peek_parent (GTK_BUILDABLE_GET_IFACE (buildable));
parent_iface->add_child (buildable, builder, child, type);
}
}
static void
_buildable_iface_init (GtkBuildableIface *iface)
{
iface->add_child = clapper_gtk_audio_add_child;
}
#define parent_class clapper_gtk_audio_parent_class
G_DEFINE_TYPE_WITH_CODE (ClapperGtkAudio, clapper_gtk_audio, CLAPPER_GTK_TYPE_AV,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, _buildable_iface_init))
enum
{
PROP_0,
PROP_CHILD,
PROP_LAST
};
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static inline void
_unparent_child (ClapperGtkAudio *self)
{
GtkWidget *child;
if ((child = gtk_widget_get_first_child (GTK_WIDGET (self))))
gtk_widget_unparent (child);
}
/**
* clapper_gtk_audio_new:
*
* Creates a new #ClapperGtkAudio instance.
*
* Newly created audio widget will also have set "scaletempo" GStreamer element
* as default audio filter on its [class@Clapper.Player] and disable video and
* subtitle streams. This can be changed after construction by setting
* corresponding player properties.
*
* Returns: a new audio #GtkWidget.
*/
GtkWidget *
clapper_gtk_audio_new (void)
{
return g_object_new (CLAPPER_GTK_TYPE_AUDIO, NULL);
}
/**
* clapper_gtk_audio_set_child:
* @audio: a #ClapperGtkAudio
* @child: (nullable): a #GtkWidget
*
* Set a child #GtkWidget of @audio.
*/
void
clapper_gtk_audio_set_child (ClapperGtkAudio *self, GtkWidget *child)
{
g_return_if_fail (CLAPPER_GTK_IS_AUDIO (self));
g_return_if_fail (GTK_IS_WIDGET (child));
_unparent_child (self);
if (child)
gtk_widget_set_parent (child, GTK_WIDGET (self));
}
/**
* clapper_gtk_audio_get_child:
* @audio: a #ClapperGtkAudio
*
* Get a child #GtkWidget of @audio.
*
* Returns: (transfer none) (nullable): #GtkWidget set as child.
*/
GtkWidget *
clapper_gtk_audio_get_child (ClapperGtkAudio *self)
{
g_return_val_if_fail (CLAPPER_GTK_IS_AUDIO (self), NULL);
return gtk_widget_get_first_child (GTK_WIDGET (self));
}
static void
clapper_gtk_audio_init (ClapperGtkAudio *self)
{
}
static void
clapper_gtk_audio_constructed (GObject *object)
{
ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object);
ClapperPlayer *player;
G_OBJECT_CLASS (parent_class)->constructed (object);
player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self));
clapper_player_set_video_enabled (player, FALSE);
clapper_player_set_subtitles_enabled (player, FALSE);
}
static void
clapper_gtk_audio_dispose (GObject *object)
{
ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object);
_unparent_child (self);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_gtk_audio_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object);
switch (prop_id) {
case PROP_CHILD:
g_value_set_object (value, clapper_gtk_audio_get_child (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_gtk_audio_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperGtkAudio *self = CLAPPER_GTK_AUDIO_CAST (object);
switch (prop_id) {
case PROP_CHILD:
clapper_gtk_audio_set_child (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_gtk_audio_class_init (ClapperGtkAudioClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkaudio", GST_DEBUG_FG_MAGENTA,
"Clapper GTK Audio");
gobject_class->constructed = clapper_gtk_audio_constructed;
gobject_class->get_property = clapper_gtk_audio_get_property;
gobject_class->set_property = clapper_gtk_audio_set_property;
gobject_class->dispose = clapper_gtk_audio_dispose;
/**
* ClapperGtkAudio:child:
*
* The child widget of `ClapperGtkAudio`.
*/
param_specs[PROP_CHILD] = g_param_spec_object ("child",
NULL, NULL, GTK_TYPE_WIDGET,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GENERIC);
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-audio");
}

View File

@@ -0,0 +1,49 @@
/* Clapper GTK Integration Library
* Copyright (C) 2025 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
#endif
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <clapper-gtk/clapper-gtk-av.h>
#include <clapper-gtk/clapper-gtk-visibility.h>
G_BEGIN_DECLS
#define CLAPPER_GTK_TYPE_AUDIO (clapper_gtk_audio_get_type())
#define CLAPPER_GTK_AUDIO_CAST(obj) ((ClapperGtkAudio *)(obj))
CLAPPER_GTK_API
G_DECLARE_FINAL_TYPE (ClapperGtkAudio, clapper_gtk_audio, CLAPPER_GTK, AUDIO, ClapperGtkAv)
CLAPPER_GTK_API
GtkWidget * clapper_gtk_audio_new (void);
CLAPPER_GTK_API
void clapper_gtk_audio_set_child (ClapperGtkAudio *audio, GtkWidget *child);
CLAPPER_GTK_API
GtkWidget * clapper_gtk_audio_get_child (ClapperGtkAudio *audio);
G_END_DECLS

View File

@@ -0,0 +1,645 @@
/* Clapper GTK Integration Library
* Copyright (C) 2025 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
/**
* ClapperGtkAv:
*
* A base class for GTK audio and video widgets.
*
* See its descendants: [class@ClapperGtk.Audio] and [class@ClapperGtk.Video].
*
* # Actions
*
* #ClapperGtkAv defines a set of built-in actions:
*
* ```yaml
* - "av.toggle-play": toggle play/pause
* - "av.play": start/resume playback
* - "av.pause": pause playback
* - "av.stop": stop playback
* - "av.seek": seek to position (variant "d")
* - "av.seek-custom": seek to position using seek method (variant "(di)")
* - "av.toggle-mute": toggle mute state
* - "av.set-mute": set mute state (variant "b")
* - "av.volume-up": increase volume by 2%
* - "av.volume-down": decrease volume by 2%
* - "av.set-volume": set volume to specified value (variant "d")
* - "av.speed-up": increase speed (from 0.05x - 2x range to nearest quarter)
* - "av.speed-down": decrease speed (from 0.05x - 2x range to nearest quarter)
* - "av.set-speed": set speed to specified value (variant "d")
* - "av.previous-item": select previous item in queue
* - "av.next-item": select next item in queue
* - "av.select-item": select item at specified index in queue (variant "u")
* ```
*
* Since: 0.10
*/
#include "config.h"
#include <math.h>
#include "clapper-gtk-av.h"
#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01)
#define DEFAULT_AUTO_INHIBIT FALSE
#define GST_CAT_DEFAULT clapper_gtk_av_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
typedef struct _ClapperGtkAvPrivate ClapperGtkAvPrivate;
struct _ClapperGtkAvPrivate
{
ClapperPlayer *player;
gboolean auto_inhibit;
guint inhibit_cookie;
};
#define parent_class clapper_gtk_av_parent_class
G_DEFINE_TYPE_WITH_PRIVATE (ClapperGtkAv, clapper_gtk_av, GTK_TYPE_WIDGET)
enum
{
PROP_0,
PROP_PLAYER,
PROP_AUTO_INHIBIT,
PROP_INHIBITED,
PROP_LAST
};
static gboolean provider_added = FALSE;
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static void
toggle_play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
switch (clapper_player_get_state (player)) {
case CLAPPER_PLAYER_STATE_PLAYING:
clapper_player_pause (player);
break;
case CLAPPER_PLAYER_STATE_STOPPED:
case CLAPPER_PLAYER_STATE_PAUSED:
clapper_player_play (player);
break;
default:
break;
}
}
static void
play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
clapper_player_play (player);
}
static void
pause_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
clapper_player_pause (player);
}
static void
stop_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
clapper_player_stop (player);
}
static void
seek_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble position = g_variant_get_double (parameter);
clapper_player_seek (player, position);
}
static void
seek_custom_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
ClapperPlayerSeekMethod method = CLAPPER_PLAYER_SEEK_METHOD_NORMAL;
gdouble position = 0;
g_variant_get (parameter, "(di)", &position, &method);
clapper_player_seek_custom (player, position, method);
}
static void
toggle_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
clapper_player_set_mute (player, !clapper_player_get_mute (player));
}
static void
set_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gboolean mute = g_variant_get_boolean (parameter);
clapper_player_set_mute (player, mute);
}
static void
volume_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble volume = (clapper_player_get_volume (player) + 0.02);
if (volume > 2.0)
volume = 2.0;
clapper_player_set_volume (player, PERCENTAGE_ROUND (volume));
}
static void
volume_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble volume = (clapper_player_get_volume (player) - 0.02);
if (volume < 0)
volume = 0;
clapper_player_set_volume (player, PERCENTAGE_ROUND (volume));
}
static void
set_volume_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble volume = g_variant_get_double (parameter);
clapper_player_set_volume (player, volume);
}
static void
speed_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble dest, speed = clapper_player_get_speed (player);
if (speed >= 2.0)
return;
dest = 0.25;
while (speed >= dest)
dest += 0.25;
if (dest > 2.0)
dest = 2.0;
clapper_player_set_speed (player, dest);
}
static void
speed_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble dest, speed = clapper_player_get_speed (player);
if (speed <= 0.05)
return;
dest = 2.0;
while (speed <= dest)
dest -= 0.25;
if (dest < 0.05)
dest = 0.05;
clapper_player_set_speed (player, dest);
}
static void
set_speed_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
gdouble speed = g_variant_get_double (parameter);
clapper_player_set_speed (player, speed);
}
static void
previous_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
clapper_queue_select_previous_item (clapper_player_get_queue (player));
}
static void
next_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
clapper_queue_select_next_item (clapper_player_get_queue (player));
}
static void
select_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperPlayer *player = clapper_gtk_av_get_player (self);
guint index = g_variant_get_uint32 (parameter);
clapper_queue_select_index (clapper_player_get_queue (player), index);
}
static void
_ensure_css_provider (void)
{
GdkDisplay *display;
if (provider_added)
return;
display = gdk_display_get_default ();
if (G_LIKELY (display != NULL)) {
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider,
CLAPPER_GTK_RESOURCE_PREFIX "/css/styles.css");
gtk_style_context_add_provider_for_display (display,
(GtkStyleProvider *) provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1);
g_object_unref (provider);
provider_added = TRUE;
}
}
static inline void
_set_inhibit_session (ClapperGtkAv *self, gboolean inhibit)
{
ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self);
GtkRoot *root;
GApplication *app;
gboolean inhibited = (priv->inhibit_cookie != 0);
if (inhibited == inhibit)
return;
GST_DEBUG_OBJECT (self, "Trying to %sinhibit session...", (inhibit) ? "" : "un");
root = gtk_widget_get_root (GTK_WIDGET (self));
if (!root && !GTK_IS_WINDOW (root)) {
GST_WARNING_OBJECT (self, "Cannot %sinhibit session "
"without root window", (inhibit) ? "" : "un");
return;
}
/* NOTE: Not using application from window prop,
* as it goes away early when unrooting */
app = g_application_get_default ();
if (!app && !GTK_IS_APPLICATION (app)) {
GST_WARNING_OBJECT (self, "Cannot %sinhibit session "
"without window application set", (inhibit) ? "" : "un");
return;
}
if (inhibited) {
gtk_application_uninhibit (GTK_APPLICATION (app), priv->inhibit_cookie);
priv->inhibit_cookie = 0;
}
if (inhibit) {
priv->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (app),
GTK_WINDOW (root), GTK_APPLICATION_INHIBIT_IDLE,
"Media is playing");
}
GST_DEBUG_OBJECT (self, "Session %sinhibited", (inhibit) ? "" : "un");
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_INHIBITED]);
}
static void
_player_state_changed_cb (ClapperPlayer *player,
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkAv *self)
{
ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self);
if (priv->auto_inhibit) {
ClapperPlayerState state = clapper_player_get_state (player);
_set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING);
}
}
/**
* clapper_gtk_av_get_player:
* @av: a #ClapperGtkAv
*
* Get #ClapperPlayer used by this #ClapperGtkAv instance.
*
* Returns: (transfer none): a #ClapperPlayer used by widget.
*
* Since: 0.10
*/
ClapperPlayer *
clapper_gtk_av_get_player (ClapperGtkAv *self)
{
ClapperGtkAvPrivate *priv;
g_return_val_if_fail (CLAPPER_GTK_IS_AV (self), NULL);
priv = clapper_gtk_av_get_instance_private (self);
return priv->player;
}
/**
* clapper_gtk_av_set_auto_inhibit:
* @av: a #ClapperGtkAv
* @inhibit: whether to enable automatic session inhibit
*
* Set whether widget should try to automatically inhibit session
* from idling (and possibly screen going black) when media is playing.
*
* Since: 0.10
*/
void
clapper_gtk_av_set_auto_inhibit (ClapperGtkAv *self, gboolean inhibit)
{
ClapperGtkAvPrivate *priv;
g_return_if_fail (CLAPPER_GTK_IS_AV (self));
priv = clapper_gtk_av_get_instance_private (self);
if (priv->auto_inhibit != inhibit) {
priv->auto_inhibit = inhibit;
/* Uninhibit if we were auto inhibited earlier */
if (!priv->auto_inhibit)
_set_inhibit_session (self, FALSE);
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_AUTO_INHIBIT]);
}
}
/**
* clapper_gtk_av_get_auto_inhibit:
* @av: a #ClapperGtkAv
*
* Get whether automatic session inhibit is enabled.
*
* Returns: %TRUE if enabled, %FALSE otherwise.
*
* Since: 0.10
*/
gboolean
clapper_gtk_av_get_auto_inhibit (ClapperGtkAv *self)
{
ClapperGtkAvPrivate *priv;
g_return_val_if_fail (CLAPPER_GTK_IS_AV (self), FALSE);
priv = clapper_gtk_av_get_instance_private (self);
return priv->auto_inhibit;
}
/**
* clapper_gtk_av_get_inhibited:
* @av: a #ClapperGtkAv
*
* Get whether session is currently inhibited by
* [property@ClapperGtk.Av:auto-inhibit].
*
* Returns: %TRUE if inhibited, %FALSE otherwise.
*
* Since: 0.10
*/
gboolean
clapper_gtk_av_get_inhibited (ClapperGtkAv *self)
{
ClapperGtkAvPrivate *priv;
g_return_val_if_fail (CLAPPER_GTK_IS_AV (self), FALSE);
priv = clapper_gtk_av_get_instance_private (self);
return (priv->inhibit_cookie != 0);
}
static void
clapper_gtk_av_root (GtkWidget *widget)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self);
_ensure_css_provider ();
GTK_WIDGET_CLASS (parent_class)->root (widget);
if (priv->auto_inhibit) {
ClapperPlayerState state = clapper_player_get_state (priv->player);
_set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING);
}
}
static void
clapper_gtk_av_unroot (GtkWidget *widget)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (widget);
_set_inhibit_session (self, FALSE);
GTK_WIDGET_CLASS (parent_class)->unroot (widget);
}
static void
clapper_gtk_av_init (ClapperGtkAv *self)
{
ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self);
priv->auto_inhibit = DEFAULT_AUTO_INHIBIT;
}
static void
clapper_gtk_av_constructed (GObject *object)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object);
ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self);
GstElement *afilter;
priv->player = clapper_player_new ();
g_signal_connect (priv->player, "notify::state",
G_CALLBACK (_player_state_changed_cb), self);
afilter = gst_element_factory_make ("scaletempo", NULL);
if (G_LIKELY (afilter != NULL))
clapper_player_set_audio_filter (priv->player, afilter);
G_OBJECT_CLASS (parent_class)->constructed (object);
}
static void
clapper_gtk_av_dispose (GObject *object)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object);
ClapperGtkAvPrivate *priv = clapper_gtk_av_get_instance_private (self);
/* Something else might still be holding a reference on the player,
* thus we should disconnect everything before disposing template */
if (priv->player) {
g_signal_handlers_disconnect_by_func (priv->player,
_player_state_changed_cb, self);
}
gst_clear_object (&priv->player);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
clapper_gtk_av_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object);
switch (prop_id) {
case PROP_PLAYER:
g_value_set_object (value, clapper_gtk_av_get_player (self));
break;
case PROP_AUTO_INHIBIT:
g_value_set_boolean (value, clapper_gtk_av_get_auto_inhibit (self));
break;
case PROP_INHIBITED:
g_value_set_boolean (value, clapper_gtk_av_get_inhibited (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_gtk_av_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
ClapperGtkAv *self = CLAPPER_GTK_AV_CAST (object);
switch (prop_id) {
case PROP_AUTO_INHIBIT:
clapper_gtk_av_set_auto_inhibit (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clapper_gtk_av_class_init (ClapperGtkAvClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergtkav", GST_DEBUG_FG_MAGENTA,
"Clapper GTK AV");
widget_class->root = clapper_gtk_av_root;
widget_class->unroot = clapper_gtk_av_unroot;
gobject_class->constructed = clapper_gtk_av_constructed;
gobject_class->get_property = clapper_gtk_av_get_property;
gobject_class->set_property = clapper_gtk_av_set_property;
gobject_class->dispose = clapper_gtk_av_dispose;
/**
* ClapperGtkAv:player:
*
* A #ClapperPlayer used by widget.
*/
param_specs[PROP_PLAYER] = g_param_spec_object ("player",
NULL, NULL, CLAPPER_TYPE_PLAYER,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* ClapperGtkAv:auto-inhibit:
*
* Try to automatically inhibit session when media is playing.
*/
param_specs[PROP_AUTO_INHIBIT] = g_param_spec_boolean ("auto-inhibit",
NULL, NULL, DEFAULT_AUTO_INHIBIT,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* ClapperGtkAv:inhibited:
*
* Get whether session is currently inhibited by playback.
*/
param_specs[PROP_INHIBITED] = g_param_spec_boolean ("inhibited",
NULL, NULL, FALSE,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
gtk_widget_class_install_action (widget_class, "av.toggle-play", NULL, toggle_play_action_cb);
gtk_widget_class_install_action (widget_class, "av.play", NULL, play_action_cb);
gtk_widget_class_install_action (widget_class, "av.pause", NULL, pause_action_cb);
gtk_widget_class_install_action (widget_class, "av.stop", NULL, stop_action_cb);
gtk_widget_class_install_action (widget_class, "av.seek", "d", seek_action_cb);
gtk_widget_class_install_action (widget_class, "av.seek-custom", "(di)", seek_custom_action_cb);
gtk_widget_class_install_action (widget_class, "av.toggle-mute", NULL, toggle_mute_action_cb);
gtk_widget_class_install_action (widget_class, "av.set-mute", "b", set_mute_action_cb);
gtk_widget_class_install_action (widget_class, "av.volume-up", NULL, volume_up_action_cb);
gtk_widget_class_install_action (widget_class, "av.volume-down", NULL, volume_down_action_cb);
gtk_widget_class_install_action (widget_class, "av.set-volume", "d", set_volume_action_cb);
gtk_widget_class_install_action (widget_class, "av.speed-up", NULL, speed_up_action_cb);
gtk_widget_class_install_action (widget_class, "av.speed-down", NULL, speed_down_action_cb);
gtk_widget_class_install_action (widget_class, "av.set-speed", "d", set_speed_action_cb);
gtk_widget_class_install_action (widget_class, "av.previous-item", NULL, previous_item_action_cb);
gtk_widget_class_install_action (widget_class, "av.next-item", NULL, next_item_action_cb);
gtk_widget_class_install_action (widget_class, "av.select-item", "u", select_item_action_cb);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GENERIC);
gtk_widget_class_set_css_name (widget_class, "clapper-gtk-av");
}

View File

@@ -0,0 +1,60 @@
/* Clapper GTK Integration Library
* Copyright (C) 2025 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* <https://www.gnu.org/licenses/>.
*/
#pragma once
#if !defined(__CLAPPER_GTK_INSIDE__) && !defined(CLAPPER_GTK_COMPILATION)
#error "Only <clapper-gtk/clapper-gtk.h> can be included directly."
#endif
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <clapper/clapper.h>
#include <clapper-gtk/clapper-gtk-visibility.h>
G_BEGIN_DECLS
#define CLAPPER_GTK_TYPE_AV (clapper_gtk_av_get_type())
#define CLAPPER_GTK_AV_CAST(obj) ((ClapperGtkAv *)(obj))
CLAPPER_GTK_API
G_DECLARE_DERIVABLE_TYPE (ClapperGtkAv, clapper_gtk_av, CLAPPER_GTK, AV, GtkWidget)
struct _ClapperGtkAvClass
{
GtkWidgetClass parent_class;
/*< private >*/
gpointer padding[4];
};
CLAPPER_GTK_API
ClapperPlayer * clapper_gtk_av_get_player (ClapperGtkAv *av);
CLAPPER_GTK_API
void clapper_gtk_av_set_auto_inhibit (ClapperGtkAv *av, gboolean inhibit);
CLAPPER_GTK_API
gboolean clapper_gtk_av_get_auto_inhibit (ClapperGtkAv *av);
CLAPPER_GTK_API
gboolean clapper_gtk_av_get_inhibited (ClapperGtkAv *av);
G_END_DECLS

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -83,7 +82,7 @@ clapper_gtk_next_item_button_init (ClapperGtkNextItemButton *self)
{ {
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
gtk_button_set_icon_name (GTK_BUTTON (self), "media-skip-forward-symbolic"); gtk_button_set_icon_name (GTK_BUTTON (self), "media-skip-forward-symbolic");
gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "video.next-item"); gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "av.next-item");
} }
static void static void

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -83,7 +82,7 @@ clapper_gtk_previous_item_button_init (ClapperGtkPreviousItemButton *self)
{ {
gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
gtk_button_set_icon_name (GTK_BUTTON (self), "media-skip-backward-symbolic"); gtk_button_set_icon_name (GTK_BUTTON (self), "media-skip-backward-symbolic");
gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "video.previous-item"); gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "av.previous-item");
} }
static void static void

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -396,6 +395,47 @@ _update_duration_label (ClapperGtkSeekBar *self, gdouble duration)
gtk_adjustment_set_upper (adjustment, 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 static void
_update_scale_marks (ClapperGtkSeekBar *self, ClapperTimeline *timeline) _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) { for (i = 0; i < n_markers; ++i) {
ClapperMarker *marker = clapper_timeline_get_marker (timeline, 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); 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_TOP, NULL);
gtk_scale_add_mark (GTK_SCALE (self->scale), start, GTK_POS_BOTTOM, 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); gst_object_unref (marker);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -84,7 +83,7 @@ static void
clapper_gtk_toggle_play_button_init (ClapperGtkTogglePlayButton *self) clapper_gtk_toggle_play_button_init (ClapperGtkTogglePlayButton *self)
{ {
gtk_button_set_icon_name (GTK_BUTTON (self), PLAY_ICON_NAME); gtk_button_set_icon_name (GTK_BUTTON (self), PLAY_ICON_NAME);
gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "video.toggle-play"); gtk_actionable_set_action_name (GTK_ACTIONABLE (self), "av.toggle-play");
} }
static void static void

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
#include "config.h" #include "config.h"
@@ -22,7 +21,7 @@
#include <glib/gi18n-lib.h> #include <glib/gi18n-lib.h>
#include "clapper-gtk-utils-private.h" #include "clapper-gtk-utils-private.h"
#include "clapper-gtk-video.h" #include "clapper-gtk-av.h"
static gboolean initialized = FALSE; static gboolean initialized = FALSE;
@@ -30,18 +29,18 @@ static gboolean initialized = FALSE;
* clapper_gtk_get_player_from_ancestor: * clapper_gtk_get_player_from_ancestor:
* @widget: a #GtkWidget * @widget: a #GtkWidget
* *
* Get [class@Clapper.Player] used by [class@ClapperGtk.Video] ancestor of @widget. * Get [class@Clapper.Player] used by [class@ClapperGtk.Av] ancestor of @widget.
* *
* This utility is a convenience wrapper for calling [method@Gtk.Widget.get_ancestor] * This utility is a convenience wrapper for calling [method@Gtk.Widget.get_ancestor]
* of type `CLAPPER_GTK_TYPE_VIDEO` and [method@ClapperGtk.Video.get_player] with * of type `CLAPPER_GTK_TYPE_AV` and [method@ClapperGtk.Av.get_player] with
* additional %NULL checking and type casting. * additional %NULL checking and type casting.
* *
* This is meant to be used mainly for custom widget development as an easy access to the * This is meant to be used mainly for custom widget development as an easy access to the
* underlying parent [class@Clapper.Player] object. If you want to get the player from * underlying parent [class@Clapper.Player] object. If you want to get the player from
* [class@ClapperGtk.Video] widget itself, use [method@ClapperGtk.Video.get_player] instead. * [class@ClapperGtk.Av] widget itself, use [method@ClapperGtk.Av.get_player] instead.
* *
* Rememeber that this function will return %NULL when widget does not have * Rememeber that this function will return %NULL when widget does not have
* a [class@ClapperGtk.Video] ancestor in widget hierarchy (widget is not yet placed). * a [class@ClapperGtk.Av] ancestor in widget hierarchy (widget is not yet placed).
* *
* Returns: (transfer none) (nullable): a #ClapperPlayer from ancestor of a @widget. * Returns: (transfer none) (nullable): a #ClapperPlayer from ancestor of a @widget.
*/ */
@@ -53,8 +52,8 @@ clapper_gtk_get_player_from_ancestor (GtkWidget *widget)
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
if ((parent = gtk_widget_get_ancestor (widget, CLAPPER_GTK_TYPE_VIDEO))) if ((parent = gtk_widget_get_ancestor (widget, CLAPPER_GTK_TYPE_AV)))
player = clapper_gtk_video_get_player (CLAPPER_GTK_VIDEO_CAST (parent)); player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (parent));
return player; return player;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -23,8 +22,8 @@
* A ready to be used GTK video widget implementing Clapper API. * A ready to be used GTK video widget implementing Clapper API.
* *
* #ClapperGtkVideo is the main widget exposed by `ClapperGtk` API. It both displays * #ClapperGtkVideo is the main widget exposed by `ClapperGtk` API. It both displays
* videos played by [class@Clapper.Player] (exposed as its property) and manages * videos played by [class@Clapper.Player] (exposed as [property@ClapperGtk.Av:player] property)
* revealing and fading of any additional widgets overlaid on top of it. * and manages revealing and fading of any additional widgets overlaid on top of it.
* *
* Other widgets provided by `ClapperGtk` library, once placed anywhere on video * Other widgets provided by `ClapperGtk` library, once placed anywhere on video
* (including nesting within another widget like [class@Gtk.Box]) will automatically * (including nesting within another widget like [class@Gtk.Box]) will automatically
@@ -35,7 +34,7 @@
* # Basic usage * # Basic usage
* *
* A typical use case is to embed video widget as part of your app where video playback * A typical use case is to embed video widget as part of your app where video playback
* is needed. Get the [class@Clapper.Player] belonging to the video widget and start adding * is needed. Get the [class@Clapper.Player] belonging to the AV widget and start adding
* new [class@Clapper.MediaItem] items to the [class@Clapper.Queue] for playback. * new [class@Clapper.MediaItem] items to the [class@Clapper.Queue] for playback.
* For more information please refer to the Clapper playback library documentation. * For more information please refer to the Clapper playback library documentation.
* *
@@ -47,27 +46,8 @@
* *
* # Actions * # Actions
* *
* #ClapperGtkVideo defines a set of built-in actions: * You can use built-in actions of parent [class@ClapperGtk.Av].
* * See its documentation, for the list of available ones.
* ```yaml
* - "video.toggle-play": toggle play/pause
* - "video.play": start/resume playback
* - "video.pause": pause playback
* - "video.stop": stop playback
* - "video.seek": seek to position (variant "d")
* - "video.seek-custom": seek to position using seek method (variant "(di)")
* - "video.toggle-mute": toggle mute state
* - "video.set-mute": set mute state (variant "b")
* - "video.volume-up": increase volume by 2%
* - "video.volume-down": decrease volume by 2%
* - "video.set-volume": set volume to specified value (variant "d")
* - "video.speed-up": increase speed (from 0.05x - 2x range to nearest quarter)
* - "video.speed-down": decrease speed (from 0.05x - 2x range to nearest quarter)
* - "video.set-speed": set speed to specified value (variant "d")
* - "video.previous-item": select previous item in queue
* - "video.next-item": select next item in queue
* - "video.select-item": select item at specified index in queue (variant "u")
* ```
* *
* # ClapperGtkVideo as GtkBuildable * # ClapperGtkVideo as GtkBuildable
* *
@@ -94,8 +74,6 @@
#include "config.h" #include "config.h"
#include <math.h>
#include "clapper-gtk-enums.h" #include "clapper-gtk-enums.h"
#include "clapper-gtk-video.h" #include "clapper-gtk-video.h"
#include "clapper-gtk-lead-container.h" #include "clapper-gtk-lead-container.h"
@@ -103,11 +81,8 @@
#include "clapper-gtk-buffering-animation-private.h" #include "clapper-gtk-buffering-animation-private.h"
#include "clapper-gtk-video-placeholder-private.h" #include "clapper-gtk-video-placeholder-private.h"
#define PERCENTAGE_ROUND(a) (round ((gdouble) a / 0.01) * 0.01)
#define DEFAULT_FADE_DELAY 3000 #define DEFAULT_FADE_DELAY 3000
#define DEFAULT_TOUCH_FADE_DELAY 5000 #define DEFAULT_TOUCH_FADE_DELAY 5000
#define DEFAULT_AUTO_INHIBIT FALSE
#define MIN_MOTION_DELAY 100000 #define MIN_MOTION_DELAY 100000
@@ -116,7 +91,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _ClapperGtkVideo struct _ClapperGtkVideo
{ {
GtkWidget parent; ClapperGtkAv parent;
GtkWidget *overlay; GtkWidget *overlay;
GtkWidget *status; GtkWidget *status;
@@ -126,10 +101,8 @@ struct _ClapperGtkVideo
GtkGesture *click_gesture; GtkGesture *click_gesture;
/* Props */ /* Props */
ClapperPlayer *player;
guint fade_delay; guint fade_delay;
guint touch_fade_delay; guint touch_fade_delay;
gboolean auto_inhibit;
GPtrArray *overlays; GPtrArray *overlays;
GPtrArray *fading_overlays; GPtrArray *fading_overlays;
@@ -141,8 +114,6 @@ struct _ClapperGtkVideo
guint fade_timeout; guint fade_timeout;
gboolean reveal, revealed; gboolean reveal, revealed;
guint inhibit_cookie;
/* Current pointer coords and type */ /* Current pointer coords and type */
gdouble x, y; gdouble x, y;
gboolean is_touch; gboolean is_touch;
@@ -175,17 +146,14 @@ _buildable_iface_init (GtkBuildableIface *iface)
} }
#define parent_class clapper_gtk_video_parent_class #define parent_class clapper_gtk_video_parent_class
G_DEFINE_TYPE_WITH_CODE (ClapperGtkVideo, clapper_gtk_video, GTK_TYPE_WIDGET, G_DEFINE_TYPE_WITH_CODE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK_TYPE_AV,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, _buildable_iface_init)) G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, _buildable_iface_init))
enum enum
{ {
PROP_0, PROP_0,
PROP_PLAYER,
PROP_FADE_DELAY, PROP_FADE_DELAY,
PROP_TOUCH_FADE_DELAY, PROP_TOUCH_FADE_DELAY,
PROP_AUTO_INHIBIT,
PROP_INHIBITED,
PROP_LAST PROP_LAST
}; };
@@ -196,209 +164,111 @@ enum
SIGNAL_LAST SIGNAL_LAST
}; };
static gboolean provider_added = FALSE;
static GParamSpec *param_specs[PROP_LAST] = { NULL, }; static GParamSpec *param_specs[PROP_LAST] = { NULL, };
static guint signals[SIGNAL_LAST] = { 0, }; static guint signals[SIGNAL_LAST] = { 0, };
/* FIXME: 1.0: Remove these compat actions, since they were moved to base class */
static void static void
toggle_play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) toggle_play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.toggle-play", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
switch (clapper_player_get_state (player)) {
case CLAPPER_PLAYER_STATE_PLAYING:
clapper_player_pause (player);
break;
case CLAPPER_PLAYER_STATE_STOPPED:
case CLAPPER_PLAYER_STATE_PAUSED:
clapper_player_play (player);
break;
default:
break;
}
} }
static void static void
play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) play_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.play", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
clapper_player_play (player);
} }
static void static void
pause_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) pause_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.pause", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
clapper_player_pause (player);
} }
static void static void
stop_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) stop_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.stop", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
clapper_player_stop (player);
} }
static void static void
seek_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) seek_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.seek", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble position = g_variant_get_double (parameter);
clapper_player_seek (player, position);
} }
static void static void
seek_custom_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) seek_custom_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.seek-custom", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
ClapperPlayerSeekMethod method = CLAPPER_PLAYER_SEEK_METHOD_NORMAL;
gdouble position = 0;
g_variant_get (parameter, "(di)", &position, &method);
clapper_player_seek_custom (player, position, method);
} }
static void static void
toggle_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) toggle_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.toggle-mute", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
clapper_player_set_mute (player, !clapper_player_get_mute (player));
} }
static void static void
set_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) set_mute_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.set-mute", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gboolean mute = g_variant_get_boolean (parameter);
clapper_player_set_mute (player, mute);
} }
static void static void
volume_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) volume_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.volume-up", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble volume = (clapper_player_get_volume (player) + 0.02);
if (volume > 2.0)
volume = 2.0;
clapper_player_set_volume (player, PERCENTAGE_ROUND (volume));
} }
static void static void
volume_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) volume_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.volume-down", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble volume = (clapper_player_get_volume (player) - 0.02);
if (volume < 0)
volume = 0;
clapper_player_set_volume (player, PERCENTAGE_ROUND (volume));
} }
static void static void
set_volume_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) set_volume_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.set-volume", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble volume = g_variant_get_double (parameter);
clapper_player_set_volume (player, volume);
} }
static void static void
speed_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) speed_up_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.speed-up", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble dest, speed = clapper_player_get_speed (player);
if (speed >= 2.0)
return;
dest = 0.25;
while (speed >= dest)
dest += 0.25;
if (dest > 2.0)
dest = 2.0;
clapper_player_set_speed (player, dest);
} }
static void static void
speed_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) speed_down_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.speed-down", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble dest, speed = clapper_player_get_speed (player);
if (speed <= 0.05)
return;
dest = 2.0;
while (speed <= dest)
dest -= 0.25;
if (dest < 0.05)
dest = 0.05;
clapper_player_set_speed (player, dest);
} }
static void static void
set_speed_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) set_speed_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.set-speed", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
gdouble speed = g_variant_get_double (parameter);
clapper_player_set_speed (player, speed);
} }
static void static void
previous_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) previous_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.previous-item", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
clapper_queue_select_previous_item (clapper_player_get_queue (player));
} }
static void static void
next_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) next_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.next-item", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
clapper_queue_select_next_item (clapper_player_get_queue (player));
} }
static void static void
select_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter) select_item_action_cb (GtkWidget *widget, const gchar *action_name, GVariant *parameter)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); gtk_widget_activate_action_variant (widget, "av.select-item", parameter);
ClapperPlayer *player = clapper_gtk_video_get_player (self);
guint index = g_variant_get_uint32 (parameter);
clapper_queue_select_index (clapper_player_get_queue (player), index);
} }
static void static void
@@ -872,73 +742,6 @@ touch_released_cb (GtkGestureClick *click, gint n_press,
_reset_fade_timeout (self); _reset_fade_timeout (self);
} }
static void
_ensure_css_provider (void)
{
GdkDisplay *display;
if (provider_added)
return;
display = gdk_display_get_default ();
if (G_LIKELY (display != NULL)) {
GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider,
CLAPPER_GTK_RESOURCE_PREFIX "/css/styles.css");
gtk_style_context_add_provider_for_display (display,
(GtkStyleProvider *) provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION - 1);
g_object_unref (provider);
provider_added = TRUE;
}
}
static inline void
_set_inhibit_session (ClapperGtkVideo *self, gboolean inhibit)
{
GtkRoot *root;
GApplication *app;
gboolean inhibited = (self->inhibit_cookie != 0);
if (inhibited == inhibit)
return;
GST_DEBUG_OBJECT (self, "Trying to %sinhibit session...", (inhibit) ? "" : "un");
root = gtk_widget_get_root (GTK_WIDGET (self));
if (!root && !GTK_IS_WINDOW (root)) {
GST_WARNING_OBJECT (self, "Cannot %sinhibit session "
"without root window", (inhibit) ? "" : "un");
return;
}
/* NOTE: Not using application from window prop,
* as it goes away early when unrooting */
app = g_application_get_default ();
if (!app && !GTK_IS_APPLICATION (app)) {
GST_WARNING_OBJECT (self, "Cannot %sinhibit session "
"without window application set", (inhibit) ? "" : "un");
return;
}
if (inhibited) {
gtk_application_uninhibit (GTK_APPLICATION (app), self->inhibit_cookie);
self->inhibit_cookie = 0;
}
if (inhibit) {
self->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (app),
GTK_WINDOW (root), GTK_APPLICATION_INHIBIT_IDLE,
"Video is playing");
}
GST_DEBUG_OBJECT (self, "Session %sinhibited", (inhibit) ? "" : "un");
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_INHIBITED]);
}
static inline void static inline void
_set_buffering_animation_enabled (ClapperGtkVideo *self, gboolean enabled) _set_buffering_animation_enabled (ClapperGtkVideo *self, gboolean enabled)
{ {
@@ -964,9 +767,6 @@ _player_state_changed_cb (ClapperPlayer *player,
{ {
ClapperPlayerState state = clapper_player_get_state (player); ClapperPlayerState state = clapper_player_get_state (player);
if (self->auto_inhibit)
_set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING);
_set_buffering_animation_enabled (self, state == CLAPPER_PLAYER_STATE_BUFFERING); _set_buffering_animation_enabled (self, state == CLAPPER_PLAYER_STATE_BUFFERING);
} }
@@ -1107,7 +907,7 @@ _fading_overlay_revealed_cb (GtkRevealer *revealer,
* *
* Creates a new #ClapperGtkVideo instance. * Creates a new #ClapperGtkVideo instance.
* *
* Newly created video widget will also set some default GStreamer elements * Newly created video widget will also have set some default GStreamer elements
* on its [class@Clapper.Player]. This includes Clapper own video sink and * on its [class@Clapper.Player]. This includes Clapper own video sink and
* a "scaletempo" element as audio filter. Both can still be changed after * a "scaletempo" element as audio filter. Both can still be changed after
* construction by setting corresponding player properties. * construction by setting corresponding player properties.
@@ -1188,19 +988,21 @@ clapper_gtk_video_add_fading_overlay (ClapperGtkVideo *self, GtkWidget *widget)
} }
/** /**
* clapper_gtk_video_get_player: * clapper_gtk_video_get_player: (skip)
* @video: a #ClapperGtkVideo * @video: a #ClapperGtkVideo
* *
* Get #ClapperPlayer used by this #ClapperGtkVideo instance. * Get #ClapperPlayer used by this #ClapperGtkVideo instance.
* *
* Returns: (transfer none): a #ClapperPlayer used by video. * Returns: (transfer none): a #ClapperPlayer used by video.
*
* Deprecated: 0.10: Use [method@ClapperGtk.Av.get_player] instead.
*/ */
ClapperPlayer * ClapperPlayer *
clapper_gtk_video_get_player (ClapperGtkVideo *self) clapper_gtk_video_get_player (ClapperGtkVideo *self)
{ {
g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), NULL); g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), NULL);
return self->player; return clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self));
} }
/** /**
@@ -1276,60 +1078,58 @@ clapper_gtk_video_get_touch_fade_delay (ClapperGtkVideo *self)
} }
/** /**
* clapper_gtk_video_set_auto_inhibit: * clapper_gtk_video_set_auto_inhibit: (skip)
* @video: a #ClapperGtkVideo * @video: a #ClapperGtkVideo
* @inhibit: whether to enable automatic session inhibit * @inhibit: whether to enable automatic session inhibit
* *
* Set whether video should try to automatically inhibit session * Set whether video should try to automatically inhibit session
* from idling (and possibly screen going black) when video is playing. * from idling (and possibly screen going black) when video is playing.
*
* Deprecated: 0.10: Use [method@ClapperGtk.Av.set_auto_inhibit] instead.
*/ */
void void
clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *self, gboolean inhibit) clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *self, gboolean inhibit)
{ {
g_return_if_fail (CLAPPER_GTK_IS_VIDEO (self)); g_return_if_fail (CLAPPER_GTK_IS_VIDEO (self));
if (self->auto_inhibit != inhibit) { clapper_gtk_av_set_auto_inhibit (CLAPPER_GTK_AV_CAST (self), inhibit);
self->auto_inhibit = inhibit;
/* Uninhibit if we were auto inhibited earlier */
if (!self->auto_inhibit)
_set_inhibit_session (self, FALSE);
g_object_notify_by_pspec (G_OBJECT (self), param_specs[PROP_AUTO_INHIBIT]);
}
} }
/** /**
* clapper_gtk_video_get_auto_inhibit: * clapper_gtk_video_get_auto_inhibit: (skip)
* @video: a #ClapperGtkVideo * @video: a #ClapperGtkVideo
* *
* Get whether automatic session inhibit is enabled. * Get whether automatic session inhibit is enabled.
* *
* Returns: %TRUE if enabled, %FALSE otherwise. * Returns: %TRUE if enabled, %FALSE otherwise.
*
* Deprecated: 0.10: Use [method@ClapperGtk.Av.get_auto_inhibit] instead.
*/ */
gboolean gboolean
clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *self) clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *self)
{ {
g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), FALSE); g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), FALSE);
return self->auto_inhibit; return clapper_gtk_av_get_auto_inhibit (CLAPPER_GTK_AV_CAST (self));
} }
/** /**
* clapper_gtk_video_get_inhibited: * clapper_gtk_video_get_inhibited: (skip)
* @video: a #ClapperGtkVideo * @video: a #ClapperGtkVideo
* *
* Get whether session is currently inhibited by * Get whether session is currently inhibited by
* [property@ClapperGtk.Video:auto-inhibit]. * [property@ClapperGtk.Av:auto-inhibit].
* *
* Returns: %TRUE if inhibited, %FALSE otherwise. * Returns: %TRUE if inhibited, %FALSE otherwise.
*
* Deprecated: 0.10: Use [method@ClapperGtk.Av.get_inhibited] instead.
*/ */
gboolean gboolean
clapper_gtk_video_get_inhibited (ClapperGtkVideo *self) clapper_gtk_video_get_inhibited (ClapperGtkVideo *self)
{ {
g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), FALSE); g_return_val_if_fail (CLAPPER_GTK_IS_VIDEO (self), FALSE);
return (self->inhibit_cookie != 0); return clapper_gtk_av_get_inhibited (CLAPPER_GTK_AV_CAST (self));
} }
static void static void
@@ -1338,8 +1138,6 @@ clapper_gtk_video_root (GtkWidget *widget)
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget); ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (widget);
GtkRoot *root; GtkRoot *root;
_ensure_css_provider ();
GTK_WIDGET_CLASS (parent_class)->root (widget); GTK_WIDGET_CLASS (parent_class)->root (widget);
root = gtk_widget_get_root (widget); root = gtk_widget_get_root (widget);
@@ -1351,11 +1149,6 @@ clapper_gtk_video_root (GtkWidget *widget)
G_CALLBACK (_window_is_active_cb), self); G_CALLBACK (_window_is_active_cb), self);
_window_is_active_cb (window, NULL, self); _window_is_active_cb (window, NULL, self);
} }
if (self->auto_inhibit) {
ClapperPlayerState state = clapper_player_get_state (self->player);
_set_inhibit_session (self, state == CLAPPER_PLAYER_STATE_PLAYING);
}
} }
static void static void
@@ -1369,8 +1162,6 @@ clapper_gtk_video_unroot (GtkWidget *widget)
_window_is_active_cb, self); _window_is_active_cb, self);
} }
_set_inhibit_session (self, FALSE);
GTK_WIDGET_CLASS (parent_class)->unroot (widget); GTK_WIDGET_CLASS (parent_class)->unroot (widget);
} }
@@ -1386,7 +1177,6 @@ clapper_gtk_video_init (ClapperGtkVideo *self)
self->fade_delay = DEFAULT_FADE_DELAY; self->fade_delay = DEFAULT_FADE_DELAY;
self->touch_fade_delay = DEFAULT_TOUCH_FADE_DELAY; self->touch_fade_delay = DEFAULT_TOUCH_FADE_DELAY;
self->auto_inhibit = DEFAULT_AUTO_INHIBIT;
/* Ensure private types */ /* Ensure private types */
g_type_ensure (CLAPPER_GTK_TYPE_STATUS); g_type_ensure (CLAPPER_GTK_TYPE_STATUS);
@@ -1401,15 +1191,18 @@ static void
clapper_gtk_video_constructed (GObject *object) clapper_gtk_video_constructed (GObject *object)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object); ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object);
GstElement *afilter, *vsink; GstElement *vsink;
ClapperPlayer *player;
ClapperQueue *queue; ClapperQueue *queue;
self->player = clapper_player_new (); G_OBJECT_CLASS (parent_class)->constructed (object);
queue = clapper_player_get_queue (self->player);
g_signal_connect (self->player, "notify::state", player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self));
queue = clapper_player_get_queue (player);
g_signal_connect (player, "notify::state",
G_CALLBACK (_player_state_changed_cb), self); G_CALLBACK (_player_state_changed_cb), self);
g_signal_connect (self->player, "notify::video-sink", g_signal_connect (player, "notify::video-sink",
G_CALLBACK (_video_sink_changed_cb), self); G_CALLBACK (_video_sink_changed_cb), self);
vsink = gst_element_factory_make ("clappersink", NULL); vsink = gst_element_factory_make ("clappersink", NULL);
@@ -1429,28 +1222,23 @@ clapper_gtk_video_constructed (GObject *object)
} }
} }
clapper_player_set_video_sink (self->player, vsink); clapper_player_set_video_sink (player, vsink);
} }
afilter = gst_element_factory_make ("scaletempo", NULL); g_signal_connect (player, "error",
if (G_LIKELY (afilter != NULL))
clapper_player_set_audio_filter (self->player, afilter);
g_signal_connect (self->player, "error",
G_CALLBACK (_player_error_cb), self); G_CALLBACK (_player_error_cb), self);
g_signal_connect (self->player, "missing-plugin", g_signal_connect (player, "missing-plugin",
G_CALLBACK (_player_missing_plugin_cb), self); G_CALLBACK (_player_missing_plugin_cb), self);
g_signal_connect (queue, "notify::current-item", g_signal_connect (queue, "notify::current-item",
G_CALLBACK (_queue_current_item_changed_cb), self); G_CALLBACK (_queue_current_item_changed_cb), self);
G_OBJECT_CLASS (parent_class)->constructed (object);
} }
static void static void
clapper_gtk_video_dispose (GObject *object) clapper_gtk_video_dispose (GObject *object)
{ {
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object); ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object);
ClapperPlayer *player;
if (self->notify_revealed_id != 0) { if (self->notify_revealed_id != 0) {
GtkRevealer *revealer = GTK_REVEALER (g_ptr_array_index (self->fading_overlays, 0)); GtkRevealer *revealer = GTK_REVEALER (g_ptr_array_index (self->fading_overlays, 0));
@@ -1461,18 +1249,20 @@ clapper_gtk_video_dispose (GObject *object)
g_clear_handle_id (&self->fade_timeout, g_source_remove); g_clear_handle_id (&self->fade_timeout, g_source_remove);
player = clapper_gtk_av_get_player (CLAPPER_GTK_AV_CAST (self));
/* Something else might still be holding a reference on the player, /* Something else might still be holding a reference on the player,
* thus we should disconnect everything before disposing template */ * thus we should disconnect everything before disposing template */
if (self->player) { if (player) { // NULL if dispose run multiple times
ClapperQueue *queue = clapper_player_get_queue (self->player); ClapperQueue *queue = clapper_player_get_queue (player);
g_signal_handlers_disconnect_by_func (self->player, g_signal_handlers_disconnect_by_func (player,
_player_state_changed_cb, self); _player_state_changed_cb, self);
g_signal_handlers_disconnect_by_func (self->player, g_signal_handlers_disconnect_by_func (player,
_video_sink_changed_cb, self); _video_sink_changed_cb, self);
g_signal_handlers_disconnect_by_func (self->player, g_signal_handlers_disconnect_by_func (player,
_player_error_cb, self); _player_error_cb, self);
g_signal_handlers_disconnect_by_func (self->player, g_signal_handlers_disconnect_by_func (player,
_player_missing_plugin_cb, self); _player_missing_plugin_cb, self);
g_signal_handlers_disconnect_by_func (queue, g_signal_handlers_disconnect_by_func (queue,
@@ -1482,7 +1272,6 @@ clapper_gtk_video_dispose (GObject *object)
gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_VIDEO); gtk_widget_dispose_template (GTK_WIDGET (object), CLAPPER_GTK_TYPE_VIDEO);
g_clear_pointer (&self->overlay, gtk_widget_unparent); g_clear_pointer (&self->overlay, gtk_widget_unparent);
gst_clear_object (&self->player);
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
@@ -1505,21 +1294,12 @@ clapper_gtk_video_get_property (GObject *object, guint prop_id,
ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object); ClapperGtkVideo *self = CLAPPER_GTK_VIDEO_CAST (object);
switch (prop_id) { switch (prop_id) {
case PROP_PLAYER:
g_value_set_object (value, clapper_gtk_video_get_player (self));
break;
case PROP_FADE_DELAY: case PROP_FADE_DELAY:
g_value_set_uint (value, clapper_gtk_video_get_fade_delay (self)); g_value_set_uint (value, clapper_gtk_video_get_fade_delay (self));
break; break;
case PROP_TOUCH_FADE_DELAY: case PROP_TOUCH_FADE_DELAY:
g_value_set_uint (value, clapper_gtk_video_get_touch_fade_delay (self)); g_value_set_uint (value, clapper_gtk_video_get_touch_fade_delay (self));
break; break;
case PROP_AUTO_INHIBIT:
g_value_set_boolean (value, clapper_gtk_video_get_auto_inhibit (self));
break;
case PROP_INHIBITED:
g_value_set_boolean (value, clapper_gtk_video_get_inhibited (self));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -1539,9 +1319,6 @@ clapper_gtk_video_set_property (GObject *object, guint prop_id,
case PROP_TOUCH_FADE_DELAY: case PROP_TOUCH_FADE_DELAY:
clapper_gtk_video_set_touch_fade_delay (self, g_value_get_uint (value)); clapper_gtk_video_set_touch_fade_delay (self, g_value_get_uint (value));
break; break;
case PROP_AUTO_INHIBIT:
clapper_gtk_video_set_auto_inhibit (self, g_value_get_boolean (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -1566,15 +1343,6 @@ clapper_gtk_video_class_init (ClapperGtkVideoClass *klass)
gobject_class->dispose = clapper_gtk_video_dispose; gobject_class->dispose = clapper_gtk_video_dispose;
gobject_class->finalize = clapper_gtk_video_finalize; gobject_class->finalize = clapper_gtk_video_finalize;
/**
* ClapperGtkVideo:player:
*
* A #ClapperPlayer used by video.
*/
param_specs[PROP_PLAYER] = g_param_spec_object ("player",
NULL, NULL, CLAPPER_TYPE_PLAYER,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/** /**
* ClapperGtkVideo:fade-delay: * ClapperGtkVideo:fade-delay:
* *
@@ -1594,24 +1362,6 @@ clapper_gtk_video_class_init (ClapperGtkVideoClass *klass)
NULL, NULL, 1, G_MAXUINT, DEFAULT_TOUCH_FADE_DELAY, NULL, NULL, 1, G_MAXUINT, DEFAULT_TOUCH_FADE_DELAY,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* ClapperGtkVideo:auto-inhibit:
*
* Try to automatically inhibit session when video is playing.
*/
param_specs[PROP_AUTO_INHIBIT] = g_param_spec_boolean ("auto-inhibit",
NULL, NULL, DEFAULT_AUTO_INHIBIT,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* ClapperGtkVideo:inhibited:
*
* Get whether session is currently inhibited by the video.
*/
param_specs[PROP_INHIBITED] = g_param_spec_boolean ("inhibited",
NULL, NULL, FALSE,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/** /**
* ClapperGtkVideo::toggle-fullscreen: * ClapperGtkVideo::toggle-fullscreen:
* @video: a #ClapperGtkVideo * @video: a #ClapperGtkVideo
@@ -1643,6 +1393,8 @@ clapper_gtk_video_class_init (ClapperGtkVideoClass *klass)
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs); g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
/* FIXME: 1.0: Remove these actions, since they were moved to
* base class AV widget, but are here for compat reasons. */
gtk_widget_class_install_action (widget_class, "video.toggle-play", NULL, toggle_play_action_cb); gtk_widget_class_install_action (widget_class, "video.toggle-play", NULL, toggle_play_action_cb);
gtk_widget_class_install_action (widget_class, "video.play", NULL, play_action_cb); gtk_widget_class_install_action (widget_class, "video.play", NULL, play_action_cb);
gtk_widget_class_install_action (widget_class, "video.pause", NULL, pause_action_cb); gtk_widget_class_install_action (widget_class, "video.pause", NULL, pause_action_cb);

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
#pragma once #pragma once
@@ -28,6 +27,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <clapper/clapper.h> #include <clapper/clapper.h>
#include <clapper-gtk/clapper-gtk-av.h>
#include <clapper-gtk/clapper-gtk-visibility.h> #include <clapper-gtk/clapper-gtk-visibility.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -36,7 +36,7 @@ G_BEGIN_DECLS
#define CLAPPER_GTK_VIDEO_CAST(obj) ((ClapperGtkVideo *)(obj)) #define CLAPPER_GTK_VIDEO_CAST(obj) ((ClapperGtkVideo *)(obj))
CLAPPER_GTK_API CLAPPER_GTK_API
G_DECLARE_FINAL_TYPE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK, VIDEO, GtkWidget) G_DECLARE_FINAL_TYPE (ClapperGtkVideo, clapper_gtk_video, CLAPPER_GTK, VIDEO, ClapperGtkAv)
CLAPPER_GTK_API CLAPPER_GTK_API
GtkWidget * clapper_gtk_video_new (void); GtkWidget * clapper_gtk_video_new (void);
@@ -47,7 +47,7 @@ void clapper_gtk_video_add_overlay (ClapperGtkVideo *video, GtkWidget *widget);
CLAPPER_GTK_API CLAPPER_GTK_API
void clapper_gtk_video_add_fading_overlay (ClapperGtkVideo *video, GtkWidget *widget); void clapper_gtk_video_add_fading_overlay (ClapperGtkVideo *video, GtkWidget *widget);
CLAPPER_GTK_API CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_get_player)
ClapperPlayer * clapper_gtk_video_get_player (ClapperGtkVideo *video); ClapperPlayer * clapper_gtk_video_get_player (ClapperGtkVideo *video);
CLAPPER_GTK_API CLAPPER_GTK_API
@@ -62,13 +62,13 @@ void clapper_gtk_video_set_touch_fade_delay (ClapperGtkVideo *video, guint delay
CLAPPER_GTK_API CLAPPER_GTK_API
guint clapper_gtk_video_get_touch_fade_delay (ClapperGtkVideo *video); guint clapper_gtk_video_get_touch_fade_delay (ClapperGtkVideo *video);
CLAPPER_GTK_API CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_set_auto_inhibit)
void clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *video, gboolean inhibit); void clapper_gtk_video_set_auto_inhibit (ClapperGtkVideo *video, gboolean inhibit);
CLAPPER_GTK_API CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_get_auto_inhibit)
gboolean clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *video); gboolean clapper_gtk_video_get_auto_inhibit (ClapperGtkVideo *video);
CLAPPER_GTK_API CLAPPER_GTK_DEPRECATED_FOR(clapper_gtk_av_get_inhibited)
gboolean clapper_gtk_video_get_inhibited (ClapperGtkVideo *video); gboolean clapper_gtk_video_get_inhibited (ClapperGtkVideo *video);
G_END_DECLS G_END_DECLS

View File

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

View File

@@ -129,6 +129,15 @@ clapper-gtk-seek-bar label {
margin-left: 2px; margin-left: 2px;
margin-right: 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 { clapper-gtk-extra-menu-button popover .spinsidebutton {
min-width: 28px; min-width: 28px;

View File

@@ -90,6 +90,8 @@ clappergtk_conf_inc = [
clappergtk_headers = [ clappergtk_headers = [
'clapper-gtk.h', 'clapper-gtk.h',
'clapper-gtk-audio.h',
'clapper-gtk-av.h',
'clapper-gtk-enums.h', 'clapper-gtk-enums.h',
'clapper-gtk-billboard.h', 'clapper-gtk-billboard.h',
'clapper-gtk-container.h', 'clapper-gtk-container.h',
@@ -109,6 +111,8 @@ clappergtk_headers = [
clappergtk_visibility_header, clappergtk_visibility_header,
] ]
clappergtk_sources = [ clappergtk_sources = [
'clapper-gtk-audio.c',
'clapper-gtk-av.c',
'clapper-gtk-billboard.c', 'clapper-gtk-billboard.c',
'clapper-gtk-buffering-animation.c', 'clapper-gtk-buffering-animation.c',
'clapper-gtk-buffering-paintable.c', 'clapper-gtk-buffering-paintable.c',

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<interface domain="clapper-gtk"> <interface domain="clapper-gtk">
<template class="ClapperGtkVideo" parent="GtkWidget"> <template class="ClapperGtkVideo" parent="ClapperGtkAv">
<child type="overlay"> <child type="overlay">
<object class="ClapperGtkStatus" id="status"> <object class="ClapperGtkStatus" id="status">
<property name="halign">center</property> <property name="halign">center</property>

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
#pragma once #pragma once
@@ -45,12 +44,16 @@ 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_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_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); void clapper_app_bus_post_object_desc_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GstObject *object, const gchar *desc);
void clapper_app_bus_post_desc_with_details_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, const gchar *desc, const gchar *details); void clapper_app_bus_post_desc_with_details_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, const gchar *desc, const gchar *details);
void clapper_app_bus_post_message_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GstMessage *msg);
void clapper_app_bus_post_error_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GError *error, const gchar *debug_info); void clapper_app_bus_post_error_signal (ClapperAppBus *app_bus, GstObject *src, guint signal_id, GError *error, const gchar *debug_info);
G_END_DECLS G_END_DECLS

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
#include <gio/gio.h> #include <gio/gio.h>
@@ -22,6 +21,7 @@
#include "clapper-bus-private.h" #include "clapper-bus-private.h"
#include "clapper-app-bus-private.h" #include "clapper-app-bus-private.h"
#include "clapper-player-private.h" #include "clapper-player-private.h"
#include "clapper-queue-private.h"
#include "clapper-media-item-private.h" #include "clapper-media-item-private.h"
#include "clapper-timeline-private.h" #include "clapper-timeline-private.h"
@@ -42,9 +42,11 @@ enum
CLAPPER_APP_BUS_STRUCTURE_PROP_NOTIFY, CLAPPER_APP_BUS_STRUCTURE_PROP_NOTIFY,
CLAPPER_APP_BUS_STRUCTURE_REFRESH_STREAMS, CLAPPER_APP_BUS_STRUCTURE_REFRESH_STREAMS,
CLAPPER_APP_BUS_STRUCTURE_REFRESH_TIMELINE, CLAPPER_APP_BUS_STRUCTURE_REFRESH_TIMELINE,
CLAPPER_APP_BUS_STRUCTURE_INSERT_PLAYLIST,
CLAPPER_APP_BUS_STRUCTURE_SIMPLE_SIGNAL, CLAPPER_APP_BUS_STRUCTURE_SIMPLE_SIGNAL,
CLAPPER_APP_BUS_STRUCTURE_OBJECT_DESC_SIGNAL, CLAPPER_APP_BUS_STRUCTURE_OBJECT_DESC_SIGNAL,
CLAPPER_APP_BUS_STRUCTURE_DESC_WITH_DETAILS_SIGNAL, CLAPPER_APP_BUS_STRUCTURE_DESC_WITH_DETAILS_SIGNAL,
CLAPPER_APP_BUS_STRUCTURE_MESSAGE_SIGNAL,
CLAPPER_APP_BUS_STRUCTURE_ERROR_SIGNAL CLAPPER_APP_BUS_STRUCTURE_ERROR_SIGNAL
}; };
@@ -53,9 +55,11 @@ static ClapperBusQuark _structure_quarks[] = {
{"prop-notify", 0}, {"prop-notify", 0},
{"refresh-streams", 0}, {"refresh-streams", 0},
{"refresh-timeline", 0}, {"refresh-timeline", 0},
{"insert-playlist", 0},
{"simple-signal", 0}, {"simple-signal", 0},
{"object-desc-signal", 0}, {"object-desc-signal", 0},
{"desc-with-details-signal", 0}, {"desc-with-details-signal", 0},
{"message", 0},
{"error-signal", 0}, {"error-signal", 0},
{NULL, 0} {NULL, 0}
}; };
@@ -66,6 +70,7 @@ enum
CLAPPER_APP_BUS_FIELD_PSPEC, CLAPPER_APP_BUS_FIELD_PSPEC,
CLAPPER_APP_BUS_FIELD_SIGNAL_ID, CLAPPER_APP_BUS_FIELD_SIGNAL_ID,
CLAPPER_APP_BUS_FIELD_OBJECT, CLAPPER_APP_BUS_FIELD_OBJECT,
CLAPPER_APP_BUS_FIELD_OTHER_OBJECT,
CLAPPER_APP_BUS_FIELD_DESC, CLAPPER_APP_BUS_FIELD_DESC,
CLAPPER_APP_BUS_FIELD_DETAILS, CLAPPER_APP_BUS_FIELD_DETAILS,
CLAPPER_APP_BUS_FIELD_ERROR, CLAPPER_APP_BUS_FIELD_ERROR,
@@ -77,6 +82,7 @@ static ClapperBusQuark _field_quarks[] = {
{"pspec", 0}, {"pspec", 0},
{"signal-id", 0}, {"signal-id", 0},
{"object", 0}, {"object", 0},
{"other-object", 0},
{"desc", 0}, {"desc", 0},
{"details", 0}, {"details", 0},
{"error", 0}, {"error", 0},
@@ -161,6 +167,36 @@ _handle_refresh_timeline_msg (GstMessage *msg, const GstStructure *structure)
clapper_timeline_refresh (timeline); 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 void
clapper_app_bus_post_simple_signal (ClapperAppBus *self, GstObject *src, guint signal_id) clapper_app_bus_post_simple_signal (ClapperAppBus *self, GstObject *src, guint signal_id)
{ {
@@ -242,6 +278,53 @@ _handle_desc_with_details_signal_msg (GstMessage *msg, const GstStructure *struc
g_free (details); g_free (details);
} }
void
clapper_app_bus_post_message_signal (ClapperAppBus *self,
GstObject *src, guint signal_id, GstMessage *msg)
{
/* Check for any "message" signal connection */
if (g_signal_handler_find (src, G_SIGNAL_MATCH_ID,
signal_id, 0, NULL, NULL, NULL) != 0) {
const GstStructure *structure = gst_message_get_structure (msg);
GQuark detail;
if (G_UNLIKELY (structure == NULL))
return;
detail = g_quark_from_string (gst_structure_get_name (structure));
/* If specific detail is connected or ALL "message" handler */
if (g_signal_handler_find (src, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL,
signal_id, detail, NULL, NULL, NULL) != 0
|| g_signal_handler_find (src, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL,
signal_id, 0, NULL, NULL, NULL) != 0) {
GstStructure *structure = gst_structure_new_id (_STRUCTURE_QUARK (MESSAGE_SIGNAL),
_FIELD_QUARK (SIGNAL_ID), G_TYPE_UINT, signal_id,
_FIELD_QUARK (DETAILS), G_TYPE_UINT, detail,
_FIELD_QUARK (OBJECT), GST_TYPE_MESSAGE, msg,
NULL);
gst_bus_post (GST_BUS_CAST (self), gst_message_new_application (src, structure));
}
}
}
static inline void
_handle_message_signal_msg (GstMessage *msg, const GstStructure *structure)
{
guint signal_id = 0;
GQuark detail = 0;
GstMessage *fwd_message = NULL;
gst_structure_id_get (structure,
_FIELD_QUARK (SIGNAL_ID), G_TYPE_UINT, &signal_id,
_FIELD_QUARK (DETAILS), G_TYPE_UINT, &detail,
_FIELD_QUARK (OBJECT), GST_TYPE_MESSAGE, &fwd_message,
NULL);
g_signal_emit (_MESSAGE_SRC_GOBJECT (msg), signal_id, detail, fwd_message);
gst_message_unref (fwd_message);
}
void void
clapper_app_bus_post_error_signal (ClapperAppBus *self, clapper_app_bus_post_error_signal (ClapperAppBus *self,
GstObject *src, guint signal_id, GstObject *src, guint signal_id,
@@ -286,10 +369,14 @@ clapper_app_bus_message_func (GstBus *bus, GstMessage *msg, gpointer user_data G
_handle_refresh_streams_msg (msg, structure); _handle_refresh_streams_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (REFRESH_TIMELINE)) else if (quark == _STRUCTURE_QUARK (REFRESH_TIMELINE))
_handle_refresh_timeline_msg (msg, structure); _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)) else if (quark == _STRUCTURE_QUARK (SIMPLE_SIGNAL))
_handle_simple_signal_msg (msg, structure); _handle_simple_signal_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (OBJECT_DESC_SIGNAL)) else if (quark == _STRUCTURE_QUARK (OBJECT_DESC_SIGNAL))
_handle_object_desc_signal_msg (msg, structure); _handle_object_desc_signal_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (MESSAGE_SIGNAL))
_handle_message_signal_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (ERROR_SIGNAL)) else if (quark == _STRUCTURE_QUARK (ERROR_SIGNAL))
_handle_error_signal_msg (msg, structure); _handle_error_signal_msg (msg, structure);
else if (quark == _STRUCTURE_QUARK (DESC_WITH_DETAILS_SIGNAL)) else if (quark == _STRUCTURE_QUARK (DESC_WITH_DETAILS_SIGNAL))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,14 +12,15 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
#include "clapper-cache-private.h" #include "clapper-cache-private.h"
#include "clapper-version.h" #include "clapper-version.h"
#include "clapper-extractable.h" #include "clapper-extractable.h"
#include "clapper-playlistable.h"
#include "clapper-reactable.h" #include "clapper-reactable.h"
#define CLAPPER_CACHE_HEADER "CLAPPER" #define CLAPPER_CACHE_HEADER "CLAPPER"
@@ -27,6 +28,7 @@
typedef enum typedef enum
{ {
CLAPPER_CACHE_IFACE_EXTRACTABLE = 1, CLAPPER_CACHE_IFACE_EXTRACTABLE = 1,
CLAPPER_CACHE_IFACE_PLAYLISTABLE,
CLAPPER_CACHE_IFACE_REACTABLE, CLAPPER_CACHE_IFACE_REACTABLE,
} ClapperCacheIfaces; } ClapperCacheIfaces;
@@ -245,6 +247,8 @@ clapper_cache_read_iface (const gchar **data)
switch (iface_id) { switch (iface_id) {
case CLAPPER_CACHE_IFACE_EXTRACTABLE: case CLAPPER_CACHE_IFACE_EXTRACTABLE:
return CLAPPER_TYPE_EXTRACTABLE; return CLAPPER_TYPE_EXTRACTABLE;
case CLAPPER_CACHE_IFACE_PLAYLISTABLE:
return CLAPPER_TYPE_PLAYLISTABLE;
case CLAPPER_CACHE_IFACE_REACTABLE: case CLAPPER_CACHE_IFACE_REACTABLE:
return CLAPPER_TYPE_REACTABLE; return CLAPPER_TYPE_REACTABLE;
default: default:
@@ -437,6 +441,8 @@ clapper_cache_store_iface (GByteArray *bytes, GType iface)
if (iface == CLAPPER_TYPE_EXTRACTABLE) if (iface == CLAPPER_TYPE_EXTRACTABLE)
iface_id = CLAPPER_CACHE_IFACE_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) else if (iface == CLAPPER_TYPE_REACTABLE)
iface_id = CLAPPER_CACHE_IFACE_REACTABLE; iface_id = CLAPPER_CACHE_IFACE_REACTABLE;
else else

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -47,12 +46,14 @@
#include "clapper-enhancer-proxy-list.h" #include "clapper-enhancer-proxy-list.h"
#include "clapper-basic-functions.h" #include "clapper-basic-functions.h"
#include "clapper-cache-private.h" #include "clapper-cache-private.h"
#include "clapper-extractable.h"
#include "clapper-reactable.h"
#include "clapper-player-private.h" #include "clapper-player-private.h"
#include "clapper-utils-private.h" #include "clapper-utils-private.h"
#include "clapper-enums.h" #include "clapper-enums.h"
#include "clapper-extractable.h"
#include "clapper-playlistable.h"
#include "clapper-reactable.h"
#include "clapper-functionalities-availability.h" #include "clapper-functionalities-availability.h"
#if CLAPPER_WITH_ENHANCERS_LOADER #if CLAPPER_WITH_ENHANCERS_LOADER
@@ -87,6 +88,8 @@ struct _ClapperEnhancerProxy
ClapperEnhancerParamFlags scope; ClapperEnhancerParamFlags scope;
GstStructure *local_config; GstStructure *local_config;
gboolean allowed;
/* GSettings are not thread-safe, /* GSettings are not thread-safe,
* so store schema instead */ * so store schema instead */
GSettingsSchema *schema; GSettingsSchema *schema;
@@ -101,6 +104,7 @@ enum
PROP_MODULE_DIR, PROP_MODULE_DIR,
PROP_DESCRIPTION, PROP_DESCRIPTION,
PROP_VERSION, PROP_VERSION,
PROP_TARGET_CREATION_ALLOWED,
PROP_LAST PROP_LAST
}; };
@@ -230,6 +234,8 @@ clapper_enhancer_proxy_copy (ClapperEnhancerProxy *src_proxy, const gchar *copy_
if (src_proxy->local_config) if (src_proxy->local_config)
copy->local_config = gst_structure_copy (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_UNLOCK (src_proxy);
gst_object_ref_sink (copy); gst_object_ref_sink (copy);
@@ -360,6 +366,8 @@ clapper_enhancer_proxy_fill_from_cache (ClapperEnhancerProxy *self)
if (G_UNLIKELY ((self->ifaces[i] = clapper_cache_read_iface (&data)) == 0)) if (G_UNLIKELY ((self->ifaces[i] = clapper_cache_read_iface (&data)) == 0))
goto abort_reading; goto abort_reading;
} }
/* Reactable type is always last */
self->allowed = (self->ifaces[self->n_ifaces - 1] != CLAPPER_TYPE_REACTABLE);
} }
/* Restore ParamSpecs */ /* Restore ParamSpecs */
@@ -457,7 +465,8 @@ clapper_enhancer_proxy_export_to_cache (ClapperEnhancerProxy *self)
gboolean gboolean
clapper_enhancer_proxy_fill_from_instance (ClapperEnhancerProxy *self, GObject *enhancer) clapper_enhancer_proxy_fill_from_instance (ClapperEnhancerProxy *self, GObject *enhancer)
{ {
const GType enhancer_types[] = { CLAPPER_TYPE_EXTRACTABLE, CLAPPER_TYPE_REACTABLE }; /* 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; GType *ifaces;
GParamSpec **pspecs; GParamSpec **pspecs;
GParamFlags enhancer_flags; GParamFlags enhancer_flags;
@@ -466,9 +475,12 @@ clapper_enhancer_proxy_fill_from_instance (ClapperEnhancerProxy *self, GObject *
/* Filter to only Clapper interfaces */ /* Filter to only Clapper interfaces */
ifaces = g_type_interfaces (G_OBJECT_TYPE (enhancer), &n); ifaces = g_type_interfaces (G_OBJECT_TYPE (enhancer), &n);
for (i = 0; i < n; ++i) { 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]) { if (ifaces[i] == enhancer_types[j]) {
ifaces[write_index++] = ifaces[i]; ifaces[write_index++] = ifaces[i];
self->allowed = (j < n_types - 1);
break; // match found, do next iface break; // match found, do next iface
} }
} }
@@ -1089,6 +1101,58 @@ clapper_enhancer_proxy_set_locally_with_table (ClapperEnhancerProxy *self, GHash
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 static void
clapper_enhancer_proxy_init (ClapperEnhancerProxy *self) clapper_enhancer_proxy_init (ClapperEnhancerProxy *self)
{ {
@@ -1138,6 +1202,25 @@ clapper_enhancer_proxy_get_property (GObject *object, guint prop_id,
case PROP_VERSION: case PROP_VERSION:
g_value_set_string (value, clapper_enhancer_proxy_get_version (self)); g_value_set_string (value, clapper_enhancer_proxy_get_version (self));
break; 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: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -1153,6 +1236,7 @@ clapper_enhancer_proxy_class_init (ClapperEnhancerProxyClass *klass)
"Clapper Enhancer Proxy"); "Clapper Enhancer Proxy");
gobject_class->get_property = clapper_enhancer_proxy_get_property; 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; gobject_class->finalize = clapper_enhancer_proxy_finalize;
/** /**
@@ -1210,5 +1294,29 @@ clapper_enhancer_proxy_class_init (ClapperEnhancerProxyClass *klass)
NULL, NULL, NULL, 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);
/**
* 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); g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
} }

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
#include "config.h" #include "config.h"
@@ -33,10 +32,9 @@ static HMODULE _enhancers_dll_handle = NULL;
// Supported interfaces // Supported interfaces
#include "clapper-extractable.h" #include "clapper-extractable.h"
#include "clapper-playlistable.h"
#include "clapper-reactable.h" #include "clapper-reactable.h"
#include <clapper-functionalities-availability.h>
#define GST_CAT_DEFAULT clapper_enhancers_loader_debug #define GST_CAT_DEFAULT clapper_enhancers_loader_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
@@ -55,6 +53,28 @@ _import_enhancers (const gchar *enhancers_path)
g_strfreev (dir_paths); 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: * clapper_enhancers_loader_initialize:
* *
@@ -113,36 +133,6 @@ clapper_enhancers_loader_initialize (ClapperEnhancerProxyList *proxies)
ClapperEnhancerProxy *proxy; ClapperEnhancerProxy *proxy;
gboolean filled; gboolean filled;
/* FIXME: 1.0: Remove together with features code and manager.
* These would clash with each other, so avoid loading these
* as enhancers when also compiled as part of the library. */
#if (CLAPPER_HAVE_MPRIS || CLAPPER_HAVE_DISCOVERER || CLAPPER_HAVE_SERVER)
guint f_index;
const gchar *module_name = peas_plugin_info_get_module_name (info);
const gchar *ported_features[] = {
#if CLAPPER_HAVE_MPRIS
"clapper-mpris",
#endif
#if CLAPPER_HAVE_DISCOVERER
"clapper-discoverer",
#endif
#if CLAPPER_HAVE_SERVER
"clapper-server",
#endif
};
for (f_index = 0; f_index < G_N_ELEMENTS (ported_features); ++f_index) {
if (strcmp (module_name, ported_features[f_index]) == 0) {
GST_INFO ("Skipped \"%s\" enhancer module, since its"
" loaded from deprecated feature object", module_name);
g_clear_object (&info);
}
}
if (!info) // cleared when exists as feature
continue;
#endif
/* Clapper supports only 1 proxy per plugin. Each plugin can /* Clapper supports only 1 proxy per plugin. Each plugin can
* ship 1 class, but it can implement more than 1 interface. */ * ship 1 class, but it can implement more than 1 interface. */
proxy = clapper_enhancer_proxy_new_global_take ((GObject *) info); proxy = clapper_enhancer_proxy_new_global_take ((GObject *) info);
@@ -151,12 +141,12 @@ clapper_enhancers_loader_initialize (ClapperEnhancerProxyList *proxies)
* Otherwise make an instance and fill missing data from it (slow). */ * Otherwise make an instance and fill missing data from it (slow). */
if (!(filled = clapper_enhancer_proxy_fill_from_cache (proxy))) { if (!(filled = clapper_enhancer_proxy_fill_from_cache (proxy))) {
GObject *enhancer; GObject *enhancer;
const GType main_types[] = { CLAPPER_TYPE_EXTRACTABLE, CLAPPER_TYPE_REACTABLE }; const GType main_types[] = { CLAPPER_TYPE_EXTRACTABLE, CLAPPER_TYPE_PLAYLISTABLE, CLAPPER_TYPE_REACTABLE };
guint j; guint j;
/* We cannot ask libpeas for "any" of our main interfaces, so try each one until found */ /* 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) { 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); filled = clapper_enhancer_proxy_fill_from_instance (proxy, enhancer);
g_object_unref (enhancer); g_object_unref (enhancer);
@@ -201,21 +191,8 @@ clapper_enhancers_loader_initialize (ClapperEnhancerProxyList *proxies)
GObject * GObject *
clapper_enhancers_loader_create_enhancer (ClapperEnhancerProxy *proxy, GType iface_type) clapper_enhancers_loader_create_enhancer (ClapperEnhancerProxy *proxy, GType iface_type)
{ {
GObject *enhancer = NULL; if (!clapper_enhancer_proxy_get_target_creation_allowed (proxy))
PeasPluginInfo *info = (PeasPluginInfo *) clapper_enhancer_proxy_get_peas_info (proxy); return NULL;
g_mutex_lock (&load_lock); return _force_create_enhancer (proxy, iface_type);
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;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -12,9 +12,8 @@
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the * License along with this library; if not, see
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * <https://www.gnu.org/licenses/>.
* Boston, MA 02110-1301, USA.
*/ */
/** /**
@@ -95,6 +94,13 @@ clapper_harvest_new (void)
return harvest; 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 gboolean
clapper_harvest_unpack (ClapperHarvest *self, clapper_harvest_unpack (ClapperHarvest *self,
GstBuffer **buffer, gsize *buf_size, GstCaps **caps, GstBuffer **buffer, gsize *buf_size, GstCaps **caps,
@@ -222,7 +228,6 @@ clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
gchar *filename; gchar *filename;
const gchar *data, *read_str; const gchar *data, *read_str;
const guint8 *buf_data; const guint8 *buf_data;
guint8 *buf_copy;
gsize buf_size; gsize buf_size;
gint64 epoch_cached, epoch_now = 0; gint64 epoch_cached, epoch_now = 0;
gdouble exp_seconds; gdouble exp_seconds;
@@ -282,10 +287,10 @@ clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
goto finish; goto finish;
} }
/* Read media type */ /* Read caps */
read_str = clapper_cache_read_string (&data); read_str = clapper_cache_read_string (&data);
if (G_UNLIKELY (read_str == NULL)) { if (G_UNLIKELY (read_str == NULL)) {
GST_ERROR_OBJECT (self, "Could not read media type from cache file"); GST_ERROR_OBJECT (self, "Could not read caps from cache file");
goto finish; goto finish;
} }
@@ -297,9 +302,12 @@ clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
} }
/* Fill harvest */ /* Fill harvest */
buf_copy = g_memdup2 (buf_data, buf_size); if (!(self->caps = gst_caps_from_string (read_str))) {
if (!clapper_harvest_fill (self, read_str, buf_copy, buf_size)) GST_ERROR_OBJECT (self, "Could not construct caps from cache");
goto finish; goto finish;
}
self->buffer = gst_buffer_new_memdup (buf_data, buf_size);
self->buf_size = buf_size;
/* Read tags */ /* Read tags */
read_str = clapper_cache_read_string (&data); read_str = clapper_cache_read_string (&data);
@@ -333,7 +341,6 @@ clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
const GstStructure *config, GUri *uri) const GstStructure *config, GUri *uri)
{ {
GByteArray *bytes; GByteArray *bytes;
const GstStructure *caps_structure;
gchar *filename, *temp_str = NULL; gchar *filename, *temp_str = NULL;
gboolean data_ok = TRUE; gboolean data_ok = TRUE;
@@ -367,12 +374,13 @@ clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
clapper_cache_store_string (bytes, temp_str); // NULL when no config clapper_cache_store_string (bytes, temp_str); // NULL when no config
g_clear_pointer (&temp_str, g_free); g_clear_pointer (&temp_str, g_free);
/* Store media type */ /* Store caps */
caps_structure = gst_caps_get_structure (self->caps, 0); temp_str = gst_caps_to_string (self->caps);
if (G_LIKELY (caps_structure != NULL)) { if (G_LIKELY (temp_str != NULL)) {
clapper_cache_store_string (bytes, gst_structure_get_name (caps_structure)); clapper_cache_store_string (bytes, temp_str);
g_clear_pointer (&temp_str, g_free);
} else { } else {
GST_ERROR_OBJECT (self, "Cannot cache empty caps"); GST_ERROR_OBJECT (self, "Cannot cache caps");
data_ok = FALSE; data_ok = FALSE;
} }
@@ -435,11 +443,15 @@ clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *pro
* *
* Commonly used media types are: * 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. * Returns: %TRUE when filled successfully, %FALSE if taken data was empty.
* *
@@ -460,6 +472,7 @@ clapper_harvest_fill (ClapperHarvest *self, const gchar *media_type, gpointer da
if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG) { if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG) {
gboolean is_printable = (strcmp (media_type, "application/dash+xml") == 0) gboolean is_printable = (strcmp (media_type, "application/dash+xml") == 0)
|| (strcmp (media_type, "application/x-hls") == 0) || (strcmp (media_type, "application/x-hls") == 0)
|| (strcmp (media_type, "text/x-uri") == 0)
|| (strcmp (media_type, "text/uri-list") == 0); || (strcmp (media_type, "text/uri-list") == 0);
if (is_printable) { if (is_printable) {

View File

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

View File

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

View File

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

View File

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

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