help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] Re: Cairo + SDL


From: Paolo Bonzini
Subject: [Help-smalltalk] Re: Cairo + SDL
Date: Wed, 16 Apr 2008 17:38:46 +0200
User-agent: Thunderbird 2.0.0.12 (Macintosh/20080213)

Tony Garnock-Jones wrote:
Paolo Bonzini wrote:
Seriously, I think we can make a different package (something like
CocoaApp) that does the same things as SDLmain.m (see
http://fisheye1.cenqua.com/browse/~raw,r=1.1/twin-e/twin-e/SDLMain.m for
the source), and make it a prerequisite of SDL on Mac OS X.

That is a good idea.

We might want to retain two binaries, though, one with and one without
SDL support

The attached proof-of-concept is more similar to what I had in mind: do the MacOS-specific stuff in a module, so that we can just run your EventSource code (with some contortions) in a separate process.

The first patch includes the C and ObjC code, the second is the modifications that are needed for your demos to work (some modifications are because I load Brad's bindings in a separate SDL.LibSDL namespace).

The main problem I still have is that snapshots don't work but I don't have time now to look at it.

Paolo
diff --git a/configure.ac b/configure.ac
index 879907f..8953750 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,13 @@ case "$host" in
   alpha*-*-*) CFLAGS="$CFLAGS -mieee" ;;
 esac
 
+# We don't require Automake 1.10, so invoke _AM_DEPENDENCIES manually.  And
+# since we actually use Objective-C only on Mac OS (for libsdl), for now we
+# get by with using gcc as an Objective-C compiler.
+AC_SUBST(OBJC, [$CC])
+AC_SUBST(OBJCFLAGS, [$CFLAGS])
+_AM_DEPENDENCIES(OBJC)
+
 AC_PROG_SED
 AC_PROG_AWK
 AC_PROG_LN_S
@@ -387,6 +394,17 @@ GST_PACKAGE_ENABLE([NCurses],
   [ac_cv_lib_ncurses_initscr])
 GST_PACKAGE_ENABLE([NetClients], [net])
 GST_PACKAGE_ENABLE([DhbNumericalMethods], [numerics])
+
+GST_PACKAGE_ENABLE([LibSDL], [sdl/libsdl],
+  [AM_PATH_SDL([], gst_cv_sdl=yes, gst_cv_sdl=no)
+  case "$SDL_LIBS" in
+    *-framework,Cocoa* | *"-framework Cocoa"*) gst_cv_sdl_uses_cocoa=yes ;;
+    *) gst_cv_sdl_uses_cocoa=no ;;
+  esac
+  AM_CONDITIONAL([HAVE_COCOA], [test $gst_cv_sdl_uses_cocoa = yes])],
+  [gst_cv_sdl],
+  [Makefile], [sdl.la])
+
 GST_PACKAGE_ENABLE([Compiler], [stinst/compiler])
 GST_PACKAGE_ENABLE([Parser], [stinst/parser])
 GST_PACKAGE_ENABLE([ClassPublisher], [stinst/doc])
diff --git a/main.c b/main.c
index 5f07bf1..18341ea 100644
--- a/main.c
+++ b/main.c
@@ -339,7 +339,12 @@ main(int argc, const char **argv)
     (struct loaded_file *) alloca (sizeof (struct loaded_file) * argc);
 
   gst_set_executable_path (argv[0]);
-  parse_args (argc, argv);
+#ifdef __APPLE__
+  if (argc >= 2 && strncmp (argv[1], "-psn", 4) == 0)
+    gst_smalltalk_args (argc - 1, argv + 1);
+  else
+#endif
+    parse_args (argc, argv);
 
   /* These might go away in the next release.  */
   if (!kernel_dir)
diff --git a/packages/sdl/libsdl/Makefile.am b/packages/sdl/libsdl/Makefile.am
new file mode 100644
index 0000000..e449f97
--- /dev/null
+++ b/packages/sdl/libsdl/Makefile.am
@@ -0,0 +1,15 @@
+gst_module_ldflags = -rpath $(moduledir) -release $(VERSION) -module \
+        -no-undefined -export-symbols-regex gst_initModule
+
+module_LTLIBRARIES = sdl.la
+sdl_la_SOURCES = gst-sdl.c
+sdl_la_LIBADD = $(SDL_LIBS)
+sdl_la_LDFLAGS = $(gst_module_ldflags)
+
+if HAVE_COCOA
+sdl_la_SOURCES += gst-sdlmain-cocoa.m
+endif
+
+noinst_HEADERS = gst-sdl.h
+
+AM_CPPFLAGS = -I$(top_srcdir)/libgst -I$(top_srcdir)/lib-src $(SDL_CFLAGS)
diff --git a/packages/sdl/libsdl/SDL.st b/packages/sdl/libsdl/SDL.st
index 5b72336..6bbf820 100644
--- a/packages/sdl/libsdl/SDL.st
+++ b/packages/sdl/libsdl/SDL.st
@@ -69,6 +69,30 @@ sdlInitEverything
 
 !Sdl class methodsFor: 'C call-outs'!
 
+sdlForkEventLoop: aBlock
+    "Execute aBlock within an SDL event loop.  Returns only when
+     #sdlStopEventLoop is called, but forks aBlock in a separate Smalltalk
+     process."
+
+    | s |
+    s := Semaphore new.
+    self sdlStartEventLoop: [
+       [aBlock ensure: [s signal]] fork].
+    s wait!
+
+sdlStartEventLoop: aBlock
+    "Execute aBlock within an SDL event loop.  Returns only #sdlStopEventLoop
+     is called, but calls aBlock."
+
+    <cCall: 'SDL_StartEventLoop' returning: #void 
+        args: #( #smalltalk )>!
+
+sdlStopEventLoop
+    "Tell SDL to stop the event loop."
+
+    <cCall: 'SDL_StopEventLoop' returning: #void 
+        args: #( )>!
+
 sdlInit: aUint
     "I Initialize SDL. My c function call prototype:
 
diff --git a/packages/sdl/libsdl/gst-sdl.c b/packages/sdl/libsdl/gst-sdl.c
new file mode 100644
index 0000000..95e1a8f
--- /dev/null
+++ b/packages/sdl/libsdl/gst-sdl.c
@@ -0,0 +1,48 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst-sdl.h"
+
+VMProxy *vmProxy;
+
+/* MacOS versions are Objective-C, so they are in sdlmain_cocoa.m.  */
+#ifndef __APPLE__
+int
+gst_SDL_Init (Uint32 flags)
+{
+  int rc = SDL_Init (flags);
+  if (rc < 0)
+    return rc;
+
+#ifdef _WIN32
+  /* Some more work is needed under Win32.  */
+  SDL_SetModuleHandle (GetModuleHandle(NULL));
+#endif
+
+  atexit (SDL_Quit);
+  return rc;
+}
+    
+void
+gst_SDL_StartEventLoop (OOP blockOOP)
+{
+  vmProxy->strMsgSend (blockOOP, "value", NULL);
+}
+
+void
+gst_SDL_StopEventLoop (void)
+{
+}
+#endif
+
+/* Module initialization function.  */
+
+void
+gst_initModule (VMProxy * proxy)
+{
+  vmProxy = proxy;
+  vmProxy->defineCFunc ("SDL_Init", gst_SDL_Init);
+  vmProxy->defineCFunc ("SDL_StartEventLoop", gst_SDL_StartEventLoop);
+  vmProxy->defineCFunc ("SDL_StopEventLoop", gst_SDL_StopEventLoop);
+}
diff --git a/packages/sdl/libsdl/gst-sdl.h b/packages/sdl/libsdl/gst-sdl.h
new file mode 100644
index 0000000..65503d3
--- /dev/null
+++ b/packages/sdl/libsdl/gst-sdl.h
@@ -0,0 +1,12 @@
+#ifndef GST_SDL_H
+#define GST_SDL_H 1
+
+#include <SDL.h>
+#include "gstpub.h"
+
+extern VMProxy *vmProxy;
+extern int gst_SDL_Init (Uint32 flags);
+extern void gst_SDL_StartEventLoop (OOP blockOOP);
+extern void gst_SDL_StopEventLoop (void);
+
+#endif
diff --git a/packages/sdl/libsdl/gst-sdlmain-cocoa.m 
b/packages/sdl/libsdl/gst-sdlmain-cocoa.m
new file mode 100644
index 0000000..fa11624
--- /dev/null
+++ b/packages/sdl/libsdl/gst-sdlmain-cocoa.m
@@ -0,0 +1,144 @@
+#import "gst-sdl.h"
+#import <Cocoa/Cocoa.h>
+#import <unistd.h>
+
+/* An internal Apple class used to setup Apple menus */
address@hidden NSAppleMenuController:NSObject {}
+- (void)controlMenu:(NSMenu *)aMenu;
address@hidden
+
address@hidden GSTCocoaMainApplication : NSApplication
address@hidden
+
address@hidden GSTCocoaMain : NSObject
address@hidden
+
+
+static OOP                     eventLoopBlockOOP;
+static NSAutoreleasePool       *pool;
+static GSTCocoaMain            *cocoaMain;
+
address@hidden GSTCocoaMainApplication
+/* Invoked from the Quit menu item */
+- (void)terminate:(id)sender
+{
+  /* Post a SDL_QUIT event */
+  SDL_Event event;
+  event.type = SDL_QUIT;
+  SDL_PushEvent(&event);
+}
address@hidden
+
+
+/* The main class of the application, the application's delegate */
address@hidden GSTCocoaMain
+
+
+void setup_apple_menu(void)
+{
+  /* warning: this code is very odd */
+  NSAppleMenuController *appleMenuController;
+  NSMenu *appleMenu;
+  NSMenuItem *appleMenuItem;
+
+  appleMenuController = [[NSAppleMenuController alloc] init];
+  appleMenu = [[NSMenu alloc] initWithTitle:@""];
+  appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil 
keyEquivalent:@""];
+  
+  [appleMenuItem setSubmenu:appleMenu];
+
+  /* yes, we do need to add it and then remove it --
+     if you don't add it, it doesn't get displayed
+     if you don't remove it, you have an extra, titleless item in the menubar
+     when you remove it, it appears to stick around
+     very, very odd */
+  [[NSApp mainMenu] addItem:appleMenuItem];
+  [appleMenuController controlMenu:appleMenu];
+  [[NSApp mainMenu] removeItem:appleMenuItem];
+  [appleMenu release];
+  [appleMenuItem release];
+}
+
+/* Create a window menu */
+void setup_window_menu(void)
+{
+  NSMenu               *windowMenu;
+  NSMenuItem   *windowMenuItem;
+  NSMenuItem   *menuItem;
+
+
+  windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+  
+  /* "Minimize" item */
+  menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" 
action:@selector(performMiniaturize:) keyEquivalent:@"m"];
+  [windowMenu addItem:menuItem];
+  [menuItem release];
+  
+  /* Put menu into the menubar */
+  windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil 
keyEquivalent:@""];
+  [windowMenuItem setSubmenu:windowMenu];
+  [[NSApp mainMenu] addItem:windowMenuItem];
+  
+  /* Tell the application object that this is now the window menu */
+  [NSApp setWindowsMenu:windowMenu];
+
+  /* Finally give up our references to the objects */
+  [windowMenu release];
+  [windowMenuItem release];
+}
+
+static void gst_SDL_Quit ()
+{
+  SDL_Quit ();
+  [cocoaMain release];
+  [pool release];
+}
+
+/* Replacement for NSApplicationMain */
+int
+gst_SDL_Init (Uint32 flags)
+{
+  int rc;
+  pool = [[NSAutoreleasePool alloc] init];
+
+  /* Ensure the application object is initialised */
+  [GSTCocoaMainApplication sharedApplication];
+    
+  /* Set up the menubar */
+  [NSApp setMainMenu:[[NSMenu alloc] init]];
+  setup_apple_menu();
+  setup_window_menu();
+    
+  /* Create GSTCocoaMain and make it the app delegate */
+  cocoaMain = [[GSTCocoaMain alloc] init];
+  [NSApp setDelegate:cocoaMain];
+
+  rc = SDL_Init (flags);
+  if (rc < 0)
+    return rc;
+
+  atexit (gst_SDL_Quit);
+  return rc;
+}
+    
+void
+gst_SDL_StartEventLoop (OOP blockOOP)
+{
+  eventLoopBlockOOP = blockOOP;
+
+  /* Start the main event loop */
+  [NSApp run];
+}
+
+void
+gst_SDL_StopEventLoop (void)
+{
+  [NSApp stop: NSApp];
+}
+
+/* Called when the internal event loop has just started running */
+- (void) applicationDidFinishLaunching: (NSNotification *) note
+{
+  vmProxy->strMsgSend (eventLoopBlockOOP, "value", NULL);
+}
address@hidden
diff --git a/packages/sdl/libsdl/package.xml b/packages/sdl/libsdl/package.xml
index fcce902..90f9549 100644
--- a/packages/sdl/libsdl/package.xml
+++ b/packages/sdl/libsdl/package.xml
@@ -35,6 +35,7 @@
   <library>libSDL_net</library>
   <library>libSDL_sound</library>
   <library>libSDL_ttf</library>
+  <module>sdl</module>
 
   <file>CON_console.st</file>
   <file>DT_drawtext.st</file>
diff --git a/packages/sdl/libsdl/stamp-classes 
b/packages/sdl/libsdl/stamp-classes
new file mode 100644
index 0000000..e69de29
diff -ru cairo-tony/Display.st cairo-demos/Display.st
--- cairo-tony/Display.st       2008-01-25 16:30:21.000000000 +0100
+++ cairo-demos/Display.st      2008-04-16 16:45:41.000000000 +0200
@@ -1,7 +1,7 @@
 Rectangle extend [
     withSdlRect: aBlock [
        | r |
-       r := SdlRect new.
+       r := SDL.LibSDL.SdlRect new.
        r x value: origin x.
        r y value: origin y.
        r w value: self width.
diff -ru cairo-tony/EventSource.st cairo-demos/EventSource.st
--- cairo-tony/EventSource.st   2008-01-20 20:54:01.000000000 +0100
+++ cairo-demos/EventSource.st  2008-04-16 17:19:52.000000000 +0200
@@ -175,16 +175,24 @@
     ]
 
     eventLoop [
-       | e |
-       loopRunning := true.
-       [ loopRunning ] whileTrue: [
-           e := self waitEvent.
-           self dispatchEvent: e.
-       ].
+       Sdl sdlStartEventLoop: [
+           | e |
+           loopRunning := true.
+           [ loopRunning ] whileTrue: [
+               e := self waitEvent.
+               self dispatchEvent: e.
+           ].
+       ]
+    ]
+
+    startEventLoop [
+       SdlKeyboard sdlEnableUnicode: 1.
+       [ self eventLoop ] fork name: 'SdlEventSource eventLoop'.
     ]
 
     interruptEventLoop [
        loopRunning := false.
+       Sdl sdlStopEventLoop.
     ]
 ].
 
@@ -196,13 +204,11 @@
     initialize [
        Instance := self new.
        ObjectMemory addDependent: self.
-       self update: #returnFromSnapshot.
     ]
 
     update: aspect [
        aspect == #returnFromSnapshot ifTrue: [
-           SdlKeyboard sdlEnableUnicode: 1.
-           [ Instance eventLoop ] fork name: 'SdlEventSource eventLoop'.
+           self instance handler isNil ifFalse: [ self instance startEventLoop 
].
            ^self].
        aspect == #aboutToQuit ifTrue: [
            Instance interruptEventLoop.
diff -ru cairo-tony/buttondemo.st cairo-demos/buttondemo.st
--- cairo-tony/buttondemo.st    2008-01-20 20:54:01.000000000 +0100
+++ cairo-demos/buttondemo.st   2008-04-16 17:03:44.000000000 +0200
@@ -621,20 +621,20 @@
     root [ ^root ]
 
     initialize [
-       recogniser := GestureRecogniser new target: self.
-       SdlEventSource instance handler: recogniser.
-
        context := CairoContext onSurface: (CairoSdlSurface onSdlForm: Display).
        renderSemaphore := Semaphore forMutualExclusion.
        invalidRect := nil.
        refreshPauseCount := 0.
-
        root := RootWidget new.
+       recogniser := GestureRecogniser new target: self.
+
        renderSemaphore name: 'World renderSemaphore'.
 
        renderProcess := [ self renderLoop ] fork.
        renderProcess terminateOnQuit.
        renderProcess name: 'World renderLoop'.
+
+       SdlEventSource instance handler: recogniser; startEventLoop.
     ]
 
     resume [
diff -ru cairo-tony/demo.st cairo-demos/demo.st
--- cairo-tony/demo.st  2008-01-28 21:56:13.000000000 +0100
+++ cairo-demos/demo.st 2008-04-16 16:55:49.000000000 +0200
@@ -27,7 +27,7 @@
   ]
 
   run [
-    SdlEventSource instance handler: self.
+    SdlEventSource instance handler: self; startEventLoop.
     self winningDirectAccess.
     self winningCairo.
 
diff -ru cairo-tony/loadscript.st cairo-demos/loadscript.st
--- cairo-tony/loadscript.st    2008-01-15 08:44:47.000000000 +0100
+++ cairo-demos/loadscript.st   2008-04-16 16:28:32.000000000 +0200
@@ -1,9 +1,5 @@
-FileStream fileIn: 'sdl/SDL.st'.
-FileStream fileIn: 'sdl/SDL_video.st'.
-FileStream fileIn: 'sdl/SDL_events.st'.
-FileStream fileIn: 'sdl/SDL_keyboard.st'.
-FileStream fileIn: 'sdl/SDL_keysym.st'.
-"FileStream fileIn: 'sdl/SDL_image.st'."
+PackageLoader fileInPackage: 'LibSDL'.
+Namespace current: SDL.LibSDL.
 
 FileStream fileIn: 'EventSource.st'.
 FileStream fileIn: 'Display.st'.
diff -ru cairo-tony/zowie.st cairo-demos/zowie.st
--- cairo-tony/zowie.st 2008-01-25 16:20:59.000000000 +0100
+++ cairo-demos/zowie.st        2008-04-16 17:07:14.000000000 +0200
@@ -17,7 +17,6 @@
         context := CairoContext onSurface: (CairoSdlSurface onSdlForm: 
Display).
         recogniser := GestureRecogniser new target: self.
         damageList := DamageList new initialize.
-        SdlEventSource instance handler: recogniser.
        renderSemaphore := Semaphore forMutualExclusion.
 
        renderSemaphore name: 'World renderSemaphore'.
@@ -25,6 +24,7 @@
        renderProcess := [ self renderLoop ] fork.
        renderProcess terminateOnQuit.
        renderProcess name: 'World renderLoop'.
+        SdlEventSource instance handler: recogniser; startEventLoop.
     ]
     
     scene: lens [

reply via email to

[Prev in Thread] Current Thread [Next in Thread]