SDL_main.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:16k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_main.c,v 1.4 2002/04/22 21:38:02 wmay Exp $";
  21. #endif
  22. /* This file takes care of command line argument parsing, and stdio redirection
  23.    in the MacOS environment.
  24.  */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #if TARGET_API_MAC_CARBON
  30. #include <Carbon.h>
  31. #else
  32. #include <Dialogs.h>
  33. #include <Fonts.h>
  34. #include <Events.h>
  35. #include <Resources.h>
  36. #include <Folders.h>
  37. #endif
  38. /* Include the SDL main definition header */
  39. #include "SDL.h"
  40. #include "SDL_main.h"
  41. #ifdef main
  42. #undef main
  43. #endif
  44. /* The standard output files */
  45. #define STDOUT_FILE "stdout.txt"
  46. #define STDERR_FILE "stderr.txt"
  47. #if !defined(__MWERKS__) && !TARGET_API_MAC_CARBON
  48. /* In MPW, the qd global has been removed from the libraries */
  49. QDGlobals qd;
  50. #endif
  51. /* Structure for keeping prefs in 1 variable */
  52. typedef struct {
  53.     Str255  command_line;
  54.     Str255  video_driver_name;
  55.     Boolean output_to_file;
  56. }  PrefsRecord;
  57. /* See if the command key is held down at startup */
  58. static Boolean CommandKeyIsDown(void)
  59. {
  60. KeyMap  theKeyMap;
  61. GetKeys(theKeyMap);
  62. if (((unsigned char *) theKeyMap)[6] & 0x80) {
  63. return(true);
  64. }
  65. return(false);
  66. }
  67. /* Parse a command line buffer into arguments */
  68. static int ParseCommandLine(char *cmdline, char **argv)
  69. {
  70. char *bufp;
  71. int argc;
  72. argc = 0;
  73. for ( bufp = cmdline; *bufp; ) {
  74. /* Skip leading whitespace */
  75. while ( isspace(*bufp) ) {
  76. ++bufp;
  77. }
  78. /* Skip over argument */
  79. if ( *bufp == '"' ) {
  80. ++bufp;
  81. if ( *bufp ) {
  82. if ( argv ) {
  83. argv[argc] = bufp;
  84. }
  85. ++argc;
  86. }
  87. /* Skip over word */
  88. while ( *bufp && (*bufp != '"') ) {
  89. ++bufp;
  90. }
  91. } else {
  92. if ( *bufp ) {
  93. if ( argv ) {
  94. argv[argc] = bufp;
  95. }
  96. ++argc;
  97. }
  98. /* Skip over word */
  99. while ( *bufp && ! isspace(*bufp) ) {
  100. ++bufp;
  101. }
  102. }
  103. if ( *bufp ) {
  104. if ( argv ) {
  105. *bufp = '';
  106. }
  107. ++bufp;
  108. }
  109. }
  110. if ( argv ) {
  111. argv[argc] = NULL;
  112. }
  113. return(argc);
  114. }
  115. /* Remove the output files if there was no output written */
  116. static void cleanup_output(void)
  117. {
  118. FILE *file;
  119. int empty;
  120. /* Flush the output in case anything is queued */
  121. fclose(stdout);
  122. fclose(stderr);
  123. /* See if the files have any output in them */
  124. file = fopen(STDOUT_FILE, "rb");
  125. if ( file ) {
  126. empty = (fgetc(file) == EOF) ? 1 : 0;
  127. fclose(file);
  128. if ( empty ) {
  129. remove(STDOUT_FILE);
  130. }
  131. }
  132. file = fopen(STDERR_FILE, "rb");
  133. if ( file ) {
  134. empty = (fgetc(file) == EOF) ? 1 : 0;
  135. fclose(file);
  136. if ( empty ) {
  137. remove(STDERR_FILE);
  138. }
  139. }
  140. }
  141. static int getCurrentAppName (StrFileName name) {
  142.     ProcessSerialNumber process;
  143.     ProcessInfoRec      process_info;
  144.     FSSpec              process_fsp;
  145.     
  146.     process.highLongOfPSN = 0;
  147.     process.lowLongOfPSN  = kCurrentProcess;
  148.     process_info.processInfoLength = sizeof (process_info);
  149.     process_info.processName    = NULL;
  150.     process_info.processAppSpec = &process_fsp;
  151.     
  152.     if ( noErr != GetProcessInformation (&process, &process_info) )
  153.        return 0;
  154.     
  155.     memcpy (name, process_fsp.name, process_fsp.name[0] + 1);
  156.     return 1;
  157. }
  158. static int getPrefsFile (FSSpec *prefs_fsp, int create) {
  159.     /* The prefs file name is the application name, possibly truncated, */
  160.     /* plus " Preferences */
  161.     
  162.     #define  SUFFIX   " Preferences"
  163.     #define  MAX_NAME 19             /* 31 - strlen (SUFFIX) */
  164.     
  165.     short  volume_ref_number;
  166.     long   directory_id;
  167.     StrFileName  prefs_name;
  168.     StrFileName  app_name;
  169.     
  170.     /* Get Preferences folder - works with Multiple Users */
  171.     if ( noErr != FindFolder ( kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
  172.                                &volume_ref_number, &directory_id) )
  173.         exit (-1);
  174.     
  175.     if ( ! getCurrentAppName (app_name) )
  176.         exit (-1);
  177.     
  178.     /* Truncate if name is too long */
  179.     if (app_name[0] > MAX_NAME )
  180.         app_name[0] = MAX_NAME;
  181.         
  182.     memcpy (prefs_name + 1, app_name + 1, app_name[0]);    
  183.     memcpy (prefs_name + app_name[0] + 1, SUFFIX, strlen (SUFFIX));
  184.     prefs_name[0] = app_name[0] + strlen (SUFFIX);
  185.    
  186.     /* Make the file spec for prefs file */
  187.     if ( noErr != FSMakeFSSpec (volume_ref_number, directory_id, prefs_name, prefs_fsp) )
  188.         if ( !create )
  189.             return 0;
  190.         else {
  191.             /* Create the prefs file */
  192.             memcpy (prefs_fsp->name, prefs_name, prefs_name[0] + 1);
  193.             prefs_fsp->parID   = directory_id;
  194.             prefs_fsp->vRefNum = volume_ref_number;
  195.                 
  196.             FSpCreateResFile (prefs_fsp, '????', 'pref', 0);
  197.             
  198.             if ( noErr != ResError () )
  199.                 return 0;
  200.         }
  201.       
  202.     return 1;
  203. }
  204. static int readPrefsResource (PrefsRecord *prefs) {
  205.     
  206.     Handle prefs_handle;
  207.     
  208.     prefs_handle = Get1Resource( 'CLne', 128 );
  209. if (prefs_handle != NULL) {
  210. int offset = 0;
  211. int j      = 0;
  212. HLock(prefs_handle);
  213. /* Get command line string */
  214. memcpy (prefs->command_line, *prefs_handle, (*prefs_handle)[0]+1);
  215. /* Get video driver name */
  216. offset += (*prefs_handle)[0] + 1;
  217. memcpy (prefs->video_driver_name, *prefs_handle + offset, (*prefs_handle)[offset] + 1);
  218. /* Get save-to-file option (1 or 0) */
  219. offset += (*prefs_handle)[offset] + 1;
  220. prefs->output_to_file = (*prefs_handle)[offset];
  221. ReleaseResource( prefs_handle );
  222.     
  223.         return ResError() == noErr;
  224.     }
  225.     return 0;
  226. }
  227. static int writePrefsResource (PrefsRecord *prefs, short resource_file) {
  228.     Handle prefs_handle;
  229.     
  230.     UseResFile (resource_file);
  231.     
  232.     prefs_handle = Get1Resource ( 'CLne', 128 );
  233.     if (prefs_handle != NULL)
  234.         RemoveResource (prefs_handle);
  235.     
  236.     prefs_handle = NewHandle ( prefs->command_line[0] + prefs->video_driver_name[0] + 4 );
  237.     if (prefs_handle != NULL) {
  238.     
  239.         int offset;
  240.         
  241.         HLock (prefs_handle);
  242.         
  243.         /* Command line text */
  244.         offset = 0;
  245.         memcpy (*prefs_handle, prefs->command_line, prefs->command_line[0] + 1);
  246.         
  247.         /* Video driver name */
  248.         offset += prefs->command_line[0] + 1;
  249.         memcpy (*prefs_handle + offset, prefs->video_driver_name, prefs->video_driver_name[0] + 1);
  250.         
  251.         /* Output-to-file option */
  252.         offset += prefs->video_driver_name[0] + 1;
  253.         *( *((char**)prefs_handle) + offset)     = (char)prefs->output_to_file;
  254.         *( *((char**)prefs_handle) + offset + 1) = 0;
  255.               
  256.         AddResource   (prefs_handle, 'CLne', 128, "pCommand Line");
  257.         WriteResource (prefs_handle);
  258.         UpdateResFile (resource_file);
  259.         DisposeHandle (prefs_handle);
  260.         
  261.         return ResError() == noErr;
  262.     }
  263.     
  264.     return 0;
  265. }
  266. static int readPreferences (PrefsRecord *prefs) {
  267.     int    no_error = 1;
  268.     FSSpec prefs_fsp;
  269.     /* Check for prefs file first */
  270.     if ( getPrefsFile (&prefs_fsp, 0) ) {
  271.     
  272.         short  prefs_resource;
  273.         
  274.         prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdPerm);
  275.         if ( prefs_resource == -1 ) /* this shouldn't happen, but... */
  276.             return 0;
  277.     
  278.         UseResFile   (prefs_resource);
  279.         no_error = readPrefsResource (prefs);     
  280.         CloseResFile (prefs_resource);
  281.     }
  282.     
  283.     /* Fall back to application's resource fork (reading only, so this is safe) */
  284.     else {
  285.     
  286.           no_error = readPrefsResource (prefs);
  287.      }
  288.     return no_error;
  289. }
  290. static int writePreferences (PrefsRecord *prefs) {
  291.     
  292.     int    no_error = 1;
  293.     FSSpec prefs_fsp;
  294.     
  295.     /* Get prefs file, create if it doesn't exist */
  296.     if ( getPrefsFile (&prefs_fsp, 1) ) {
  297.     
  298.         short  prefs_resource;
  299.         
  300.         prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdWrPerm);
  301.         if (prefs_resource == -1)
  302.             return 0;
  303.         no_error = writePrefsResource (prefs, prefs_resource);
  304.         CloseResFile (prefs_resource);
  305.     }
  306.     
  307.     return no_error;
  308. }
  309. /* This is where execution begins */
  310. int main(int argc, char *argv[])
  311. {
  312. #pragma unused(argc, argv)
  313. #define DEFAULT_ARGS "p"                /* pascal string for default args */
  314. #define DEFAULT_VIDEO_DRIVER "ptoolbox" /* pascal string for default video driver name */
  315. #define DEFAULT_OUTPUT_TO_FILE 1         /* 1 == output to file, 0 == no output */
  316. #define VIDEO_ID_DRAWSPROCKET 1          /* these correspond to popup menu choices */
  317. #define VIDEO_ID_TOOLBOX      2
  318.     PrefsRecord prefs = { DEFAULT_ARGS, DEFAULT_VIDEO_DRIVER, DEFAULT_OUTPUT_TO_FILE }; 
  319. int     nargs;
  320. char   **args;
  321. char   *commandLine;
  322. StrFileName  appNameText;
  323. int     videodriver     = VIDEO_ID_TOOLBOX;
  324.     int     settingsChanged = 0;
  325.     
  326.     long i;
  327. /* Kyle's SDL command-line dialog code ... */
  328. #if !TARGET_API_MAC_CARBON
  329. InitGraf    (&qd.thePort);
  330. InitFonts   ();
  331. InitWindows ();
  332. InitMenus   ();
  333. InitDialogs (nil);
  334. #endif
  335. InitCursor ();
  336. FlushEvents(everyEvent,0);
  337. #if !TARGET_API_MAC_CARBON
  338. MaxApplZone ();
  339. #endif
  340. MoreMasters ();
  341. MoreMasters ();
  342. #if 0
  343. /* Intialize SDL, and put up a dialog if we fail */
  344. if ( SDL_Init (0) < 0 ) {
  345. #define kErr_OK 1
  346. #define kErr_Text 2
  347.         DialogPtr errorDialog;
  348.         short   dummyType;
  349.      Rect   dummyRect;
  350.     Handle    dummyHandle;
  351.     short     itemHit;
  352. errorDialog = GetNewDialog (1001, nil, (WindowPtr)-1);
  353. DrawDialog (errorDialog);
  354. GetDialogItem (errorDialog, kErr_Text, &dummyType, &dummyHandle, &dummyRect);
  355. SetDialogItemText (dummyHandle, "pError Initializing SDL");
  356. SetPort (errorDialog);
  357. do {
  358. ModalDialog (nil, &itemHit);
  359. } while (itemHit != kErr_OK);
  360. DisposeDialog (errorDialog);
  361. exit (-1);
  362. }
  363. atexit(cleanup_output);
  364. atexit(SDL_Quit);
  365. #endif
  366. /* Set up SDL's QuickDraw environment  */
  367. #if !TARGET_API_MAC_CARBON
  368. SDL_InitQuickDraw(&qd);
  369. #endif
  370.  if ( readPreferences (&prefs) ) {
  371.         if (memcmp (prefs.video_driver_name+1, "DSp", 3) == 0)
  372.             videodriver = 1;
  373.         else if (memcmp (prefs.video_driver_name+1, "toolbox", 7) == 0)
  374.             videodriver = 2;
  375.  }
  376.  
  377. if ( CommandKeyIsDown() ) {
  378. #define kCL_OK 1
  379. #define kCL_Cancel 2
  380. #define kCL_Text 3
  381. #define kCL_File 4
  382. #define kCL_Video   6
  383.        
  384.         DialogPtr commandDialog;
  385.         short   dummyType;
  386.         Rect   dummyRect;
  387.         Handle    dummyHandle;
  388.         short     itemHit;
  389.         /* Assume that they will change settings, rather than do exhaustive check */
  390.         settingsChanged = 1;
  391.         
  392.         /* Create dialog and display it */
  393.         commandDialog = GetNewDialog (1000, nil, (DialogPtr)-1);
  394.         SetPort (commandDialog);
  395.             
  396.         /* Setup controls */
  397.         GetDialogItem   (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
  398.         SetControlValue ((ControlHandle)dummyHandle, prefs.output_to_file );
  399.         GetDialogItem     (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect);
  400.         SetDialogItemText (dummyHandle, prefs.command_line);
  401.         GetDialogItem   (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
  402.         SetControlValue ((ControlRef)dummyHandle, videodriver);
  403.         SetDialogDefaultItem (commandDialog, kCL_OK);
  404.         SetDialogCancelItem  (commandDialog, kCL_Cancel);
  405.         do {
  406.         
  407.          ModalDialog(nil, &itemHit); /* wait for user response */
  408.             
  409.             /* Toggle command-line output checkbox */
  410.          if ( itemHit == kCL_File ) {
  411.          GetDialogItem(commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
  412.          SetControlValue((ControlHandle)dummyHandle, !GetControlValue((ControlHandle)dummyHandle) );
  413.          }
  414.         } while (itemHit != kCL_OK && itemHit != kCL_Cancel);
  415.         /* Get control values, even if they did not change */
  416.         GetDialogItem     (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); /* MJS */
  417.         GetDialogItemText (dummyHandle, prefs.command_line);
  418.         GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */
  419.         prefs.output_to_file = GetControlValue ((ControlHandle)dummyHandle);
  420.         GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect);
  421.         videodriver = GetControlValue ((ControlRef)dummyHandle);
  422.         DisposeDialog (commandDialog);
  423.         if (itemHit == kCL_Cancel ) {
  424.          exit (0);
  425.         }
  426. }
  427.     
  428.     /* Set pseudo-environment variables for video driver, update prefs */
  429. switch ( videodriver ) {
  430.    case VIDEO_ID_DRAWSPROCKET: 
  431.       putenv ("SDL_VIDEODRIVER=DSp");
  432.       memcpy (prefs.video_driver_name, "pDSp", 4);
  433.       break;
  434.    case VIDEO_ID_TOOLBOX:
  435.       putenv ("SDL_VIDEODRIVER=toolbox");
  436.       memcpy (prefs.video_driver_name, "ptoolbox", 8);
  437.       break;
  438. }
  439.     /* Redirect standard I/O to files */
  440. if ( prefs.output_to_file ) {
  441. freopen (STDOUT_FILE, "w", stdout);
  442. freopen (STDERR_FILE, "w", stderr);
  443. } else {
  444. fclose (stdout);
  445. fclose (stderr);
  446. }
  447.    
  448.     if (settingsChanged) {
  449.         /* Save the prefs, even if they might not have changed (but probably did) */
  450.         if ( ! writePreferences (&prefs) )
  451.             fprintf (stderr, "WARNING: Could not save preferences!n");
  452.     }
  453.    
  454.     getCurrentAppName (appNameText); /* check for error here ? */
  455.     commandLine = (char*) malloc (appNameText[0] + prefs.command_line[0] + 2);
  456.     if ( commandLine == NULL ) {
  457.        exit(-1);
  458.     }
  459.     /* Rather than rewrite ParseCommandLine method, let's replace  */
  460.     /* any spaces in application name with underscores,            */
  461.     /* so that the app name is only 1 argument                     */   
  462.     for (i = 1; i < 1+appNameText[0]; i++)
  463.         if ( appNameText[i] == ' ' ) appNameText[i] = '_';
  464.     /* Copy app name & full command text to command-line C-string */      
  465.     memcpy (commandLine, appNameText + 1, appNameText[0]);
  466.     commandLine[appNameText[0]] = ' ';
  467.     memcpy (commandLine + appNameText[0] + 1, prefs.command_line + 1, prefs.command_line[0]);
  468.     commandLine[ appNameText[0] + 1 + prefs.command_line[0] ] = '';
  469.     /* Parse C-string into argv and argc */
  470.     nargs = ParseCommandLine (commandLine, NULL);
  471.     args = (char **)malloc((nargs+1)*(sizeof *args));
  472.     if ( args == NULL ) {
  473. exit(-1);
  474. }
  475. ParseCommandLine (commandLine, args);
  476.         
  477. /* Run the main application code */
  478. SDL_main(nargs, args);
  479. free (args);
  480. free (commandLine);
  481.    
  482.     /* Remove useless stdout.txt and stderr.txt */
  483.     cleanup_output ();
  484.    
  485. /* Exit cleanly, calling atexit() functions */
  486. exit (0);    
  487. /* Never reached, but keeps the compiler quiet */
  488. return (0);
  489. }