diff options
Diffstat (limited to 'src/sys/macosx')
-rw-r--r-- | src/sys/macosx/Schism_Tracker.app/Contents/Info.plist | 112 | ||||
-rw-r--r-- | src/sys/macosx/Schism_Tracker.app/Contents/PkgInfo | 1 | ||||
-rw-r--r-- | src/sys/macosx/Schism_Tracker.app/Contents/Resources/AppSettings.plist | 18 | ||||
-rw-r--r-- | src/sys/macosx/Schism_Tracker.app/Contents/Resources/appIcon.icns | bin | 0 -> 52550 bytes | |||
-rw-r--r-- | src/sys/macosx/Schism_Tracker.app/Contents/Resources/moduleIcon.icns | bin | 0 -> 58109 bytes | |||
-rw-r--r-- | src/sys/macosx/ibook-support.c | 103 | ||||
-rw-r--r-- | src/sys/macosx/macosx-sdlmain.m | 619 | ||||
-rw-r--r-- | src/sys/macosx/midi-macosx.c | 222 | ||||
-rw-r--r-- | src/sys/macosx/osdefs.c | 54 | ||||
-rw-r--r-- | src/sys/macosx/volume-macosx.c | 119 |
10 files changed, 1248 insertions, 0 deletions
diff --git a/src/sys/macosx/Schism_Tracker.app/Contents/Info.plist b/src/sys/macosx/Schism_Tracker.app/Contents/Info.plist new file mode 100644 index 0000000..ca4d05d --- /dev/null +++ b/src/sys/macosx/Schism_Tracker.app/Contents/Info.plist @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>schismtracker</string> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>it</string> + <string>IT</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>moduleIcon.icns</string> + <key>CFBundleMIMETypes</key> + <array> + <string>audio/mod</string> + <string>audio/x-mod</string> + </array> + <key>CFBundleTypeName</key> + <string>Impulse Tracker Module</string> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSIsAppleDefaultForType</key> + <true/> + </dict> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>669</string> + <string>amf</string> + <string>AMF</string> + <string>ams</string> + <string>AMS</string> + <string>dbm</string> + <string>DBM</string> + <string>dmf</string> + <string>DMF</string> + <string>far</string> + <string>FAR</string> + <string>mdl</string> + <string>MDL</string> + <string>med</string> + <string>MED</string> + <string>mod</string> + <string>MOD</string> + <string>mt2</string> + <string>MT2</string> + <string>mtm</string> + <string>MTM</string> + <string>okt</string> + <string>OKT</string> + <string>psm</string> + <string>PSM</string> + <string>ptm</string> + <string>PTM</string> + <string>s3m</string> + <string>S3M</string> + <string>stm</string> + <string>STM</string> + <string>ult</string> + <string>ULT</string> + <string>umx</string> + <string>UMX</string> + <string>xm</string> + <string>XM</string> + </array> + <key>CFBundleTypeIconFile</key> + <string>moduleIcon.icns</string> + <key>CFBundleMIMETypes</key> + <array> + <string>audio/mod</string> + <string>audio/x-mod</string> + </array> + <key>CFBundleTypeName</key> + <string>Audio Module</string> + <key>CFBundleTypeRole</key> + <string>Viewer</string> + <key>LSIsAppleDefaultForType</key> + <true/> + </dict> + </array> + <key>CFBundleGetInfoString</key> + <string>Schism Tracker Copyright 2003-2012 Storlek</string> + <key>CFBundleIconFile</key> + <string>appIcon.icns</string> + <key>CFBundleIdentifier</key> + <string>org.schismtracker.SchismTracker</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>Schism Tracker</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>hg</string> + <key>CFBundleSignature</key> + <string>Schm</string> + <key>CFBundleVersion</key> + <string>hg</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>CGDisableCoalescedUpdates</key> + <true/> +</dict> +</plist> diff --git a/src/sys/macosx/Schism_Tracker.app/Contents/PkgInfo b/src/sys/macosx/Schism_Tracker.app/Contents/PkgInfo new file mode 100644 index 0000000..07af6f8 --- /dev/null +++ b/src/sys/macosx/Schism_Tracker.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPLSchm
\ No newline at end of file diff --git a/src/sys/macosx/Schism_Tracker.app/Contents/Resources/AppSettings.plist b/src/sys/macosx/Schism_Tracker.app/Contents/Resources/AppSettings.plist new file mode 100644 index 0000000..62376f5 --- /dev/null +++ b/src/sys/macosx/Schism_Tracker.app/Contents/Resources/AppSettings.plist @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>EncryptAndChecksum</key> + <false/> + <key>IsDroppable</key> + <true/> + <key>OutputType</key> + <string>None</string> + <key>RemainRunningAfterCompletion</key> + <false/> + <key>RequiresAdminPrivileges</key> + <false/> + <key>ScriptInterpreter</key> + <string>/bin/sh</string> +</dict> +</plist> diff --git a/src/sys/macosx/Schism_Tracker.app/Contents/Resources/appIcon.icns b/src/sys/macosx/Schism_Tracker.app/Contents/Resources/appIcon.icns Binary files differnew file mode 100644 index 0000000..8ed3637 --- /dev/null +++ b/src/sys/macosx/Schism_Tracker.app/Contents/Resources/appIcon.icns diff --git a/src/sys/macosx/Schism_Tracker.app/Contents/Resources/moduleIcon.icns b/src/sys/macosx/Schism_Tracker.app/Contents/Resources/moduleIcon.icns Binary files differnew file mode 100644 index 0000000..597056b --- /dev/null +++ b/src/sys/macosx/Schism_Tracker.app/Contents/Resources/moduleIcon.icns diff --git a/src/sys/macosx/ibook-support.c b/src/sys/macosx/ibook-support.c new file mode 100644 index 0000000..71bd00b --- /dev/null +++ b/src/sys/macosx/ibook-support.c @@ -0,0 +1,103 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com> + * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org> + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "headers.h" +#include "util.h" + +int macosx_ibook_fnswitch(int setting); /* FIXME: ugliness */ + +#ifdef MACOSX + +#include <IOKit/IOKitLib.h> +#include <IOKit/IOReturn.h> +#include <ApplicationServices/ApplicationServices.h> +#include <IOKit/hidsystem/IOHIDLib.h> +#include <IOKit/hidsystem/IOHIDParameter.h> + +#define kMyDriversKeyboardClassName "AppleADBKeyboard" +#define kfnSwitchError 200 +#define kfnAppleMode 0 +#define kfntheOtherMode 1 + +#ifndef kIOHIDFKeyModeKey +#define kIOHIDFKeyModeKey "HIDFKeyMode" +#endif + +int macosx_ibook_fnswitch(int setting) +{ + kern_return_t kr; + mach_port_t mp; + io_service_t so; + /*io_name_t sn;*/ + io_connect_t dp; + io_iterator_t it; + CFDictionaryRef classToMatch; + /*CFNumberRef fnMode;*/ + unsigned int res, dummy; + + kr = IOMasterPort(bootstrap_port, &mp); + if (kr != KERN_SUCCESS) return -1; + + classToMatch = IOServiceMatching(kIOHIDSystemClass); + if (classToMatch == NULL) { + return -1; + } + kr = IOServiceGetMatchingServices(mp, classToMatch, &it); + if (kr != KERN_SUCCESS) return -1; + + so = IOIteratorNext(it); + IOObjectRelease(it); + + if (!so) return -1; + + kr = IOServiceOpen(so, mach_task_self(), kIOHIDParamConnectType, &dp); + if (kr != KERN_SUCCESS) return -1; + + kr = IOHIDGetParameter(dp, CFSTR(kIOHIDFKeyModeKey), sizeof(res), + &res, (IOByteCount *) &dummy); + if (kr != KERN_SUCCESS) { + IOServiceClose(dp); + return -1; + } + + if (setting == kfnAppleMode || setting == kfntheOtherMode) { + dummy = setting; + kr = IOHIDSetParameter(dp, CFSTR(kIOHIDFKeyModeKey), + &dummy, sizeof(dummy)); + if (kr != KERN_SUCCESS) { + IOServiceClose(dp); + return -1; + } + } + + IOServiceClose(dp); + /* old setting... */ + return res; +} + +#else + +int macosx_ibook_fnswitch(UNUSED int setting) +{ + return 0; +} +#endif diff --git a/src/sys/macosx/macosx-sdlmain.m b/src/sys/macosx/macosx-sdlmain.m new file mode 100644 index 0000000..df7f440 --- /dev/null +++ b/src/sys/macosx/macosx-sdlmain.m @@ -0,0 +1,619 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com> + * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org> + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* wee.... + +this is used to do some schism-on-macosx customization +and get access to cocoa stuff + +pruned up some here :) -mrsb + + */ + +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser <dwaliss1@purdue.edu> + Non-NIB-Code & other changes: Max Horn <max@quendi.de> + + Feel free to customize this file to suit your needs +*/ + +extern char *initial_song; + +#include <SDL.h> /* necessary here */ +#include "event.h" +#include "osdefs.h" + +#define Cursor AppleCursor +#import <Cocoa/Cocoa.h> +#undef Cursor + +@interface SDLMain : NSObject +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; +@end + +#import <sys/param.h> /* for MAXPATHLEN */ +#import <unistd.h> + +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetProcessName ( CPSProcessSerNum *psn, char *processname); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +int macosx_did_finderlaunch; + +#define KEQ_FN(n) [NSString stringWithFormat:@"%C", NSF##n##FunctionKey] + +@interface SDLApplication : NSApplication +@end + +@interface NSApplication(OtherMacOSXExtensions) +-(void)setAppleMenu:(NSMenu*)m; +@end + +@implementation SDLApplication +/* 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); +} +- (void)_menu_callback:(id)sender +{ + SDL_Event e; + NSString *px; + const char *po; + + px = [sender representedObject]; + po = [px UTF8String]; + if (po) { + e.type = SCHISM_EVENT_NATIVE; + e.user.code = SCHISM_EVENT_NATIVE_SCRIPT; + e.user.data1 = strdup(po); + SDL_PushEvent(&e); + } +} + + +@end + +/* The main class of the application, the application's delegate */ +@implementation SDLMain + +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + SDL_Event e; + const char *po; + + if (!filename) return NO; + + po = [filename UTF8String]; + if (po) { + e.type = SCHISM_EVENT_NATIVE; + e.user.code = SCHISM_EVENT_NATIVE_OPEN; + e.user.data1 = strdup(po); + /* if we started as a result of a doubleclick on + a document, then Main still hasn't really started yet. + */ + initial_song = strdup(po); + SDL_PushEvent(&e); + return YES; + } else { + return NO; + } +} + +/* other interesting ones: +- (BOOL)application:(NSApplication *)theApplication printFile:(NSString *)filename +- (BOOL)applicationOpenUntitledFile:(NSApplication *)theApplication +*/ +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, true, (unsigned char *) parentdir, MAXPATHLEN)) { + assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } + +} + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenu *otherMenu; + NSMenuItem *menuItem; + + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + [appleMenu addItemWithTitle:@"About Schism Tracker" + action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + /* other schism items */ + menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Help" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(1)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"help"]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"View Patterns" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(2)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"pattern"]; + menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Orders/Panning" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(11)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"orders"]; + menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Variables" + action:@selector(_menu_callback:) + keyEquivalent:[NSString stringWithFormat:@"%C", NSF12FunctionKey]]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"variables"]; + menuItem = (NSMenuItem*)[appleMenu addItemWithTitle:@"Message Editor" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(9)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"message_edit"]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + [appleMenu addItemWithTitle:@"Hide Schism Tracker" action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + [appleMenu addItemWithTitle:@"Quit Schism Tracker" action:@selector(terminate:) keyEquivalent:@"q"]; + + /* Put menu into the menubar */ + menuItem = (NSMenuItem*)[[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* File menu */ + otherMenu = [[NSMenu alloc] initWithTitle:@"File"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"New..." + action:@selector(_menu_callback:) + keyEquivalent:@"n"]; + [menuItem setKeyEquivalentModifierMask:NSControlKeyMask]; + [menuItem setRepresentedObject: @"new"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Load..." + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(9)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"load"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Save Current" + action:@selector(_menu_callback:) + keyEquivalent:@"s"]; + [menuItem setKeyEquivalentModifierMask:NSControlKeyMask]; + [menuItem setRepresentedObject: @"save"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Save As..." + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(10)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"save_as"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Export..." + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(10)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"export_song"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Message Log" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(11)]; + [menuItem setKeyEquivalentModifierMask:NSFunctionKeyMask|NSControlKeyMask]; + [menuItem setRepresentedObject: @"logviewer"]; + menuItem = (NSMenuItem*)[[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:otherMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Playback menu */ + otherMenu = [[NSMenu alloc] initWithTitle:@"Playback"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Show Infopage" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(5)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"info"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Play Song" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(5)]; + [menuItem setKeyEquivalentModifierMask:NSControlKeyMask]; + [menuItem setRepresentedObject: @"play"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Play Pattern" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(6)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"play_pattern"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Play from Order" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(6)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"play_order"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Play from Mark/Cursor" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(7)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"play_mark"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Stop" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(8)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"stop"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Calculate Length" + action:@selector(_menu_callback:) + keyEquivalent:@"p"]; + [menuItem setKeyEquivalentModifierMask:(NSFunctionKeyMask|NSControlKeyMask)]; + [menuItem setRepresentedObject: @"calc_length"]; + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:otherMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Sample menu */ + otherMenu = [[NSMenu alloc] initWithTitle:@"Samples"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Sample List" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(3)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"sample_page"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Sample Library" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(3)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"sample_library"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Reload Soundcard" + action:@selector(_menu_callback:) + keyEquivalent:@"g"]; + [menuItem setKeyEquivalentModifierMask:NSControlKeyMask]; + [menuItem setRepresentedObject: @"init_sound"]; + menuItem = (NSMenuItem*)[[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:otherMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Instrument menu */ + otherMenu = [[NSMenu alloc] initWithTitle:@"Instruments"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Instrument List" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(4)]; + [menuItem setKeyEquivalentModifierMask:0]; + [menuItem setRepresentedObject: @"inst_page"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Instrument Library" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(4)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"inst_library"]; + menuItem = (NSMenuItem*)[[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:otherMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Settings menu */ + otherMenu = [[NSMenu alloc] initWithTitle:@"Settings"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Preferences" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(5)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"preferences"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"MIDI Configuration" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(1)]; + [menuItem setKeyEquivalentModifierMask:NSShiftKeyMask]; + [menuItem setRepresentedObject: @"midi_config"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Palette Editor" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(12)]; + [menuItem setKeyEquivalentModifierMask:NSControlKeyMask]; + [menuItem setRepresentedObject: @"palette_page"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Font Editor" + action:@selector(_menu_callback:) + keyEquivalent:@""]; + [menuItem setRepresentedObject: @"font_editor"]; + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"System Configuration" + action:@selector(_menu_callback:) + keyEquivalent:KEQ_FN(1)]; + [menuItem setKeyEquivalentModifierMask:NSControlKeyMask]; + [menuItem setRepresentedObject: @"system_config"]; + + menuItem = (NSMenuItem*)[otherMenu addItemWithTitle:@"Toggle Fullscreen" + action:@selector(_menu_callback:) + keyEquivalent:@"\r"]; + [menuItem setKeyEquivalentModifierMask:(NSControlKeyMask|NSAlternateKeyMask)]; + [menuItem setRepresentedObject: @"fullscreen"]; + menuItem = (NSMenuItem*)[[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:otherMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(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]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + CPSProcessSerNum PSN; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; + + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) { + if (!macosx_did_finderlaunch) { + CPSSetProcessName(&PSN,"Schism Tracker"); + } + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [SDLApplication sharedApplication]; + } + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + + /* Hand off to main application code */ + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} +@end + + +@implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + +@end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgc = 1; + gFinderLaunch = YES; + macosx_did_finderlaunch = 1; + } else { + gArgc = argc; + gFinderLaunch = NO; + macosx_did_finderlaunch = 0; + } + gArgv = argv; + + CustomApplicationMain (argc, argv); + + return 0; +} + +/* these routines provide clipboard encapsulation */ +const char *macosx_clippy_get(void) +{ + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *type = [pb availableTypeFromArray:[NSArray + arrayWithObject:NSStringPboardType]]; + NSString *contents; + const char *po; + + if (type == nil) return ""; + + contents = [pb stringForType:type]; + if (contents == nil) return ""; + po = [contents UTF8String]; + if (!po) return ""; + return po; +} +void macosx_clippy_put(const char *buf) +{ + NSString *contents = [NSString stringWithUTF8String:buf]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; + [pb setString:contents forType:NSStringPboardType]; +} +// ktt appears to be 1/60th of a second? +unsigned int key_repeat_rate(void) +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + int ktt = [defaults integerForKey:@"KeyRepeat"]; + if (!ktt || ktt < 0) ktt = 4; // eh? + ktt = (ktt * 1000) / 60; + return (unsigned)ktt; +} +unsigned int key_repeat_delay(void) +{ + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + int ktt = [defaults integerForKey:@"InitialKeyRepeat"]; + if (!ktt || ktt < 0) ktt = 35; + ktt = (ktt * 1000) / 60; + return (unsigned)ktt; +} +int key_scancode_lookup(int k, int def) +{ + switch (k & 127) { + case 0x32: /* QZ_BACKQUOTE */ return SDLK_BACKQUOTE; + case 0x12: /* QZ_1 */ return SDLK_1; + case 0x13: /* QZ_2 */ return SDLK_2; + case 0x14: /* QZ_3 */ return SDLK_3; + case 0x15: /* QZ_4 */ return SDLK_4; + case 0x17: /* QZ_5 */ return SDLK_5; + case 0x16: /* QZ_6 */ return SDLK_6; + case 0x1A: /* QZ_7 */ return SDLK_7; + case 0x1C: /* QZ_8 */ return SDLK_8; + case 0x19: /* QZ_9 */ return SDLK_9; + case 0x1D: /* QZ_0 */ return SDLK_0; + case 0x1B: /* QZ_MINUS */ return SDLK_MINUS; + case 0x18: /* QZ_EQUALS */ return SDLK_EQUALS; + case 0x0C: /* QZ_q */ return SDLK_q; + case 0x0D: /* QZ_w */ return SDLK_w; + case 0x0E: /* QZ_e */ return SDLK_e; + case 0x0F: /* QZ_r */ return SDLK_r; + case 0x11: /* QZ_t */ return SDLK_t; + case 0x10: /* QZ_y */ return SDLK_y; + case 0x20: /* QZ_u */ return SDLK_u; + case 0x22: /* QZ_i */ return SDLK_i; + case 0x1F: /* QZ_o */ return SDLK_o; + case 0x23: /* QZ_p */ return SDLK_p; + case 0x21: /* QZ_[ */ return SDLK_LEFTBRACKET; + case 0x1E: /* QZ_] */ return SDLK_RIGHTBRACKET; + case 0x2A: /* QZ_backslash */ return SDLK_BACKSLASH; + case 0x00: /* QZ_a */ return SDLK_a; + case 0x01: /* QZ_s */ return SDLK_s; + case 0x02: /* QZ_d */ return SDLK_d; + case 0x03: /* QZ_f */ return SDLK_f; + case 0x05: /* QZ_g */ return SDLK_g; + case 0x04: /* QZ_h */ return SDLK_h; + case 0x26: /* QZ_j */ return SDLK_j; + case 0x28: /* QZ_k */ return SDLK_k; + case 0x25: /* QZ_l */ return SDLK_l; + case 0x29: /* QZ_; */ return SDLK_SEMICOLON; + case 0x27: /* QZ_quote */ return SDLK_QUOTE; + case 0x06: /* QZ_z */ return SDLK_z; + case 0x07: /* QZ_x */ return SDLK_x; + case 0x08: /* QZ_c */ return SDLK_c; + case 0x09: /* QZ_v */ return SDLK_v; + case 0x0B: /* QZ_b */ return SDLK_b; + case 0x2D: /* QZ_n */ return SDLK_n; + case 0x2E: /* QZ_m */ return SDLK_m; + case 0x2B: /* QZ_, */ return SDLK_COMMA; + case 0x2F: /* QZ_. */ return SDLK_PERIOD; + case 0x2C: /* QZ_slash */ return SDLK_SLASH; + case 0x31: /* QZ_space */ return SDLK_SPACE; + default: return def; + }; +} diff --git a/src/sys/macosx/midi-macosx.c b/src/sys/macosx/midi-macosx.c new file mode 100644 index 0000000..3342e2c --- /dev/null +++ b/src/sys/macosx/midi-macosx.c @@ -0,0 +1,222 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com> + * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org> + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "headers.h" + +#include "midi.h" + +#include "util.h" + +#ifdef MACOSX + +#include <CoreServices/CoreServices.h> +#include <CoreMIDI/MIDIServices.h> +#include <CoreAudio/HostTime.h> + +static MIDIClientRef client = NULL; +static MIDIPortRef portIn = NULL; +static MIDIPortRef portOut = NULL; + +static int max_outputs = 0; +static int max_inputs = 0; + +struct macosx_midi { + char *name; + MIDIEndpointRef ep; + unsigned char packet[1024]; + MIDIPacketList *pl; + MIDIPacket *x; +}; + +static void readProc(const MIDIPacketList *np, UNUSED void *rc, void *crc) +{ + struct midi_port *p; + struct macosx_midi *m; + MIDIPacket *x; + unsigned long i; + + p = (struct midi_port *)crc; + m = (struct macosx_midi *)p->userdata; + + x = (MIDIPacket*)&np->packet[0]; + for (i = 0; i < np->numPackets; i++) { + midi_received_cb(p, x->data, x->length); + x = MIDIPacketNext(x); + } +} +static void _macosx_send(struct midi_port *p, const unsigned char *data, + unsigned int len, unsigned int delay) +{ + struct macosx_midi *m; + + m = (struct macosx_midi *)p->userdata; + if (!m->x) { + m->x = MIDIPacketListInit(m->pl); + } + + /* msec to nsec? */ + m->x = MIDIPacketListAdd(m->pl, sizeof(m->packet), + m->x, (MIDITimeStamp)AudioConvertNanosToHostTime( + AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) + (1000000*delay)), + len, data); +} +static void _macosx_drain(struct midi_port *p) +{ + struct macosx_midi *m; + + m = (struct macosx_midi *)p->userdata; + if (m->x) { + MIDISend(portOut, m->ep, m->pl); + m->x = NULL; + } +} + +/* lifted from portmidi */ +static char *get_ep_name(MIDIEndpointRef ep) +{ + MIDIEntityRef entity; + MIDIDeviceRef device; + CFStringRef endpointName = NULL, deviceName = NULL, fullName = NULL; + CFStringEncoding defaultEncoding; + char* newName; + + /* get the default string encoding */ + defaultEncoding = CFStringGetSystemEncoding(); + + /* get the entity and device info */ + MIDIEndpointGetEntity(ep, &entity); + MIDIEntityGetDevice(entity, &device); + + /* create the nicely formated name */ + MIDIObjectGetStringProperty(ep, kMIDIPropertyName, &endpointName); + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &deviceName); + if (deviceName != NULL) { + fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@: %@"), + deviceName, endpointName); + } else { + fullName = endpointName; + } + + /* copy the string into our buffer */ + newName = (char*)mem_alloc(CFStringGetLength(fullName) + 1); + CFStringGetCString(fullName, newName, CFStringGetLength(fullName) + 1, + defaultEncoding); + + /* clean up */ + if (endpointName) CFRelease(endpointName); + if (deviceName) CFRelease(deviceName); + if (fullName) CFRelease(fullName); + + return newName; +} + +static int _macosx_start(struct midi_port *p) +{ + struct macosx_midi *m; + m = (struct macosx_midi *)p->userdata; + + if (p->io & MIDI_INPUT + && MIDIPortConnectSource(portIn, m->ep, (void*)p) != noErr) { + return 0; + } + + if (p->io & MIDI_OUTPUT) { + m->pl = (MIDIPacketList*)m->packet; + m->x = NULL; + } + return 1; +} +static int _macosx_stop(struct midi_port *p) +{ + struct macosx_midi *m; + m = (struct macosx_midi *)p->userdata; + if (p->io & MIDI_INPUT + && MIDIPortDisconnectSource(portIn, m->ep) != noErr) { + return 0; + } + return 1; +} + +static void _macosx_poll(struct midi_provider *p) +{ + struct macosx_midi *data; + MIDIEndpointRef ep; + int i; + + int num_out, num_in; + + num_out = MIDIGetNumberOfDestinations(); + num_in = MIDIGetNumberOfSources(); + + for (i = max_outputs; i < num_out; i++) { + ep = MIDIGetDestination(i); + if (!ep) continue; + data = mem_alloc(sizeof(struct macosx_midi)); + memcpy(&data->ep, &ep, sizeof(ep)); + data->name = get_ep_name(ep); + midi_port_register(p, MIDI_OUTPUT, data->name, data, 1); + } + max_outputs = i; + + + for (i = max_inputs; i < num_in; i++) { + ep = MIDIGetSource(i); + if (!ep) continue; + data = mem_alloc(sizeof(struct macosx_midi)); + memcpy(&data->ep, &ep, sizeof(ep)); + data->name = get_ep_name(ep); + midi_port_register(p, MIDI_INPUT, data->name, data, 1); + } + max_inputs = i; + +} + +int macosx_midi_setup(void) +{ + static struct midi_driver driver; + + memset(&driver,0,sizeof(driver)); + driver.flags = MIDI_PORT_CAN_SCHEDULE; + driver.poll = _macosx_poll; + driver.thread = NULL; + driver.enable = _macosx_start; + driver.disable = _macosx_stop; + driver.send = _macosx_send; + driver.drain = _macosx_drain; + + if (MIDIClientCreate(CFSTR("Schism Tracker"), NULL, NULL, &client) != noErr) { + return 0; + } + if (MIDIInputPortCreate(client, CFSTR("Input port"), readProc, NULL, &portIn) != noErr) { + return 0; + } + if (MIDIOutputPortCreate(client, CFSTR("Output port"), &portOut) != noErr) { + return 0; + } + + if (!midi_provider_register("Mac OS X", &driver)) return 0; + + return 1; +} + +#endif diff --git a/src/sys/macosx/osdefs.c b/src/sys/macosx/osdefs.c new file mode 100644 index 0000000..57fd832 --- /dev/null +++ b/src/sys/macosx/osdefs.c @@ -0,0 +1,54 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com> + * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org> + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "headers.h" +#include "osdefs.h" +#include "event.h" +#include "song.h" + +const char *osname = "macosx"; + + +int macosx_sdlevent(SDL_Event *event) +{ + if (event->type == SDL_KEYDOWN || event->type == SDL_KEYUP) { + if (event->key.keysym.sym == 0) { + switch (event->key.keysym.scancode) { + case 106: // mac F16 key + event->key.keysym.sym = SDLK_PRINT; + event->key.keysym.mod = KMOD_CTRL; + return 1; + case 234: // XXX what key is this? + if (event->type == SDL_KEYDOWN) + song_set_current_order(song_get_current_order() - 1); + return 0; + case 233: // XXX what key is this? + if (event->type == SDL_KEYUP) + song_set_current_order(song_get_current_order() + 1); + return 0; + }; + } + } + return 1; +} + diff --git a/src/sys/macosx/volume-macosx.c b/src/sys/macosx/volume-macosx.c new file mode 100644 index 0000000..d07d947 --- /dev/null +++ b/src/sys/macosx/volume-macosx.c @@ -0,0 +1,119 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com> + * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org> + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "headers.h" + +#include "util.h" + +#ifdef MACOSX + +#include <CoreServices/CoreServices.h> +#include <CoreAudio/AudioHardware.h> + +int macosx_volume_get_max(void); +int macosx_volume_get_max(void) +{ + return 65535; +} + +void macosx_volume_read(int *left, int *right); +void macosx_volume_read(int *left, int *right) +{ + UInt32 size; + AudioDeviceID od; + OSStatus e; + UInt32 ch[2]; + Float32 fl[2]; + int i; + + if (left) *left = 0; + if (right) *right = 0; + + size=sizeof(od); + e = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, + &size, &od); + if (e != 0) return; + + size=sizeof(ch); + e = AudioDeviceGetProperty(od, + 0, /* QA1016 says "0" is master channel */ + false, + kAudioDevicePropertyPreferredChannelsForStereo, + &size, + &ch); + if (e != 0) return; + + for (i = 0; i < 2; i++) { + size = sizeof(Float32); + e = AudioDeviceGetProperty(od, /* device */ + ch[i], /* preferred stereo channel */ + false, /* output device */ + kAudioDevicePropertyVolumeScalar, + &size, + &fl[i]); + if (e != 0) return; + } + if (left) *left = fl[0] * 65536.0f; + if (right) *right = fl[1] * 65536.0f; +} + +void macosx_volume_write(int left, int right); +void macosx_volume_write(int left, int right) +{ + UInt32 size; + AudioDeviceID od; + OSStatus e; + UInt32 ch[2]; + Float32 fl[2]; + int i; + + size=sizeof(od); + e = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, + &size, &od); + if (e != 0) return; + + size=sizeof(ch); + e = AudioDeviceGetProperty(od, + 0, /* QA1016 says "0" is master channel */ + false, + kAudioDevicePropertyPreferredChannelsForStereo, + &size, + &ch); + if (e != 0) return; + + fl[0] = ((float)left) / 65536.0f; + fl[1] = ((float)right) / 65536.0f; + + for (i = 0; i < 2; i++) { + e = AudioDeviceSetProperty(od, /* device */ + NULL, /* no timestamp */ + ch[i], /* preferred stereo channel */ + false, /* output device */ + kAudioDevicePropertyVolumeScalar, + sizeof(Float32), + &fl[i]); + if (e != 0) return; + } +} + +#endif |