Search
lxdream.org :: lxdream/src/vmu/vmulist.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/vmu/vmulist.c
changeset 1296:30ecee61f811
prev1071:182cfe43c09e
author nkeynes
date Sat Jan 26 14:00:48 2013 +1000 (9 years ago)
permissions -rw-r--r--
last change Change glib includes to #include <glib.h> rather than the individual
headers, as recent glib versions are breaking on this
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.h>
    22 #include "vmulist.h"
    23 #include "config.h"
    25 DEFINE_HOOK(vmulist_change_hook, vmulist_change_hook_t);
    27 typedef struct vmulist_entry {
    28     const gchar *filename;
    29     vmu_volume_t vol;
    30     int attach_count;
    31 } *vmulist_entry_t;
    33 /** 
    34  * Doubly-linked list of vmulist_entry_t maintained in sorted order by display name.
    35  * Could be augmented with a hashtable if it gets too long
    36  */
    37 static GList *vmu_list;
    39 #define ENTRY(it) ((vmulist_entry_t)(it)->data)
    40 #define VOLUME(it) (ENTRY(it)->vol)
    41 #define DISPLAY_NAME(it) vmulist_display_name(ENTRY(it))
    43 static const char *vmulist_display_name(vmulist_entry_t ent)
    44 {
    45     if( ent->filename == NULL ) {
    46         return NULL;
    47     }
    48     const char *s = strrchr(ent->filename, '/' );
    49     if( s == NULL || *(s+1) == '\0' ) {
    50         return ent->filename;
    51     } else {
    52         return s+1;
    53     }
    54 }
    56 static void vmulist_update_config( void ) 
    57 {
    58     GList *temp = NULL, *it;
    60     for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
    61         vmulist_entry_t entry = ENTRY(it);
    62         temp = g_list_append( temp, (char *)entry->filename );
    63     }
    64     lxdream_set_global_config_list_value( CONFIG_VMU, temp );
    65     g_list_free( temp );
    66 }
    68 static vmulist_entry_t vmulist_get_entry_by_name( const gchar *name )
    69 {
    70     GList *it;
    71     for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
    72         const gchar *vmu_name = DISPLAY_NAME(it);
    73         if( name == NULL ? vmu_name == NULL : vmu_name != NULL && strcmp( vmu_name, name ) == 0 ) {
    74             return ENTRY(it);
    75         }
    76     }
    77     return NULL; // not found
    78 }
    80 static vmulist_entry_t vmulist_get_entry_by_filename( const gchar *name )
    81 {
    82     GList *it;
    83     for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
    84         const gchar *vmu_name = ENTRY(it)->filename;
    85         if( name == NULL ? vmu_name == NULL : vmu_name != NULL && strcmp( vmu_name, name ) == 0 ) {
    86             return ENTRY(it);
    87         }
    88     }
    89     return NULL; // not found
    90 }
    92 static vmulist_entry_t vmulist_get_entry_by_volume( vmu_volume_t vol )
    93 {
    94     GList *it;
    95     for( it = vmu_list; it != NULL; it = g_list_next(it) ) {
    96         if( VOLUME(it) == vol ) {
    97             return ENTRY(it);
    98         }
    99     }
   100     return NULL; // not found
   101 }
   103 static vmulist_entry_t vmulist_get_entry_by_index( unsigned int index )
   104 {
   105     return (vmulist_entry_t)g_list_nth_data(vmu_list,index);
   106 }
   108 static gint vmulist_display_name_compare( gconstpointer a, gconstpointer b )
   109 {
   110     const char *aname = vmulist_display_name((vmulist_entry_t)a);    
   111     const char *bname = vmulist_display_name((vmulist_entry_t)b);
   112     if( aname == bname )
   113         return 0;
   114     if( aname == NULL ) 
   115         return -1;
   116     if( bname == NULL )
   117         return 1;
   118     return strcmp(aname,bname);
   119 }
   121 /** 
   122  * Add a new entry into the list, maintaining the sorted order.
   123  * If the filename is already in the list, it is updated instead.
   124  */ 
   125 static vmulist_entry_t vmulist_add_entry( const gchar *filename, vmu_volume_t vol )
   126 {
   127     vmulist_entry_t entry = vmulist_get_entry_by_filename(filename);
   128     if( entry == NULL ) {
   129         entry = g_malloc( sizeof(struct vmulist_entry) );
   130         entry->filename = g_strdup(filename);
   131         entry->vol = vol;
   132         vmu_list = g_list_insert_sorted(vmu_list, entry, vmulist_display_name_compare );
   133         vmulist_update_config();
   135         CALL_HOOKS( vmulist_change_hook, VMU_ADDED, g_list_index(vmu_list,entry) );
   136     } else {
   137         if( entry->vol != vol && entry->vol != NULL )
   138             vmu_volume_destroy( entry->vol );
   139         entry->vol = vol;
   140         /* NOTE: at the moment this can't require a resort, but if we allow
   141          * user-editable display names it will
   142          */ 
   143     }
   144     entry->attach_count = 0;
   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 }
.