diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | Makefile.am | 15 | ||||
-rw-r--r-- | audio-player.c | 979 | ||||
-rw-r--r-- | audio-player.h | 121 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | main.c | 32 | ||||
-rw-r--r-- | tag-reader.c | 649 | ||||
-rw-r--r-- | tag-reader.h | 100 |
8 files changed, 33 insertions, 1884 deletions
@@ -1,3 +1,17 @@ +2008-06-30 Jorn Baayen <jorn@openedhand.com> + + * Makefile.am: + * audio-player.c: + * audio-player.h: + * configure.ac: + * main.c (set_playing_row), (eos_cb), (add_uri), + (tag_reader_uri_scanned_cb), (play_pause_button_toggled_cb), + (main): + * tag-reader.c: + * tag-reader.h: + + Use libowl-av. + 2008-06-28 Jorn Baayen <jorn@openedhand.com> * audio-player.c (bus_message_state_change_cb): diff --git a/Makefile.am b/Makefile.am index af740ff..ac21829 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,20 +8,7 @@ LDADD = $(DEPS_LIBS) gaku_SOURCES = \ main.c \ - audio-player.c audio-player.h \ - playlist-parser.c playlist-parser.h \ - tag-reader.c tag-reader.h \ - marshal.c marshal.h - -%.h: %.list - $(GLIB_GENMARSHAL) --prefix=$* $< --header > $@ - -%.c: %.list - $(GLIB_GENMARSHAL) --prefix=$* $< --body > $@ - -EXTRA_DIST = marshal.list -BUILT_SOURCES = marshal.c marshal.h -CLEANFILES = $(BUILT_SOURCES) + playlist-parser.c playlist-parser.h desktopdir = $(datadir)/applications dist_desktop_DATA = gaku.desktop diff --git a/audio-player.c b/audio-player.c deleted file mode 100644 index dc4707d..0000000 --- a/audio-player.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - * Copyright (C) 2006 OpenedHand Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Jorn Baayen <jorn@openedhand.com> - */ - -#include <gst/gst.h> - -#include "audio-player.h" - -G_DEFINE_TYPE (AudioPlayer, - audio_player, - G_TYPE_OBJECT); - -struct _AudioPlayerPrivate { - GstElement *playbin; - - char *uri; - - gboolean can_seek; - - int buffer_percent; - - int duration; - - guint tick_timeout_id; -}; - -enum { - PROP_0, - PROP_URI, - PROP_PLAYING, - PROP_POSITION, - PROP_VOLUME, - PROP_CAN_SEEK, - PROP_BUFFER_PERCENT, - PROP_DURATION -}; - -enum { - TAG_LIST_AVAILABLE, - EOS, - ERROR, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -#define TICK_TIMEOUT 0.5 - -/* TODO: Possibly retrieve these through introspection. The problem is that we - * need them in class_init already. */ -#define GST_VOL_DEFAULT 1.0 -#define GST_VOL_MAX 4.0 - -/** - * An error occured. - **/ -static void -bus_message_error_cb (GstBus *bus, - GstMessage *message, - AudioPlayer *audio_player) -{ - GError *error; - - error = NULL; - gst_message_parse_error (message, - &error, - NULL); - - g_signal_emit (audio_player, - signals[ERROR], - 0, - error); - - g_error_free (error); - -} - -/** - * End of stream reached. - **/ -static void -bus_message_eos_cb (GstBus *bus, - GstMessage *message, - AudioPlayer *audio_player) -{ - /** - * Make sure UI is in sync. - **/ - g_object_notify (G_OBJECT (audio_player), "position"); - - /** - * Emit EOS signal. - **/ - g_signal_emit (audio_player, - signals[EOS], - 0); -} - -/** - * Tag list available. - **/ -static void -bus_message_tag_cb (GstBus *bus, - GstMessage *message, - AudioPlayer *audio_player) -{ - GstTagList *tag_list; - - gst_message_parse_tag (message, &tag_list); - - g_signal_emit (audio_player, - signals[TAG_LIST_AVAILABLE], - 0, - tag_list); - - gst_tag_list_free (tag_list); -} - -/** - * Buffering information available. - **/ -static void -bus_message_buffering_cb (GstBus *bus, - GstMessage *message, - AudioPlayer *audio_player) -{ - const GstStructure *str; - - str = gst_message_get_structure (message); - if (!str) - return; - - if (!gst_structure_get_int (str, - "buffer-percent", - &audio_player->priv->buffer_percent)) - return; - - g_object_notify (G_OBJECT (audio_player), "buffer-percent"); -} - -/** - * Duration information available. - **/ -static void -bus_message_duration_cb (GstBus *bus, - GstMessage *message, - AudioPlayer *audio_player) -{ - GstFormat format; - gint64 duration; - - gst_message_parse_duration (message, - &format, - &duration); - - if (format != GST_FORMAT_TIME) - return; - - audio_player->priv->duration = duration / GST_SECOND; - - g_object_notify (G_OBJECT (audio_player), "duration"); -} - -/** - * A state change occured. - **/ -static void -bus_message_state_change_cb (GstBus *bus, - GstMessage *message, - AudioPlayer *audio_player) -{ - gpointer src; - GstState old_state, new_state; - - src = GST_MESSAGE_SRC (message); - - if (src != audio_player->priv->playbin) - return; - - gst_message_parse_state_changed (message, - &old_state, - &new_state, - NULL); - - if (old_state == GST_STATE_READY && - new_state == GST_STATE_PAUSED) { - GstQuery *query; - - /** - * Determine whether we can seek. - **/ - query = gst_query_new_seeking (GST_FORMAT_TIME); - - if (gst_element_query (audio_player->priv->playbin, query)) { - gst_query_parse_seeking (query, - NULL, - &audio_player->priv->can_seek, - NULL, - NULL); - } else { - /** - * Could not query for ability to seek. Assume seek - * is supported. - **/ - - audio_player->priv->can_seek = TRUE; - } - - gst_query_unref (query); - - g_object_notify (G_OBJECT (audio_player), "can-seek"); - - /** - * Determine the duration. - **/ - query = gst_query_new_duration (GST_FORMAT_TIME); - - if (gst_element_query (audio_player->priv->playbin, query)) { - gint64 duration; - - gst_query_parse_duration (query, - NULL, - &duration); - - audio_player->priv->duration = duration / GST_SECOND; - - g_object_notify (G_OBJECT (audio_player), "duration"); - } - - gst_query_unref (query); - } -} - -/** - * Called every TICK_TIMEOUT secs to notify of a position change. - **/ -static gboolean -tick_timeout (AudioPlayer *audio_player) -{ - g_object_notify (G_OBJECT (audio_player), "position"); - - return TRUE; -} - -/** - * Constructs the GStreamer pipeline. - **/ -static void -construct_pipeline (AudioPlayer *audio_player) -{ - - GstElement *audiosink; - GstBus *bus; - - /** - * playbin. - **/ - audio_player->priv->playbin = - gst_element_factory_make ("playbin", "playbin"); - if (!audio_player->priv->playbin) { - g_warning ("No playbin found. Playback will not work."); - - return; - } - - /** - * An audiosink. - **/ - audiosink = gst_element_factory_make ("gconfaudiosink", "audiosink"); - if (!audiosink) { - g_warning ("No gconfaudiosink found. Trying autoaudiosink ..."); - - audiosink = gst_element_factory_make ("autoaudiosink", - "audiosink"); - if (!audiosink) { - g_warning ("No autoaudiosink found. " - "Trying alsasink ..."); - - audiosink = gst_element_factory_make ("alsasink", - "audiosink"); - if (!audiosink) { - g_warning ("No audiosink could be found. " - "Audio will not be available."); - } - } - } - - /** - * Click sinks into playbin. - **/ - g_object_set (G_OBJECT (audio_player->priv->playbin), - "audio-sink", audiosink, - "video-sink", NULL, - NULL); - - /** - * Connect to signals on bus. - **/ - bus = gst_pipeline_get_bus (GST_PIPELINE (audio_player->priv->playbin)); - - gst_bus_add_signal_watch (bus); - - g_signal_connect_object (bus, - "message::error", - G_CALLBACK (bus_message_error_cb), - audio_player, - 0); - g_signal_connect_object (bus, - "message::eos", - G_CALLBACK (bus_message_eos_cb), - audio_player, - 0); - g_signal_connect_object (bus, - "message::tag", - G_CALLBACK (bus_message_tag_cb), - audio_player, - 0); - g_signal_connect_object (bus, - "message::buffering", - G_CALLBACK (bus_message_buffering_cb), - audio_player, - 0); - g_signal_connect_object (bus, - "message::duration", - G_CALLBACK (bus_message_duration_cb), - audio_player, - 0); - g_signal_connect_object (bus, - "message::state-changed", - G_CALLBACK (bus_message_state_change_cb), - audio_player, - 0); - - gst_object_unref (GST_OBJECT (bus)); -} - -static void -audio_player_init (AudioPlayer *audio_player) -{ - /** - * Create pointer to private data. - **/ - audio_player->priv = - G_TYPE_INSTANCE_GET_PRIVATE (audio_player, - TYPE_AUDIO_PLAYER, - AudioPlayerPrivate); - - /** - * Construct GStreamer pipeline: playbin with sinks from GConf. - **/ - construct_pipeline (audio_player); -} - -static void -audio_player_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - AudioPlayer *audio_player; - - audio_player = AUDIO_PLAYER (object); - - switch (property_id) { - case PROP_URI: - audio_player_set_uri (audio_player, - g_value_get_string (value)); - break; - case PROP_PLAYING: - audio_player_set_playing (audio_player, - g_value_get_boolean (value)); - break; - case PROP_POSITION: - audio_player_set_position (audio_player, - g_value_get_int (value)); - break; - case PROP_VOLUME: - audio_player_set_volume (audio_player, - g_value_get_double (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -audio_player_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - AudioPlayer *audio_player; - - audio_player = AUDIO_PLAYER (object); - - switch (property_id) { - case PROP_URI: - g_value_set_string - (value, - audio_player_get_uri (audio_player)); - break; - case PROP_PLAYING: - g_value_set_boolean - (value, - audio_player_get_playing (audio_player)); - break; - case PROP_POSITION: - g_value_set_int - (value, - audio_player_get_position (audio_player)); - break; - case PROP_VOLUME: - g_value_set_double - (value, - audio_player_get_volume (audio_player)); - break; - case PROP_CAN_SEEK: - g_value_set_boolean - (value, - audio_player_get_can_seek (audio_player)); - break; - case PROP_BUFFER_PERCENT: - g_value_set_int - (value, - audio_player_get_buffer_percent (audio_player)); - break; - case PROP_DURATION: - g_value_set_int - (value, - audio_player_get_duration (audio_player)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -audio_player_dispose (GObject *object) -{ - AudioPlayer *audio_player; - GObjectClass *object_class; - - audio_player = AUDIO_PLAYER (object); - - if (audio_player->priv->playbin) { - gst_element_set_state (audio_player->priv->playbin, - GST_STATE_NULL); - - gst_object_unref (GST_OBJECT (audio_player->priv->playbin)); - audio_player->priv->playbin = NULL; - } - - if (audio_player->priv->tick_timeout_id > 0) { - g_source_remove (audio_player->priv->tick_timeout_id); - audio_player->priv->tick_timeout_id = 0; - } - - object_class = G_OBJECT_CLASS (audio_player_parent_class); - object_class->dispose (object); -} - -static void -audio_player_finalize (GObject *object) -{ - AudioPlayer *audio_player; - GObjectClass *object_class; - - audio_player = AUDIO_PLAYER (object); - - g_free (audio_player->priv->uri); - - object_class = G_OBJECT_CLASS (audio_player_parent_class); - object_class->finalize (object); -} - -static void -audio_player_class_init (AudioPlayerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = audio_player_set_property; - object_class->get_property = audio_player_get_property; - object_class->dispose = audio_player_dispose; - object_class->finalize = audio_player_finalize; - - g_type_class_add_private (klass, sizeof (AudioPlayerPrivate)); - - g_object_class_install_property - (object_class, - PROP_URI, - g_param_spec_string - ("uri", - "URI", - "The loaded URI.", - NULL, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property - (object_class, - PROP_PLAYING, - g_param_spec_boolean - ("playing", - "Playing", - "TRUE if playing.", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property - (object_class, - PROP_POSITION, - g_param_spec_int - ("position", - "Position", - "The position in the current stream in seconds.", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property - (object_class, - PROP_VOLUME, - g_param_spec_double - ("volume", - "Volume", - "The audio volume.", - 0, GST_VOL_MAX, GST_VOL_DEFAULT, - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property - (object_class, - PROP_CAN_SEEK, - g_param_spec_boolean - ("can-seek", - "Can seek", - "TRUE if the current stream is seekable.", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property - (object_class, - PROP_BUFFER_PERCENT, - g_param_spec_int - ("buffer-percent", - "Buffer percent", - "The percentage the current stream buffer is filled.", - 0, 100, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - g_object_class_install_property - (object_class, - PROP_DURATION, - g_param_spec_int - ("duration", - "Duration", - "The duration of the current stream in seconds.", - 0, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); - - signals[TAG_LIST_AVAILABLE] = - g_signal_new ("tag-list-available", - TYPE_AUDIO_PLAYER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (AudioPlayerClass, - tag_list_available), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - signals[EOS] = - g_signal_new ("eos", - TYPE_AUDIO_PLAYER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (AudioPlayerClass, - eos), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[ERROR] = - g_signal_new ("error", - TYPE_AUDIO_PLAYER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (AudioPlayerClass, - error), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); -} - -/** - * audio_player_new - * - * Return value: A new #AudioPlayer. - **/ -AudioPlayer * -audio_player_new (void) -{ - return g_object_new (TYPE_AUDIO_PLAYER, NULL); -} - -/** - * audio_player_set_uri - * @audio_player: A #AudioPlayer - * @uri: A URI - * - * Loads @uri. - **/ -void -audio_player_set_uri (AudioPlayer *audio_player, - const char *uri) -{ - GstState state, pending; - - g_return_if_fail (IS_AUDIO_PLAYER (audio_player)); - - if (!audio_player->priv->playbin) - return; - - g_free (audio_player->priv->uri); - - if (uri) { - audio_player->priv->uri = g_strdup (uri); - - /** - * Ensure the tick timeout is installed. - * - * We also have it installed in PAUSED state, because - * seeks etc may have a delayed effect on the position. - **/ - if (audio_player->priv->tick_timeout_id == 0) { - audio_player->priv->tick_timeout_id = - g_timeout_add (TICK_TIMEOUT * 1000, - (GSourceFunc) tick_timeout, - audio_player); - } - } else { - audio_player->priv->uri = NULL; - - /** - * Remove tick timeout. - **/ - if (audio_player->priv->tick_timeout_id > 0) { - g_source_remove (audio_player->priv->tick_timeout_id); - audio_player->priv->tick_timeout_id = 0; - } - } - - /** - * Reset properties. - **/ - audio_player->priv->can_seek = FALSE; - audio_player->priv->duration = 0; - - /** - * Store old state. - **/ - gst_element_get_state (audio_player->priv->playbin, - &state, - &pending, - 0); - if (pending) - state = pending; - - /** - * State to NULL. - **/ - gst_element_set_state (audio_player->priv->playbin, GST_STATE_NULL); - - /** - * Set new URI. - **/ - g_object_set (audio_player->priv->playbin, - "uri", uri, - NULL); - - /** - * Restore state. - **/ - if (uri) - gst_element_set_state (audio_player->priv->playbin, state); - - /** - * Emit notififications for all these to make sure UI is not showing - * any properties of the old URI. - **/ - g_object_notify (G_OBJECT (audio_player), "uri"); - g_object_notify (G_OBJECT (audio_player), "can-seek"); - g_object_notify (G_OBJECT (audio_player), "duration"); - g_object_notify (G_OBJECT (audio_player), "position"); -} - -/** - * audio_player_get_uri - * @audio_player: A #AudioPlayer - * - * Return value: The loaded URI, or NULL if none set. - **/ -const char * -audio_player_get_uri (AudioPlayer *audio_player) -{ - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), NULL); - - return audio_player->priv->uri; -} - -/** - * audio_player_set_playing - * @audio_player: A #AudioPlayer - * @playing: TRUE if @audio_player should be playing, FALSE otherwise - * - * Sets the playback state of @audio_player to @playing. - **/ -void -audio_player_set_playing (AudioPlayer *audio_player, - gboolean playing) -{ - g_return_if_fail (IS_AUDIO_PLAYER (audio_player)); - - if (!audio_player->priv->playbin) - return; - - /** - * Choose the correct state for the pipeline. - **/ - if (audio_player->priv->uri) { - GstState state; - - if (playing) - state = GST_STATE_PLAYING; - else - state = GST_STATE_PAUSED; - - gst_element_set_state (audio_player->priv->playbin, state); - } else { - if (playing) - g_warning ("Tried to play, but no URI is loaded."); - - /** - * Do nothing. - **/ - } - - g_object_notify (G_OBJECT (audio_player), "playing"); - - /** - * Make sure UI is in sync. - **/ - g_object_notify (G_OBJECT (audio_player), "position"); -} - -/** - * audio_player_get_playing - * @audio_player: A #AudioPlayer - * - * Return value: TRUE if @audio_player is playing. - **/ -gboolean -audio_player_get_playing (AudioPlayer *audio_player) -{ - GstState state, pending; - - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), FALSE); - - if (!audio_player->priv->playbin) - return FALSE; - - gst_element_get_state (audio_player->priv->playbin, - &state, - &pending, - 0); - - if (pending) - return (pending == GST_STATE_PLAYING); - else - return (state == GST_STATE_PLAYING); -} - -/** - * audio_player_set_position - * @audio_player: A #AudioPlayer - * @position: The position in the current stream in seconds. - * - * Sets the position in the current stream to @position. - **/ -void -audio_player_set_position (AudioPlayer *audio_player, - int position) -{ - GstState state, pending; - - g_return_if_fail (IS_AUDIO_PLAYER (audio_player)); - - if (!audio_player->priv->playbin) - return; - - /** - * Store old state. - **/ - gst_element_get_state (audio_player->priv->playbin, - &state, - &pending, - 0); - if (pending) - state = pending; - - /** - * State to PAUSED. - **/ - gst_element_set_state (audio_player->priv->playbin, GST_STATE_PAUSED); - - /** - * Perform the seek. - **/ - gst_element_seek (audio_player->priv->playbin, - 1.0, - GST_FORMAT_TIME, - GST_SEEK_FLAG_FLUSH, - GST_SEEK_TYPE_SET, - position * GST_SECOND, - 0, 0); - /** - * Restore state. - **/ - gst_element_set_state (audio_player->priv->playbin, state); -} - -/** - * audio_player_get_position - * @audio_player: A #AudioPlayer - * - * Return value: The position in the current file in seconds. - **/ -int -audio_player_get_position (AudioPlayer *audio_player) -{ - GstQuery *query; - gint64 position; - - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), -1); - - if (!audio_player->priv->playbin) - return -1; - - query = gst_query_new_position (GST_FORMAT_TIME); - - if (gst_element_query (audio_player->priv->playbin, query)) { - gst_query_parse_position (query, - NULL, - &position); - } else - position = 0; - - gst_query_unref (query); - - return (position / GST_SECOND); -} - -/** - * audio_player_set_volume - * @audio_player: A #AudioPlayer - * @volume: The audio volume to set, in the range 0.0 - 4.0. - * - * Sets the current audio volume to @volume. - **/ -void -audio_player_set_volume (AudioPlayer *audio_player, - double volume) -{ - g_return_if_fail (IS_AUDIO_PLAYER (audio_player)); - g_return_if_fail (volume >= 0.0 && volume <= GST_VOL_MAX); - - if (!audio_player->priv->playbin) - return; - - g_object_set (G_OBJECT (audio_player->priv->playbin), - "volume", volume, - NULL); - - g_object_notify (G_OBJECT (audio_player), "volume"); -} - -/** - * audio_player_get_volume - * @audio_player: A #AudioPlayer - * - * Return value: The current audio volume, in the range 0.0 - 4.0. - **/ -double -audio_player_get_volume (AudioPlayer *audio_player) -{ - double volume; - - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), 0); - - if (!audio_player->priv->playbin) - return 0.0; - - g_object_get (audio_player->priv->playbin, - "volume", &volume, - NULL); - - return volume; -} - -/** - * audio_player_get_can_seek - * @audio_player: A #AudioPlayer - * - * Return value: TRUE if the current stream is seekable. - **/ -gboolean -audio_player_get_can_seek (AudioPlayer *audio_player) -{ - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), FALSE); - - return audio_player->priv->can_seek; -} - -/** - * audio_player_get_buffer_percent - * @audio_player: A #AudioPlayer - * - * Return value: Percentage the current stream buffer is filled. - **/ -int -audio_player_get_buffer_percent (AudioPlayer *audio_player) -{ - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), -1); - - return audio_player->priv->buffer_percent; -} - -/** - * audio_player_get_duration - * @audio_player: A #AudioPlayer - * - * Return value: The duration of the current stream in seconds. - **/ -int -audio_player_get_duration (AudioPlayer *audio_player) -{ - g_return_val_if_fail (IS_AUDIO_PLAYER (audio_player), -1); - - return audio_player->priv->duration; -} diff --git a/audio-player.h b/audio-player.h deleted file mode 100644 index d57e222..0000000 --- a/audio-player.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2006 OpenedHand Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Jorn Baayen <jorn@openedhand.com> - */ - -#ifndef __AUDIO_PLAYER_H__ -#define __AUDIO_PLAYER_H__ - -#include <glib-object.h> -#include <gst/gsttaglist.h> - -G_BEGIN_DECLS - -#define TYPE_AUDIO_PLAYER \ - (audio_player_get_type ()) -#define AUDIO_PLAYER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TYPE_AUDIO_PLAYER, \ - AudioPlayer)) -#define AUDIO_PLAYER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TYPE_AUDIO_PLAYER, \ - AudioPlayerClass)) -#define IS_AUDIO_PLAYER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TYPE_AUDIO_PLAYER)) -#define IS_AUDIO_PLAYER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TYPE_AUDIO_PLAYER)) -#define AUDIO_PLAYER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TYPE_AUDIO_PLAYER, \ - AudioPlayerClass)) - -typedef struct _AudioPlayerPrivate AudioPlayerPrivate; - -typedef struct { - GObject parent; - - AudioPlayerPrivate *priv; -} AudioPlayer; - -typedef struct { - GObjectClass parent_class; - - /* Signals */ - void (* tag_list_available) (AudioPlayer *audio_player, - GstTagList *tag_list); - void (* eos) (AudioPlayer *audio_player); - void (* error) (AudioPlayer *audio_player, - GError *error); - - /* Future padding */ - void (* _reserved1) (void); - void (* _reserved2) (void); - void (* _reserved3) (void); - void (* _reserved4) (void); -} AudioPlayerClass; - -GType -audio_player_get_type (void) G_GNUC_CONST; - -AudioPlayer * -audio_player_new (void); - -void -audio_player_set_uri (AudioPlayer *audio_player, - const char *uri); - -const char * -audio_player_get_uri (AudioPlayer *audio_player); - -void -audio_player_set_playing (AudioPlayer *audio_player, - gboolean playing); - -gboolean -audio_player_get_playing (AudioPlayer *audio_player); - -void -audio_player_set_position (AudioPlayer *audio_player, - int position); - -int -audio_player_get_position (AudioPlayer *audio_player); - -void -audio_player_set_volume (AudioPlayer *audio_player, - double volume); - -double -audio_player_get_volume (AudioPlayer *audio_player); - -gboolean -audio_player_get_can_seek (AudioPlayer *audio_player); - -int -audio_player_get_buffer_percent (AudioPlayer *audio_player); - -int -audio_player_get_duration (AudioPlayer *audio_player); - -G_END_DECLS - -#endif /* __AUDIO_PLAYER_H__ */ diff --git a/configure.ac b/configure.ac index a6a29ae..6c031c4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,15 +1,12 @@ AC_PREREQ(2.52) AC_INIT(gaku, 0.1, http://o-hand.com) -AC_CONFIG_SRCDIR(audio-player.c) +AC_CONFIG_SRCDIR(main.c) AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) AM_CONFIG_HEADER(config.h) AC_PROG_CPP AC_PROG_CC -PKG_CHECK_MODULES(DEPS, gtk+-2.0 gstreamer-0.10) - -GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` -AC_SUBST(GLIB_GENMARSHAL) +PKG_CHECK_MODULES(DEPS, gtk+-2.0 gstreamer-0.10 libowl-av) AC_OUTPUT([Makefile]) @@ -21,19 +21,19 @@ #include <gst/gst.h> #include <gtk/gtk.h> +#include <libowl-av/owl-audio-player.h> +#include <libowl-av/owl-tag-reader.h> #include <string.h> -#include "audio-player.h" #include "playlist-parser.h" -#include "tag-reader.h" typedef struct { /** * Our special objects. **/ - AudioPlayer *audio_player; + OwlAudioPlayer *audio_player; PlaylistParser *playlist_parser; - TagReader *tag_reader; + OwlTagReader *tag_reader; /** * UI objects. @@ -156,7 +156,7 @@ set_playing_row (AppData *data, COL_TITLE, &title, -1); - audio_player_set_uri (data->audio_player, uri); + owl_audio_player_set_uri (data->audio_player, uri); update_title (data, title); @@ -236,8 +236,8 @@ next (AppData *data) * End of stream reached. **/ static void -eos_cb (AudioPlayer *player, - AppData *data) +eos_cb (OwlAudioPlayer *player, + AppData *data) { /** * Go to next song. @@ -296,7 +296,7 @@ add_uri (AppData *data, /** * Feed to tag reader. **/ - tag_reader_scan_uri (data->tag_reader, uri); + owl_tag_reader_scan_uri (data->tag_reader, uri); /** * Play this song if nothing is playing. @@ -313,11 +313,11 @@ add_uri (AppData *data, * TagReader is done scanning an URI. Update UI. **/ static void -tag_reader_uri_scanned_cb (TagReader *tag_reader, - const char *uri, - GError *error, - GstTagList *tag_list, - AppData *data) +tag_reader_uri_scanned_cb (OwlTagReader *tag_reader, + const char *uri, + GError *error, + GstTagList *tag_list, + AppData *data) { GtkTreeModel *tree_model; GtkTreeIter iter; @@ -411,7 +411,7 @@ static void play_pause_button_toggled_cb (GtkToggleButton *button, AppData *data) { - audio_player_set_playing (data->audio_player, button->active); + owl_audio_player_set_playing (data->audio_player, button->active); } /** @@ -692,7 +692,7 @@ main (int argc, char **argv) /** * Set up AudioPlayer. **/ - data->audio_player = audio_player_new (); + data->audio_player = owl_audio_player_new (); g_signal_connect (data->audio_player, "eos", @@ -717,7 +717,7 @@ main (int argc, char **argv) /** * Set up TagReader. **/ - data->tag_reader = tag_reader_new (); + data->tag_reader = owl_tag_reader_new (); g_signal_connect (data->tag_reader, "uri-scanned", diff --git a/tag-reader.c b/tag-reader.c deleted file mode 100644 index ee6a4da..0000000 --- a/tag-reader.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Copyright (C) 2006 OpenedHand Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Jorn Baayen <jorn@openedhand.com> - */ - -#include <gst/gst.h> -#include <string.h> - -#include "marshal.h" - -#include "tag-reader.h" - -G_DEFINE_TYPE (TagReader, - tag_reader, - G_TYPE_OBJECT); - -struct _TagReaderPrivate { - GstElement *pipeline; - GstElement *src; - GstElement *decodebin; - GstElement *sink; - - GQueue *queue; - - guint next_id; - - GError *current_error; - GstTagList *current_tag_list; -}; - -enum { - SIGNAL_URI_SCANNED, - SIGNAL_LAST -}; - -static guint signals[SIGNAL_LAST]; - -typedef struct { - char *uri; - guint id; -} ScanUriData; - -static void -scan_uri_data_free (ScanUriData *data) -{ - g_free (data->uri); - - g_slice_free (ScanUriData, data); -} - -/** - * Feed the head of the queue to the pipeline. - **/ -static void -feed_head (TagReader *tag_reader) -{ - ScanUriData *data; - - data = g_queue_peek_head (tag_reader->priv->queue); - if (!data) - return; - - /** - * Get appropriate src element. - **/ - tag_reader->priv->src = - gst_element_make_from_uri (GST_URI_SRC, data->uri, "src"); - - /** - * Add to pipeline & link up. - **/ - gst_bin_add (GST_BIN (tag_reader->priv->pipeline), - tag_reader->priv->src); - gst_element_link (tag_reader->priv->src, tag_reader->priv->decodebin); - - /** - * Play pipeline. - **/ - gst_element_set_state (tag_reader->priv->pipeline, - GST_STATE_PLAYING); -} - -/** - * Purge the head of the queue. - **/ -static void -flush_head (TagReader *tag_reader) -{ - ScanUriData *data; - - /** - * Stop pipeline. - **/ - gst_element_set_state (tag_reader->priv->pipeline, - GST_STATE_NULL); - - /** - * Remove source element. - **/ - gst_element_unlink (tag_reader->priv->src, tag_reader->priv->decodebin); - gst_bin_remove (GST_BIN (tag_reader->priv->pipeline), - tag_reader->priv->src); - - /** - * Pop head from queue. - **/ - data = g_queue_pop_head (tag_reader->priv->queue); - - /** - * Call callback. - **/ - g_signal_emit (tag_reader, - signals[SIGNAL_URI_SCANNED], - 0, - data->uri, - tag_reader->priv->current_error, - tag_reader->priv->current_tag_list); - - /** - * Free data. - **/ - if (tag_reader->priv->current_error) { - g_error_free (tag_reader->priv->current_error); - tag_reader->priv->current_error = NULL; - } - - if (tag_reader->priv->current_tag_list) { - gst_tag_list_free (tag_reader->priv->current_tag_list); - tag_reader->priv->current_tag_list = NULL; - } - - scan_uri_data_free (data); -} - -/** - * An error occured. - **/ -static void -bus_message_error_cb (GstBus *bus, - GstMessage *message, - TagReader *tag_reader) -{ - ScanUriData *data; - - data = g_queue_peek_head (tag_reader->priv->queue); - - gst_message_parse_error (message, - &tag_reader->priv->current_error, - NULL); - - flush_head (tag_reader); - feed_head (tag_reader); -} - -/** - * End of stream reached. - **/ -static void -bus_message_eos_cb (GstBus *bus, - GstMessage *message, - TagReader *tag_reader) -{ - flush_head (tag_reader); - feed_head (tag_reader); -} - -/** - * Tag list available. - **/ -static void -bus_message_tag_cb (GstBus *bus, - GstMessage *message, - TagReader *tag_reader) -{ - GstTagList *tags, *new_tags; - - gst_message_parse_tag (message, &tags); - - new_tags = gst_tag_list_merge (tag_reader->priv->current_tag_list, tags, GST_TAG_MERGE_REPLACE); - - if (tag_reader->priv->current_tag_list) - gst_tag_list_free (tag_reader->priv->current_tag_list); - gst_tag_list_free (tags); - - tag_reader->priv->current_tag_list = new_tags; -} - -/** - * Application message received. - **/ -static void -bus_message_application_cb (GstBus *bus, - GstMessage *message, - TagReader *tag_reader) -{ - gpointer src; - const GstStructure *structure; - const char *structure_name; - ScanUriData *data; - GstQuery *query; - - /** - * Verify this is the fakesink handoff event. - **/ - src = GST_MESSAGE_SRC (message); - if (src != tag_reader->priv->sink) - return; - - structure = gst_message_get_structure (message); - structure_name = gst_structure_get_name (structure); - if (strcmp (structure_name, "handoff")) - return; - - /** - * Get relevant ScanUriData. - **/ - data = g_queue_peek_head (tag_reader->priv->queue); - - /** - * Determine the duration. - **/ - query = gst_query_new_duration (GST_FORMAT_TIME); - - if (gst_element_query (tag_reader->priv->pipeline, query)) { - gint64 duration; - - gst_query_parse_duration (query, - NULL, - &duration); - - /** - * Create tag list if none exists yet. - **/ - if (!tag_reader->priv->current_tag_list) { - tag_reader->priv->current_tag_list = - gst_tag_list_new (); - } - - /** - * Merge duration info into tag list. - **/ - gst_tag_list_add (tag_reader->priv->current_tag_list, - GST_TAG_MERGE_REPLACE, - GST_TAG_DURATION, - duration, - NULL); - } - - gst_query_unref (query); - - /** - * Next, please. - **/ - flush_head (tag_reader); - feed_head (tag_reader); -} - -/** - * New decoded pad: Hook up to fakesink. - **/ -static void -decodebin_new_decoded_pad_cb (GstElement *decodebin, - GstPad *pad, - gboolean last, - TagReader *tag_reader) -{ - GstPad *sink_pad; - - /** - * The last discovered pad will always be the one hooked up to - * the sink. - **/ - sink_pad = gst_element_get_pad (tag_reader->priv->sink, "sink"); - gst_pad_link (pad, sink_pad); -} - -/** - * Data of an unknown type fed. - **/ -static void -decodebin_unknown_type_cb (GstElement *decodebin, - GstPad *pad, - GstCaps *caps, - TagReader *tag_reader) -{ - tag_reader->priv->current_error = - g_error_new (TAG_READER_ERROR, - TAG_READER_ERROR_UNKNOWN_TYPE, - "Unknown type"); - - flush_head (tag_reader); - feed_head (tag_reader); -} - -/** - * Fakesink hands over a buffer. - **/ -static void -fakesink_handoff_cb (GstElement *fakesink, - GstBuffer *buffer, - GstPad *pad, - TagReader *tag_reader) -{ - GstStructure *structure; - GstMessage *message; - GstBus *bus; - - /** - * Post a message to the bus, as we are in another thread here. - **/ - structure = gst_structure_new ("handoff", NULL); - message = gst_message_new_application (GST_OBJECT (fakesink), - structure); - - bus = gst_pipeline_get_bus (GST_PIPELINE (tag_reader->priv->pipeline)); - gst_bus_post (bus, message); - gst_object_unref (GST_OBJECT (bus)); -} - -/** - * Constructs the GStreamer pipeline. - **/ -static void -construct_pipeline (TagReader *tag_reader) -{ - - GstBus *bus; - - /** - * The pipeline. - **/ - tag_reader->priv->pipeline = gst_pipeline_new ("pipeline"); - - /** - * No src element yet. - **/ - tag_reader->priv->src = NULL; - - /** - * A decodebin. - **/ - tag_reader->priv->decodebin = - gst_element_factory_make ("decodebin", "decodebin"); - if (!tag_reader->priv->decodebin) { - g_warning ("No decodebin found. Tag reading will not work."); - - return; - } - - gst_bin_add (GST_BIN (tag_reader->priv->pipeline), - tag_reader->priv->decodebin); - - g_signal_connect_object (tag_reader->priv->decodebin, - "new-decoded-pad", - G_CALLBACK (decodebin_new_decoded_pad_cb), - tag_reader, - 0); - g_signal_connect_object (tag_reader->priv->decodebin, - "unknown-type", - G_CALLBACK (decodebin_unknown_type_cb), - tag_reader, - 0); - - /** - * A fakesink. - **/ - tag_reader->priv->sink = - gst_element_factory_make ("fakesink", "fakesink"); - if (!tag_reader->priv->sink) { - g_warning ("No fakesink found. Tag reading will not work."); - - return; - } - - gst_bin_add (GST_BIN (tag_reader->priv->pipeline), - tag_reader->priv->sink); - - g_object_set (tag_reader->priv->sink, - "signal-handoffs", TRUE, - NULL); - - g_signal_connect_object (tag_reader->priv->sink, - "handoff", - G_CALLBACK (fakesink_handoff_cb), - tag_reader, - 0); - - /** - * Connect to signals on bus. - **/ - bus = gst_pipeline_get_bus (GST_PIPELINE (tag_reader->priv->pipeline)); - - gst_bus_add_signal_watch (bus); - - g_signal_connect_object (bus, - "message::error", - G_CALLBACK (bus_message_error_cb), - tag_reader, - 0); - g_signal_connect_object (bus, - "message::eos", - G_CALLBACK (bus_message_eos_cb), - tag_reader, - 0); - g_signal_connect_object (bus, - "message::tag", - G_CALLBACK (bus_message_tag_cb), - tag_reader, - 0); - g_signal_connect_object (bus, - "message::application", - G_CALLBACK (bus_message_application_cb), - tag_reader, - 0); - - gst_object_unref (GST_OBJECT (bus)); -} - -static void -tag_reader_init (TagReader *tag_reader) -{ - /** - * Create pointer to private data. - **/ - tag_reader->priv = - G_TYPE_INSTANCE_GET_PRIVATE (tag_reader, - TYPE_TAG_READER, - TagReaderPrivate); - - /** - * Create scanning queue. - **/ - tag_reader->priv->queue = g_queue_new (); - - /** - * Initialize next ScanUriData ID. - **/ - tag_reader->priv->next_id = 1; - - /** - * No current URI yet. - **/ - tag_reader->priv->current_error = NULL; - tag_reader->priv->current_tag_list = NULL; - - /** - * Construct GStreamer pipeline. - **/ - construct_pipeline (tag_reader); -} - -static void -tag_reader_dispose (GObject *object) -{ - TagReader *tag_reader; - GObjectClass *object_class; - - tag_reader = TAG_READER (object); - - if (tag_reader->priv->pipeline) { - gst_element_set_state (tag_reader->priv->pipeline, - GST_STATE_NULL); - - gst_object_unref (GST_OBJECT (tag_reader->priv->pipeline)); - tag_reader->priv->pipeline = NULL; - } - - object_class = G_OBJECT_CLASS (tag_reader_parent_class); - object_class->dispose (object); -} - -static void -tag_reader_finalize (GObject *object) -{ - TagReader *tag_reader; - GObjectClass *object_class; - - tag_reader = TAG_READER (object); - - if (tag_reader->priv->current_error) - g_error_free (tag_reader->priv->current_error); - if (tag_reader->priv->current_tag_list) - gst_tag_list_free (tag_reader->priv->current_tag_list); - - g_queue_foreach (tag_reader->priv->queue, - (GFunc) scan_uri_data_free, - NULL); - g_queue_free (tag_reader->priv->queue); - - object_class = G_OBJECT_CLASS (tag_reader_parent_class); - object_class->finalize (object); -} - -static void -tag_reader_class_init (TagReaderClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = tag_reader_dispose; - object_class->finalize = tag_reader_finalize; - - g_type_class_add_private (klass, sizeof (TagReaderPrivate)); - - signals[SIGNAL_URI_SCANNED] = - g_signal_new ("uri-scanned", - TYPE_TAG_READER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (TagReaderClass, uri_scanned), - NULL, - NULL, - marshal_VOID__STRING_POINTER_POINTER, - G_TYPE_NONE, - 3, - G_TYPE_STRING, - G_TYPE_POINTER, - G_TYPE_POINTER); -} - -/** - * tag_reader_new - * - * Return value: A new #TagReader. - **/ -TagReader * -tag_reader_new (void) -{ - return g_object_new (TYPE_TAG_READER, NULL); -} - -/** - * tag_reader_scan_uri - * @tag_reader: A #TagReader - * @uri: An URI - * - * Queues @uri up for tag reading. - * - * Return value: A scan ID as @guint. - **/ -guint -tag_reader_scan_uri (TagReader *tag_reader, - const char *uri) -{ - ScanUriData *data; - - g_return_val_if_fail (IS_TAG_READER (tag_reader), 0); - g_return_val_if_fail (uri != NULL, 0); - - data = g_slice_new (ScanUriData); - - data->uri = g_strdup (uri); - data->id = tag_reader->priv->next_id++; - - g_queue_push_tail (tag_reader->priv->queue, data); - - if (g_queue_get_length (tag_reader->priv->queue) == 1) { - /** - * The queue was empty, so we were idle. This means - * we need to start the pump again by feeding the new - * uri to the pipeline. - **/ - feed_head (tag_reader); - } - - return data->id; -} - -/** - * Find a ScanUriData by its ID. - **/ -static int -find_scan_uri_data (gconstpointer a, - gconstpointer b) -{ - guint ai = GPOINTER_TO_UINT (a); - guint bi = GPOINTER_TO_UINT (b); - - if (ai < bi) - return -1; - else if (ai > bi) - return 1; - else - return 0; -} - -/** - * tag_reader_cancal_scan_uri - * @tag_reader: A #TagReader - * @scan_id: The #guint scan ID as returned by #tag_reader_scan_uri - * - * Cancels the scanning of URI with ID @scan_id. - **/ -void -tag_reader_cancel_scan_uri (TagReader *tag_reader, - guint scan_id) -{ - GList *link; - - g_return_if_fail (IS_TAG_READER (tag_reader)); - - link = g_queue_find_custom (tag_reader->priv->queue, - GUINT_TO_POINTER (scan_id), - find_scan_uri_data); - if (!link) { - g_warning ("Not scanning URI with ID %u", scan_id); - - return; - } - - if (!link->prev) { - /** - * We were just processing this one. Use standard - * flushing process. - **/ - flush_head (tag_reader); - } else { - /** - * This one is queued up. Dequeue. - **/ - scan_uri_data_free (link->data); - g_queue_delete_link (tag_reader->priv->queue, link); - } -} - -/** - * Returns the tag reader error quark. - **/ -GQuark -tag_reader_error_quark (void) -{ - return g_quark_from_static_string ("tag-reader-error"); -} diff --git a/tag-reader.h b/tag-reader.h deleted file mode 100644 index 0086258..0000000 --- a/tag-reader.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2006 OpenedHand Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Jorn Baayen <jorn@openedhand.com> - */ - -#ifndef __TAG_READER_H__ -#define __TAG_READER_H__ - -#include <glib-object.h> -#include <gst/gsttaglist.h> - -G_BEGIN_DECLS - -typedef enum { - TAG_READER_ERROR_UNKNOWN_TYPE -} TagReaderError; - -GQuark tag_reader_error_quark (void); - -#define TAG_READER_ERROR \ - (tag_reader_error_quark ()) - -#define TYPE_TAG_READER \ - (tag_reader_get_type ()) -#define TAG_READER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TYPE_TAG_READER, \ - TagReader)) -#define TAG_READER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TYPE_TAG_READER, \ - TagReaderClass)) -#define IS_TAG_READER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TYPE_TAG_READER)) -#define IS_TAG_READER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TYPE_TAG_READER)) -#define TAG_READER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TYPE_TAG_READER, \ - TagReaderClass)) - -typedef struct _TagReaderPrivate TagReaderPrivate; - -typedef struct { - GObject parent; - - TagReaderPrivate *priv; -} TagReader; - -typedef struct { - GObjectClass parent_class; - - /* Signals */ - void (* uri_scanned) (TagReader *tag_reader, - const char *uri, - GError *error, - GstTagList *tag_list); - - /* Future padding */ - void (* _reserved1) (void); - void (* _reserved2) (void); - void (* _reserved3) (void); - void (* _reserved4) (void); -} TagReaderClass; - -GType -tag_reader_get_type (void) G_GNUC_CONST; - -TagReader * -tag_reader_new (void); - -guint -tag_reader_scan_uri (TagReader *tag_reader, - const char *uri); - -void -tag_reader_cancel_scan_uri (TagReader *tag_reader, - guint scan_id); - -G_END_DECLS - -#endif /* __TAG_READER_H__ */ |