[Top][All Lists]
[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 [