#!/usr/bin/env perl # gmplayer.wrapper - Multi-purpose wrapper for "gmplayer". # License: BSD-style # Revision: 230108 #--------------------------------------------------------------------- # overview #--------------------------------------------------------------------- # 1. This script is a wrapper for "gmplayer". It serves four purposes: # # a. It enforces a single-instance restriction - see note 3 # b. It fixes a problem with "gmplayer.bin" - see note 4 # c. It adds a "--skin" option switch - see note 5 # d. It provides a workaround for a "skin" issue - see note 6 #--------------------------------------------------------------------- # 2. Basic setup issues: # # a. If this script is used, the original "gmplayer" program must # be renamed to "gmplayer.bin", and this script must be renamed # to "gmplayer". # # b. This script is distro-dependent. In particular, it requires # three distro-specific utilities named "getx11dim", "killany", # and "resetpcmvol". Note: You should be able to obtain these # utilities from the same place as this script. # # c. This script requires additional utilities; e.g., "file", # "xdpyinfo", and "xvinfo". The additional utilities are pre- # installed on most standard Linux distros. #--------------------------------------------------------------------- # 3. This script enforces a single-instance restriction. Specifically, # it terminates any existing instances of "gmplayer.bin". #--------------------------------------------------------------------- # 4. In some cases, "gmplayer.bin" will use the "xv" video output dri- # ver whether or not XOrg supports "xv" mode on the current system. # This script implements a workaround for the problem. # Details: This script invokes "xvinfo" internally. If "xvinfo" # doesn't like the current video hardware, this script modifies [or # creates] a "gmplayer" configuration file. If the video output driver # was set to "xv" previously, or if the setting was missing, or if the # file itself was missing, the output file selects "x11" mode instead # of "xv" mode. #--------------------------------------------------------------------- # 5. This script intercepts option switches of the form: # # --skin=NAME # If a switch like this is specified, the wrapper modifies the config- # uration file mentioned previously to select the specified "gmplayer" # "skin". Note: Multiple associated settings may be changed. # Special case: If NAME is "default", the wrapper sets a default skin # if [and only if] one hasn't been selected yet. # Two caveats: (a) This script doesn't validate the specified "skin" # setting. (b) Presently, the "equals" sign is required. This script # doesn't support switches of the form "--skin NAME". #--------------------------------------------------------------------- # 6. Under [at least] some window managers, the standard version of # "gmplayer" doesn't take taskbars into account when positioning its # main window. When "--skin=..." is used, this wrapper tries to ad- # dress the problem. # Caveat: This feature requires the standard "file" utility and a # distro-specific utility named "getx11dim". As noted previously, you # should be able to obtain "getx11dim" from the same place that # you got this script. #--------------------------------------------------------------------- # 7. On exit, this script normally chains to "gmplayer.bin". Arguments # are passed through [except for "--skin" switches]. Note: If XOrg # isn't running, this script prints an error message instead. #--------------------------------------------------------------------- # module setup #--------------------------------------------------------------------- require 5.6.1; use strict; use Carp; use warnings; # Trap warnings $SIG {__WARN__} = sub { die @_; }; #--------------------------------------------------------------------- # 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 #--------------------------------------------------------------------- # $DEFAULT_SKIN specifies the default "skin" that should be selected # when "--skin=default" is used. # $HEIGHT_TASKBAR specifies the vertical space [expressed in pixel # rows] that should be allowed for a taskbar. # IE specifies an error-message prefix string. # $TARGET_PROGRAM should specify the name of the target executable to # be run. Presently, an absolute path is required. # Important: The filename specified by $TARGET_PROGRAM [disregarding # the path component, if any] should be different than the name of # this script, or infinite loops may occur. my $DEFAULT_SKIN = 'handheld'; my $HEIGHT_TASKBAR = 45; my $IE = 'gmplayer wrapper: Error'; my $TARGET_PROGRAM = '__META_PREFIX__/bin/gmplayer.bin'; #--------------------------------------------------------------------- # Absolute path for "padsp" program my $PROG_AOSS = '/usr/bin/padsp'; #--------------------------------------------------------------------- # main routine #--------------------------------------------------------------------- sub Main { my $data; # Data buffer my $skin = ""; # New "skin" setting my $n; # Scratch (integer) my $str; # Scratch (string ) my $FlagModDriver = FALSE; # Flag: Modify driver setting[s] my $FlagModSkin = FALSE; # Flag: Modify "skin" setting[s] my $FlagModFile = FALSE; # Flag: Modify configuration file #--------------------------------------------------------------------- # Initial setup. system "killany -9 gmplayer.bin"; system "resetpcmvol"; my $HOME = $ENV {HOME}; $HOME = "/tmp" unless defined $HOME; $str = `/usr/X11R6/bin/xvinfo 2>&1`; $str = "" if !defined $str; if ($str =~ m@unable to open display@i) { die "Error: gmplayer requires X\n"; } if (($str =~ m@\bno adapt[eo]rs? (found|present)\b@i) || ($str =~ m@extension "?XVideo"? missing@i) || ($str =~ m@No X-?Video Extension@i)) { $FlagModDriver = TRUE; } for (@ARGV) { next unless m@^-+skin=(\w+)\z@i; $skin = $1; $_ = ""; } @ARGV = grep { length; } @ARGV; $FlagModSkin = TRUE if length $skin; $FlagModFile = $FlagModDriver || $FlagModSkin; #--------------------------------------------------------------------- # Create configuration file, if necessary. my $cfgdir = "$HOME/.mplayer"; my $cfgfile = "$cfgdir/gui.conf"; if (!-e $cfgfile) { unlink $cfgfile if -l $cfgfile; system "mkdir -p $cfgdir"; system "touch $cfgfile"; $FlagModFile = $FlagModDriver = TRUE; } #--------------------------------------------------------------------- # Update configuration file, if necessary. if ($FlagModFile && (-f $cfgfile) && open (IFD, "<$cfgfile")) { undef $/; $data = ; $data = "" if !defined $data; my $orig_data = $data; my $WSZ = '[\011\040]*'; $data =~ s@\s*\z@\n@s; if ($FlagModDriver) { $data =~ s@vo_driver${WSZ}=${WSZ}"xv"@vo_driver = "x11"@; if ($data !~ m@\bvo_driver${WSZ}=@) { $data .= "vo_driver = \"x11\"\n"; } } if ($FlagModSkin) { if ($skin =~ m@^default\z@i) { $skin = $DEFAULT_SKIN; } else { $data =~ s@gui_skin${WSZ}=${WSZ}"\w+"@gui_skin = "$skin"@; } if ($data !~ m@\bgui_skin${WSZ}=@) { $data =~ s@\s*\z@\n@; $data .= "gui_skin = \"$skin\"\n"; } while ($data =~ s@(^|\n)gui_(main|video_out)_pos_[xy]${WSZ}=[^\012]*\n@$1@g) {} my $skin_file = << "END"; __META_PREFIX__/share/mplayer/skins/$skin/main.png END $skin_file =~ s@\s+\z@@s; while (TRUE) { last if !-B $skin_file; $str = `file $skin_file 2>&1`; $str = "" if !defined $str; last unless $str =~ m@\d+${WSZ}x${WSZ}(\d+)@; my $HeightImage = $1; $str = `getx11dim 2>&1`; $str = "" if !defined $str; if ($str !~ m@^\d+x\d+@) { $str = `xdpyinfo 2>&1`; $str = "" if !defined $str; $str =~ y/\011\040/ /s; $str = $1 if $str =~ m@dimensions: +(\d+x\d+) +pixels@i; } last unless $str =~ m@^\d+x(\d+)@; my $HeightDisplay = $1; # Sanity check last if ($HeightDisplay < 600) || ($HeightDisplay > 1200); # Note: Allow room for a taskbar $n = $HeightDisplay - ($HeightImage + $HEIGHT_TASKBAR); last unless $n > 10; $data .= << "END"; gui_main_pos_y = "$n" END last; } } if (($data ne $orig_data) && open (OFD, ">$cfgfile")) { print OFD $data; close OFD; } } #--------------------------------------------------------------------- # Wrap it up. unshift (@ARGV, $TARGET_PROGRAM); exec $PROG_AOSS, @ARGV; } #--------------------------------------------------------------------- # main program #--------------------------------------------------------------------- &Main(); # Call the main routine exit ZERO; # Not reached