Search
lxdream.org :: lxdream/src/cocoaui/cocoaui.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/cocoaui/cocoaui.c
changeset 686:afd1bd3f1acc
prev685:fa1589b42be7
next691:ad3356543392
author nkeynes
date Sat Jun 14 11:54:15 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Change colour params to float
Convert background processing over to scene structure (fixes some depth issues as well)
Add color unclamp when supported
file annotate diff log raw
nkeynes@681
     1
/**
nkeynes@681
     2
 * $Id$
nkeynes@681
     3
 *
nkeynes@681
     4
 * Core Cocoa-based user interface
nkeynes@681
     5
 *
nkeynes@681
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@681
     7
 *
nkeynes@681
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@681
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@681
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@681
    11
 * (at your option) any later version.
nkeynes@681
    12
 *
nkeynes@681
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@681
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@681
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@681
    16
 * GNU General Public License for more details.
nkeynes@681
    17
 */
nkeynes@681
    18
nkeynes@681
    19
#include <AppKit/AppKit.h>
nkeynes@681
    20
#include <stdio.h>
nkeynes@681
    21
#include <stdlib.h>
nkeynes@685
    22
#include <string.h>
nkeynes@681
    23
#include <sys/time.h>
nkeynes@681
    24
#include "lxdream.h"
nkeynes@681
    25
#include "dreamcast.h"
nkeynes@681
    26
#include "dream.h"
nkeynes@681
    27
#include "gui.h"
nkeynes@681
    28
#include "cocoaui/cocoaui.h"
nkeynes@681
    29
nkeynes@681
    30
void cocoa_gui_update( void );
nkeynes@681
    31
void cocoa_gui_start( void );
nkeynes@681
    32
void cocoa_gui_stop( void );
nkeynes@681
    33
void cocoa_gui_run_later( void );
nkeynes@681
    34
uint32_t cocoa_gui_run_slice( uint32_t nanosecs );
nkeynes@681
    35
nkeynes@681
    36
struct dreamcast_module cocoa_gui_module = { "gui", NULL,
nkeynes@681
    37
                  cocoa_gui_update, 
nkeynes@681
    38
                  cocoa_gui_start, 
nkeynes@681
    39
                  cocoa_gui_run_slice, 
nkeynes@681
    40
                  cocoa_gui_stop, 
nkeynes@681
    41
                  NULL, NULL };
nkeynes@681
    42
nkeynes@681
    43
/**
nkeynes@681
    44
 * Count of running nanoseconds - used to cut back on the GUI runtime
nkeynes@681
    45
 */
nkeynes@681
    46
static uint32_t cocoa_gui_nanos = 0;
nkeynes@681
    47
static uint32_t cocoa_gui_ticks = 0;
nkeynes@681
    48
static struct timeval cocoa_gui_lasttv;
nkeynes@681
    49
static BOOL cocoa_gui_autorun = NO;
nkeynes@681
    50
nkeynes@681
    51
@interface NSApplication (PrivateAdditions)
nkeynes@681
    52
- (void) setAppleMenu:(NSMenu *)aMenu;
nkeynes@681
    53
@end
nkeynes@681
    54
nkeynes@681
    55
static void cocoa_gui_create_menu(void)
nkeynes@681
    56
{
nkeynes@681
    57
    NSMenu *appleMenu, *services;
nkeynes@681
    58
    NSMenuItem *menuItem;
nkeynes@681
    59
    NSString *title;
nkeynes@681
    60
    NSString *appName;
nkeynes@681
    61
    
nkeynes@681
    62
    appName = @"Lxdream";
nkeynes@681
    63
    appleMenu = [[NSMenu alloc] initWithTitle:@""];
nkeynes@681
    64
nkeynes@681
    65
    /* Add menu items */
nkeynes@681
    66
    title = [@"About " stringByAppendingString:appName];
nkeynes@681
    67
    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
nkeynes@681
    68
    [appleMenu addItem:[NSMenuItem separatorItem]];
nkeynes@681
    69
nkeynes@681
    70
    // Services Menu
nkeynes@681
    71
    services = [[[NSMenu alloc] init] autorelease];
nkeynes@681
    72
    [appleMenu addItemWithTitle:@"Services" action:nil keyEquivalent:@""];
nkeynes@681
    73
    [appleMenu setSubmenu: services forItem: [appleMenu itemWithTitle: @"Services"]];
nkeynes@681
    74
nkeynes@681
    75
    // Hide AppName
nkeynes@681
    76
    title = [@"Hide " stringByAppendingString:appName];
nkeynes@681
    77
    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
nkeynes@681
    78
nkeynes@681
    79
    // Hide Others
nkeynes@681
    80
    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" 
nkeynes@681
    81
                                                  action:@selector(hideOtherApplications:) 
nkeynes@681
    82
                                           keyEquivalent:@"h"];
nkeynes@681
    83
    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
nkeynes@681
    84
nkeynes@681
    85
    // Show All
nkeynes@681
    86
    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
nkeynes@681
    87
    [appleMenu addItem:[NSMenuItem separatorItem]];
nkeynes@681
    88
nkeynes@681
    89
    // Quit AppName
nkeynes@681
    90
    title = [@"Quit " stringByAppendingString:appName];
nkeynes@681
    91
    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
nkeynes@681
    92
nkeynes@681
    93
    /* Put menu into the menubar */
nkeynes@681
    94
    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil  keyEquivalent:@""];
nkeynes@681
    95
    [menuItem setSubmenu: appleMenu];
nkeynes@681
    96
    NSMenu *menu = [NSMenu new];
nkeynes@681
    97
    [menu addItem: menuItem];
nkeynes@681
    98
    
nkeynes@681
    99
    NSMenu *fileMenu = [[NSMenu alloc] initWithTitle: NS_("File")];
nkeynes@681
   100
    [fileMenu addItemWithTitle: NS_("Load Binary") action: @selector(load_binary_action:) keyEquivalent: @"b"];
nkeynes@681
   101
    [fileMenu addItemWithTitle: NS_("GD-Rom") action: @selector(mount_action:) keyEquivalent: @"g"];
nkeynes@681
   102
    [fileMenu addItem: [NSMenuItem separatorItem]];
nkeynes@681
   103
    [[fileMenu addItemWithTitle: NS_("Reset") action: @selector(reset_action:) keyEquivalent: @"r"]
nkeynes@681
   104
      setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
nkeynes@681
   105
    [fileMenu addItemWithTitle: NS_("Pause") action: @selector(pause_action:) keyEquivalent: @"p"];
nkeynes@681
   106
    [fileMenu addItemWithTitle: NS_("Resume") action: @selector(run_action:) keyEquivalent: @"r"];
nkeynes@681
   107
    [fileMenu addItem: [NSMenuItem separatorItem]];
nkeynes@681
   108
    [fileMenu addItemWithTitle: NS_("Load State") action: @selector(load_action:) keyEquivalent: @"o"];
nkeynes@681
   109
    [fileMenu addItemWithTitle: NS_("Save State") action: @selector(save_action:) keyEquivalent: @"s"];
nkeynes@681
   110
    
nkeynes@681
   111
    menuItem = [[NSMenuItem alloc] initWithTitle:NS_("File") action: nil keyEquivalent: @""];
nkeynes@681
   112
    [menuItem setSubmenu: fileMenu];
nkeynes@681
   113
    [menu addItem: menuItem];
nkeynes@681
   114
    
nkeynes@681
   115
    /* Tell the application object that this is now the application menu */
nkeynes@681
   116
    [NSApp setMainMenu: menu];
nkeynes@681
   117
    [NSApp setAppleMenu: appleMenu];
nkeynes@681
   118
    [NSApp setServicesMenu: services];
nkeynes@681
   119
nkeynes@681
   120
    /* Finally give up our references to the objects */
nkeynes@681
   121
    [appleMenu release];
nkeynes@681
   122
    [menuItem release];
nkeynes@681
   123
    [menu release];
nkeynes@681
   124
}
nkeynes@681
   125
nkeynes@681
   126
@interface LxdreamDelegate : NSObject
nkeynes@681
   127
@end
nkeynes@681
   128
nkeynes@681
   129
@implementation LxdreamDelegate
nkeynes@681
   130
- (void)windowWillClose: (NSNotification *)notice
nkeynes@681
   131
{
nkeynes@681
   132
    dreamcast_shutdown();
nkeynes@681
   133
    exit(0);
nkeynes@681
   134
}
nkeynes@681
   135
- (void)windowDidBecomeMain: (NSNotification *)notice
nkeynes@681
   136
{
nkeynes@681
   137
    if( cocoa_gui_autorun ) {
nkeynes@681
   138
        cocoa_gui_autorun = NO;
nkeynes@681
   139
        cocoa_gui_run_later();
nkeynes@681
   140
    }
nkeynes@681
   141
}
nkeynes@681
   142
- (void) load_action: (id)sender
nkeynes@681
   143
{
nkeynes@681
   144
    NSOpenPanel *panel = [NSOpenPanel openPanel];
nkeynes@681
   145
    NSArray *fileTypes = [NSArray arrayWithObject: @"dst"];
nkeynes@681
   146
    int result = [panel runModalForDirectory: NSHomeDirectory() file: nil types: fileTypes];
nkeynes@681
   147
    if( result == NSOKButton && [[panel filenames] count] > 0 ) {
nkeynes@681
   148
        NSString *filename = [[panel filenames] objectAtIndex: 0];
nkeynes@681
   149
        dreamcast_load_state( [filename UTF8String] );
nkeynes@681
   150
    }
nkeynes@681
   151
}
nkeynes@681
   152
- (void) save_action: (id)sender
nkeynes@681
   153
{
nkeynes@681
   154
    NSSavePanel *panel = [NSSavePanel savePanel];
nkeynes@681
   155
    [panel setRequiredFileType: @"dst"];
nkeynes@681
   156
    int result = [panel runModalForDirectory: NSHomeDirectory() file:@""];
nkeynes@681
   157
    if( result == NSOKButton ) {
nkeynes@681
   158
        NSString *filename = [panel filename];
nkeynes@681
   159
        dreamcast_save_state( [filename UTF8String] );
nkeynes@681
   160
    }
nkeynes@681
   161
}
nkeynes@681
   162
- (void) load_binary_action: (id)sender
nkeynes@681
   163
{
nkeynes@681
   164
    NSOpenPanel *panel = [NSOpenPanel openPanel];
nkeynes@681
   165
    int result = [panel runModalForDirectory: NSHomeDirectory() file: nil types: nil];
nkeynes@681
   166
    if( result == NSOKButton && [[panel filenames] count] > 0 ) {
nkeynes@681
   167
        NSString *filename = [[panel filenames] objectAtIndex: 0];
nkeynes@681
   168
        file_load_magic( [filename UTF8String] );
nkeynes@681
   169
    }
nkeynes@681
   170
}
nkeynes@681
   171
- (void) mount_action: (id)sender
nkeynes@681
   172
{
nkeynes@681
   173
    NSOpenPanel *panel = [NSOpenPanel openPanel];
nkeynes@681
   174
    int result = [panel runModalForDirectory: NSHomeDirectory() file: nil types: nil];
nkeynes@681
   175
    if( result == NSOKButton && [[panel filenames] count] > 0 ) {
nkeynes@681
   176
        NSString *filename = [[panel filenames] objectAtIndex: 0];
nkeynes@681
   177
        gdrom_mount_image( [filename UTF8String] );
nkeynes@681
   178
    }
nkeynes@681
   179
}
nkeynes@681
   180
- (void) pause_action: (id)sender
nkeynes@681
   181
{
nkeynes@681
   182
    dreamcast_stop();
nkeynes@681
   183
}
nkeynes@681
   184
nkeynes@681
   185
- (void) reset_action: (id)sender
nkeynes@681
   186
{
nkeynes@681
   187
    dreamcast_reset();
nkeynes@681
   188
}
nkeynes@681
   189
- (void) run_action: (id)sender
nkeynes@681
   190
{
nkeynes@681
   191
    cocoa_gui_run_later();
nkeynes@681
   192
}
nkeynes@681
   193
- (void) run_immediate
nkeynes@681
   194
{
nkeynes@681
   195
    dreamcast_run();
nkeynes@681
   196
}
nkeynes@681
   197
@end
nkeynes@681
   198
nkeynes@681
   199
nkeynes@681
   200
gboolean gui_parse_cmdline( int *argc, char **argv[] )
nkeynes@681
   201
{
nkeynes@685
   202
    /* If started from the finder, the first (and only) arg will look something like 
nkeynes@685
   203
    * -psn_0_... - we want to remove this so that lxdream doesn't try to process it 
nkeynes@685
   204
    * normally
nkeynes@685
   205
    */
nkeynes@685
   206
    if( *argc == 2 && strncmp((*argv)[1], "-psn_", 5) == 0 ) {
nkeynes@685
   207
        *argc = 1;
nkeynes@685
   208
    }
nkeynes@685
   209
    return TRUE;
nkeynes@681
   210
}
nkeynes@681
   211
nkeynes@681
   212
gboolean gui_init( gboolean withDebug )
nkeynes@681
   213
{
nkeynes@681
   214
    dreamcast_register_module( &cocoa_gui_module );
nkeynes@681
   215
    
nkeynes@681
   216
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
nkeynes@681
   217
    [NSApplication sharedApplication];
nkeynes@681
   218
    LxdreamDelegate *delegate = [[LxdreamDelegate alloc] init];
nkeynes@681
   219
    [NSApp setDelegate: delegate];
nkeynes@686
   220
    NSString *iconFile = [[NSBundle mainBundle] pathForResource:@"dcemu" ofType:@"gif"];
nkeynes@686
   221
    NSImage *iconImage = [[NSImage alloc] initWithContentsOfFile: iconFile];
nkeynes@686
   222
    [NSApp setApplicationIconImage: iconImage];   
nkeynes@681
   223
    cocoa_gui_create_menu();
nkeynes@681
   224
    NSWindow *window = cocoa_gui_create_main_window();
nkeynes@681
   225
    [window makeKeyAndOrderFront: nil];
nkeynes@681
   226
    [NSApp activateIgnoringOtherApps: YES];   
nkeynes@681
   227
    [pool release];
nkeynes@681
   228
}
nkeynes@681
   229
nkeynes@681
   230
void gui_main_loop( gboolean run )
nkeynes@681
   231
{
nkeynes@681
   232
    if( run ) {
nkeynes@681
   233
        cocoa_gui_autorun = YES;
nkeynes@681
   234
        /*
nkeynes@681
   235
             */
nkeynes@681
   236
    }
nkeynes@681
   237
	[NSApp run];
nkeynes@681
   238
}
nkeynes@681
   239
nkeynes@681
   240
void gui_update_state(void)
nkeynes@681
   241
{
nkeynes@681
   242
    cocoa_gui_update();
nkeynes@681
   243
}
nkeynes@681
   244
nkeynes@681
   245
gboolean gui_error_dialog( const char *msg, ... )
nkeynes@681
   246
{
nkeynes@685
   247
    NSString *error_string;
nkeynes@685
   248
    
nkeynes@685
   249
    va_list args;
nkeynes@685
   250
    va_start(args, msg);
nkeynes@685
   251
    error_string = [[NSString alloc] initWithFormat: [NSString stringWithCString: msg] arguments: args];
nkeynes@685
   252
    NSRunAlertPanel(@"Error in lxdream", error_string, nil, nil, nil);
nkeynes@685
   253
    va_end(args);
nkeynes@681
   254
}
nkeynes@681
   255
nkeynes@681
   256
void gui_update_io_activity( io_activity_type io, gboolean active )
nkeynes@681
   257
{
nkeynes@681
   258
nkeynes@681
   259
}
nkeynes@681
   260
nkeynes@681
   261
nkeynes@681
   262
uint32_t cocoa_gui_run_slice( uint32_t nanosecs )
nkeynes@681
   263
{
nkeynes@681
   264
    NSEvent *event;
nkeynes@681
   265
    NSAutoreleasePool *pool;
nkeynes@681
   266
nkeynes@681
   267
    cocoa_gui_nanos += nanosecs;
nkeynes@681
   268
    if( cocoa_gui_nanos > GUI_TICK_PERIOD ) { /* 10 ms */
nkeynes@681
   269
        cocoa_gui_nanos -= GUI_TICK_PERIOD;
nkeynes@681
   270
        cocoa_gui_ticks ++;
nkeynes@681
   271
        uint32_t current_period = cocoa_gui_ticks * GUI_TICK_PERIOD;
nkeynes@681
   272
nkeynes@681
   273
        // Run the event loop
nkeynes@681
   274
        pool = [NSAutoreleasePool new];
nkeynes@681
   275
        while( (event = [NSApp nextEventMatchingMask: NSAnyEventMask untilDate: nil 
nkeynes@681
   276
                         inMode: NSDefaultRunLoopMode dequeue: YES]) != nil ) {
nkeynes@681
   277
            [NSApp sendEvent: event];
nkeynes@681
   278
        }
nkeynes@681
   279
        [pool release];
nkeynes@681
   280
nkeynes@681
   281
        struct timeval tv;
nkeynes@681
   282
        gettimeofday(&tv,NULL);
nkeynes@681
   283
        uint32_t ns = ((tv.tv_sec - cocoa_gui_lasttv.tv_sec) * 1000000000) + 
nkeynes@681
   284
        (tv.tv_usec - cocoa_gui_lasttv.tv_usec)*1000;
nkeynes@681
   285
        if( (ns * 1.05) < current_period ) {
nkeynes@681
   286
            // We've gotten ahead - sleep for a little bit
nkeynes@681
   287
            struct timespec tv;
nkeynes@681
   288
            tv.tv_sec = 0;
nkeynes@681
   289
            tv.tv_nsec = current_period - ns;
nkeynes@681
   290
            nanosleep(&tv, &tv);
nkeynes@681
   291
        }
nkeynes@681
   292
nkeynes@681
   293
        /* Update the display every 10 ticks (ie 10 times a second) and 
nkeynes@681
   294
         * save the current tv value */
nkeynes@681
   295
        if( cocoa_gui_ticks > 10 ) {
nkeynes@681
   296
            gchar buf[32];
nkeynes@681
   297
            cocoa_gui_ticks -= 10;
nkeynes@681
   298
nkeynes@681
   299
            double speed = (float)( (double)current_period * 100.0 / ns );
nkeynes@681
   300
            cocoa_gui_lasttv.tv_sec = tv.tv_sec;
nkeynes@681
   301
            cocoa_gui_lasttv.tv_usec = tv.tv_usec;
nkeynes@681
   302
            snprintf( buf, 32, _("Running (%2.4f%%)"), speed );
nkeynes@681
   303
            [((LxdreamMainWindow *)[NSApp mainWindow]) setStatusText: buf];
nkeynes@681
   304
nkeynes@681
   305
        }
nkeynes@681
   306
    }
nkeynes@681
   307
    return nanosecs;
nkeynes@681
   308
}
nkeynes@681
   309
nkeynes@681
   310
void cocoa_gui_update( void )
nkeynes@681
   311
{
nkeynes@681
   312
    
nkeynes@681
   313
}
nkeynes@681
   314
nkeynes@681
   315
void cocoa_gui_start( void )
nkeynes@681
   316
{
nkeynes@681
   317
    LxdreamMainWindow *win = (LxdreamMainWindow *)[NSApp mainWindow];
nkeynes@681
   318
    [win setRunning: YES];
nkeynes@681
   319
    cocoa_gui_nanos = 0;
nkeynes@681
   320
    gettimeofday(&cocoa_gui_lasttv,NULL);
nkeynes@681
   321
}
nkeynes@681
   322
nkeynes@681
   323
void cocoa_gui_stop( void )
nkeynes@681
   324
{
nkeynes@681
   325
    LxdreamMainWindow *win = (LxdreamMainWindow *)[NSApp mainWindow];
nkeynes@681
   326
    [win setRunning: NO];
nkeynes@681
   327
}
nkeynes@681
   328
nkeynes@681
   329
/**
nkeynes@681
   330
 * Queue a dreamcast_run() to execute after the currently event(s)
nkeynes@681
   331
 */
nkeynes@681
   332
void cocoa_gui_run_later( void )
nkeynes@681
   333
{
nkeynes@681
   334
    [[NSRunLoop currentRunLoop] performSelector: @selector(run_immediate) 
nkeynes@681
   335
         target: [NSApp delegate] argument: nil order: 1 
nkeynes@681
   336
         modes: [NSArray arrayWithObject: NSDefaultRunLoopMode] ];
nkeynes@681
   337
}
.