[AD] allegro extension for other languages

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


While trying to get Allegro to work in OSX under mzscheme I had to hack
the osx internals a little bit. The basic hack is to not let OS X start
up a normal Cocoa run loop, but rather let mzscheme call the update()
method repeatedly to pump events from OS X into Allegro. Even though its
simple this took me a while to come up with and I thought maybe it could
be part of Allegro so other people can benefit from it. If its in the
source it wont affect any other applications at all, someone would have
to explicitly call the methods involved to affect anything. Im not sure
what other languages like AlPy are doing to get Allegro working in OS X
if they are at all but I imagine its something similar.

Attached is the source in its current ugly form.
#include "allegro.h"
#include "allegro/internal/aintern.h"
#include "allegro/platform/aintosx.h"

#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach_port.h>
#include <servers/bootstrap.h>

extern int    __crt0_argc;
extern char **__crt0_argv;
extern NSBundle *osx_bundle;
extern void* osx_event_mutex;
extern NSCursor *osx_cursor;
extern NSCursor *osx_blank_cursor;
extern AllegroWindow *osx_window;
extern void (*osx_window_close_hook)(void);
extern int osx_gfx_mode;
extern int osx_emulate_mouse_buttons;
extern int osx_window_first_expose;

@interface MyApp : NSApplication
@end

/* the run method doesnt do anything really except create a mutex that
 * is used in other places. The "run" loop is implemented by repeated
 * calls to the update() method below. This can be done from mzscheme
 * or from a thread spawned in the C code.
 */
@implementation MyApp
- (void) run
{
   osx_event_mutex=_unix_create_mutex();
   [self finishLaunching];
   // printf( "App finished launching\n" );
}

/* i dont know what this does but I guess its important */
- (void)applicationDidChangeScreenParameters: (NSNotification *)aNotification
{
   CFDictionaryRef mode;
   int new_refresh_rate;
   
   if ((osx_window) && (osx_gfx_mode == OSX_GFX_WINDOW)) 
   {
      osx_setup_colorconv_blitter();
      [osx_window display];
   }
   /*
   mode = CGDisplayCurrentMode(kCGDirectMainDisplay);
   CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberSInt32Type, &new_refresh_rate);
   if (new_refresh_rate <= 0)
      new_refresh_rate = 70;
   refresh_rate = new_refresh_rate;
   */
}

/* method for just polling the event queue */
- (void) update_event
{
	_unix_lock_mutex(osx_event_mutex);
	osx_event_handler();
	_unix_unlock_mutex(osx_event_mutex);
}

/* method for just updating the screen. theoretically this only
 * needs to be called after the screen is modified via some draw function
 * or a blit( screen, ... ). If updating the screen is slow then it
 * shouldnt be updated in the same function as polling the event queue
 * which is why the two functions are split up
 */
- (void) update_screen
{
	if (osx_gfx_mode == OSX_GFX_WINDOW)
		osx_update_dirty_lines();
	_unix_lock_mutex(osx_event_mutex);
	if (osx_gfx_mode == OSX_GFX_FULL) {
		if ((osx_palette) && (osx_palette_dirty)) {
			CGDisplaySetPalette(kCGDirectMainDisplay, osx_palette);
			osx_palette_dirty = FALSE;
		}
	}
	_unix_unlock_mutex(osx_event_mutex);
}

// - (void) update: ( NSTimer *)  timer
/* update the event queue and the screen in the same function */
- (void) update
{
	// printf( "Update\n" );
	/*
	struct timeval time;
	gettimeofday( &time, NULL );
	printf( "Time = %d\n", time.tv_usec );
	*/
	if (osx_gfx_mode == OSX_GFX_WINDOW)
		osx_update_dirty_lines();
	_unix_lock_mutex(osx_event_mutex);
	if (osx_gfx_mode == OSX_GFX_FULL) {
		if ((osx_palette) && (osx_palette_dirty)) {
			CGDisplaySetPalette(kCGDirectMainDisplay, osx_palette);
			osx_palette_dirty = FALSE;
		}
	}
	osx_event_handler();
	_unix_unlock_mutex(osx_event_mutex);
}
@end

/* set the name of the program to 'mzscheme' and set up the NSApplication
 * to make Cocoa happy
 */
void osx_startup( const char * name ){
	__crt0_argv = (char **)malloc( sizeof(char*) );
	__crt0_argv[ 0 ] = name;
	osx_bootstrap_ok();
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	[MyApp sharedApplication];
	[NSApp run];
}

/* helper functions to call the update methods */
void osx_update_event(){
	[NSApp update_event];
}

void osx_update_screen(){
	[NSApp update_screen];
}

void osx_update(){
	// printf( "osx_update\n" );
	[NSApp update];
}

/* try to schedule the update method to be called repeatedly by Cocoa itself.
 * this doesnt really work since we took over the run method so Cocoa doesnt
 * get a chance to perform its own functions, such as calling timers
 */
void osx_begin_update() {
	printf( "Begin updating\n" );
	[NSTimer scheduledTimerWithTimeInterval: 1.0/70.0 target: NSApp selector: @selector(update:) userInfo: nil repeats: YES];
}


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/