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