Search
lxdream.org :: lxdream/src/vmu/vmulist.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/vmu/vmulist.c
changeset 1034:7044e01148f0
next1035:e3093fd7d1da
author nkeynes
date Wed Jun 24 02:41:12 2009 +0000 (11 years ago)
permissions -rw-r--r--
last change Add initial VMU support
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/vmu/vmulist.c Wed Jun 24 02:41:12 2009 +0000
1.3 @@ -0,0 +1,314 @@
1.4 +/**
1.5 + * $Id: vmulist.c 869 2008-09-08 07:56:33Z nkeynes $
1.6 + *
1.7 + * VMU management - maintains a list of all known VMUs
1.8 + *
1.9 + * Copyright (c) 2009 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include <string.h>
1.23 +#include <stdlib.h>
1.24 +#include <glib/glist.h>
1.25 +#include <glib/gstrfuncs.h>
1.26 +#include "vmulist.h"
1.27 +#include "config.h"
1.28 +
1.29 +DEFINE_HOOK(vmulist_change_hook, vmulist_change_hook_t);
1.30 +
1.31 +typedef struct vmulist_entry {
1.32 + const gchar *filename;
1.33 + vmu_volume_t vol;
1.34 + int attach_count;
1.35 +} *vmulist_entry_t;
1.36 +
1.37 +/**
1.38 + * Doubly-linked list of vmulist_entry_t maintained in sorted order by display name.
1.39 + * Could be augmented with a hashtable if it gets too long
1.40 + */
1.41 +static GList *vmu_list;
1.42 +
1.43 +#define ENTRY(it) ((vmulist_entry_t)(it)->data)
1.44 +#define VOLUME(it) (ENTRY(it)->vol)
1.45 +#define DISPLAY_NAME(it) vmulist_display_name(ENTRY(it))
1.46 +
1.47 +static const char *vmulist_display_name(vmulist_entry_t ent)
1.48 +{
1.49 + if( ent->filename == NULL ) {
1.50 + return NULL;
1.51 + }
1.52 + const char *s = strrchr(ent->filename, '/' );
1.53 + if( s == NULL || *(s+1) == '\0' ) {
1.54 + return ent->filename;
1.55 + } else {
1.56 + return s+1;
1.57 + }
1.58 +}
1.59 +
1.60 +static void vmulist_update_config( void )
1.61 +{
1.62 + GList *temp = NULL, *it;
1.63 +
1.64 + for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
1.65 + vmulist_entry_t entry = ENTRY(it);
1.66 + temp = g_list_append( temp, (char *)entry->filename );
1.67 + }
1.68 + lxdream_set_global_config_list_value( CONFIG_VMU, temp );
1.69 + g_list_free( temp );
1.70 +}
1.71 +
1.72 +static vmulist_entry_t vmulist_get_entry_by_name( const gchar *name )
1.73 +{
1.74 + GList *it;
1.75 + for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
1.76 + const gchar *vmu_name = DISPLAY_NAME(it);
1.77 + if( name == NULL ? vmu_name == NULL : vmu_name != NULL && strcmp( vmu_name, name ) == 0 ) {
1.78 + return ENTRY(it);
1.79 + }
1.80 + }
1.81 + return NULL; // not found
1.82 +}
1.83 +
1.84 +static vmulist_entry_t vmulist_get_entry_by_filename( const gchar *name )
1.85 +{
1.86 + GList *it;
1.87 + for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
1.88 + const gchar *vmu_name = ENTRY(it)->filename;
1.89 + if( name == NULL ? vmu_name == NULL : vmu_name != NULL && strcmp( vmu_name, name ) == 0 ) {
1.90 + return ENTRY(it);
1.91 + }
1.92 + }
1.93 + return NULL; // not found
1.94 +}
1.95 +
1.96 +static vmulist_entry_t vmulist_get_entry_by_volume( vmu_volume_t vol )
1.97 +{
1.98 + GList *it;
1.99 + for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
1.100 + if( VOLUME(it) == vol ) {
1.101 + return ENTRY(it);
1.102 + }
1.103 + }
1.104 + return NULL; // not found
1.105 +}
1.106 +
1.107 +static vmulist_entry_t vmulist_get_entry_by_index( unsigned int index )
1.108 +{
1.109 + return (vmulist_entry_t)g_list_nth_data(vmu_list,index);
1.110 +}
1.111 +
1.112 +static gint vmulist_display_name_compare( gconstpointer a, gconstpointer b )
1.113 +{
1.114 + const char *aname = vmulist_display_name((vmulist_entry_t)a);
1.115 + const char *bname = vmulist_display_name((vmulist_entry_t)b);
1.116 + if( aname == bname )
1.117 + return 0;
1.118 + if( aname == NULL )
1.119 + return -1;
1.120 + if( bname == NULL )
1.121 + return 1;
1.122 + return strcmp(aname,bname);
1.123 +}
1.124 +
1.125 +/**
1.126 + * Add a new entry into the list, maintaining the sorted order.
1.127 + * If the filename is already in the list, it is updated instead.
1.128 + */
1.129 +static vmulist_entry_t vmulist_add_entry( const gchar *filename, vmu_volume_t vol )
1.130 +{
1.131 + vmulist_entry_t entry = vmulist_get_entry_by_filename(filename);
1.132 + if( entry == NULL ) {
1.133 + entry = g_malloc( sizeof(struct vmulist_entry) );
1.134 + entry->filename = g_strdup(filename);
1.135 + entry->vol = vol;
1.136 + vmu_list = g_list_insert_sorted(vmu_list, entry, vmulist_display_name_compare );
1.137 + } else {
1.138 + if( entry->vol != vol && entry->vol != NULL )
1.139 + vmu_volume_destroy( entry->vol );
1.140 + entry->vol = vol;
1.141 + /* NOTE: at the moment this can't require a resort, but if we allow
1.142 + * user-editable display names it will
1.143 + */
1.144 + }
1.145 + entry->attach_count = 0;
1.146 +
1.147 + vmulist_update_config();
1.148 + CALL_HOOKS( vmulist_change_hook, VMU_ADDED, g_list_index(vmu_list,entry) );
1.149 + return entry;
1.150 +}
1.151 +
1.152 +static void vmulist_remove_entry( vmulist_entry_t entry )
1.153 +{
1.154 + int idx = g_list_index(vmu_list, entry);
1.155 + vmu_list = g_list_remove( vmu_list, entry );
1.156 + g_free( (char *)entry->filename );
1.157 + g_free( entry );
1.158 + vmulist_update_config();
1.159 + CALL_HOOKS( vmulist_change_hook, VMU_REMOVED, idx );
1.160 +}
1.161 +
1.162 +static unsigned int vmulist_get_index( vmulist_entry_t entry )
1.163 +{
1.164 + return g_list_index( vmu_list, entry );
1.165 +}
1.166 +
1.167 +int vmulist_add_vmu( const gchar *filename, vmu_volume_t vol )
1.168 +{
1.169 + vmulist_entry_t entry = vmulist_add_entry( filename, vol );
1.170 + return vmulist_get_index(entry);
1.171 +}
1.172 +
1.173 +void vmulist_remove_vmu( vmu_volume_t vol )
1.174 +{
1.175 + vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
1.176 + if( entry != NULL ) {
1.177 + vmulist_remove_entry(entry);
1.178 + }
1.179 +}
1.180 +
1.181 +const char *vmulist_get_name( unsigned int idx )
1.182 +{
1.183 + vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
1.184 + if( entry != NULL ) {
1.185 + return vmulist_display_name(entry);
1.186 + }
1.187 + return NULL;
1.188 +}
1.189 +
1.190 +const char *vmulist_get_filename( unsigned int idx )
1.191 +{
1.192 + vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
1.193 + if( entry != NULL ) {
1.194 + return entry->filename;
1.195 + }
1.196 + return NULL;
1.197 +}
1.198 +
1.199 +const char *vmulist_get_volume_name( vmu_volume_t vol )
1.200 +{
1.201 + vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
1.202 + if( entry != NULL ) {
1.203 + return entry->filename;
1.204 + }
1.205 + return NULL;
1.206 +}
1.207 +
1.208 +vmu_volume_t vmulist_get_vmu( unsigned int idx )
1.209 +{
1.210 + vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
1.211 + if( entry != NULL ) {
1.212 + if( entry->vol == NULL ) {
1.213 + entry->vol = vmu_volume_load(entry->filename);
1.214 + }
1.215 + return entry->vol;
1.216 + }
1.217 + return NULL;
1.218 +}
1.219 +
1.220 +vmu_volume_t vmulist_get_vmu_by_name( const gchar *name )
1.221 +{
1.222 + vmulist_entry_t entry = vmulist_get_entry_by_name(name);
1.223 + if( entry != NULL ) {
1.224 + if( entry->vol == NULL ) {
1.225 + entry->vol = vmu_volume_load(entry->filename);
1.226 + }
1.227 + return entry->vol;
1.228 + }
1.229 + return NULL;
1.230 +}
1.231 +
1.232 +vmu_volume_t vmulist_get_vmu_by_filename( const gchar *name )
1.233 +{
1.234 + vmulist_entry_t entry = vmulist_get_entry_by_filename(name);
1.235 + if( entry != NULL ) {
1.236 + if( entry->vol == NULL ) {
1.237 + entry->vol = vmu_volume_load(entry->filename);
1.238 + }
1.239 + return entry->vol;
1.240 + } else {
1.241 + vmu_volume_t vol = vmu_volume_load( name );
1.242 + vmulist_add_entry( name, vol );
1.243 + return vol;
1.244 + }
1.245 +}
1.246 +
1.247 +int vmulist_get_index_by_filename( const gchar *name )
1.248 +{
1.249 + vmulist_entry_t entry = vmulist_get_entry_by_filename(name);
1.250 + if( entry != NULL ) {
1.251 + return g_list_index( vmu_list, entry );
1.252 + }
1.253 + return -1;
1.254 +}
1.255 +
1.256 +
1.257 +int vmulist_create_vmu( const gchar *filename, gboolean create_only )
1.258 +{
1.259 + vmu_volume_t vol = vmu_volume_new_default(filename);
1.260 +
1.261 + if( vmu_volume_save( filename, vol, create_only ) ) {
1.262 + return vmulist_add_vmu( filename, vol );
1.263 + } else {
1.264 + vmu_volume_destroy(vol);
1.265 + }
1.266 + return -1;
1.267 +}
1.268 +
1.269 +gboolean vmulist_attach_vmu( vmu_volume_t vol, const gchar *where )
1.270 +{
1.271 + vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
1.272 + if( entry == NULL ) {
1.273 + return FALSE;
1.274 + }
1.275 + entry->attach_count++;
1.276 + return TRUE;
1.277 +}
1.278 +
1.279 +void vmulist_detach_vmu( vmu_volume_t vol )
1.280 +{
1.281 + vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
1.282 + if( entry != NULL && entry->attach_count > 0 ) {
1.283 + entry->attach_count--;
1.284 + }
1.285 +}
1.286 +
1.287 +unsigned int vmulist_get_size(void)
1.288 +{
1.289 + return g_list_length(vmu_list);
1.290 +}
1.291 +
1.292 +void vmulist_init( void )
1.293 +{
1.294 + GList *filenames = lxdream_get_global_config_list_value( CONFIG_VMU );
1.295 + GList *ptr;
1.296 + for( ptr = filenames; ptr != NULL; ptr = g_list_next(ptr) ) {
1.297 + vmulist_add_entry( (gchar *)ptr->data, NULL );
1.298 + g_free( ptr->data );
1.299 + }
1.300 + g_list_free( filenames );
1.301 +}
1.302 +
1.303 +void vmulist_save_all( void )
1.304 +{
1.305 + GList *it;
1.306 + for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
1.307 + vmulist_entry_t entry = ENTRY(it);
1.308 + if( entry->vol != NULL && vmu_volume_is_dirty(entry->vol) ) {
1.309 + vmu_volume_save(entry->filename, entry->vol, FALSE);
1.310 + }
1.311 + }
1.312 +}
1.313 +
1.314 +void vmulist_shutdown( void )
1.315 +{
1.316 + vmulist_save_all();
1.317 +}
.