Search
lxdream.org :: lxdream/src/vmu/vmulist.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/vmu/vmulist.c
changeset 1035:e3093fd7d1da
prev1034:7044e01148f0
next1071:182cfe43c09e
author nkeynes
date Wed Jun 24 05:10:25 2009 +0000 (11 years ago)
permissions -rw-r--r--
last change Set svn:keywords property on new files
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     } else {
   135         if( entry->vol != vol && entry->vol != NULL )
   136             vmu_volume_destroy( entry->vol );
   137         entry->vol = vol;
   138         /* NOTE: at the moment this can't require a resort, but if we allow
   139          * user-editable display names it will
   140          */ 
   141     }
   142     entry->attach_count = 0;
   144     vmulist_update_config();
   145     CALL_HOOKS( vmulist_change_hook, VMU_ADDED, g_list_index(vmu_list,entry) );
   146     return entry;
   147 }
   149 static void vmulist_remove_entry( vmulist_entry_t entry )
   150 {
   151     int idx = g_list_index(vmu_list, entry);
   152     vmu_list = g_list_remove( vmu_list, entry );
   153     g_free( (char *)entry->filename );
   154     g_free( entry );
   155     vmulist_update_config();
   156     CALL_HOOKS( vmulist_change_hook, VMU_REMOVED, idx );
   157 }
   159 static unsigned int vmulist_get_index( vmulist_entry_t entry )
   160 {
   161     return g_list_index( vmu_list, entry );
   162 }
   164 int vmulist_add_vmu( const gchar *filename, vmu_volume_t vol )
   165 {
   166     vmulist_entry_t entry = vmulist_add_entry( filename, vol );
   167     return vmulist_get_index(entry);
   168 }
   170 void vmulist_remove_vmu( vmu_volume_t vol )
   171 {
   172     vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
   173     if( entry != NULL ) {
   174         vmulist_remove_entry(entry);
   175     }
   176 }
   178 const char *vmulist_get_name( unsigned int idx )
   179 {
   180     vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
   181     if( entry != NULL ) {
   182         return vmulist_display_name(entry);
   183     }
   184     return NULL;
   185 }
   187 const char *vmulist_get_filename( unsigned int idx )
   188 {
   189     vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
   190     if( entry != NULL ) {
   191         return entry->filename;
   192     }
   193     return NULL;
   194 }
   196 const char *vmulist_get_volume_name( vmu_volume_t vol )
   197 {
   198     vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
   199     if( entry != NULL ) {
   200         return entry->filename;
   201     } 
   202     return NULL;
   203 }
   205 vmu_volume_t vmulist_get_vmu( unsigned int idx )
   206 {
   207     vmulist_entry_t entry = vmulist_get_entry_by_index(idx);
   208     if( entry != NULL ) {
   209         if( entry->vol == NULL ) {
   210             entry->vol = vmu_volume_load(entry->filename);
   211         }
   212         return entry->vol;
   213     }
   214     return NULL;
   215 }
   217 vmu_volume_t vmulist_get_vmu_by_name( const gchar *name )
   218 {
   219     vmulist_entry_t entry = vmulist_get_entry_by_name(name);
   220     if( entry != NULL ) {
   221         if( entry->vol == NULL ) {
   222             entry->vol = vmu_volume_load(entry->filename);
   223         }
   224         return entry->vol;
   225     }
   226     return NULL;
   227 }
   229 vmu_volume_t vmulist_get_vmu_by_filename( const gchar *name )
   230 {
   231     vmulist_entry_t entry = vmulist_get_entry_by_filename(name);
   232     if( entry != NULL ) {
   233         if( entry->vol == NULL ) {
   234             entry->vol = vmu_volume_load(entry->filename);
   235         }
   236         return entry->vol;
   237     } else {
   238         vmu_volume_t vol = vmu_volume_load( name );
   239         vmulist_add_entry( name, vol );
   240         return vol;
   241     }
   242 }
   244 int vmulist_get_index_by_filename( const gchar *name )
   245 {
   246     vmulist_entry_t entry = vmulist_get_entry_by_filename(name);
   247     if( entry != NULL ) {
   248         return g_list_index( vmu_list, entry );
   249     }
   250     return -1;
   251 }
   254 int vmulist_create_vmu( const gchar *filename, gboolean create_only )
   255 {
   256     vmu_volume_t vol = vmu_volume_new_default(filename);
   258     if( vmu_volume_save( filename, vol, create_only ) ) {
   259         return vmulist_add_vmu( filename, vol );
   260     } else {
   261         vmu_volume_destroy(vol);
   262     }
   263     return -1;
   264 }
   266 gboolean vmulist_attach_vmu( vmu_volume_t vol, const gchar *where )
   267 {
   268     vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
   269     if( entry == NULL ) {
   270         return FALSE;
   271     }
   272     entry->attach_count++;
   273     return TRUE;
   274 }
   276 void vmulist_detach_vmu( vmu_volume_t vol )
   277 {
   278     vmulist_entry_t entry = vmulist_get_entry_by_volume(vol);
   279     if( entry != NULL && entry->attach_count > 0 ) {
   280         entry->attach_count--;
   281     }
   282 }
   284 unsigned int vmulist_get_size(void)
   285 {
   286     return g_list_length(vmu_list);
   287 }
   289 void vmulist_init( void )
   290 {
   291     GList *filenames = lxdream_get_global_config_list_value( CONFIG_VMU );
   292     GList *ptr;
   293     for( ptr = filenames; ptr != NULL; ptr = g_list_next(ptr) ) {
   294         vmulist_add_entry( (gchar *)ptr->data, NULL );
   295         g_free( ptr->data );
   296     }
   297     g_list_free( filenames );
   298 }
   300 void vmulist_save_all( void )
   301 {
   302     GList *it;
   303     for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
   304         vmulist_entry_t entry = ENTRY(it);
   305         if( entry->vol != NULL && vmu_volume_is_dirty(entry->vol) ) {
   306             vmu_volume_save(entry->filename, entry->vol, FALSE);
   307         }
   308     }
   309 }
   311 void vmulist_shutdown( void )
   312 {
   313     vmulist_save_all();
   314 }
.