RSS

(root)/calliope : /src/base/musicsource.h (revision 452)

Line Revision Contents
1 17 /*  Calliope Music Player
2 185  *  Copyright 2005-09 Sam Thursfield <ssssam gmail.com>
3 17  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15 269  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 17  */
17 269
18 17 //
19 // Musicsource is the base class for library, filesource, cdsource etc. It could
20 // be thought of as the 'core' of calliope.
21 //
22 // Here is how the db code functions: see also entry & schema. Results & input
23 24 // is done in source_views of Entry objects. Each entry can reference other entries.
24 17 // FIXME: this won't be right soon with checkin & checkout
25 // Implementations differ in how they work; in Library your query returns a new
26 // tree representing the data you queried while CdSource and FileSource (and any
27 // other descendents of MusicSourceImporting) return the actual entry objects
28 // storted in the source. For this reason entries must not be read or written to
29 // outside the GDK thread unless you are sure they come from library or something.
30 //
31 // FIXME: this makes multithreading a whole lot less use, it would be nice to be
32 // able to copy entry trees or give them mutexes or something. Perhaps each
33 // source should have its own mutex to save blocking on gdk lock. Actually this
34 // is a pretty good idea !!
35 //
36 269 // Any query returns all the entries pointed to by the queried entry, but not
37 17 // those that point to it. For example, if you query a Recording object you will
38 // get its Composition, Artist and the composition's artist. You will not get
39 // any of the Files or the Tracks for that recording, which would need to be
40 // found using query_entry_children.
41 //
42 269 // Any queried entry should be unref'ed when done with.
43 17 //
44 24
45 // music_source_add_entry accepts a tree of entries to be added. This
46 17 // function checks if the entry exists in the db already and if not, adds it.
47 // The id field is totally ignored. Returns the new id of the entry. I know it
48 // would be more useful to return the entry itself but in the case of library
49 // for example, we could be passing an entry in an importing db to add-entry.
50 // This clearly can't be modified so library would have to create a brand new
51 // entry to return - which is pretty wasteful and its more efficient I think to
52 269 // just return the id and you have to query it if you still need the entry.
53 17 //
54
55 24 // MusicSourceView provides a GtkTreeModel interface on the database, with a completely
56 // customisable structure. This is how sorting, etc is provided.
57 //
58
59 17 #ifndef _MUSIC_SOURCE_H
60 #define _MUSIC_SOURCE_H
61
62 #include <glib-object.h>
63 24 //#include "conftool.h"
64 130 #include "debug.h"
65 17 #include "entry.h"
66
67 #define MUSIC_SOURCE_TYPE               (music_source_get_type ())
68 #define MUSIC_SOURCE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUSIC_SOURCE_TYPE, MusicSource))
69 #define MUSIC_SOURCE_CLASS(obj)         (G_TYPE_CHECK_CLASS_CAST ((obj), MUSIC_SOURCE_TYPE, MusicSourceClass))
70 #define IS_MUSIC_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUSIC_SOURCE_TYPE))
71 #define IS_MUSIC_SOURCE_CLASS(obj)      (G_TYPE_CHECK_CLASS_TYPE ((obj), MUSIC_SOURCE_TYPE))
72 #define MUSIC_SOURCE_GET_CLASS(inst)    (G_TYPE_INSTANCE_GET_CLASS ((inst), MUSIC_SOURCE_TYPE, MusicSourceClass))
73
74 24 typedef struct _MusicSourceView MusicSourceView;
75
76 17 typedef struct MusicSourcePrivate MusicSourcePrivate;
77 typedef struct {
78         GObject parent;
79         MusicSourcePrivate *priv;
80 269 } MusicSource;
81 17
82 215 #include "viewconfig.h"
83
84 17 typedef struct {
85         GObjectClass parent;
86         gboolean (*is_empty)(MusicSource *self);
87         gboolean (*get_loaded)(MusicSource *self);
88         char *(*get_summary)(MusicSource *self);
89
90 269         int (*get_n_entries)(MusicSource *self, EntryType type, int *highest_id, int *dead);
91         int (*get_group_id)(MusicSource *self, int recording_id);
92 17         gboolean (*is_valid_id)(MusicSource *self, EntryType type, int id);
93
94         Entry *(*query_entry)(MusicSource *self, EntryType type, int id);
95 92         GSList *(*query_relations)(MusicSource *self, EntryType local_type, int local_id, int relation_apid);
96 102         int (*query_n_relations)(MusicSource *musicsource, int local_id, EntryType foreign_type, int foreign_property_id, int limit);
97
98 17         GSList *(*query_entry_children)(MusicSource *self, int parent_id, EntryType child_entry_type, int child_property);
99         GSList *(*query_entry_children_ids)(MusicSource *self, int parent_id, EntryType child_entry_type, int child_property);
100         GSList *(*query_ids)(MusicSource *self, EntryType entry_type);
101         GSList *(*query_matching_except)(MusicSource *musicsource, Entry *entry, int ignored_property_absolute_id);
102 269
103 215         MusicSourceView *(*create_view)(MusicSource *source, ViewConfig *config);
104 17
105 451         void (*add_entry_internal)    (MusicSource *self, Entry *entry);
106 452         void (*update_entry_internal) (MusicSource *self, Entry *entry, int shadow_override_id,
107                                    void *shadow_override_value);
108 451         void (*remove_entry_internal) (MusicSource *self, EntryType type, int id);
109         void (*update_foreign_keys)   (MusicSource *self, Entry *from_entry, Entry *to_entry);
110
111 17         void (*begin_transaction)(MusicSource *self);
112         void (*end_transaction)(MusicSource *self);
113         void (*update_entry_property)(MusicSource *self, EntryType entry_type, int entry_id, int property_id, const void *value);
114         int (*add_entry)(MusicSource *self, Entry *entry);
115         void (*remove_entry)(MusicSource *self, EntryType type, int id);
116         Entry *(*checkout_entry)(MusicSource *self, EntryType type, int id);
117         void (*checkin_entry)(MusicSource *self, Entry *entry);
118 95         void (*flush)(MusicSource *self);
119 17         void (*wipe)(MusicSource *self);
120 206         void (*dump)(MusicSource *self, gboolean detailed);
121 17         void (*export_recordings)(MusicSource *self, GSList *recording_list, MusicSource *destination);
122 451
123         /* Internal functions */
124         int (*find_entry) (MusicSource *self, Entry *entry, Entry *caller);
125 17 } MusicSourceClass;
126
127 269 typedef enum {
128 17         MUSIC_SOURCE_SIGNAL_STATUS_CHANGED,
129 144         MUSIC_SOURCE_SIGNAL_BUSY,
130 269
131 17         MUSIC_SOURCE_SIGNAL_WIPED,
132         MUSIC_SOURCE_SIGNAL_COUNT
133 269 } MusicSourceSignal;
134 17
135 GType music_source_get_type(void) G_GNUC_CONST;
136
137 gboolean music_source_is_empty(MusicSource *self);
138 // FIXME: is this still necessary ??
139 gboolean music_source_get_loaded(MusicSource *self);
140 const char *music_source_get_title(MusicSource *self);
141 char *music_source_get_summary(MusicSource *self);
142
143 358 /* We can't use gsignal for the entry change notification because of the complex emission strategy
144  * it needs. This does take away the gsignal benefit of being cross-language, but also adds a lot
145  * of speed. Perhaps if being monolingual ever becomes a problem a two-stage emission process is the
146  * best answer where both C functions and glib closures can be connected. */
147 typedef void (*EntryNotifyFunc)(MusicSource *music_source, Entry *old_entry, Entry *new_entry,
148                                 void *user_data);
149 void music_source_connect_entry_notify (MusicSource *self, EntryType detail,
150                                         const gboolean watch_only, EntryNotifyFunc callback,
151                                         void *user_data);
152 393 void music_source_disconnect_entry_notify (MusicSource *self, EntryType detail, 
153                                            EntryNotifyFunc callback, void *user_data);
154 void music_source_connect_entry_notify_object (MusicSource *self, EntryType detail,
155                                                const gboolean watch_only, EntryNotifyFunc callback,
156                                                GObject *object);
157 358
158 17 // music_source_get_n_entries returns the number of a given type of entries.
159 // highest_id and n_dead reflect the way removal of entries works: because it is
160 // impractical to change entry id's during runtime if an entry is deleted it's
161 // id is simply marked as dead. Therefore if you want to refer to every entry by
162 // id or something like that (like how shuffle playorders work) don't be naive
163 269 // and just use the total number of entries (which = highest_id-n_dead)
164 17 //
165 269 int music_source_get_n_entries(MusicSource *self, EntryType type, int *highest_id, int *dead);
166 17
167 gboolean music_source_is_valid_id(MusicSource *source, EntryType type, int id);
168
169 130 #ifdef ENTRY_TRACK_REFERENCE_OWNERS
170 17         Entry *music_source_query_entry_tracking(MusicSource *source, EntryType type, int id, const char *owner_name, const char *file, int line_no);
171         GSList *music_source_query_entry_children_tracking(MusicSource *source, int parent_id, EntryType child_entry_type, int child_property, const char *owner_name, const char *file, int line_no);
172 92         GSList *music_source_query_relations_tracking(MusicSource *source, EntryType local_type, int local_id, int relation_apid, const char *owner_name, const char *file, int line_no);
173 17         GSList *music_source_query_matching_except_tracking(MusicSource *musicsource, Entry *entry, int ignored_property_absolute_id, const char *owner_name, const char *file, int line_no);
174         Entry *music_source_checkout_entry_tracking(MusicSource *self, EntryType type, int id, const char *owner_name, const char *file, int line_no);
175         void music_source_checkin_entry_tracking(MusicSource *self, Entry *entry, const char *owner_name, const char *file, int line_no);
176
177         #define music_source_query_entry(s, t, i, o)    music_source_query_entry_tracking(s, t, i, o, __FILE__, __LINE__)
178         #define music_source_query_entry_children(s, p, t, i, o)        music_source_query_entry_children_tracking(s, p, t, i, o, __FILE__, __LINE__)
179 93         #define music_source_query_relations(s, t, i, r, o)     music_source_query_relations_tracking(s, t, i, r, o, __FILE__, __LINE__)
180 17         #define music_source_query_matching_except(s, e, i, o)  music_source_query_matching_except_tracking(s, e, i, o, __FILE__, __LINE__)
181         #define music_source_checkout_entry(s, t, i, o) music_source_checkout_entry_tracking(s, t, i, o, __FILE__, __LINE__)
182         #define music_source_checkin_entry(s, e, o)     music_source_checkin_entry_tracking(s, e, o, __FILE__, __LINE__)
183 #else
184         Entry *music_source_query_entry_internal(MusicSource *source, EntryType type, int id);
185
186         // Returns list of Entry *
187 92         // FIXME: obsoleted by query_relations
188 17         GSList *music_source_query_entry_children_internal(MusicSource *source, int parent_id, EntryType child_entry_type, int child_property);
189
190 92         // Returns list of Entry *
191         GSList *music_source_query_relations_internal(MusicSource *self, EntryType local_type, int local_id, int relation_apid);
192
193 17         // Finds all entries that match the given one, with the exception of one
194         // property. Remember all children are checked in matching so for example
195 269         // you can find releases that match on everything but album artist. Will
196 17         // never return the given entry.
197 269         //
198 17         GSList *music_source_query_matching_except_internal(MusicSource *musicsource, Entry *entry, int ignored_property_absolute_id);
199
200         // music_source_checkout_entry & music_source_checkin_entry are for if you want
201         // to edit an entry a whole lot, like if you just read the tags from a file for
202 269         // example. checkout returns a source_view of entries similar to query_entry but these
203         // ones you can modify. Any entries in the source_view with id 0 will be added
204 17         // automatically during checkin. For examples of use see files.c or cdsource.
205 269         // !! Once an entry has been checked in you cannot use it !!!
206 17         // !! You will have to query it again !!!
207         //
208         Entry *music_source_checkout_entry_internal(MusicSource *self, EntryType type, int id);
209         void music_source_checkin_entry_internal(MusicSource *self, Entry *entry);
210 269
211 17         #define music_source_query_entry(s, t, i, o)    music_source_query_entry_internal(s, t, i)
212         #define music_source_query_entry_children(s, p, t, i, o)        music_source_query_entry_children_internal(s, p, t, i)
213 92         #define music_source_query_relations(s, t, i, r, o)             music_source_query_relations_internal(s, t, i, r)
214 269         #define music_source_query_matching_except(s, e, i, o)  music_source_query_matching_except_internal(s, e, i)
215 17         #define music_source_checkout_entry(s, t, i, o) music_source_checkout_entry_internal(s, t, i)
216         #define music_source_checkin_entry(s, e, o)             music_source_checkin_entry_internal(s, e)
217 #endif
218
219 24 // FIXME: how many of these query ones do we need now there is views ??
220
221 102 int music_source_query_n_relations(MusicSource *musicsource, int local_id, EntryType foreign_type, int foreign_property_id, int limit);
222
223 17 // Returns list of int
224 GSList *music_source_query_entry_children_ids(MusicSource *source, int parent_id, EntryType child_entry_type, int child_property);
225
226 // Returns list of int
227 GSList *music_source_query_ids(MusicSource *source, int entry_type);
228
229 215 MusicSourceView *music_source_create_view(MusicSource *source, ViewConfig *config);
230 24
231 269 // These only have an effect on the library. begin_transaction should be called before you make lots of writes to the database, and
232 17 // end_transaction should be called right after, otherwise it will go like 100x slower.
233 void music_source_begin_transaction(MusicSource *self);
234 void music_source_end_transaction(MusicSource *self);
235
236 int music_source_add_entry(MusicSource *self, Entry *entry);
237
238 // music_source_remove_entry deletes a specific entry by ID. 
239 // NOTE: it is important !! that you don't hold any references to related entries
240 // when you remove an entry - for example, if I remove the last track of an album
241 // its refcount will drop to 1 and it will be removed as well. Unless I still
242 // hold a reference somewhere else in which case it will hang around forever !!
243 // This applies to importing sources anyway.
244 // FIXME: I guess we should do something about this issue ?
245 void music_source_remove_entry(MusicSource *self, EntryType type, int id);
246
247 // music_source_update_entry_property changes one property of an entry. If lots
248 269 // of changes are being made checkin/checkout should be used instead to prevent
249 17 // emitting the same changed signals over and over again.
250 //
251 void music_source_update_entry_property(MusicSource *self, EntryType entry_type, int entry_id, int property_id, const void *value);
252
253 95 void music_source_flush(MusicSource *self);
254 17 void music_source_wipe(MusicSource *self);
255 void music_source_export_recordings(MusicSource *self, GSList *recording_list, MusicSource *destination);
256
257 #endif

Loggerhead is a web-based interface for Bazaar branches