Mac Screensaver

BlitzMax Forums/BlitzMax Programming/Mac Screensaver

ImaginaryHuman(Posted 2006) [#1]
I'm trying to figure out how to get a BlitzMax screensaver to work on a Mac. I found working Windows code on the forums which is cool but irrelevant to Mac.

I read a few websites that sort of point the direction but of course mainly in C or Java and with little clue of how to integrate with BlitzMax.

From what I understand so far, it's not quite the same as on Windows. In Windows our screensaver exe basically can do whatever it likes, it deals with opening its own screen and closing it and setting up its own event handling and basically is just a regular program that gets called with some flags passed to it to select whether to do fullscreen, a preview, or a configuration. Of course the details of the preview window involve interacting with Windows but it appears to work from what I've read. This seems like a pretty simple arrangement.

On the Mac a screensaver seems to be built around the screensaver/screensaver.h include file which is in something like C, maybe C++ or Objective C. That seems to imply that the screensaver has to be coded IN C, or written in some other language and imported into the C program and compiled within the XCode IDE. It seems that you get given an NSView screen by default which also seems not to be double buffered, and you get this system timer that calls a function for each frame to render. So you need to add any blitz code to get called within that framework which sounds like the reverse of having blitz include the header files.

So the issue then is how to be calling blitz code from within a C program. This makes it C-centric and not blitz-centric, plus the problem of needing to open a proper OpenGL graphics display or using MaxGUI for configuration (which Mac refers to as a `sheet` which slides into view within the Screensaver preference window. I can see that it would be fairly simple to code a screensaver in C, but how would one go about including BlitzMax routines to do all the graphics? Compiling the default setup for a screensaver in XCode actually does make a working screensaver, except that you basically just have a black screen and nothing to look at.

One idea I thought is to actually use XCode to compile the exe, and to have BlitzMax's compiler generate linkable files or something that could be linked into the XCode project within the functions that get called. But even if that is possible, how would C then call the appropriate pieces of code, e.g. the config panel, the startup, shutdown, and per-frame-update? It would be much nicer if the whole thing could just be a regular BlitzMax-centric app including any necessary C bits. But I don't know that that would work. It seems that MacOS runs a generic screensaver handler program which then executes the selected screensaver itself... so the screensaver IS just a regular program, but it's a C-based program.

Has anyone tried to get this working in a Max compatible way? Any code to share? Anyone like to take a stab at coming up with the basic pieces needed to make a Mac screensaver? It looks like the below code is the basic structure of the C screensaver program. I don't understand some parts of it. Any help getting proper screensavers to work on the mac would be much appreciated!

#import "MySaverView.h"


@implementation MySaverView

- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview
{
    self = [super initWithFrame:frame isPreview:isPreview];
    if (self) {
        [self setAnimationTimeInterval:1/30.0];
    }
    return self;
}

- (void)startAnimation
{
    [super startAnimation];
}

- (void)stopAnimation
{
    [super stopAnimation];
}

- (void)drawRect:(NSRect)rect
{
    [super drawRect:rect];
}

- (void)animateOneFrame
{
    return;
}

- (BOOL)hasConfigureSheet
{
    return NO;
}

- (NSWindow*)configureSheet
{
    return nil;
}

@end



ImaginaryHuman(Posted 2006) [#2]
If anything, how would I include and call some blitz code from within this C program ... ie use one blitz program whose functions can be externalized somehow?


DannyD(Posted 2006) [#3]
Why not try the Mac forum here ?


ImaginaryHuman(Posted 2006) [#4]
Because nobody looks at it


Garrett(Posted 2006) [#5]
I do, but I'm still new to BlitzMax so I'm not a whole lot of help. I haven't
checked into making savers on OS X yet, but it was on my list of "wanna do's".

-Garrett


ImaginaryHuman(Posted 2006) [#6]
I'm sure it'd be quite popular if we can get it working.


JoeRetro(Posted 2006) [#7]
Have a look here.

Links don't work? Check out the back-up site.


ImaginaryHuman(Posted 2006) [#8]
Thanks I already saw that page. It just shows use of the original Objective-C code from apple with screensaver effects inserted, it doesn't help us to integrate with Blitz.


Garrett(Posted 2006) [#9]
It'd be sweet if it was something similar to windows where we only needed to
grab the command line info being sent to our executables.

I wonder if we can use some of that C or Objective C with BlitzMax? BlitzMax
does allow us to use such code with BlitzMax.

Unfortunately, I'm only at the tiny tip of learning C.

-Garrett


ImaginaryHuman(Posted 2006) [#10]
From what I gather so far, at the given time where there is no keyboard or mouse activity, the o/s calls the screensaver controller program which, based on which screensaver is chosen, runs a given .saver screensaver, which I presume is *probably* just a regular exe file (not sure). It might not be, as I think I read that the saver is actually a whole folder containing several parts as a `bundle`. What I can tell is that the exe file has to usually use the `screensaver framework` which is mainly screensaver/screensaver.h include file, plus some functions which encapsulate certain pieces of code. I'm not sure why those functions have to have certain names - it's almost as if they are called from somewhere else within the app. I think possibly that the header files include the basic routines to a) open an NView single-buffered screen, b) set up a timer which then c) calls the `animateoneframe` function - which you can define the contents of, at the given interval. So I'm thinking that the header file handles opening the display, setting up a frame timer for flipping, and calling the functions to initialize/shutdown and do one frame of animation. The question is, do we even NEED this header to do that for us, if blitz were going to provide ability to handle flipping, graphics set up and other routines. Another point to consider is there is a function referring to whether a configuration panel is defined, and another that actually creates and operates the panel. It seems the panel has to be attached to a `sheet` which I guess is a sliding gui panel that drops down in the system prefs screensaver window. So it looks like you'd have to tap into and use an o/s compatible GUI arrangement - ie wouldn't be able to really use MaxGUI, or be able to integrate MaxGUI with the system prefs.

Thoughts following this are, maybe we would have to settle for a screensaver that detects the keyboard and allows a given `config` key to be pressed which then displays a graphics-based or popup-maxgui-based config window, but it wouldn't be embedded in the system prefs and presumably might not show in the preview window. The question then leads to - how do we get the preview window working. It seems you have to use the NSView display as given by the o/s in order to have it be scaled down and rendered in the preview. So then - how to integrate the NSView with Max's graphics display so that Max's display shows in the o/s preview window.

Seems like some complicated stuff that would have to be hacked together at a low level. OR.... use XCode to compile, use the o/s's framework for screensavers, and have the screensaver in Objective C call functions in an included blitz app or .a file or whatever. Who knows.

An alternative is to bypass the system screensaver altogether, go with the old fashioned screensaver system like `after dark` which monitors key and mouse input and handles the triggering of the saver, which could all be within one blitz app. But it would not be part of the system screensaver prefs - which would've been really nice.

Unfortunately it is not as simple as windows. You don't get parameters passed to a regular exe file to tell it what to do, and you don't get to open your own screen or handle your own frame timing or use your own gui system or open your own config window in whatever form you like. Windows actually has a lot more freedom that way. Mac being somewhat more proprietary requires that you play nicely with the o/s, which makes it hard for BlitzMax.


ImaginaryHuman(Posted 2006) [#11]
I did some more investigating.

A Mac screensaver isn't just one file. It is a `bundle` of files and folders. When the folder is named whatever.saver, it hides the fact that it is a folder and displays as a single file. If you remove .saver from the name, you can see the folder contents.

Each screensaver comprises a main folder called "Contents". Within that folder are four items: info.plist which seems to be an xml `plist` file that describes some things about the application/bundle etc, pbdevelopment.plist which is another xml file describing some more stuff, a `MacOS` folder containing the actual screensaver itself which appears to show as a console program (non gui app), a `Resources` folder which contains an English.lproj folder which contains two files: ConfigureSheet.nib and Localizable.strings. The localization file appears to contain some localized strings that probably appear within the app as messages to the user. The nib file seems to be an `interface builder` file which when clicked on will launch interface builder, and basically contains the gui configuration sheet that appears when you click `config` in the system screensaver prefs - you can actually edit the interface. I'm not sure, based on Objective C, how the interface events are handled or where or what the result of certain events achieves or where you define that.

All these files comprise a screensaver - this is taken from the `Amseq` screensaver.

With this in mind, how much of this and how many of these files can be tailored to work with a Blitzmax screensaver in any way?

I tried compiling a Blitzmax app as a non-gui app and replacing an existing screensaver exe with it. Although the saver shows as an option in the system prefs, if you select it it tells you the bundle is damaged and cannot load the screensaver. Presumably either some of the file contents conflict or are invalid, or the blitz exe should be making some calls to stuff in the screensaver.h header file to `register` it as a real screensaver or to set it up for being used as one, ie in the preview window etc. Since that is absent from the blitz app I'm thinking it doesn't recognize the exe as a screensaver.

That aside I tried leaving that screensaver selected anyway. The hotcorner did run the app but the default NSView screen took over so you see nothing and I don't think the blitz app reall executed.

So either things will have to revolve around getting the c code into blitzmax, or the max code into c. ????


Garrett(Posted 2006) [#12]
That's exactly how any app is on OS X. They all have the contents folder, they
all have the plist file and the MacOS folder. Rename any .app file on OS X, and
then you access it like any other folder. So there's no issue there so far. Now
it's just a matter of nailing down how we can communicate with OS X and the
Preferences > Screensaver window.

I bet you right now we could take just about any app and rename it with the
.saver extention, that it'll show up in the screen saver list. Won't have any
access to anything else, but I bet if you hit the preview button that it launches
whatever we toss in there.

If you don't play with that anytime soon, I will. But got some things to do
before I can get to doing that.

Later,
-Garrett


ImaginaryHuman(Posted 2006) [#13]
Actually I tried to rename a regular app to .saver and it would not allow it, it converts the name to name.saver.app and will refuse to take the .app off the end.

I also couldn't find a way to show the .app extension or to remove it. I can add it, but then I think it's really called name.app.app, as osX removes the .app and doesn't seem to let you see the contents of the app. But I'm sure there's a way.

Not sure what distinguishes an app from a bundle. There must be some differences.

But I don't really think it will matter. I think we have to look at creating the screensaver at the sourcecode level not at the compiled-file level. I don't think it's as simple as just substituting the saver file, as I did that and it did not work.


Garrett(Posted 2006) [#14]
Might have to try the name chanes in a terminal window.

-Garrett


ImaginaryHuman(Posted 2006) [#15]
dont know how ;-D


JoeRetro(Posted 2006) [#16]
Here's another link with source code.

Maybe this will be more helpful.


ImaginaryHuman(Posted 2006) [#17]
The sources are probably interesting but I couldn't get the archives to open, and I am guessing all of these are written in C which really doesn't help us with our blitzmax endeavours. It seems that pretty much all screensavers on the mac are currently written using the screensaver framework in C or Objective C. There isn't anything that these screensaver examples are doing that isn't already being done with the screensaver.h include file, they are just filling in the contents of the functions that display a nice effect on the screen, all the rest is the same. Its the same structure and the same system code.

I looked through some other screensavers that are already on my computer and they all looked much the same in their basic use of the screensaver framework. I'm not really concerned with what effect the screensaver produces, at this point we're just trying to get anything to work at all using blitz code for the graphics. Thanks for trying though.

That piece of sourcecode that I posted originally is the same that is being used by all those screensavers, and none of them ever step outside of it. They just put nice graphical effects into the animateoneframe function and that's about it.

Our question here is how to have blitzmax write the graphics routines and integrate with the configuration and the preview.


ImaginaryHuman(Posted 2006) [#18]
I tried a simple blitzmax program that I put in the same folder as a real compiled XCode screensaver project, to import PaulSaverView.m and compared to trying to import it as a C file it actually compiled most of the way alright, until the linking phase. I get these errors:

Import "PaulSaverView.m"

Building Blitz
Compiling:PaulSaverView.m
Compiling:Blitz.bmx
Linking:Blitz
ld: Undefined symbols:
.objc_class_name_ScreenSaverView
Build Error: Failed to link /Developer/TestProjects/PaulSaver/Blitz.app/Contents/MacOS/Blitz
Process complete


Any ideas? I am also thinking we might have to remove some parts of screensaver.h because it includes everything needed to build an application including the appkit and the foundation framework. But what does this error mean?


DannyD(Posted 2006) [#19]
Believe it or not there is a Mac OS X forum here but it's hard to find. I'm trying to get the forum administrator to move the Mac os X forum from the very bottom of the forum lists to the BlitzMax list. Considering the only Blitz product available for Mac os X is BlitzMax it makes sense. Currently Mac topics end up in the general forum and disappear very quickly. I urge all Mac users who would like to see the forum promoted and visible to all to contact the Blitz webmaster using this link http://www.blitzbasic.com/Contact/_index_.php


ImaginaryHuman(Posted 2006) [#20]
I started asking within that forum and am getting some gradual results


DannyD(Posted 2006) [#21]
Great to hear that. did you contact the webmaster to get the forum promoted to an area where everyone is aware of it?


ImaginaryHuman(Posted 2006) [#22]
No. I think it has to stay where the other platform-specific areas are, along with the linux and windows forums.

Good luck on your conquest though. :-)