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