filename | src/vmu/vmulist.c |
changeset | 1071:182cfe43c09e |
prev | 1035:e3093fd7d1da |
next | 1296:30ecee61f811 |
author | nkeynes |
date | Tue Feb 28 17:25:26 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Implement display output for the GLES2 case (no fixed function rendering) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
4 * VMU management - maintains a list of all known VMUs
5 *
6 * Copyright (c) 2009 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <string.h>
20 #include <stdlib.h>
21 #include <glib/glist.h>
22 #include <glib/gstrfuncs.h>
23 #include "vmulist.h"
24 #include "config.h"
26 DEFINE_HOOK(vmulist_change_hook, vmulist_change_hook_t);
28 typedef struct vmulist_entry {
29 const gchar *filename;
30 vmu_volume_t vol;
31 int attach_count;
32 } *vmulist_entry_t;
34 /**
35 * Doubly-linked list of vmulist_entry_t maintained in sorted order by display name.
36 * Could be augmented with a hashtable if it gets too long
37 */
38 static GList *vmu_list;
40 #define ENTRY(it) ((vmulist_entry_t)(it)->data)
41 #define VOLUME(it) (ENTRY(it)->vol)
42 #define DISPLAY_NAME(it) vmulist_display_name(ENTRY(it))
44 static const char *vmulist_display_name(vmulist_entry_t ent)
45 {
46 if( ent->filename == NULL ) {
47 return NULL;
48 }
49 const char *s = strrchr(ent->filename, '/' );
50 if( s == NULL || *(s+1) == '\0' ) {
51 return ent->filename;
52 } else {
53 return s+1;
54 }
55 }
57 static void vmulist_update_config( void )
58 {
59 GList *temp = NULL, *it;
61 for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
62 vmulist_entry_t entry = ENTRY(it);
63 temp = g_list_append( temp, (char *)entry->filename );
64 }
65 lxdream_set_global_config_list_value( CONFIG_VMU, temp );
66 g_list_free( temp );
67 }
69 static vmulist_entry_t vmulist_get_entry_by_name( const gchar *name )
70 {
71 GList *it;
72 for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
73 const gchar *vmu_name = DISPLAY_NAME(it);
74 if( name == NULL ? vmu_name == NULL : vmu_name != NULL && strcmp( vmu_name, name ) == 0 ) {
75 return ENTRY(it);
76 }
77 }
78 return NULL; // not found
79 }
81 static vmulist_entry_t vmulist_get_entry_by_filename( const gchar *name )
82 {
83 GList *it;
84 for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
85 const gchar *vmu_name = ENTRY(it)->filename;
86 if( name == NULL ? vmu_name == NULL : vmu_name != NULL && strcmp( vmu_name, name ) == 0 ) {
87 return ENTRY(it);
88 }
89 }
90 return NULL; // not found
91 }
93 static vmulist_entry_t vmulist_get_entry_by_volume( vmu_volume_t vol )
94 {
95 GList *it;
96 for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
97 if( VOLUME(it) == vol ) {
98 return ENTRY(it);
99 }
100 }
101 return NULL; // not found
102 }
104 static vmulist_entry_t vmulist_get_entry_by_index( unsigned int index )
105 {
106 return (vmulist_entry_t)g_list_nth_data(vmu_list,index);
107 }
109 static gint vmulist_display_name_compare( gconstpointer a, gconstpointer b )
110 {
111 const char *aname = vmulist_display_name((vmulist_entry_t)a);
112 const char *bname = vmulist_display_name((vmulist_entry_t)b);
113 if( aname == bname )
114 return 0;
115 if( aname == NULL )
116 return -1;
117 if( bname == NULL )
118 return 1;
119 return strcmp(aname,bname);
120 }
122 /**
123 * Add a new entry into the list, maintaining the sorted order.
124 * If the filename is already in the list, it is updated instead.
125 */
126 static vmulist_entry_t vmulist_add_entry( const gchar *filename, vmu_volume_t vol )
127 {
128 vmulist_entry_t entry = vmulist_get_entry_by_filename(filename);
129 if( entry == NULL ) {
130 entry = g_malloc( sizeof(struct vmulist_entry) );
131 entry->filename = g_strdup(filename);
132 entry->vol = vol;
133 vmu_list = g_list_insert_sorted(vmu_list, entry, vmulist_display_name_compare );
134 vmulist_update_config();
136 CALL_HOOKS( vmulist_change_hook, VMU_ADDED, g_list_index(vmu_list,entry) );
137 } else {
138 if( entry->vol != vol && entry->vol != NULL )
139 vmu_volume_destroy( entry->vol );
140 entry->vol = vol;
141 /* NOTE: at the moment this can't require a resort, but if we allow
142 * user-editable display names it will
143 */
144 }
145 entry->attach_count = 0;
147 return entry;
148 }
150 static void vmulist_remove_entry( vmulist_entry_t entry )
151 {
152 int idx = g_list_index(vmu_list, entry);
153 vmu_list = g_list_remove( vmu_list, entry );
154 g_free( (char *)entry->filename );
155 g_free( entry );
156 vmulist_update_config();
157 CALL_HOOKS( vmulist_change_hook, VMU_REMOVED, idx );
158 }
160 static unsigned int vmulist_get_index( vmulist_entry_t entry )
161 {
162 return g_list_index( vmu_list, entry );
163 }
165 int vmulist_add_vmu( const gchar *filename, vmu_volume_t vol )
166 {
167 vmulist_entry_t entry = vmulist_add_entry( filename, vol );
168 return vmulist_get_index(entry);
169 }
171 void vmulist_remove_vmu( vmu_volume_t vol )
172 {
173 vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
174 if( entry != NULL ) {
175 vmulist_remove_entry(entry);
176 }
177 }
179 const char *vmulist_get_name( unsigned int idx )
180 {
181 vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
182 if( entry != NULL ) {
183 return vmulist_display_name(entry);
184 }
185 return NULL;
186 }
188 const char *vmulist_get_filename( unsigned int idx )
189 {
190 vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
191 if( entry != NULL ) {
192 return entry->filename;
193 }
194 return NULL;
195 }
197 const char *vmulist_get_volume_name( vmu_volume_t vol )
198 {
199 vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
200 if( entry != NULL ) {
201 return entry->filename;
202 }
203 return NULL;
204 }
206 vmu_volume_t vmulist_get_vmu( unsigned int idx )
207 {
208 vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
209 if( entry != NULL ) {
210 if( entry->vol == NULL ) {
211 entry->vol = vmu_volume_load(entry->filename);
212 }
213 return entry->vol;
214 }
215 return NULL;
216 }
218 vmu_volume_t vmulist_get_vmu_by_name( const gchar *name )
219 {
220 vmulist_entry_t entry = vmulist_get_entry_by_name(name);
221 if( entry != NULL ) {
222 if( entry->vol == NULL ) {
223 entry->vol = vmu_volume_load(entry->filename);
224 }
225 return entry->vol;
226 }
227 return NULL;
228 }
230 vmu_volume_t vmulist_get_vmu_by_filename( const gchar *name )
231 {
232 vmulist_entry_t entry = vmulist_get_entry_by_filename(name);
233 if( entry != NULL ) {
234 if( entry->vol == NULL ) {
235 entry->vol = vmu_volume_load(entry->filename);
236 }
237 return entry->vol;
238 } else {
239 vmu_volume_t vol = vmu_volume_load( name );
240 vmulist_add_entry( name, vol );
241 return vol;
242 }
243 }
245 int vmulist_get_index_by_filename( const gchar *name )
246 {
247 vmulist_entry_t entry = vmulist_get_entry_by_filename(name);
248 if( entry != NULL ) {
249 return g_list_index( vmu_list, entry );
250 }
251 return -1;
252 }
255 int vmulist_create_vmu( const gchar *filename, gboolean create_only )
256 {
257 vmu_volume_t vol = vmu_volume_new_default(filename);
259 if( vmu_volume_save( filename, vol, create_only ) ) {
260 return vmulist_add_vmu( filename, vol );
261 } else {
262 vmu_volume_destroy(vol);
263 }
264 return -1;
265 }
267 gboolean vmulist_attach_vmu( vmu_volume_t vol, const gchar *where )
268 {
269 vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
270 if( entry == NULL ) {
271 return FALSE;
272 }
273 entry->attach_count++;
274 return TRUE;
275 }
277 void vmulist_detach_vmu( vmu_volume_t vol )
278 {
279 vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
280 if( entry != NULL && entry->attach_count > 0 ) {
281 entry->attach_count--;
282 }
283 }
285 unsigned int vmulist_get_size(void)
286 {
287 return g_list_length(vmu_list);
288 }
290 void vmulist_init( void )
291 {
292 GList *filenames = lxdream_get_global_config_list_value( CONFIG_VMU );
293 GList *ptr;
294 for( ptr = filenames; ptr != NULL; ptr = g_list_next(ptr) ) {
295 vmulist_add_entry( (gchar *)ptr->data, NULL );
296 g_free( ptr->data );
297 }
298 g_list_free( filenames );
299 }
301 void vmulist_save_all( void )
302 {
303 GList *it;
304 for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
305 vmulist_entry_t entry = ENTRY(it);
306 if( entry->vol != NULL && vmu_volume_is_dirty(entry->vol) ) {
307 vmu_volume_save(entry->filename, entry->vol, FALSE);
308 }
309 }
310 }
312 void vmulist_shutdown( void )
313 {
314 vmulist_save_all();
315 }
.