Search
lxdream.org :: lxdream/src/vmu/vmulist.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/vmu/vmulist.c
changeset 1071:182cfe43c09e
prev1035:e3093fd7d1da
next1296:30ecee61f811
author nkeynes
date Tue Feb 28 18:22:52 2012 +1000 (10 years ago)
permissions -rw-r--r--
last change Add a GL-only video driver for android usage (since the Java code is
responsible for creating the context)
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 }
.