Update of /cvsroot/beepmp/bmpx/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25648/src Added Files: Makefile.am bmp-system-control.xml bmp.marshalers bmp_button.c bmp_button.h bmp_button_toggle.c bmp_button_toggle.h bmp_configuration.c bmp_configuration.h bmp_dock.c bmp_dock.h bmp_list.c bmp_list.h bmp_marshalers.c bmp_marshalers.h bmp_metadata.c bmp_metadata.h bmp_play.c bmp_play.gst.c bmp_play.gst.h bmp_play.h bmp_playlist.c bmp_playlist.h bmp_rel.c bmp_rel.h bmp_resource_manager.c bmp_resource_manager.h bmp_slider.c bmp_slider.h bmp_sm.c bmp_sm.h bmp_system_control.c bmp_system_control.h bmp_system_control_glue.h bmp_tooltips.c bmp_tooltips.h bmp_ui.c bmp_ui.h bmp_window.c bmp_window.h chroma_button.c chroma_button.h chroma_list.c chroma_list.h chroma_list.old.c chroma_vscrollbar.c chroma_vscrollbar.h chroma_widgets.h dnd.h error.h fam_monitor.c fam_monitor.h g_object_get.c g_object_get.h g_object_get.in.c g_object_get.in.h g_object_get.types glade.c glade.h gtkbindings.h gtkcontainer.h gtkhsv.c gtkhsv.h gtkmarshalers.h gtkprivate.h list_manager.c list_manager.h logger.c logger.h main.c main.h mkgets.sh song.c song.h types.h ui_about_dialog.c ui_about_dialog.h ui_callbacks.c ui_callbacks.h ui_equalizer.c ui_equalizer.h ui_main.c ui_main.h ui_playlist.c ui_playlist.h ui_prefswin.c ui_prefswin.h ui_util.c ui_util.h util.c util.h xml_document.c xml_document.h Log Message: Readded src/ tree, updated icons and images --- NEW FILE: ui_playlist.c --- #include <string.h> #include <stdlib.h> #include <glib/gi18n.h> #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <glade/glade.h> #include <main.h> #include <bmp_ui.h> #include <dnd.h> #include <ui_main.h> #include <ui_playlist.h> #include <ui_util.h> /* bmp_dock.c/bmp_dock.h (C) 1998-2003 XMMS.org, (C) 2004-2005 BMP DT */ #include <bmp_dock.h> #include <bmp_window.h> [...2155 lines suppressed...] "signal::row_activated", G_CALLBACK(on_playlist_playlists_row_activated), bmp_play, NULL); g_object_connect (G_OBJECT(chroma_widgets[BMP_CHROMA_LIST_TRACKLIST]->widget), "signal::changed", G_CALLBACK(on_playlist_tracklist_changed), self, "signal::row_activated", G_CALLBACK(on_playlist_tracklist_row_activated), bmp_play, NULL); /* Initialize Actions (indirectly) */ chroma_list_emit_changed(CHROMA_LIST(chroma_widgets[BMP_CHROMA_LIST_PLAYLISTS]->widget)); chroma_list_emit_changed(CHROMA_LIST(chroma_widgets[BMP_CHROMA_LIST_TRACKLIST]->widget)); return self; } --- NEW FILE: ui_playlist.h --- #ifndef UI_PLAYLIST_H #define UI_PLAYLIST_H #include <glib-object.h> #define BMP_TYPE_WINDOW_PLAYLIST (bmp_window_playlist_get_type ()) #define BMP_WINDOW_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BMP_TYPE_WINDOW_PLAYLIST, BmpWindowPlaylist)) #define BMP_WINDOW_PLAYLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BMP_TYPE_WINDOW_PLAYLIST, BmpWindowPlaylistClass)) #define BMP_IS_WINDOW_PLAYLIST(obj) (GTK_CHECK_TYPE ((obj), BMP_TYPE_WINDOW_PLAYLIST)) #define BMP_IS_WINDOW_PLAYLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BMP_TYPE_WINDOW_PLAYLIST)) #define BMP_WINDOW_PLAYLIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BMP_TYPE_WINDOW_PLAYLIST, BmpWindowPlaylistClass)) typedef struct _BmpWindowPlaylist BmpWindowPlaylist; typedef struct _BmpWindowPlaylistClass BmpWindowPlaylistClass; typedef struct _BmpWindowPlaylistPrivate BmpWindowPlaylistPrivate; struct _BmpWindowPlaylist { GObject parent; BmpWindowPlaylistPrivate *private; GtkWidget *window; }; struct _BmpWindowPlaylistClass { GObjectClass parent; }; GType bmp_window_playlist_get_type (void); BmpWindowPlaylist* bmp_window_playlist_new (void); void bmp_window_playlist_finalize_init (BmpWindowPlaylist *self); void bmp_window_playlist_configure(BmpWindowPlaylist *window_playlist); /* FIXME: Make this properties */ void bmp_window_playlist_set_font(BmpWindowPlaylist *window_playlist, const gchar * font); gint bmp_window_playlist_get_vsep_width (BmpWindowPlaylist *window_main); void bmp_window_playlist_resize_widgets (BmpWindowPlaylist *self); #endif /* UI_PLAYLIST_H */ --- NEW FILE: bmp_resource_manager.c --- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ #include <gtk/gtk.h> #include <bmp_resource_manager.h> G_DEFINE_TYPE(BmpResourceManager, bmp_resource_manager, G_TYPE_OBJECT) #if 0 typedef enum { BMP_RESOURCE_MANAGER_N_SIGNALS } BmpResourceManagerSignals; static guint bmp_resource_manager_signals[BMP_RESOURCE_MANAGER_N_SIGNALS] = {}; #endif typedef enum { BMP_RESOURCE_MANAGER_N_PROPERTIES } BmpResourceManagerProperties; struct _BmpResourceManagerPrivate { gboolean dispose_has_run; GHashTable *root; }; static void free_resource_item (BmpResource *item) { } static GHashTable* get_path (BmpResourceManager *self, const gchar *path) { BmpResource *resource; GHashTable *ht_path; gchar **path_elements, **_path_elements; g_return_val_if_fail (BMP_IS_RESOURCE_MANAGER(self), NULL); ht_path = self->private->root; if (! path) return ht_path; path_elements = g_strsplit (path, RM_PATH_DELIMITER_S, -1); if (! path_elements) return NULL; _path_elements = path_elements; while (*path_elements) { resource = g_hash_table_lookup (ht_path, *path_elements); if (! resource) { g_strfreev(_path_elements); return NULL; } else { ht_path = resource->value; path_elements++; } } return ht_path; } static BmpResource* get_item (BmpResourceManager *self, const gchar *path, const gchar *item_name) { GHashTable *ht_path; ht_path = get_path (self, path); return g_hash_table_lookup (ht_path, item_name); } static void create_new_node_path (BmpResourceManager *self, const gchar *path, const gchar *name) { GHashTable *ht, *ht_path; BmpResource *item; item = g_new0(BmpResource,1); ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_resource_item); item->type = BMP_RESOURCE_BRANCH; item->name = g_strdup(name); item->destroy = NULL; item->lock = NULL; item->value = ht; ht_path = get_path (self, path); if (! ht_path) { free_resource_item (item); return; } g_hash_table_insert (ht_path, name, item); } static void create_new_node_item (BmpResourceManager *self, const gchar *path, const gchar *name, gpointer value, GDestroyNotify destroy) { GHashTable *ht_path; BmpResource *item; item = g_new0(BmpResource,1); item->type = BMP_RESOURCE_DATA; item->name = g_strdup(name); item->destroy = destroy; item->lock = g_mutex_new(); item->value = value; ht_path = get_path (self, path); if (! ht_path) { free_resource_item (item); return; } g_hash_table_insert (ht_path, name, item); } /* Public API */ gboolean bmp_resource_manager_create_path (BmpResourceManager *self, const gchar *parent_path, const gchar *path) { create_new_node_path (self, parent_path, path); return TRUE; } gboolean bmp_resource_manager_append_item (BmpResourceManager *self, const gchar *path, const gchar *name, gpointer item_value, GDestroyNotify item_value_destroy) { create_new_node_item (self, path, name, item_value, item_value_destroy); return TRUE; } gpointer bmp_resource_manager_get_item (BmpResourceManager *self, const gchar *path, const gchar *name) { BmpResource *item; item = get_item (self, path, name); if (! item) return NULL; return item->value; } gpointer bmp_resource_manager_get_item_locked (BmpResourceManager *self, const gchar *path, const gchar *name) { BmpResource *item; item = get_item (self, path, name); if (! item) return NULL; g_mutex_lock (item->lock); return item->value; } void bmp_resource_manager_unlock_item (BmpResourceManager *self, const gchar *path, const gchar *name) { BmpResource *item; item = get_item (self, path, name); if (! item) return NULL; g_mutex_unlock (item->lock); } /* GObject */ static void bmp_resource_manager_init (BmpResourceManager *self) { self->private = g_new (BmpResourceManagerPrivate, 1); self->private->dispose_has_run = FALSE; self->private->root = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void bmp_resource_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { default: /* We don't have any other property... */ g_assert (FALSE); break; } } static void bmp_resource_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { default: /* We don't have any other property... */ g_assert (FALSE); break; } } static GObject * bmp_resource_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *obj; { /* Invoke parent constructor. */ BmpResourceManagerClass *klass; GObjectClass *parent_class; klass = BMP_RESOURCE_MANAGER_CLASS (g_type_class_peek (BMP_TYPE_RESOURCE_MANAGER)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); obj = parent_class->constructor (type, n_construct_properties, construct_properties); } /* do stuff. */ return obj; } static void bmp_resource_manager_dispose (GObject *obj) { BmpResourceManager *self = (BmpResourceManager *)obj; if (self->private->dispose_has_run) { /* If dispose did already run, return. */ return; } /* Make sure dispose does not run twice. */ self->private->dispose_has_run = TRUE; /* * In dispose, you are supposed to free all types referenced from this * object which might themselves hold a reference to self. Generally, * the most simple solution is to unref all members on which you own a * reference. */ } static void bmp_resource_manager_finalize (GObject *obj) { BmpResourceManager *self = (BmpResourceManager *)obj; /* * Here, complete object destruction. * You might not need to do much... */ g_free (self->private); } BmpResourceManager* bmp_resource_manager_new (void) { BmpResourceManager *rm; rm = g_object_new (bmp_resource_manager_get_type (), NULL); return rm; } static void bmp_resource_manager_class_init (BmpResourceManagerClass *g_class) { GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); gobject_class->set_property = bmp_resource_manager_set_property; gobject_class->get_property = bmp_resource_manager_get_property; gobject_class->dispose = bmp_resource_manager_dispose; gobject_class->finalize = bmp_resource_manager_finalize; gobject_class->constructor = bmp_resource_manager_constructor; } --- NEW FILE: gtkhsv.c --- /* HSV color selector for GTK+ * * Copyright (C) 1999 The Free Software Foundation * * Authors: Simon Budig <Sim...@un...> (original code) * Federico Mena-Quintero <fed...@gi...> (cleanup for GTK+) * Jonathan Blandford <jr...@re...> (cleanup for GTK+) * * 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 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 [...1749 lines suppressed...] gint8 *dash_list; focus_gc = gdk_gc_new (widget->window); gdk_gc_copy (focus_gc, widget->style->fg_gc[GTK_WIDGET_STATE (widget)]); gtk_widget_style_get (widget, "focus-line-width", line_width, "focus-line-pattern", (gchar *)&dash_list, NULL); gdk_gc_set_line_attributes (focus_gc, *line_width, dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); if (dash_list[0]) gdk_gc_set_dashes (focus_gc, 0, dash_list, strlen ((const gchar*)dash_list)); g_free (dash_list); return focus_gc; } --- NEW FILE: bmp_configuration.c --- #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <signal.h> #include <getopt.h> #include <pthread.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <glib.h> #include <glib-object.h> #include <glib/gstdio.h> #include <gtk/gtk.h> #include <libxml/tree.h> [...970 lines suppressed...] g_value_init (&value, G_TYPE_INT); g_value_set_int (&value, value_arg); bmp_configuration_key_set (configuration, domain_id, key_id, &value, TRUE); } void bmp_configuration_key_set_string (BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, gchar *value_arg) { GValue value = {0,}; g_value_init (&value, G_TYPE_STRING); g_value_set_string (&value, value_arg); bmp_configuration_key_set (configuration, domain_id, key_id, &value, TRUE); } --- NEW FILE: bmp_play.gst.h --- #ifndef _BMP_PLAY_H #define _BMP_PLAY_H #include <glib-object.h> #include <gst/gst.h> #define BMP_TYPE_PLAY (bmp_play_get_type ()) #define PLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BMP_TYPE_PLAY, BmpPlay)) #define PLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BMP_TYPE_PLAY, BmpPlayClass)) #define BMP_IS_PLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BMP_TYPE_PLAY)) #define BMP_IS_PLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BMP_TYPE_PLAY)) #define PLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BMP_TYPE_PLAY, BmpPlayClass)) typedef struct _BmpPlay BmpPlay; typedef struct _BmpPlayClass BmpPlayClass; typedef struct _BmpPlayPrivate BmpPlayPrivate; struct _BmpPlay { GObject parent; /* * instance members */ BmpPlayPrivate *private; }; struct _BmpPlayClass { GObjectClass parent; void (*eos) (BmpPlay * self); void (*error) (BmpPlay * self); void (*buffer) (BmpPlay * self); void (*no_sound) (BmpPlay * self); }; typedef enum { PLAYSTATUS_STOPPED = 1 << 1, PLAYSTATUS_PLAYING = 1 << 2, PLAYSTATUS_PAUSED = 1 << 3, PLAYSTATUS_SEEKING = 1 << 4, PLAYSTATUS_WAITING = 1 << 5 } BmpPlaybackstatus; /* * used by BMP_TYPE_PLAY */ GType bmp_play_get_type(void); /* * API */ BmpPlay* bmp_play_new(void); gboolean bmp_play_prepare(BmpPlay * self); gboolean bmp_play_set_stream(BmpPlay * self, const gchar * uri); gboolean bmp_play_ready(BmpPlay * self); gboolean bmp_play_change_stream(BmpPlay * self, const gchar * uri); gboolean bmp_play_play_stream(BmpPlay * self); gboolean bmp_play_pause_stream(BmpPlay * self); gboolean bmp_play_stop_stream (BmpPlay * play); gboolean bmp_play_seek_stream(BmpPlay * self, gint offset); gint bmp_play_get_time(BmpPlay * self); gint bmp_play_get_length(BmpPlay * self); GstElementState bmp_play_get_element_state(BmpPlay * self); void bmp_play_set_volume(BmpPlay * self, gdouble volume); void bmp_play_probe_outsinks(BmpPlay * play); #endif /* PLAY_H */ --- NEW FILE: bmp_rel.c --- /* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * 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 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, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Modified by the GLib Team and others 1997-2000. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with * GLib at ftp://ftp.gtk.org/pub/gtk/. */ /* * MT safe */ #include <stdarg.h> #include <string.h> #include <glib.h> #include <bmp_rel.h> typedef struct _GRealTuples GRealTuples; struct _BmpRelation { gint fields; gint current_field; GHashTable *all_tuples; GHashTable **hashed_tuple_tables; GMemChunk *tuple_chunk; gint count; }; struct _GRealTuples { gint len; gint width; gpointer *data; }; static gboolean tuple_equal_2 (gconstpointer v_a, gconstpointer v_b) { gpointer* a = (gpointer*) v_a; gpointer* b = (gpointer*) v_b; return a[0] == b[0] && a[1] == b[1]; } static guint tuple_hash_2 (gconstpointer v_a) { gpointer* a = (gpointer*) v_a; return (gulong)a[0] ^ (gulong)a[1]; } static GHashFunc tuple_hash (gint fields) { switch (fields) { case 2: return tuple_hash_2; default: g_error ("no tuple hash for %d", fields); } return NULL; } static GEqualFunc tuple_equal (gint fields) { switch (fields) { case 2: return tuple_equal_2; default: g_error ("no tuple equal for %d", fields); } return NULL; } BmpRelation* bmp_relation_new (gint fields) { BmpRelation* rel = g_new0 (BmpRelation, 1); rel->fields = fields; rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk", fields * sizeof (gpointer), fields * sizeof (gpointer) * 128, G_ALLOC_AND_FREE); rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields)); rel->hashed_tuple_tables = g_new0 (GHashTable*, fields); return rel; } static void bmp_relation_free_array (gpointer key, gpointer value, gpointer user_data) { g_hash_table_destroy ((GHashTable*) value); } void bmp_relation_destroy (BmpRelation *relation) { gint i; if (relation) { g_hash_table_destroy (relation->all_tuples); g_mem_chunk_destroy (relation->tuple_chunk); for (i = 0; i < relation->fields; i += 1) { if (relation->hashed_tuple_tables[i]) { g_hash_table_foreach (relation->hashed_tuple_tables[i], bmp_relation_free_array, NULL); g_hash_table_destroy (relation->hashed_tuple_tables[i]); } } g_free (relation->hashed_tuple_tables); g_free (relation); } } void bmp_relation_index (BmpRelation *relation, gint field, GHashFunc hash_func, GEqualFunc key_equal_func) { g_return_if_fail (relation != NULL); g_return_if_fail (relation->count == 0 && relation->hashed_tuple_tables[field] == NULL); relation->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_equal_func); } void bmp_relation_insert (BmpRelation *relation, ...) { gpointer* tuple = g_chunk_new (gpointer, relation->tuple_chunk); va_list args; gint i; va_start(args, relation); for (i = 0; i < relation->fields; i += 1) tuple[i] = va_arg(args, gpointer); va_end(args); g_hash_table_insert (relation->all_tuples, tuple, tuple); relation->count += 1; for (i = 0; i < relation->fields; i += 1) { GHashTable *table; gpointer key; GHashTable *per_key_table; table = relation->hashed_tuple_tables[i]; if (table == NULL) continue; key = tuple[i]; per_key_table = g_hash_table_lookup (table, key); if (per_key_table == NULL) { per_key_table = g_hash_table_new (tuple_hash (relation->fields), tuple_equal (relation->fields)); g_hash_table_insert (table, key, per_key_table); } g_hash_table_insert (per_key_table, tuple, tuple); } } static void bmp_relation_delete_tuple (gpointer tuple_key, gpointer tuple_value, gpointer user_data) { gpointer *tuple = (gpointer*) tuple_value; BmpRelation *rel = (BmpRelation *) user_data; gint j; g_assert (tuple_key == tuple_value); for (j = 0; j < rel->fields; j += 1) { GHashTable *one_table = rel->hashed_tuple_tables[j]; gpointer one_key; GHashTable *per_key_table; if (one_table == NULL) continue; if (j == rel->current_field) /* can't delete from the table we're foreaching in */ continue; one_key = tuple[j]; per_key_table = g_hash_table_lookup (one_table, one_key); g_hash_table_remove (per_key_table, tuple); } g_hash_table_remove (rel->all_tuples, tuple); rel->count -= 1; } gint bmp_relation_delete (BmpRelation *relation, gconstpointer key, gint field) { GHashTable *table = relation->hashed_tuple_tables[field]; GHashTable *key_table; gint count = relation->count; g_return_val_if_fail (relation != NULL, 0); g_return_val_if_fail (table != NULL, 0); key_table = g_hash_table_lookup (table, key); if (!key_table) return 0; relation->current_field = field; g_hash_table_foreach (key_table, bmp_relation_delete_tuple, relation); g_hash_table_remove (table, key); g_hash_table_destroy (key_table); /* @@@ FIXME: Remove empty hash tables. */ return count - relation->count; } static void bmp_relation_select_tuple (gpointer tuple_key, gpointer tuple_value, gpointer user_data) { gpointer *tuple = (gpointer*) tuple_value; GRealTuples *tuples = (GRealTuples*) user_data; gint stride = sizeof (gpointer) * tuples->width; g_assert (tuple_key == tuple_value); memcpy (tuples->data + (tuples->len * tuples->width), tuple, stride); tuples->len += 1; } BmpTuples* bmp_relation_select (BmpRelation *relation, gconstpointer key, gint field) { GHashTable *table = relation->hashed_tuple_tables[field]; GHashTable *key_table; GRealTuples *tuples = g_new0 (GRealTuples, 1); gint count; g_return_val_if_fail (relation != NULL, NULL); g_return_val_if_fail (table != NULL, NULL); key_table = g_hash_table_lookup (table, key); if (!key_table) return (BmpTuples*)tuples; count = bmp_relation_count (relation, key, field); tuples->data = g_malloc (sizeof (gpointer) * relation->fields * count); tuples->width = relation->fields; g_hash_table_foreach (key_table, bmp_relation_select_tuple, tuples); g_assert (count == tuples->len); return (BmpTuples*)tuples; } typedef struct _RelationSelectData RelationSelectData; struct _RelationSelectData { GList *tables; gpointer key; gint count; GCompareDataFunc compare_data_func; gpointer compare_user_data; }; static void relation_select_custom (gpointer key, gpointer value, RelationSelectData *select_data) { if (select_data->compare_data_func (key, select_data->key, select_data->compare_user_data)) { select_data->tables = g_list_append (select_data->tables, value); select_data->count += g_hash_table_size (value); } } BmpTuples* bmp_relation_select_custom (BmpRelation *relation, gconstpointer key, gint field, GCompareDataFunc compare_data_func, gpointer user_data) { GHashTable *table = relation->hashed_tuple_tables[field]; GHashTable *key_table; GRealTuples *tuples = g_new0 (GRealTuples, 1); RelationSelectData *select_data = g_new0(RelationSelectData, 1); gint count; g_return_val_if_fail (relation != NULL, NULL); g_return_val_if_fail (table != NULL, NULL); select_data->tables = NULL; select_data->key = key; select_data->count = 0; select_data->compare_user_data = user_data; select_data->compare_data_func = compare_data_func; g_hash_table_foreach (table, relation_select_custom, select_data); if (! select_data->tables) return (BmpTuples*)tuples; count = select_data->count; tuples->data = g_malloc (sizeof (gpointer) * relation->fields * count); tuples->width = relation->fields; while (select_data->tables) { g_hash_table_foreach (select_data->tables->data, bmp_relation_select_tuple, tuples); select_data->tables = g_list_next (select_data->tables); } g_assert (count == tuples->len); return (BmpTuples*)tuples; } gint bmp_relation_count (BmpRelation *relation, gconstpointer key, gint field) { GHashTable *table = relation->hashed_tuple_tables[field]; GHashTable *key_table; g_return_val_if_fail (relation != NULL, 0); g_return_val_if_fail (table != NULL, 0); key_table = g_hash_table_lookup (table, key); if (!key_table) return 0; return g_hash_table_size (key_table); } gboolean bmp_relation_exists (BmpRelation *relation, ...) { gpointer* tuple = g_chunk_new (gpointer, relation->tuple_chunk); va_list args; gint i; gboolean result; va_start(args, relation); for (i = 0; i < relation->fields; i += 1) tuple[i] = va_arg(args, gpointer); va_end(args); result = g_hash_table_lookup (relation->all_tuples, tuple) != NULL; g_mem_chunk_free (relation->tuple_chunk, tuple); return result; } void bmp_tuples_destroy (BmpTuples *tuples0) { GRealTuples *tuples = (GRealTuples*) tuples0; if (tuples) { g_free (tuples->data); g_free (tuples); } } gpointer bmp_tuples_index (BmpTuples *tuples0, gint index, gint field) { GRealTuples *tuples = (GRealTuples*) tuples0; g_return_val_if_fail (tuples0 != NULL, NULL); g_return_val_if_fail (field < tuples->width, NULL); return tuples->data[index * tuples->width + field]; } /* Print */ static void bmp_relation_print_one (gpointer tuple_key, gpointer tuple_value, gpointer user_data) { gint i; GString *gstring; BmpRelation* rel = (BmpRelation*) user_data; gpointer* tuples = (gpointer*) tuple_value; gstring = g_string_new ("["); for (i = 0; i < rel->fields; i += 1) { g_string_append_printf (gstring, "%p", tuples[i]); if (i < (rel->fields - 1)) g_string_append (gstring, ","); } g_string_append (gstring, "]"); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, gstring->str); g_string_free (gstring, TRUE); } static void bmp_relation_print_index (gpointer tuple_key, gpointer tuple_value, gpointer user_data) { BmpRelation* rel = (BmpRelation*) user_data; GHashTable* table = (GHashTable*) tuple_value; g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** key %p", tuple_key); g_hash_table_foreach (table, bmp_relation_print_one, rel); } void bmp_relation_print (BmpRelation *relation) { gint i; g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** all tuples (%d)", relation->count); g_hash_table_foreach (relation->all_tuples, bmp_relation_print_one, relation); for (i = 0; i < relation->fields; i += 1) { if (relation->hashed_tuple_tables[i] == NULL) continue; g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "*** index %d", i); g_hash_table_foreach (relation->hashed_tuple_tables[i], bmp_relation_print_index, relation); } } --- NEW FILE: bmp_play.gst.c --- #include <string.h> #include <assert.h> #include <signal.h> #include <getopt.h> #include <pthread.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <unistd.h> #include <glib.h> #include <glib-object.h> #include <bmp_play.h> #include <config.h> #ifdef HAVE_GST #include <gst/gst.h> G_DEFINE_TYPE (BmpPlay, bmp_play, G_TYPE_OBJECT) enum { BMP_PLAY_SIGNAL_EOS, BMP_PLAY_SIGNAL_ERROR, BMP_PLAY_SIGNAL_BUFFER, BMP_PLAY_SIGNAL_NO_SOUND_OUTPUT, BMP_PLAY_N_SIGNALS }; static guint signals[BMP_PLAY_N_SIGNALS] = { 0, 0, 0, 0 }; enum { BMP_PLAY_PROP_STREAM = 1, BMP_PLAY_PROP_PLAYSTATUS = 2, BMP_PLAY_N_PROPS }; struct _BmpPlayPrivate { gboolean dispose_has_run; GstElement *playbin; GstElement *outsink; gchar *uri; gint playstatus; gdouble volume; }; static GObject *bmp_play_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties); static GstBusSyncReply bmp_play_bus_watch (GstBus *bus, GstMessage *message, BmpPlay *self); #if 0 void dn_caps_cb (GstElement * identity, GObject * obj, GParamSpec * pspec, gpointer data) { const GstCaps *caps; GstStructure *structure; gchar *s; gint chans = 0, rate = 0; g_return_if_fail (G_IS_OBJECT (obj)); if (!GST_IS_PAD (obj) || !GST_PAD_IS_SINK (GST_PAD (obj))) return; if (!gst_pad_is_negotiated (GST_PAD (obj))) return; caps = gst_pad_get_negotiated_caps (GST_PAD (obj)); s = gst_caps_to_string (caps); g_print ("Caps: %s\n", s); g_free (s); structure = gst_caps_get_structure (caps, 0); if (gst_structure_get_int (structure, "channels", &chans) && gst_structure_get_int (structure, "rate", &rate)) { g_print ("Format: %s\nChannels: %d\nRate: %d\n", gst_structure_get_name (structure), chans, rate); } } #endif void bmp_play_set_volume (BmpPlay * play, gdouble volume) { g_return_if_fail (BMP_IS_PLAY (play)); g_object_set (play->private->playbin, "volume", volume, NULL); } static void _playobjects_destroy (BmpPlay * play) { g_return_if_fail (BMP_IS_PLAY (play)); } static void _playobjects_create (BmpPlay *play) { play->private->playbin = gst_element_factory_make ("playbin", "playbin"); play->private->outsink = gst_element_factory_make ("alsasink", "alsasink"); g_object_set (G_OBJECT(play->private->outsink), "buffer-time", (gint64)50000, NULL); g_object_set (G_OBJECT(play->private->outsink), "latency-time", (gint64)500, NULL); g_object_set (G_OBJECT(play->private->playbin), "audio-sink", play->private->outsink, NULL); g_object_set (G_OBJECT(play->private->playbin), "play-timeout", (guint64)3000000000, NULL); gst_bus_set_sync_handler (gst_element_get_bus (GST_ELEMENT (play->private->playbin)), bmp_play_bus_watch, play); } #if 0 static gboolean bmp_play_eos_cb (BmpPlay * play, GstElement * element) { g_return_val_if_fail (BMP_IS_PLAY (play), FALSE); g_signal_emit (G_OBJECT (play), signals[BMP_PLAY_SIGNAL_EOS], g_quark_from_string (""), NULL); return FALSE; } #endif static void bmp_play_error_cb (BmpPlay * play, GstElement * arg1, GError * arg2, gchar * arg3, GstElement * element) { gchar *detail; if (!arg3) detail = g_strdup (""); else detail = g_strdup (arg3); g_signal_emit (G_OBJECT (play), signals[BMP_PLAY_SIGNAL_ERROR], g_quark_from_string (detail), arg2, NULL); g_idle_add ((GSourceFunc) _playobjects_destroy, play); } gboolean bmp_play_prepare (BmpPlay * play) { g_object_set (play->private->playbin, "uri", play->private->uri, 0); return TRUE; } gboolean bmp_play_stop_stream (BmpPlay * play) { g_return_val_if_fail (BMP_IS_PLAY (play), FALSE); gst_element_set_state (play->private->playbin, GST_STATE_READY); g_usleep(50000); return TRUE; } gboolean bmp_play_ready (BmpPlay * play) { g_return_val_if_fail (BMP_IS_PLAY (play), FALSE); gst_element_set_state (play->private->playbin, GST_STATE_READY); return TRUE; } gboolean bmp_play_play_stream (BmpPlay * play) { g_return_val_if_fail (BMP_IS_PLAY (play), FALSE); if (gst_element_set_state (play->private->playbin, GST_STATE_PLAYING) == GST_STATE_FAILURE) { gst_element_set_state (play->private->playbin, GST_STATE_READY); return FALSE; } return TRUE; } gboolean bmp_play_pause_stream (BmpPlay * play) { if (GST_STATE(play->private->playbin) == GST_STATE_PLAYING) return gst_element_set_state (play->private->playbin, GST_STATE_PAUSED); else if (GST_STATE(play->private->playbin) == GST_STATE_PAUSED) return gst_element_set_state (play->private->playbin, GST_STATE_PLAYING); } gboolean bmp_play_seek_stream (BmpPlay * play, gint offset) { GstEvent *event; GstFormat fmt = GST_FORMAT_TIME; guint64 s_offset; s_offset = offset * GST_SECOND; return gst_element_seek (play->private->playbin, 1.0, fmt, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, s_offset, GST_SEEK_TYPE_SET, s_offset); } GstElementState bmp_play_get_element_state (BmpPlay * play) { return GST_STATE (play->private->playbin); } gint bmp_play_get_time (BmpPlay * play) { GstQuery *query; GstFormat fmt = GST_FORMAT_TIME; gint64 time_in_nanoseconds, length_in_nanoseconds; gint time_in_seconds; if (!(GST_STATE (play->private->playbin) == GST_STATE_PLAYING)) return 0; query = gst_query_new_position(fmt); gst_element_query (play->private->playbin, query); gst_query_parse_position (query, &fmt, &time_in_nanoseconds, &length_in_nanoseconds); time_in_seconds = time_in_nanoseconds / 1000000000; return time_in_seconds; } gint bmp_play_get_length (BmpPlay * play) { GstQuery *query; GstFormat fmt = GST_FORMAT_TIME; gint64 time_in_nanoseconds, length_in_nanoseconds; gint time_in_seconds; if (!(GST_STATE (play->private->playbin) == GST_STATE_PLAYING)) return 0; query = gst_query_new_position(fmt); gst_element_query (play->private->playbin, query); gst_query_parse_position (query, &fmt, &time_in_nanoseconds, &length_in_nanoseconds); length_in_nanoseconds = length_in_nanoseconds / 1000000000; return length_in_nanoseconds; } static gboolean bmp_play_playstatus_notify_cb (BmpPlay * play) { gint status; g_return_val_if_fail (BMP_IS_PLAY (play), FALSE); g_object_get (play, "playstatus", &status, NULL); if (status & PLAYSTATUS_SEEKING) { bmp_play_pause_stream (play); return TRUE; } if (status & PLAYSTATUS_STOPPED) { bmp_play_stop_stream (play); return TRUE; } if (status & PLAYSTATUS_PAUSED) { bmp_play_pause_stream (play); return TRUE; } if (status & PLAYSTATUS_PLAYING) { bmp_play_play_stream (play); return TRUE; } return FALSE; } static void bmp_play_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { BmpPlay *play = (BmpPlay *) object; switch (property_id) { case BMP_PLAY_PROP_PLAYSTATUS: { gint status = g_value_get_int (value); play->private->playstatus = status; } break; case BMP_PLAY_PROP_STREAM: { gchar *stream_uri; if (play->private->uri) g_free (play->private->uri); stream_uri = g_value_dup_string (value); play->private->uri = g_strdup (stream_uri); g_object_set (play->private->playbin, "uri", play->private->uri, 0); } break; default: g_assert (FALSE); break; } } static void bmp_play_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { BmpPlay *play = (BmpPlay *) object; switch (property_id) { case BMP_PLAY_PROP_STREAM: { g_value_set_string (value, play->private->uri); } break; case BMP_PLAY_PROP_PLAYSTATUS: { g_value_set_int (value, play->private->playstatus); } break; default: /* * We don't have any other property... */ g_assert (FALSE); break; } } static void bmp_play_dispose (GObject * obj) { BmpPlay *play = (BmpPlay *) obj; if (play->private->dispose_has_run) { /* * If dispose did already run, return. */ return; } /* * Make sure dispose does not run twice. */ play->private->dispose_has_run = TRUE; /* * In dispose, you are supposed to free all types referenced from this * object which might themselves hold a reference to play. Generally, * the most simple solution is to unref all members on which you own a * reference. */ } static void bmp_play_finalize (GObject * obj) { BmpPlay *play = (BmpPlay *) obj; /* * Here, complete object destruction. * You might not need to do much... */ g_free (play->private); } static void bmp_play_class_init (BmpPlayClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GParamSpec *pspec; gobject_class->set_property = bmp_play_set_property; gobject_class->get_property = bmp_play_get_property; gobject_class->dispose = bmp_play_dispose; gobject_class->finalize = bmp_play_finalize; gobject_class->constructor = bmp_play_constructor; pspec = g_param_spec_string ("uri", "uri", "uri", "", G_PARAM_READWRITE); g_object_class_install_property (gobject_class, BMP_PLAY_PROP_STREAM, pspec); pspec = g_param_spec_int ("playstatus", "playstatus", "player playing status", 0, 128, 0, G_PARAM_READWRITE); g_object_class_install_property (gobject_class, BMP_PLAY_PROP_PLAYSTATUS, pspec); signals[BMP_PLAY_SIGNAL_BUFFER] = g_signal_new ("buffer", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET (BmpPlayClass, buffer), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[BMP_PLAY_SIGNAL_EOS] = g_signal_new ("eos", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET (BmpPlayClass, eos), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[BMP_PLAY_SIGNAL_ERROR] = g_signal_new ("error", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET (BmpPlayClass, error), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[BMP_PLAY_SIGNAL_NO_SOUND_OUTPUT] = g_signal_new ("no_sound", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET (BmpPlayClass, no_sound), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } BmpPlay * bmp_play_new (void) { BmpPlay *play; play = g_object_new (BMP_TYPE_PLAY, NULL); return play; } static GObject * bmp_play_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) { GObject *obj; { /* * Invoke parent constructor. */ BmpPlayClass *klass; GObjectClass *parent_class; klass = PLAY_CLASS (g_type_class_peek (BMP_TYPE_PLAY)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); obj = parent_class->constructor (type, n_construct_properties, construct_properties); } /* * do stuff. */ return obj; } static gboolean _idle_emit_eos (BmpPlay *play) { g_return_val_if_fail (BMP_IS_PLAY (play), FALSE); g_signal_emit (G_OBJECT (play), signals[BMP_PLAY_SIGNAL_EOS], 0, NULL); return FALSE; } #define MAX_RESET_RETRIES 1 static GstBusSyncReply bmp_play_bus_watch (GstBus *bus, GstMessage *message, BmpPlay *self) { GstElementState old_state, new_state; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_STATE_CHANGED: { gst_message_parse_state_changed(message, &old_state, &new_state); g_message("OLD_STATE: %d, NEW_STATE: %d", old_state, new_state); } break; case GST_MESSAGE_ERROR: case GST_MESSAGE_WARNING: { GError *err; gchar *debug; gst_message_parse_error (message, &err, &debug); g_print ("%s ERROR: %s\n", G_STRFUNC, err->message); g_error_free (err); g_free (debug); g_message("RESETTING Playbin"); #if 0 bmp_play_stop_stream (self); if (reset_ctr < MAX_RESET_RETRIES) { g_usleep (500000); bmp_play_play_stream (self); reset_ctr++; } else { #endif gchar *uri; g_object_get (G_OBJECT(self->private->playbin), "uri", &uri, NULL); gst_element_set_state (self->private->playbin, GST_STATE_NULL); _playobjects_create (self); g_object_set (self->private->playbin, "uri", uri, NULL); bmp_play_play_stream (self); #if 0 reset_ctr = 0; } #endif } break; case GST_MESSAGE_EOS: { /* end-of-stream */ g_message("STOP stream"); g_idle_add (_idle_emit_eos, self); } break; default: /* unhandled message */ break; } /* remove message from the queue */ return GST_BUS_DROP; } static void bmp_play_init (BmpPlay * play) { play->private = g_new (BmpPlayPrivate, 1); play->private->dispose_has_run = FALSE; play->private->uri = NULL; _playobjects_create (play); g_signal_connect (G_OBJECT (play), "notify::playstatus", G_CALLBACK (bmp_play_playstatus_notify_cb), NULL); } #endif --- NEW FILE: bmp_configuration.h --- #ifndef CONFIGURATION_H #define CONFIGURATION_H #include <glib-object.h> G_BEGIN_DECLS #define BMP_TYPE_CONFIGURATION (bmp_configuration_get_type ()) #define BMP_CONFIGURATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BMP_TYPE_CONFIGURATION, BmpConfiguration)) #define BMP_CONFIGURATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BMP_TYPE_CONFIGURATION, BmpConfigurationClass)) #define BMP_IS_CONFIGURATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BMP_TYPE_CONFIGURATION)) #define BMP_IS_CONFIGURATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BMP_TYPE_CONFIGURATION)) #define BMP_CONFIGURATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BMP_TYPE_CONFIGURATION, BmpConfigurationClass)) typedef struct _BmpConfiguration BmpConfiguration; typedef struct _BmpConfigurationClass BmpConfigurationClass; typedef struct _BmpConfigurationPrivate BmpConfigurationPrivate; struct _BmpConfiguration { GObject parent; BmpConfigurationPrivate *private; }; struct _BmpConfigurationClass { GObjectClass parent; void (*removed) (BmpConfiguration * configuration); void (*changed) (BmpConfiguration * configuration); void (*added) (BmpConfiguration * configuration); }; GType bmp_configuration_get_type(void); BmpConfiguration* bmp_configuration_new(void); gboolean bmp_configuration_save(BmpConfiguration * configuration); gboolean bmp_configuration_domain_new(BmpConfiguration * configuration, const gchar * domain_id); gboolean bmp_configuration_key_new(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, GValue * key_value); gboolean bmp_configuration_key_set(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, GValue * key_value, gboolean create); gboolean bmp_configuration_key_unset (BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, gboolean create); /* Simple API */ GHashTable* bmp_configuration_domain_fetch(BmpConfiguration *configuration, const gchar * domain_id); void bmp_configuration_ht_destroy(BmpConfiguration * configuration, GHashTable * ht); gchar* bmp_configuration_key_fetch(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id); gint bmp_configuration_key_fetch_int(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id); gboolean bmp_configuration_key_fetch_boolean(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id); void bmp_configuration_key_set_string (BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, gchar *value_arg); void bmp_configuration_key_set_int (BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, gint value_arg); void bmp_configuration_key_set_boolean (BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, gboolean value_arg); gboolean bmp_configuration_domain_exists(BmpConfiguration * configuration, const gchar * domain_id); gboolean bmp_configuration_domain_has_keys(BmpConfiguration * configuration, const gchar * domain_id); gboolean bmp_configuration_key_find(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, const gchar * key_value); /* Either key_id or key_value can be null, but of course not both */ gboolean bmp_configuration_remove_domain(BmpConfiguration * configuration, const gchar * domain_id); gboolean bmp_configuration_remove_key(BmpConfiguration * configuration, const gchar * domain_id, const gchar * key_id, const gchar * key_value); #define LOOKUP_OR_CREATE_DEFAULT(domain_id,key_id,default_value) \ if (!bmp_configuration_key_find (bmp_configuration, domain_id, key_id, NULL)) \ { \ bmp_configuration_key_set_string (bmp_configuration, domain_id, key_id, default_value); \ } #define LOOKUP_OR_CREATE_DEFAULT_INT(domain_id,key_id,default_value) \ if (!bmp_configuration_key_find (bmp_configuration, domain_id, key_id, NULL)) \ { \ bmp_configuration_key_set_int (bmp_configuration, domain_id, key_id, default_value); \ } #define LOOKUP_OR_CREATE_DEFAULT_BOOLEAN(domain_id,key_id,default_value) \ if (!bmp_configuration_key_find (bmp_configuration, domain_id, key_id, NULL)) \ { \ bmp_configuration_key_set_boolean (bmp_configuration, domain_id, key_id, default_value); \ } #endif /* CONFIGURATION_H */ --- NEW FILE: bmp_rel.h --- /* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * 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 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, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * Modified by the GLib Team and others 1997-2000. See the AUTHORS * file for a list of people on the GLib Team. See the ChangeLog * files for a list of changes. These files are distributed with * GLib at ftp://ftp.gtk.org/pub/gtk/. */ /* * Modified by M. Derezynski 2005 for BMP (http://beepmp.sf.net) */ #ifndef __BMP_REL_H__ #define __BMP_REL_H__ #include <glib/gtypes.h> G_BEGIN_DECLS typedef struct _BmpRelation BmpRelation; typedef struct _BmpTuples BmpTuples; struct _BmpTuples { guint len; }; /* BmpRelation * * Indexed Relations. Imagine a really simple table in a * database. Relations are not ordered. This data type is meant for * maintaining a N-way mapping. * * bmp_relation_new() creates a relation with FIELDS fields * * bmp_relation_destroy() frees all resources * bmp_tuples_destroy() frees the result of bmp_relation_select() * * bmp_relation_index() indexes relation FIELD with the provided * equality and hash functions. this must be done before any * calls to insert are made. * * bmp_relation_insert() inserts a new tuple. you are expected to * provide the right number of fields. * * bmp_relation_delete() deletes all relations with KEY in FIELD * bmp_relation_select() returns ... * bmp_relation_count() counts ... */ BmpRelation* bmp_relation_new (gint fields); void bmp_relation_destroy (BmpRelation *relation); void bmp_relation_index (BmpRelation *relation, gint field, GHashFunc hash_func, GEqualFunc key_equal_func); void bmp_relation_insert (BmpRelation *relation, ...); gint bmp_relation_delete (BmpRelation *relation, gconstpointer key, gint field); BmpTuples* bmp_relation_select (BmpRelation *relation, gconstpointer key, gint field); BmpTuples* bmp_relation_select_custom (BmpRelation *relation, gconstpointer key, gint field, GCompareDataFunc compare_data_func, gpointer user_data); gint bmp_relation_count (BmpRelation *relation, gconstpointer key, gint field); gboolean bmp_relation_exists (BmpRelation *relation, ...); void bmp_relation_print (BmpRelation *relation); void bmp_tuples_destroy (BmpTuples *tuples); gpointer bmp_tuples_index (BmpTuples *tuples, gint index_, gint field); G_END_DECLS #endif /* __BMP_REL_H__ */ --- NEW FILE: bmp_metadata.c --- #include <gtk/gtk.h> #include <taglib/tag_c.h> #include <main.h> #include <bmp_metadata.h> #include <bmp_rel.h> G_DEFINE_TYPE (BmpMetadataCache, bmp_metadata_cache, G_TYPE_OBJECT) struct _BmpMetadataCachePrivate { gboolean dispose_has_run; FILE *fh; gint ufid; GHashTable *ht_uri; GHashTable *ht_ufid; /* We hold a shallow-copy-based hash table for each metadatum */ GHashTable *ht_metadatum[BMP_TAG_NONE]; BmpRelation *database; }; struct _BmpTagDefine { gchar *title; gchar *id; BmpTagId tag_id; }; typedef struct _BmpTagDefine BmpTagDefine; /* We're using GST-style tag identifiers here */ static BmpTagDefine bmp_tag_defines[] = { {"Title", "title", BMP_TAG_TITLE}, {"Time", "time", BMP_TAG_TIME}, {"Track", "track-number", BMP_TAG_TRACK}, {"Rating", "rating", BMP_TAG_RATING}, {"Artist", "artist", BMP_TAG_ARTIST}, {"Album", "album", BMP_TAG_ALBUM}, {"Date", "date", BMP_TAG_DATE}, {"Genre", "genre", BMP_TAG_GENRE}, {"Comment", "comment", BMP_TAG_COMMENT}, {"Bitrate", "bitrate", BMP_TAG_BITRATE}, {"Location", "location", BMP_TAG_LOCATION} }; G_LOCK_DEFINE(METADATA); const gchar* bmp_metadata_get_id (BmpTagId tag_id) { return bmp_tag_defines[tag_id].id; } const gchar* bmp_metadata_get_title (BmpTagId tag_id) { return bmp_tag_defines[tag_id].title; } const gchar* bmp_metadata_get_field (GHashTable *metadata, BmpTagId tag_id) { return g_hash_table_lookup (metadata, bmp_metadata_get_id(tag_id)); } static void metadata_get_from_uri (GHashTable *metadata) { TagLib_File *file = NULL; TagLib_Tag *tag = NULL; TagLib_AudioProperties const *audio = NULL; gchar *artist, *album, *title, *track, *year, *genre, *comment, *ttime, *rating, *bitrate, *title_rep, *album_rep = NULL, *filename, *uri; uri = g_hash_table_lookup (metadata, "uri"); filename = g_filename_from_uri (uri, NULL, NULL); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_LOCATION), g_strdup(uri)); if (! filename) return; file = taglib_file_new (filename); if (file) { tag = taglib_file_tag (file); if (!tag) { g_message ("%s: no metadata", filename); taglib_file_free (file); return; } audio = taglib_file_audioproperties (file); track = g_strdup_printf ("%d", taglib_tag_track (tag)); year = g_strdup_printf ("%d", taglib_tag_year (tag)); artist = taglib_tag_artist (tag); album = taglib_tag_album (tag); title = taglib_tag_title (tag); genre = taglib_tag_genre (tag); comment = taglib_tag_comment (tag); ttime = g_strdup_printf ("%d", taglib_audioproperties_length (audio)); rating = g_strdup ("0"); bitrate = g_strdup_printf ("%d",taglib_audioproperties_bitrate (audio)); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_BITRATE), bitrate); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_RATING), rating); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_TIME), ttime); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_TRACK), track); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_ARTIST), g_strdup (artist)); if (strlen (title) == 0) { title_rep = g_path_get_basename (filename); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_TITLE), g_strdup (title_rep)); g_free (title_rep); } else { g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_TITLE), g_strdup (title)); } if (strlen (album) == 0) { gchar **path_frags; gint n = 0; path_frags = g_strsplit (filename, "/", -1); while (path_frags[n + 1]) { album_rep = path_frags[n++]; } g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_ALBUM), g_strdup (album_rep)); g_strfreev (path_frags); } else { g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_ALBUM), g_strdup (album)); } g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_GENRE), g_strdup (genre)); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_DATE), year); g_hash_table_insert (metadata, bmp_metadata_get_id (BMP_TAG_COMMENT), g_strdup (comment)); taglib_tag_free_strings (); taglib_file_free (file); } else { #ifdef HAVE_XINE bmp_play_get_metadata_xine (bmp_play, metadata, uri); #endif #ifdef HAVE_GST bmp_play_get_metadata_gst (bmp_play, filename); #endif } } GHashTable* bmp_metadata_get_from_uri (const gchar *uri) { GHashTable *metadata; return bmp_metadata_cache_get_metadata_for_uri (bmp_metadata_cache, uri); } typedef struct { gint start; gint end; BmpListType *list; } MetadataThreadTuple; static gpointer metadata_thread (MetadataThreadTuple *mtt) { BmpFileItem *item; GHashTable *metadata; gint n; for (n = mtt->start; n < mtt->end; n++) { item = g_list_nth(mtt->list->items, n)->data; if (item->metadata == NULL) { item->locked = TRUE; item->metadata = bmp_metadata_get_from_uri (item->uri); item->dirty = TRUE; item->locked = FALSE; } } g_thread_exit(NULL); } void bmp_metadata_get_for_files_threaded (BmpListType *list, gint start, gint end) { GThread *mt; GError *error = NULL; MetadataThreadTuple *mtt; if (!list) return; if (!list->items) return; mtt = g_new0(MetadataThreadTuple, 1); mtt->start = start; mtt->end = end; mtt->list = list; mt = g_thread_create (metadata_thread, mtt, TRUE, &error); } /* Media Cache functions */ static void bmp_metadata_cache_init (BmpMetadataCache *self) { gint n; self->private = g_new (BmpMetadataCachePrivate, 1); self->private->dispose_has_run = FALSE; self->private->ufid = -1; self->private->ht_uri = g_hash_table_new (g_str_hash, g_str_equal); self->private->ht_ufid = g_hash_table_new (g_direct_hash, g_direct_equal); for (n = 0; n < BMP_TAG_NONE; self->private->ht_metadatum[n++] = g_hash_table_new (g_str_hash, g_str_equal)); #if 0 self->private->database = bmp_relation_new (BMP_TAG_NONE); for (n = 0; n < BMP_TAG_NONE; n++) { bmp_relation_index (self->private->database, n, g_str_hash, g_str_equal); } #endif g_message("%s (INITIALIZED)", G_STRFUNC); } static void bmp_metadata_cache_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { default: g_ass... [truncated message content] |