On 14 February 2015 at 01:43, Programmingkid <programmingk...@gmail.com> wrote: > Added features: > Menu items to switch floppy and CD image files. > Menu items to eject floppy and CD image files. > Menu item to use /dev/cdrom. > Verifies with the user before quitting QEMU by displaying a dialog box. > > Signed-off-by: John Arbuckle <programmingk...@gmail.com>
Stefan, Kevin -- could you review the bits of this patch which determine whether the machine has a floppy/cdrom drive and if so let the user insert/inject it, please? (that's the emulatorHasDevice and ejectFloppy/changeFloppy functions, mostly). I don't know the block layer APIs so I can't really say if this patch is doing it in the best/ non-deprecated/etc way or not... thanks -- PMM > --- > Added yellow background to the pause label. > Removed all depreciated methods. > Using strncpy() in place of strcpy() in emulatorHasDevice() . > Eliminated all warnings when compiling. > > ui/cocoa.m | 238 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 237 insertions(+), 1 deletions(-) > > diff --git a/ui/cocoa.m b/ui/cocoa.m > index d37c29b..0e4a327 100644 > --- a/ui/cocoa.m > +++ b/ui/cocoa.m > @@ -29,6 +29,8 @@ > #include "ui/console.h" > #include "ui/input.h" > #include "sysemu/sysemu.h" > +#include "qmp-commands.h" > +#include "sysemu/blockdev.h" > > #ifndef MAC_OS_X_VERSION_10_4 > #define MAC_OS_X_VERSION_10_4 1040 > @@ -64,6 +66,9 @@ static int last_buttons; > > int gArgc; > char **gArgv; > +#define MAX_DEVICE_NAME_SIZE 10 > +char floppy_drive_name[MAX_DEVICE_NAME_SIZE], > cdrom_drive_name[MAX_DEVICE_NAME_SIZE]; > +NSTextField * pause_label; > > // keymap conversion > int keymap[] = > @@ -239,7 +244,95 @@ static int cocoa_keycode_to_qemu(int keycode) > return keymap[keycode]; > } > > +/* Handles any errors that happen with a device transaction */ > +static void handleAnyDeviceErrors(Error * err) > +{ > + if (err) { > + NSRunAlertPanel(@"Alert", [NSString stringWithCString: > error_get_pretty(err) encoding: NSASCIIStringEncoding], @"OK", nil, nil); > + error_free(err); > + } > +} > + > +/* > +Determine if the current emulator has the specified device. > +device_name: the name of the device you want: floppy, cd > +official_name: QEMU's name for the device: floppy0, ide-cd0 > +*/ > +static bool emulatorHasDevice(const char * device_name, char * official_name) > +{ > + BlockInfoList * block_device_data; > + block_device_data = qmp_query_block(false); > + if(block_device_data == NULL) { > + return false; > + } > + while(block_device_data->next != NULL) { > + /* If we found the device */ > + if (strstr(block_device_data->value->device, device_name)) { > + strncpy(official_name, block_device_data->value->device, > MAX_DEVICE_NAME_SIZE); > + qapi_free_BlockInfoList(block_device_data); > + return true; > + } > + block_device_data = block_device_data->next; > + } > + return false; > +} > + > +/* Determine if the current emulator has a floppy drive */ > +static bool emulatorHasFloppy() > +{ > + if (emulatorHasDevice("floppy", floppy_drive_name)) { > + return true; > + } else { > + return false; > + } > +} > + > +/* Determine if the current emulator has a CDROM drive */ > +static bool emulatorHasCDROM() > +{ > + if (emulatorHasDevice("cd", cdrom_drive_name)) { > + return true; > + } else { > + return false; > + } > +} > + > +/* Adds the Machine menu to the menu bar. */ > +/* Has to be added separately because QEMU needs > + to be running to determine used devices. > +*/ > +static void createMachineMenu() > +{ > + NSMenu * menu; > + NSMenuItem * menuItem; > + > + // Machine menu > + menu = [[NSMenu alloc] initWithTitle: @"Machine"]; > + [menu setAutoenablesItems: NO]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Pause" action: > @selector(pauseQemu:) keyEquivalent: @""] autorelease]]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Resume" action: > @selector(resumeQemu:) keyEquivalent: @""] autorelease]]; > + > + if(emulatorHasFloppy() || emulatorHasCDROM()) { > + [menu addItem: [NSMenuItem separatorItem]]; > + } > > + if (emulatorHasFloppy()) { > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Eject Floppy" > action: @selector(ejectFloppy:) keyEquivalent: @""] autorelease]]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Change > Floppy..." action: @selector(changeFloppy:) keyEquivalent: @""] autorelease]]; > + } > + if (emulatorHasCDROM()) { > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Eject cdrom" > action: @selector(ejectCdrom:) keyEquivalent: @""] autorelease]]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Use cdrom > image..." action: @selector(changeCdrom:) keyEquivalent: @""] autorelease]]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Use real cdrom > drive" action: @selector(useRealCdrom:) keyEquivalent: @""] autorelease]]; > + } > + [menu addItem: [NSMenuItem separatorItem]]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Reset" action: > @selector(restartQemu:) keyEquivalent: @""] autorelease]]; > + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Power Down" action: > @selector(powerDown:) keyEquivalent: @""] autorelease]]; > + menuItem = [[[NSMenuItem alloc] initWithTitle: @"Machine" action:nil > keyEquivalent:@""] autorelease]; > + [menuItem setSubmenu:menu]; > + [[NSApp mainMenu] insertItem: menuItem atIndex: 2]; /* Insert after View > menu */ > + [[menu itemWithTitle: @"Resume"] setEnabled: NO]; > +} > > /* > ------------------------------------------------------ > @@ -801,6 +894,17 @@ QemuCocoaView *cocoaView; > - (void)toggleFullScreen:(id)sender; > - (void)showQEMUDoc:(id)sender; > - (void)showQEMUTec:(id)sender; > +- (void)pauseQemu:(id)sender; > +- (void)ejectFloppy:(id)sender; > +- (void)ejectCdrom:(id)sender; > +- (void)changeCdrom:(id)sender; > +- (void)changeFloppy:(id)sender; > +- (void)restartQemu:(id)sender; > +- (void)useRealCdrom:(id)sender; > +- (void)verifyQuit:(id)sender; > +- (void)powerDown:(id)sender; > +- (void)displayPause; > +- (void)removePause; > @end > > @implementation QemuCocoaAppController > @@ -833,6 +937,22 @@ QemuCocoaView *cocoaView; > [normalWindow makeKeyAndOrderFront:self]; > [normalWindow center]; > > + /* Used for displaying pause on the screen */ > + pause_label = [NSTextField new]; > + [pause_label setBezeled:NO]; > + [pause_label setDrawsBackground:YES]; > + [pause_label setBackgroundColor: [NSColor yellowColor]]; > + [pause_label setEditable:NO]; > + [pause_label setSelectable:NO]; > + [pause_label setStringValue: @"Paused"]; > + [pause_label setFont: [NSFont fontWithName: @"Helvetica" size: 90]]; > + [pause_label setTextColor: [NSColor redColor]]; > + [pause_label sizeToFit]; > + > + /* Verify with the user before quitting QEMU */ > + NSButton *closeButton = [normalWindow > standardWindowButton:NSWindowCloseButton]; > + [closeButton setTarget: self]; > + [closeButton setAction: @selector(verifyQuit:)]; > } > return self; > } > @@ -943,6 +1063,119 @@ QemuCocoaView *cocoaView; > [[NSWorkspace sharedWorkspace] openFile:[NSString > stringWithFormat:@"%@/../doc/qemu/qemu-tech.html", > [[NSBundle mainBundle] resourcePath]] withApplication:@"Help > Viewer"]; > } > + > +/* Pause the guest */ > +- (void)pauseQemu:(id)sender > +{ > + qmp_stop(NULL); > + [sender setEnabled: NO]; > + [[[sender menu] itemWithTitle: @"Resume"] setEnabled: YES]; > + [self displayPause]; > +} > + > +/* Resume running the guest operating system */ > +- (void)resumeQemu: (id) sender > +{ > + qmp_cont(NULL); > + [sender setEnabled: NO]; > + [[[sender menu] itemWithTitle: @"Pause"] setEnabled: YES]; > + [self removePause]; > +} > + > +/* Eject the floppy0 disk */ > +- (void)ejectFloppy:(id)sender > +{ > + Error *err = NULL; > + qmp_eject(floppy_drive_name, false, false, &err); > + handleAnyDeviceErrors(err); > +} > + > +/* Displays a dialog box asking the user to select a floppy image to load */ > +- (void)changeFloppy:(id)sender > +{ > + NSOpenPanel * open_panel; > + open_panel = [NSOpenPanel openPanel]; > + [open_panel setCanChooseFiles: YES]; > + [open_panel setAllowsMultipleSelection: NO]; > + if([open_panel runModalForDirectory: nil file: nil] == NSOKButton) { > + Error *err = NULL; > + NSString * file = [[open_panel filenames] objectAtIndex: 0]; > + qmp_change_blockdev(floppy_drive_name, [file cStringUsingEncoding: > NSASCIIStringEncoding], "raw", &err); > + handleAnyDeviceErrors(err); > + } > +} > + > +// Ejects the cdrom > +- (void)ejectCdrom:(id)sender > +{ > + Error *err = NULL; > + qmp_eject(cdrom_drive_name, false, false, &err); > + handleAnyDeviceErrors(err); > +} > + > +/* Displays a dialog box asking the user to select a CD image to load */ > +- (void)changeCdrom:(id)sender > +{ > + NSOpenPanel * open_panel; > + open_panel = [NSOpenPanel openPanel]; > + [open_panel setCanChooseFiles: YES]; > + [open_panel setAllowsMultipleSelection: NO]; > + if([open_panel runModalForDirectory: nil file: nil] == NSOKButton) { > + NSString * file = [[open_panel filenames] objectAtIndex: 0]; > + Error *err = NULL; > + qmp_change_blockdev(cdrom_drive_name, [file cStringUsingEncoding: > NSASCIIStringEncoding], "raw", &err); > + handleAnyDeviceErrors(err); > + } > +} > + > +/* Restarts QEMU */ > +- (void)restartQemu:(id)sender > +{ > + qemu_system_reset_request(); > +} > + > +/* Switches QEMU to use the real cdrom drive */ > +- (void)useRealCdrom:(id)sender > +{ > + Error *err = NULL; > + qmp_change_blockdev(cdrom_drive_name, "/dev/cdrom", "raw", &err); > + handleAnyDeviceErrors(err); > +} > + > +/* Verifies if the user really wants to quit */ > +- (void)verifyQuit:(id)sender > +{ > + NSInteger response; > + response = NSRunAlertPanel(@"Quit?", @"Are you sure you want to quit?", > @"Cancel", @"Quit", nil); > + if(response == NSAlertAlternateReturn) > + qmp_quit(NULL); > +} > + > +/* Powers down the emulator */ > +- (void)powerDown:(id)sender > +{ > + qmp_system_powerdown(NULL); > +} > + > +/* Displays the word pause on the screen */ > +- (void)displayPause > +{ > + /* Coordinates have to be calculated each time because the window can > change its size */ > + int xCoord, yCoord, width, height; > + xCoord = ([normalWindow frame].size.width - [pause_label > frame].size.width)/2; > + yCoord = [normalWindow frame].size.height - [pause_label > frame].size.height - ([pause_label frame].size.height * .5); > + width = [pause_label frame].size.width; > + height = [pause_label frame].size.height; > + [pause_label setFrame: NSMakeRect(xCoord, yCoord, width, height)]; > + [cocoaView addSubview: pause_label]; > +} > + > +/* Removes the word pause from the screen */ > +- (void)removePause > +{ > + [pause_label removeFromSuperview]; > +} > + > @end > > > @@ -997,7 +1230,7 @@ int main (int argc, const char * argv[]) { > [menuItem > setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; > [menu addItemWithTitle:@"Show All" > action:@selector(unhideAllApplications:) keyEquivalent:@""]; // Show All > [menu addItem:[NSMenuItem separatorItem]]; //Separator > - [menu addItemWithTitle:@"Quit QEMU" action:@selector(terminate:) > keyEquivalent:@"q"]; > + [menu addItemWithTitle:@"Quit QEMU" action:@selector(verifyQuit:) > keyEquivalent:@"q"]; > menuItem = [[NSMenuItem alloc] initWithTitle:@"Apple" action:nil > keyEquivalent:@""]; > [menuItem setSubmenu:menu]; > [[NSApp mainMenu] addItem:menuItem]; > @@ -1128,4 +1361,7 @@ void cocoa_display_init(DisplayState *ds, int > full_screen) > > // register cleanup function > atexit(cocoa_cleanup); > + > + /* Creates and adds the Machine menu to the menubar */ > + createMachineMenu(); > } > -- > 1.7.5.4 >