Search
lxdream.org :: lxdream/src/cocoaui/cocoa_ctrl.m :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/cocoaui/cocoa_ctrl.m
changeset 1034:7044e01148f0
prev964:f2f3c7612d06
next1036:af7b0c5905dd
author nkeynes
date Wed Jun 24 02:41:12 2009 +0000 (11 years ago)
permissions -rw-r--r--
last change Add initial VMU support
file annotate diff log raw
1.1 --- a/src/cocoaui/cocoa_ctrl.m Thu Jan 15 04:15:11 2009 +0000
1.2 +++ b/src/cocoaui/cocoa_ctrl.m Wed Jun 24 02:41:12 2009 +0000
1.3 @@ -20,14 +20,20 @@
1.4 #include "config.h"
1.5 #include "display.h"
1.6 #include "maple/maple.h"
1.7 +#include "vmu/vmulist.h"
1.8
1.9 #include <glib/gstrfuncs.h>
1.10
1.11 -#define MAX_DEVICES 4
1.12 +#define FIRST_SECONDARY_DEVICE MAPLE_PORTS
1.13 +
1.14 +#define FIRST_VMU_TAG 0x1000
1.15 +#define LOAD_VMU_TAG -1
1.16 +#define CREATE_VMU_TAG -2
1.17
1.18 #define KEYBINDING_SIZE 110
1.19
1.20 static void cocoa_config_keysym_hook(void *data, const gchar *keysym);
1.21 +static gboolean cocoa_config_vmulist_hook(vmulist_change_type_t type, int idx, void *data);
1.22
1.23 @interface KeyBindingEditor (Private)
1.24 - (void)updateKeysym: (const gchar *)sym;
1.25 @@ -188,7 +194,7 @@
1.26 @interface ControllerKeyBindingView : NSView
1.27 {
1.28 maple_device_t device;
1.29 - KeyBindingField *field[MAX_KEY_BINDINGS][2];
1.30 + NSTextField *field[MAX_KEY_BINDINGS][2];
1.31 }
1.32 - (id)initWithFrame: (NSRect)frameRect;
1.33 - (void)setDevice: (maple_device_t)device;
1.34 @@ -214,21 +220,25 @@
1.35 }
1.36 - (void)controlTextDidChange: (NSNotification *)notify
1.37 {
1.38 + const gchar *p = NULL;
1.39 int binding = [[notify object] tag];
1.40 NSString *val1 = [field[binding][0] stringValue];
1.41 - NSString *val2 = [field[binding][1] stringValue];
1.42 - char buf[ [val1 length] + [val2 length] + 2 ];
1.43 - const gchar *p = NULL;
1.44 -
1.45 - if( [val1 length] == 0 ) {
1.46 - if( [val2 length] != 0 ) {
1.47 - p = [val2 UTF8String];
1.48 - }
1.49 - } else if( [val2 length] == 0 ) {
1.50 + if( field[binding][1] == NULL ) {
1.51 p = [val1 UTF8String];
1.52 } else {
1.53 - sprintf( buf, "%s,%s", [val1 UTF8String], [val2 UTF8String] );
1.54 - p = buf;
1.55 + NSString *val2 = [field[binding][1] stringValue];
1.56 + char buf[ [val1 length] + [val2 length] + 2 ];
1.57 +
1.58 + if( [val1 length] == 0 ) {
1.59 + if( [val2 length] != 0 ) {
1.60 + p = [val2 UTF8String];
1.61 + }
1.62 + } else if( [val2 length] == 0 ) {
1.63 + p = [val1 UTF8String];
1.64 + } else {
1.65 + sprintf( buf, "%s,%s", [val1 UTF8String], [val2 UTF8String] );
1.66 + p = buf;
1.67 + }
1.68 }
1.69 maple_set_device_config_value( device, binding, p );
1.70 lxdream_save_config();
1.71 @@ -237,7 +247,7 @@
1.72 {
1.73 device = newDevice;
1.74 [self removeSubviews];
1.75 - if( device != NULL ) {
1.76 + if( device != NULL && !MAPLE_IS_VMU(device) ) {
1.77 lxdream_config_entry_t config = maple_get_device_config(device);
1.78 if( config != NULL ) {
1.79 int count, i, y, x;
1.80 @@ -249,35 +259,51 @@
1.81 [self scrollRectToVisible: NSMakeRect(0,0,1,1)];
1.82 y = TEXT_GAP;
1.83 for( i=0; config[i].key != NULL; i++ ) {
1.84 + /* Add label */
1.85 NSRect frame = NSMakeRect(x, y + 2, 85, LABEL_HEIGHT);
1.86 NSTextField *label = cocoa_gui_add_label(self, NS_(config[i].label), frame);
1.87 [label setAlignment: NSRightTextAlignment];
1.88 +
1.89 + switch(config[i].type) {
1.90 + case CONFIG_TYPE_KEY:
1.91 + frame = NSMakeRect( x + 85 + TEXT_GAP, y, KEYBINDING_SIZE, TEXT_HEIGHT);
1.92 + field[i][0] = [[KeyBindingField alloc] initWithFrame: frame];
1.93 + [field[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.94 + [field[i][0] setTag: i];
1.95 + [field[i][0] setDelegate: self];
1.96 + [self addSubview: field[i][0]];
1.97
1.98 - frame = NSMakeRect( x + 85 + TEXT_GAP, y, KEYBINDING_SIZE, TEXT_HEIGHT);
1.99 - field[i][0] = [[KeyBindingField alloc] initWithFrame: frame];
1.100 - [field[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.101 - [field[i][0] setTag: i];
1.102 - [field[i][0] setDelegate: self];
1.103 - [self addSubview: field[i][0]];
1.104 -
1.105 - frame = NSMakeRect( x + 85 + KEYBINDING_SIZE + (TEXT_GAP*2), y, KEYBINDING_SIZE, TEXT_HEIGHT);
1.106 - field[i][1] = [[KeyBindingField alloc] initWithFrame: frame];
1.107 - [field[i][1] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.108 - [field[i][1] setTag: i];
1.109 - [field[i][1] setDelegate: self];
1.110 - [self addSubview: field[i][1]];
1.111 + frame = NSMakeRect( x + 85 + KEYBINDING_SIZE + (TEXT_GAP*2), y, KEYBINDING_SIZE, TEXT_HEIGHT);
1.112 + field[i][1] = [[KeyBindingField alloc] initWithFrame: frame];
1.113 + [field[i][1] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.114 + [field[i][1] setTag: i];
1.115 + [field[i][1] setDelegate: self];
1.116 + [self addSubview: field[i][1]];
1.117
1.118 - if( config[i].value != NULL ) {
1.119 - gchar **parts = g_strsplit(config[i].value,",",3);
1.120 - if( parts[0] != NULL ) {
1.121 - [field[i][0] setStringValue: [NSString stringWithCString: parts[0]]];
1.122 - if( parts[1] != NULL ) {
1.123 - [field[i][1] setStringValue: [NSString stringWithCString: parts[1]]];
1.124 + if( config[i].value != NULL ) {
1.125 + gchar **parts = g_strsplit(config[i].value,",",3);
1.126 + if( parts[0] != NULL ) {
1.127 + [field[i][0] setStringValue: [NSString stringWithCString: parts[0]]];
1.128 + if( parts[1] != NULL ) {
1.129 + [field[i][1] setStringValue: [NSString stringWithCString: parts[1]]];
1.130 + }
1.131 }
1.132 + g_strfreev(parts);
1.133 }
1.134 - g_strfreev(parts);
1.135 - }
1.136 -
1.137 + break;
1.138 + case CONFIG_TYPE_FILE:
1.139 + case CONFIG_TYPE_PATH:
1.140 + frame = NSMakeRect( x + 85 + TEXT_GAP, y, KEYBINDING_SIZE*2+TEXT_GAP, TEXT_HEIGHT);
1.141 + field[i][0] = [[NSTextField alloc] initWithFrame: frame];
1.142 + [field[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.143 + [field[i][0] setTag: i];
1.144 + [field[i][0] setDelegate: self];
1.145 + [self addSubview: field[i][0]];
1.146 + if( config[i].value != NULL ) {
1.147 + [field[i][0] setStringValue: [NSString stringWithCString: config[i].value]];
1.148 + }
1.149 + field[i][1] = NULL;
1.150 + }
1.151 y += (TEXT_HEIGHT + TEXT_GAP);
1.152 }
1.153 } else {
1.154 @@ -290,16 +316,176 @@
1.155 @end
1.156
1.157 /*************************** Top-level controller pane ***********************/
1.158 +static NSButton *addRadioButton( int port, int sub, int x, int y, id parent )
1.159 +{
1.160 + char buf[16];
1.161 +
1.162 + if( sub == 0 ) {
1.163 + snprintf( buf, sizeof(buf), _("Port %c."), 'A'+port );
1.164 + } else {
1.165 + snprintf( buf, sizeof(buf), _("VMU %d."), sub );
1.166 + }
1.167 +
1.168 + NSButton *radio = [[NSButton alloc] initWithFrame: NSMakeRect( x, y, 60, TEXT_HEIGHT )];
1.169 + [radio setTitle: [NSString stringWithUTF8String: buf]];
1.170 + [radio setTag: MAPLE_DEVID(port,sub) ];
1.171 + [radio setButtonType: NSRadioButton];
1.172 + [radio setAlignment: NSRightTextAlignment];
1.173 + [radio setTarget: parent];
1.174 + [radio setAction: @selector(radioChanged:)];
1.175 + [radio setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.176 + [parent addSubview: radio];
1.177 + return radio;
1.178 +}
1.179 +
1.180 +static void setDevicePopupSelection( NSPopUpButton *popup, maple_device_t device )
1.181 +{
1.182 + if( device == NULL ) {
1.183 + [popup selectItemAtIndex: 0];
1.184 + } else if( MAPLE_IS_VMU(device) ) {
1.185 + int idx = vmulist_get_index_by_filename( MAPLE_VMU_NAME(device) );
1.186 + if( idx == -1 ) {
1.187 + [popup selectItemAtIndex: 0];
1.188 + } else {
1.189 + [popup selectItemWithTag: FIRST_VMU_TAG + idx];
1.190 + }
1.191 + } else {
1.192 + const struct maple_device_class **devices = maple_get_device_classes();
1.193 + int i;
1.194 + for( i=0; devices[i] != NULL; i++ ) {
1.195 + if( devices[i] == device->device_class ) {
1.196 + [popup selectItemWithTag: i+1];
1.197 + return;
1.198 + }
1.199 + }
1.200 + // Should never get here, but if so...
1.201 + [popup selectItemAtIndex: 0];
1.202 + }
1.203 +}
1.204 +
1.205 +static void buildDevicePopupMenu( NSPopUpButton *popup, maple_device_t device, BOOL primary )
1.206 +{
1.207 + int j;
1.208 + const struct maple_device_class **devices = maple_get_device_classes();
1.209 +
1.210 + [popup removeAllItems];
1.211 + [popup addItemWithTitle: NS_("<empty>")];
1.212 + [[popup itemAtIndex: 0] setTag: 0];
1.213 + for( j=0; devices[j] != NULL; j++ ) {
1.214 + int isPrimaryDevice = devices[j]->flags & MAPLE_TYPE_PRIMARY;
1.215 + if( primary ? isPrimaryDevice : (!isPrimaryDevice && !MAPLE_IS_VMU_CLASS(devices[j])) ) {
1.216 + [popup addItemWithTitle: [NSString stringWithUTF8String: devices[j]->name]];
1.217 + if( device != NULL && device->device_class == devices[j] ) {
1.218 + [popup selectItemAtIndex: ([popup numberOfItems]-1)];
1.219 + }
1.220 + [[popup itemAtIndex: ([popup numberOfItems]-1)] setTag: (j+1)];
1.221 + }
1.222 + }
1.223 +
1.224 + if( !primary ) {
1.225 + BOOL vmu_selected = NO;
1.226 + const char *vmu_name;
1.227 + if( device != NULL && MAPLE_IS_VMU(device) ) {
1.228 + vmu_selected = YES;
1.229 + vmu_name = MAPLE_VMU_NAME(device);
1.230 + }
1.231 + if( [popup numberOfItems] > 0 ) {
1.232 + [[popup menu] addItem: [NSMenuItem separatorItem]];
1.233 + }
1.234 +
1.235 + unsigned int vmu_count = vmulist_get_size();
1.236 + for( j=0; j<vmu_count; j++ ) {
1.237 + const char *name = vmulist_get_name(j);
1.238 + [popup addItemWithTitle: [NSString stringWithUTF8String: name]];
1.239 + if( vmu_selected && strcmp(vmu_name, vmulist_get_filename(j)) == 0 ) {
1.240 + [popup selectItemAtIndex: ([popup numberOfItems]-1)];
1.241 + }
1.242 + [[popup itemAtIndex: ([popup numberOfItems]-1)] setTag: FIRST_VMU_TAG + j];
1.243 + }
1.244 +
1.245 + [popup addItemWithTitle: NS_("Load VMU...")];
1.246 + [[popup itemAtIndex: ([popup numberOfItems]-1)] setTag: LOAD_VMU_TAG];
1.247 + [popup addItemWithTitle: NS_("Create VMU...")];
1.248 + [[popup itemAtIndex: ([popup numberOfItems]-1)] setTag: CREATE_VMU_TAG];
1.249 + }
1.250 +
1.251 +}
1.252 +
1.253 +static NSPopUpButton *addDevicePopup( int port, int sub, int x, int y, maple_device_t device, BOOL primary, id parent )
1.254 +{
1.255 + NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(x,y,150,TEXT_HEIGHT)
1.256 + pullsDown: NO];
1.257 + [popup setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.258 + buildDevicePopupMenu(popup,device,primary);
1.259 +
1.260 + [popup setTarget: parent];
1.261 + [popup setAction: @selector(deviceChanged:)];
1.262 + [popup setTag: MAPLE_DEVID(port,sub) ];
1.263 + [parent addSubview: popup];
1.264 + return popup;
1.265 +}
1.266 +
1.267 +@interface VMULoadValidator : NSObject
1.268 +{
1.269 +}
1.270 +- (BOOL)panel:(id) sender isValidFilename: (NSString *)filename;
1.271 +@end
1.272 +
1.273 +@implementation VMULoadValidator
1.274 +- (BOOL)panel:(id) sender isValidFilename: (NSString *)filename
1.275 +{
1.276 + const char *c_fn = [filename UTF8String];
1.277 + vmu_volume_t vol = vmu_volume_load( c_fn );
1.278 + if( vol != NULL ) {
1.279 + vmulist_add_vmu(c_fn, vol);
1.280 + return YES;
1.281 + } else {
1.282 + ERROR( "Unable to load VMU file (not a valid VMU)" );
1.283 + return NO;
1.284 + }
1.285 +}
1.286 +
1.287 +@end
1.288 +
1.289 +@interface VMUCreateValidator : NSObject
1.290 +{
1.291 +}
1.292 +- (BOOL)panel:(id) sender isValidFilename: (NSString *)filename;
1.293 +@end
1.294 +
1.295 +@implementation VMUCreateValidator
1.296 +- (BOOL)panel:(id) sender isValidFilename: (NSString *)filename
1.297 +{
1.298 + const char *vmu_filename = [filename UTF8String];
1.299 + int idx = vmulist_create_vmu(vmu_filename, FALSE);
1.300 + if( idx == -1 ) {
1.301 + ERROR( "Unable to create file: %s\n", strerror(errno) );
1.302 + return NO;
1.303 + } else {
1.304 + return YES;
1.305 + }
1.306 +}
1.307 +@end
1.308 +
1.309
1.310 @interface LxdreamPrefsControllerPane: LxdreamPrefsPane
1.311 {
1.312 - struct maple_device *save_controller[4];
1.313 - NSButton *radio[4];
1.314 + struct maple_device *save_controller[MAPLE_MAX_DEVICES];
1.315 + NSButton *radio[MAPLE_MAX_DEVICES];
1.316 + NSPopUpButton *popup[MAPLE_MAX_DEVICES];
1.317 ControllerKeyBindingView *key_bindings;
1.318 }
1.319 + (LxdreamPrefsControllerPane *)new;
1.320 +- (void)vmulistChanged: (id)sender;
1.321 @end
1.322
1.323 +static gboolean cocoa_config_vmulist_hook(vmulist_change_type_t type, int idx, void *data)
1.324 +{
1.325 + LxdreamPrefsControllerPane *pane = (LxdreamPrefsControllerPane *)data;
1.326 + [pane vmulistChanged: nil];
1.327 + return TRUE;
1.328 +}
1.329 +
1.330 @implementation LxdreamPrefsControllerPane
1.331 + (LxdreamPrefsControllerPane *)new
1.332 {
1.333 @@ -310,11 +496,11 @@
1.334 if( [super initWithFrame: frameRect title: NS_("Controllers")] == nil ) {
1.335 return nil;
1.336 } else {
1.337 - const struct maple_device_class **devices = maple_get_device_classes();
1.338 - char buf[16];
1.339 int i,j;
1.340 int y = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;
1.341
1.342 + memset( radio, 0, sizeof(radio) );
1.343 + memset( save_controller, 0, sizeof(save_controller) );
1.344 NSBox *rule = [[NSBox alloc] initWithFrame:
1.345 NSMakeRect(210+(TEXT_GAP*3), 1, 1, [self contentHeight] + TEXT_GAP - 2)];
1.346 [rule setAutoresizingMask: (NSViewMaxXMargin|NSViewHeightSizable)];
1.347 @@ -334,96 +520,158 @@
1.348 [self addSubview: scrollView];
1.349 [key_bindings setDevice: maple_get_device(0,0)];
1.350
1.351 - for( i=0; i<MAX_DEVICES; i++ ) {
1.352 - int x = TEXT_GAP;
1.353 - save_controller[i] = NULL;
1.354 + for( i=0; i<MAPLE_PORTS; i++ ) {
1.355 maple_device_t device = maple_get_device(i,0);
1.356
1.357 - snprintf( buf, sizeof(buf), _("Slot %d."), i );
1.358 - radio[i] = [[NSButton alloc] initWithFrame: NSMakeRect( x, y, 60, TEXT_HEIGHT )];
1.359 - [radio[i] setTitle: [NSString stringWithUTF8String: buf]];
1.360 - [radio[i] setTag: i];
1.361 - [radio[i] setButtonType: NSRadioButton];
1.362 - [radio[i] setAlignment: NSRightTextAlignment];
1.363 - [radio[i] setTarget: self];
1.364 - [radio[i] setAction: @selector(radioChanged:)];
1.365 - [radio[i] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.366 - [self addSubview: radio[i]];
1.367 - x += 60 + TEXT_GAP;
1.368 -
1.369 - NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(x,y,150,TEXT_HEIGHT)
1.370 - pullsDown: NO];
1.371 - [popup addItemWithTitle: NS_("<empty>")];
1.372 - [popup setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.373 - [[popup itemAtIndex: 0] setTag: 0];
1.374 - for( j=0; devices[j] != NULL; j++ ) {
1.375 - [popup addItemWithTitle: [NSString stringWithUTF8String: devices[j]->name]];
1.376 - if( device != NULL && device->device_class == devices[j] ) {
1.377 - [popup selectItemAtIndex: (j+1)];
1.378 + radio[i] = addRadioButton(i,0,TEXT_GAP,y,self);
1.379 + popup[i] = addDevicePopup(i,0,60 + (TEXT_GAP*2),y,device, YES,self);
1.380 + y -= (TEXT_HEIGHT+TEXT_GAP);
1.381 +
1.382 + int j,max = device == NULL ? 0 : MAPLE_SLOTS(device->device_class);
1.383 + for( j=1; j<=MAPLE_USER_SLOTS; j++ ) {
1.384 + radio[MAPLE_DEVID(i,j)] = addRadioButton(i, j, TEXT_GAP*2, y, self);
1.385 + popup[MAPLE_DEVID(i,j)] = addDevicePopup(i, j, 60 + TEXT_GAP*2, y, maple_get_device(i,j), NO, self);
1.386 + y -= (TEXT_HEIGHT+TEXT_GAP);
1.387 + if( j > max ) {
1.388 + [radio[MAPLE_DEVID(i,j)] setEnabled: NO];
1.389 + [popup[MAPLE_DEVID(i,j)] setEnabled: NO];
1.390 }
1.391 - [[popup itemAtIndex: (j+1)] setTag: (j+1)];
1.392 }
1.393 - [popup setTarget: self];
1.394 - [popup setAction: @selector(deviceChanged:)];
1.395 - [popup setTag: i];
1.396 - [self addSubview: popup];
1.397 - y -= (TEXT_HEIGHT+TEXT_GAP);
1.398 }
1.399
1.400 [radio[0] setState: NSOnState];
1.401 +
1.402 + register_vmulist_change_hook(cocoa_config_vmulist_hook, self);
1.403 return self;
1.404 }
1.405 }
1.406 +- (void)dealloc
1.407 +{
1.408 + unregister_vmulist_change_hook(cocoa_config_vmulist_hook,self);
1.409 + [super dealloc];
1.410 +}
1.411 +- (void)vmulistChanged: (id)sender
1.412 +{
1.413 + int i;
1.414 + for( i=FIRST_SECONDARY_DEVICE; i<MAPLE_MAX_DEVICES; i++ ) {
1.415 + if( popup[i] != NULL ) {
1.416 + buildDevicePopupMenu(popup[i], maple_get_device(MAPLE_DEVID_PORT(i), MAPLE_DEVID_SLOT(i)), NO );
1.417 + }
1.418 + }
1.419 +}
1.420 - (void)radioChanged: (id)sender
1.421 {
1.422 - int slot = [sender tag];
1.423 + int tag = [sender tag];
1.424 int i;
1.425 - for( i=0; i<MAX_DEVICES; i++ ) {
1.426 - if( i != slot ) {
1.427 + for( i=0; i<MAPLE_MAX_DEVICES; i++ ) {
1.428 + if( i != tag && radio[i] != NULL ) {
1.429 [radio[i] setState: NSOffState];
1.430 }
1.431 }
1.432 - [key_bindings setDevice: maple_get_device(slot,0)];
1.433 + [key_bindings setDevice: maple_get_device(MAPLE_DEVID_PORT(tag),MAPLE_DEVID_SLOT(tag))];
1.434 }
1.435 - (void)deviceChanged: (id)sender
1.436 {
1.437 - int slot = [sender tag];
1.438 - int new_device_idx = [sender indexOfSelectedItem] - 1, i;
1.439 + int tag = [sender tag];
1.440 + int port = MAPLE_DEVID_PORT(tag);
1.441 + int slot = MAPLE_DEVID_SLOT(tag);
1.442 + int new_device_idx = [[sender selectedItem] tag], i;
1.443 maple_device_class_t new_device_class = NULL;
1.444 + const gchar *vmu_filename = NULL;
1.445
1.446 - for( i=0; i<MAX_DEVICES; i++ ) {
1.447 - if( i == slot ) {
1.448 - [radio[i] setState: NSOnState];
1.449 - } else {
1.450 - [radio[i] setState: NSOffState];
1.451 + for( i=0; i<MAPLE_MAX_DEVICES; i++ ) {
1.452 + if( radio[i] != NULL ) {
1.453 + if( i == tag ) {
1.454 + [radio[i] setState: NSOnState];
1.455 + } else {
1.456 + [radio[i] setState: NSOffState];
1.457 + }
1.458 }
1.459 }
1.460
1.461 - maple_device_t current = maple_get_device(slot,0);
1.462 + maple_device_t current = maple_get_device(port,slot);
1.463 maple_device_t new_device = NULL;
1.464 - if( new_device_idx != -1 ) {
1.465 - new_device_class = maple_get_device_classes()[new_device_idx];
1.466 + if( new_device_idx == LOAD_VMU_TAG ) {
1.467 + NSArray *array = [NSArray arrayWithObjects: @"vmu", nil];
1.468 + NSOpenPanel *panel = [NSOpenPanel openPanel];
1.469 + VMULoadValidator *valid = [[VMULoadValidator alloc] autorelease];
1.470 + [panel setDelegate: valid];
1.471 + NSInteger result = [panel runModalForDirectory: [NSString stringWithUTF8String: lxdream_get_config_value(CONFIG_VMU_PATH)]
1.472 + file: nil types: array];
1.473 + if( result == NSOKButton ) {
1.474 + vmu_filename = [[panel filename] UTF8String];
1.475 + int idx = vmulist_get_index_by_filename(vmu_filename);
1.476 + [sender selectItemWithTag: (FIRST_VMU_TAG+idx)];
1.477 + new_device_class = &vmu_class;
1.478 + } else {
1.479 + /* Cancelled - restore previous value */
1.480 + setDevicePopupSelection( sender, current );
1.481 + return;
1.482 + }
1.483 + } else if( new_device_idx == CREATE_VMU_TAG ) {
1.484 + NSSavePanel *panel = [NSSavePanel savePanel];
1.485 + [panel setTitle: NS_("Create VMU")];
1.486 + [panel setCanCreateDirectories: YES];
1.487 + [panel setRequiredFileType: @"vmu"];
1.488 + VMUCreateValidator *valid = [[VMUCreateValidator alloc] autorelease];
1.489 + [panel setDelegate: valid];
1.490 + NSInteger result = [panel runModalForDirectory: [NSString stringWithUTF8String: lxdream_get_config_value(CONFIG_VMU_PATH)]
1.491 + file: nil];
1.492 + if( result == NSFileHandlingPanelOKButton ) {
1.493 + /* Validator has already created the file by now */
1.494 + vmu_filename = [[panel filename] UTF8String];
1.495 + int idx = vmulist_get_index_by_filename(vmu_filename);
1.496 + [sender selectItemWithTag: (FIRST_VMU_TAG+idx)];
1.497 + new_device_class = &vmu_class;
1.498 + } else {
1.499 + setDevicePopupSelection( sender, current );
1.500 + return;
1.501 + }
1.502 + } else if( new_device_idx >= FIRST_VMU_TAG ) {
1.503 + vmu_filename = vmulist_get_filename( new_device_idx - FIRST_VMU_TAG );
1.504 + new_device_class = &vmu_class;
1.505 + } else if( new_device_idx > 0) {
1.506 + new_device_class = maple_get_device_classes()[new_device_idx-1];
1.507 }
1.508 - if( current == NULL ? new_device_class == NULL : current->device_class == new_device_class ) {
1.509 +
1.510 + if( current == NULL ? new_device_class == NULL :
1.511 + (current->device_class == new_device_class &&
1.512 + (!MAPLE_IS_VMU(current) || MAPLE_VMU_HAS_NAME(current, vmu_filename))) ) {
1.513 // No change
1.514 [key_bindings setDevice: current];
1.515 return;
1.516 }
1.517 if( current != NULL && current->device_class == &controller_class ) {
1.518 - save_controller[slot] = current->clone(current);
1.519 + save_controller[tag] = current->clone(current);
1.520 }
1.521 if( new_device_class == NULL ) {
1.522 - maple_detach_device(slot,0);
1.523 + maple_detach_device(port,slot);
1.524 } else {
1.525 - if( new_device_class == &controller_class && save_controller[slot] != NULL ) {
1.526 - new_device = save_controller[slot];
1.527 - save_controller[slot] = NULL;
1.528 + if( new_device_class == &controller_class && save_controller[tag] != NULL ) {
1.529 + new_device = save_controller[tag];
1.530 + save_controller[tag] = NULL;
1.531 } else {
1.532 new_device = maple_new_device( new_device_class->name );
1.533 }
1.534 - maple_attach_device(new_device,slot,0);
1.535 + if( MAPLE_IS_VMU(new_device) ) {
1.536 + MAPLE_SET_VMU_NAME(new_device,vmu_filename);
1.537 + }
1.538 + maple_attach_device(new_device,port,slot);
1.539 }
1.540 - [key_bindings setDevice: maple_get_device(slot,0)];
1.541 + [key_bindings setDevice: maple_get_device(port,slot)];
1.542 +
1.543 + if( slot == 0 ) { /* Change primary */
1.544 + int max = new_device_class == NULL ? 0 : MAPLE_SLOTS(new_device_class);
1.545 + for( i=1; i<=MAPLE_USER_SLOTS; i++ ) {
1.546 + if( i <= max ) {
1.547 + [radio[MAPLE_DEVID(port,i)] setEnabled: YES];
1.548 + [popup[MAPLE_DEVID(port,i)] setEnabled: YES];
1.549 + } else {
1.550 + [radio[MAPLE_DEVID(port,i)] setEnabled: NO];
1.551 + [popup[MAPLE_DEVID(port,i)] setEnabled: NO];
1.552 + }
1.553 + }
1.554 + }
1.555 lxdream_save_config();
1.556 }
1.557 @end
.