#!/usr/bin/env perl # supertux.wrapper - Launcher for "supertux" # License: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 # Revision: 111116 # Note: The license indicated above applies to this file. It doesn't # apply to the official version of the target program, or to any file # derived from the official package. #--------------------------------------------------------------------- # license information #--------------------------------------------------------------------- # This section may not be modified except as approved by the author or # licensor, or to make non-content changes such as adjustments to par- # agraph formatting or white space. # This version of this software is distributed under the following # license: # # Creative Commons Attribution-NonCommercial-ShareAlike 3.0 # You may use, modify, and redistribute this software without fees or # royalties, but only under the terms and conditions set forth by the # license. In particular, copies and derived works cannot be used for # commercial purposes. Additionally, the license propagates to copies # and derived works. Furthermore, you must provide attribution "in the # manner specified by the author or licensor". The latter point is # discussed below. # The author (and licensor) hereby specifies that attribution must be # handled in the following manner: a. If the software is interactive, # any About or Credits dialog boxes, windows, or output text provided # by the original version must be preserved and readily accessible to # the end user at runtime. b. If the software is non-interactive, or # if it does not provide About or Credits dialog boxes, windows, or # output text, the operating system and/or desktop environment used # must provide attribution that is visible and/or readily accessible # to the end user at runtime. # The following techniques do not meet the attribution requirements: # Attribution through text files, attribution through printed docu- # mentation, verbal attribution, or postings on external web sites # (i.e., web sites that are not an intrinsic local component of the # operating system or desktop environment used). These examples are # provided for illustrative purposes only. # It should be noted that trademarks are an additional issue. If this # software uses any trademarks, trademark-related restrictions may # apply. # This is not a complete explanation of the terms and conditions in- # volved. For more information, see the Creative Commons Attribution- # NonCommercial-ShareAlike 3.0 license. #--------------------------------------------------------------------- # explanation #--------------------------------------------------------------------- # 1. Overview. # This is a wrapper. It performs the following operations (possibly # among others): # # a. It optionally verifies that multiple instances of the program # aren't running. If the test is done, and multiple instances # are running, a fatal-error message is displayed. # # b. It optionally verifies that the program isn't running through # VNC. If the test is done, and the program is running through # VNC, a fatal-error message is displayed. # # c. It optionally verifies that direct rendering is available. # If the test is done, and direct rendering isn't available, a # fatal-error message is displayed. # # d. It optionally tries to prevent crashes related to system-mem- # ory issues. Specifically, if memory appears to be low, the # wrapper warns the user and asks for confirmation before run- # ning the main executable. # # e. It optionally sets the SDL environment variable SDL_MOUSE_ # RELATIVE to a specified integer (and exports the variable). # This fixes mouse-related problems. # # f. It optionally adjusts the standard environment variables # PATH, LD_LIBRARY_PATH, and/or PERL5LIB (and exports the vari- # ables). # # g. It optionally clips the system's Master Volume setting to # predefined minimum and maximum values. # # h. It optionally starts the Jack audio daemon with settings that # should support both regular audio and USB audio. # # i. It optionally switches to a specified "run" directory (which # is optionally created, if necessary). # # j. If no errors have occurred so far, the wrapper runs the main # executable (passing command-line arguments). # # k. If a crash occurs, the wrapper tries to switch the display # back to a usable state. # # Note: Memory-related crashes may shut down the network (by # terminating name servers, etc.). The wrapper doesn't try to # fix network problems. # # l. The original Master Volume setting is restored on exit, if # this is appropriate. # To enable, disable, or configure the tests listed here, edit the # source code and modify the appropriate settings in the "program # parameters" section. #--------------------------------------------------------------------- # 2. Requirements. # Partial list of requirements (not including the main executable): # # a. Gtk2 # b. Perl # c. Perl-Gtk2 # d. SDL - Used by "setx11dim" # e. glxinfo - Used to check the status of direct rendering # f. getx11dim - Distro-specific utility # g. setx11dim - Ditto # h. resetpcmvol - Ditto # i. LACSUB - Distro-specific Perl-based framework # Note: You should be able to obtain source code for the distro-speci- # fic components from the same site as this file. #--------------------------------------------------------------------- # standard module setup #--------------------------------------------------------------------- require 5.8.1; use strict; use Carp; use warnings; use Cwd; # Trap warnings $SIG {__WARN__} = sub { die @_; }; #--------------------------------------------------------------------- # add CPAN module(s) #--------------------------------------------------------------------- use Gtk2 '-init'; use Gtk2::SimpleList; #--------------------------------------------------------------------- # add LACSUB module(s) #--------------------------------------------------------------------- use LACSUB::GUI ( @LACSUB::GUI::EXPORT_OK ); #--------------------------------------------------------------------- # basic constants #--------------------------------------------------------------------- use constant ZERO => 0; # Zero use constant ONE => 1; # One use constant FALSE => 0; # Boolean FALSE use constant TRUE => 1; # Boolean TRUE #--------------------------------------------------------------------- # program parameters #--------------------------------------------------------------------- my $DIR_BASE = '__META_PREFIX__'; my $IE = 'Internal error'; my $PROGNAME = 'supertux'; my $REVISION = '111116'; # Revision (or release) string my $ALERT_ICON_PATH = "$DIR_BASE/misc/alert.png"; my $TARGET_EXE = "$DIR_BASE/bin/$PROGNAME.bin"; #--------------------------------------------------------------------- # If you'd like to prohibit multiple instances, set $FLAG_PROHIBIT_ # MULTI_INSTANCE to TRUE. Otherwise, set this flag to FALSE. my $FLAG_PROHIBIT_MULTI_INSTANCE = TRUE; #--------------------------------------------------------------------- # If this program shouldn't try to run under VNC, set $FLAG_PROHIBIT_ # VNC equal to TRUE. Otherwise, set this flag equal to FALSE. my $FLAG_PROHIBIT_VNC = TRUE; #--------------------------------------------------------------------- # If you'd like to enforce a direct-rendering requirement, set $FLAG_ # REQUIRE_DIRECT_RENDERING to TRUE. Otherwise, set this flag to FALSE. my $FLAG_REQUIRE_DIRECT_RENDERING = TRUE; #--------------------------------------------------------------------- # If you'd like to enforce a minimum-memory requirement, set $MIN_ # FREE_KB to a memory-size value (in KB). Otherwise, set this parame- # ter to zero. # If $MIN_FREE_KB specifies a positive integer, this program tries to # estimate the amount of system memory that's available (or that could # be made available). If the estimated amount is less than the speci- # fied amount, it'll warn the user and prompt for confirmation before # proceeding. my $MIN_FREE_KB = 100000; #--------------------------------------------------------------------- # If $SDL_MOUSE_RELATIVE is defined, and it specifies zero or a posi- # tive integer, the wrapper sets the environment variable SDL_MOUSE_ # RELATIVE equal to the specified number (and exports the vari- # able). Otherwise, the wrapper doesn't look at or change SDL_MOUSE_ # RELATIVE. # This parameter is used to prevent mouse-related problems: # # a. If the main executable uses SDL, and the mouse is slow or # "laggy", try setting $SDL_MOUSE_RELATIVE to ZERO. # # b. If you're experiencing other mouse-related problems, try set- # ting this parameter to ONE. # # c. If these settings cause problems, as opposed to fixing them, # set $SDL_MOUSE_RELATIVE to -1 or undefine it. my $SDL_MOUSE_RELATIVE = ZERO; #--------------------------------------------------------------------- # If the main executable requires any special PATH entries, you can # specify them here. Set $EXTRA_BINPATHS to a colon-delimited list of # absolute directory paths. If there's only one entry, no colons are # required. # If no special PATH entries are required, set $EXTRA_BINPATHS to an # empty string. my $EXTRA_BINPATHS = ""; #--------------------------------------------------------------------- # If the main executable requires any special LD_LIBRARY_PATH entries, # you can specify them here. Set $EXTRA_LIBPATHS to a colon-delimited # list of absolute directory paths. If there's only one entry, no co- # lons are required. # If no special LD_LIBRARY_PATH entries are required, set $EXTRA_ # LIBPATHS to an empty string. my $EXTRA_LIBPATHS = ""; #--------------------------------------------------------------------- # If the main executable requires any special PERL5LIB entries, you # can specify them here. Set $EXTRA_PERL5LIB to a colon-delimited list # of absolute directory paths. If there's only one entry, no colons # are required. # If no special PERL5LIB entries are required, set $EXTRA_PERL5LIB to # an empty string. my $EXTRA_PERL5LIB = ""; #--------------------------------------------------------------------- # If you'd like to enable a "fixup display after crash" feature, set # $FLAG_FIXUP_DISPLAY to TRUE. Otherwise, set this parameter to FALSE. # If you'd like to enable sound-related fixes and/or adjustments, set # $FLAG_FIXUP_SOUND to TRUE. Otherwise, set this parameter to FALSE. my $FLAG_FIXUP_DISPLAY = TRUE; my $FLAG_FIXUP_SOUND = TRUE; #--------------------------------------------------------------------- # If you'd like to specify a minimum initial Master Volume level, set # $MINVOL to a positive integer from one to 100. Otherwise, set this # parameter to zero. # If you'd like to specify a maximum initial Master Volume level, set # $MAXVOL to a positive integer from one to 100. Otherwise, set this # parameter to zero. # Note: If $FLAG_FIXUP_SOUND is FALSE, the $MINVOL and $MAXVOL set- # tings have mo ffect. my $MINVOL = 10; my $MAXVOL = 75; #--------------------------------------------------------------------- # If you'd like to check for the presence of the Jack audio daemon, # and to start the daemon if it's not running, set $STARTJACK to TRUE. # Otherwise, set this parameter to FALSE. my $STARTJACK = FALSE; #--------------------------------------------------------------------- # If you'd like to run the main executable from a specific directory, # set $PATH_RUNDIR to an absolute path for the directory. Otherwise, # set this parameter to an empty string. # If $PATH_RUNDIR starts with the special string "__META_HOME__", the # string in question will be replaced with an appropriate home-direc- # tory path. # If you'd like to create the directory (if any) specified by $PATH_ # RUNDIR as necessary, set $MAKE_RUNDIR to TRUE. Otherwise, set $MAKE_ # RUNDIR to FALSE. my $MAKE_RUNDIR = FALSE; my $PATH_RUNDIR = ""; #--------------------------------------------------------------------- # main routine #--------------------------------------------------------------------- sub Main { my $data; # Data buffer my $str; # Scratch #--------------------------------------------------------------------- # Initial setup. select STDERR; $| = ONE; # Set flush-on-write mode select STDOUT; $| = ONE; # Ditto (note: this line must be last) #--------------------------------------------------------------------- # Handle multiple-instances test (if enabled). &VerifyNotRunning ( -icon_path => $ALERT_ICON_PATH , -name => $PROGNAME , -pattern_this => ':\d\d\s(perl |)(\S+/|)' . $PROGNAME . '(|\.wrapper)\s' , -pattern_next => ':\d\d\s(perl |)(\S+/|)' . $PROGNAME . '\.bin\s' ) if $FLAG_PROHIBIT_MULTI_INSTANCE; #--------------------------------------------------------------------- # Handle VNC test (if enabled). &AbortIfVNC ( -icon_path => $ALERT_ICON_PATH , -name => $PROGNAME ) if $FLAG_PROHIBIT_VNC; #--------------------------------------------------------------------- # Handle direct-rendering test (if enabled). &AbortUnlessDRI ( -icon_path => $ALERT_ICON_PATH , -name => $PROGNAME ) if $FLAG_REQUIRE_DIRECT_RENDERING; #--------------------------------------------------------------------- # Handle available-memory test (if enabled). &CheckAvailableMemory ( -icon_path => $ALERT_ICON_PATH , -min_free => $MIN_FREE_KB , -name => $PROGNAME ) if defined ($MIN_FREE_KB) && ($MIN_FREE_KB =~ m@^[1-9]\d*\z@); #--------------------------------------------------------------------- # Set SDL_MOUSE_RELATIVE, if necessary. if (defined ($SDL_MOUSE_RELATIVE) && ($SDL_MOUSE_RELATIVE =~ m@^\d+\z@)) { $ENV {SDL_MOUSE_RELATIVE} = $SDL_MOUSE_RELATIVE; } #--------------------------------------------------------------------- # Adjust PATH, if necessary. if (defined ($EXTRA_BINPATHS) && length ($EXTRA_BINPATHS)) { $str = $ENV {PATH}; $str = "" unless defined $str; $str = "$EXTRA_BINPATHS:$str"; $str =~ s@^:+@@; $str =~ s@:+\z@@; $str =~ y/:/:/s; $ENV {PATH} = $str; } #--------------------------------------------------------------------- # Adjust LD_LIBRARY_PATH, if necessary. if (defined ($EXTRA_LIBPATHS) && length ($EXTRA_LIBPATHS)) { $str = $ENV {LD_LIBRARY_PATH}; $str = "" unless defined $str; $str = "$EXTRA_LIBPATHS:$str"; $str =~ s@^:+@@; $str =~ s@:+\z@@; $str =~ y/:/:/s; $ENV {LD_LIBRARY_PATH} = $str; } #--------------------------------------------------------------------- # Adjust PERL5LIB, if necessary. if (defined ($EXTRA_PERL5LIB) && length ($EXTRA_PERL5LIB)) { $str = $ENV {PERL5LIB}; $str = "" unless defined $str; $str = "$EXTRA_PERL5LIB:$str"; $str =~ s@^:+@@; $str =~ s@:+\z@@; $str =~ y/:/:/s; $ENV {PERL5LIB} = $str; } #--------------------------------------------------------------------- # Start Jack audio daemon, if necessary. if ($STARTJACK) # Was this feature requested? { # Yes # Check for presence of daemon $str = `/bin/ps ax | grep "[ /]jackd -" 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; if (!length ($str)) # Start daemon? { # Yes system "/usr/sbin/jackd-start"; sleep ONE; } } #--------------------------------------------------------------------- # Adjust initial volume (if necessary). # Note: If sound fixups are enabled, this code runs "resetpcmvol", # whether or not minimum and/or maximum volume levels are specified. # Reasons: a. "resetpcmvol" may correct certain problems either way. # b. This simplifies the cleanup code at the end of the wrapper. my $OrigVolume; # Original volume setting if ($FLAG_FIXUP_SOUND) # Are misc. "sound" features enabled? { # Yes $str = '__META_LACUTIL__/resetpcmvol --show'; $str .= " --min=$MINVOL" if defined ($MINVOL) && ($MINVOL =~ m@^\d+\z@) && ($MINVOL > ZERO) && ($MINVOL <= 100); $str .= " --max=$MAXVOL" if defined ($MAXVOL) && ($MAXVOL =~ m@^\d+\z@) && ($MAXVOL > ZERO) && ($MAXVOL <= 100); $str = `$str 2>&1`; $str = "" unless defined ($str) && ($str =~ m@^\d+\s*\z@); $str =~ s@\s+\z@@s; $OrigVolume = $str; } #--------------------------------------------------------------------- # Get initial display dimensions (if possible). my $X11DIM; if ($FLAG_FIXUP_DISPLAY) { $str = `__META_LACUTIL__/getx11dim 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; $X11DIM = $str if $str =~ m@^\d+x\d+\z@; } #--------------------------------------------------------------------- # Adjust relative paths. for (@ARGV) { next unless m@^(\w|\.{1,2}/).*\.\w{2,4}\z@ && -f $_; $str = getcwd(); $str .= '/' unless $str =~ m@/\z@; $str .= $_; $_ = $str; } #--------------------------------------------------------------------- # Go to appropriate directory. # Use a specified directory? if (defined ($PATH_RUNDIR) && length ($PATH_RUNDIR)) { # Yes if ($PATH_RUNDIR =~ m@^__META_HOME__\b(.*)\z@) { $str = $1; my $HOME = $ENV {HOME}; $HOME = '/tmp' unless defined $HOME; $PATH_RUNDIR = "$HOME$str"; } # Try to create directory? if ($MAKE_RUNDIR && (!-e $PATH_RUNDIR) && ($PATH_RUNDIR !~ m@[ \!\$]@)) { # Yes # Handle broken links unlink $PATH_RUNDIR; # Try to create directory system "mkdir -p \"$PATH_RUNDIR\""; } # Go to directory, if possible chdir $PATH_RUNDIR if -d $PATH_RUNDIR; } #--------------------------------------------------------------------- # Run the target program. system $TARGET_EXE, @ARGV; #--------------------------------------------------------------------- # Work-around for a "jackd" problem. # If "jackd" is running at this point, this code stops the daemon. # This is necessary because "jackd" breaks various programs. system "/usr/sbin/jackd-stop"; #--------------------------------------------------------------------- # Fix resulting display problems (if necessary). if (defined ($X11DIM) && length ($X11DIM)) { $str = `__META_LACUTIL__/getx11dim 2>&1`; $str = "" unless defined $str; $str =~ s@\s+\z@@s; system "__META_LACUTIL__/setx11dim --fast $X11DIM" unless $str eq $X11DIM; } system "xclockmove"; #--------------------------------------------------------------------- # Restore original volume (if possible). if ($FLAG_FIXUP_SOUND) # Are "sound" features enabled? { # Yes # Do we know the original volume? if ($OrigVolume =~ m@^\d+\z@) { # Yes - Restore it system "__META_LACUTIL__/resetpcmvol --set=$OrigVolume"; } } undef; } #--------------------------------------------------------------------- # main program #--------------------------------------------------------------------- &Main(); # Call the main routine exit ZERO; # Normal exit