Advertisement
Guest User

fapomatic.pl

a guest
Apr 16th, 2014
415
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env perl
  2. #
  3. # MPlayer wrapper to select and play random video file(s)
  4. #
  5.  
  6. # TODO: incorporate history-cleanse ?
  7.  
  8. use strict;
  9. use warnings;
  10.  
  11. use File::Find;
  12. use File::stat;
  13.  
  14. #-------------------------------------------------------------------------------------------------------#
  15. ## BEGIN CONFIGURABLE OPTIONS :
  16. #-------------------------------------------------------------------------------------------------------#
  17. my $version="3.3";      # Current Version.
  18.  
  19. # Configure your video 'collection' locations here. This is probably the only thing you need to change.
  20. our @Collections=(
  21.     "/Volumes/ENCRYPTED",
  22.     #"/mnt/pr0n",
  23. );
  24.  
  25. # Specify Alternate image viewer, it will take one argument - related filename(s)
  26. our $image_viewer="";
  27.  
  28. # Otherwise the defaults:
  29. our $def_image_viewer_osx="open";
  30. our $def_image_viewer_linux="eog";
  31.  
  32. # Autoplay the files, or give a y/n prompt? 1 = auto, 0 = prompt
  33. our $autoplay="0";
  34.  
  35. # Path to mplayer, and any default options you want to pass along
  36. our $mplayer="mplayer";
  37. our $mplayer_opts="";
  38. #our $mplayer_opts="-display :0";
  39.  
  40. # Supported file types mplayer can handle - if it's not in this list, it won't be played, even though mplayer probably supports it
  41. our @Supported_videos=("mpg","mpeg","avi","wmv","asf","mov","mp4","mkv","m4v","rmvb","flv");
  42.  
  43. # Cover images - some filetypes that may exist in your collection that mplayer should ignore / will not play
  44. our @Supported_images=(".jpg",".png",".gif",".bmp");
  45.  
  46. # Default audio volume; be careful :p
  47. our $volume_level="-volume 05";
  48.  
  49. # Set some default behavior switches; alter for desired behavior
  50. our $file_info_banner="1";  # Display info about the selected file ?
  51. our $use_colors="1";        # Colorize output ?
  52. our $verbose="0";       # Verbose by default ?
  53. our $very_verbose="0";      # Even more info ?
  54. our $fullscreen="0";        # Fullscreen mplayer ?
  55. our $sort_order="0";        # Sort by mtime (1), vs alphabetical (0)?
  56. our $cover="0";         # Open related images ?
  57. our $vol_muted="0";     # Start muted (volume 0) ?     
  58. our $nosound="0";       # Nosound (unrecoverable stream) ?     
  59. our $search="0";        # Jump to search prompt ?
  60. our $test_exists="0";       # Simple test for existance of file
  61. our $listing="0";       # List files by default ?
  62. our $list_everything="0";   # List videos, images, and unrelated files ?
  63. our $list_full_paths="0";   # Display full paths for files ?
  64. our $mplayer_output="0";    # Attach to mplayer output ?
  65. our $search_char_min="2";   # Minimum search characters ?
  66. our $specific_result="0";   # Selected file number to play ?
  67. our $debug = "0";       # Debug info by default ?
  68. our $pretend="0";       # No Exec ?
  69. our $auto_sort="1";     # 1 implies -o with -t
  70. our $fork_bomb_protect="1"; # Prevent fork bombing the system with mplayer calls
  71. our $do_exec="0";       # Probably never need to change this.
  72. our $search_char="0";       # Probably never need to change this.
  73. our $custom_dir="0";        # Probably never need to change this.
  74. our $total_videos="0";      # Probably never need to change this.
  75. our $total_images="0";      # Probably never need to change this.
  76. our $total_rejected="0";    # Probably never need to change this.
  77. our $search_term="";        # Probably never need to change this.
  78. our $search_input;      # Probably never need to change this.
  79. our $search_request;        # Probably never need to change this.
  80. our $limit_recent="0";      # Probably never need to change this.
  81. our $limit_time="0";        # Probably never need to change this.
  82. our $old_or_new;        # Probably never need to change this.
  83. our $repeat="0";        # Repeat / Range
  84. our $default_repeat="5";    # Default repeat range
  85. our $repeat_range="0";
  86. our $range_request;
  87. our $repetition;
  88. our $mplayer_max="10";      # Maximum amount of mplayer windows before limiting spawn
  89. our $video_width="0";
  90. our $video_height="0";
  91. our $target_x="0";
  92. our $target_y="0";
  93. our $screen_res_x="0";
  94. our $screen_res_y="0";
  95. our $resolution="";
  96. our $mplayer_opts_geo="";
  97. our $kill_players="0";
  98. our $kill_signal="hup";
  99. our $user_ok="";
  100. our $null_term="0";
  101. our $exclude_term="";
  102. our $timejump="0";      # start player(s) playing +x seconds into video file
  103. our $jumptime="30";     # Default jumptime
  104.  
  105. # Define highlight color codes
  106. my $color_bold = "\033[0;1m";
  107. my $color_white = "\033[0m";
  108. my $color_black = "\033[1;30m";
  109. my $color_red = "\033[1;31m";
  110. my $color_green = "\033[1;32m";
  111. my $color_blue = "\033[1;34m";
  112. my $color_yellow = "\033[1;33m";
  113. my $color_cyan = "\033[1;36m";
  114. my $color_purple = "\033[1;35m";
  115. my $color_dark_blue = "\033[0;34m";
  116. my $color_dark_red = "\033[0;31m";
  117. my $color_dark_green = "\033[0;32m";
  118. my $color_dark_yellow = "\033[0;33m";
  119. my $color_dark_cyan = "\033[0;36m";
  120. my $color_dark_purple = "\033[0;35m";
  121. my $color_dark_black = "\033[0;30m";
  122.  
  123. # Set which color to actually use for various 'tags'
  124. our $colortag_name = $color_red;
  125. our $colortag_search = $color_cyan;
  126. our $colortag_number = $color_dark_yellow;
  127. our $colortag_mtime = $color_dark_blue;
  128. our $colortag_default = $color_white;
  129. our $colortag_online = $color_bold;
  130. our $colortag_offline = $color_bold;
  131. our $colortag_warning = $color_bold;
  132. our $colortag_error = $color_bold;
  133. our $colortag_pretend = $color_dark_purple;
  134. our $colortag_exec = $color_bold;
  135. our $colortag_vidlabel = $color_bold;
  136. our $colortag_abort = $color_yellow;
  137. our $colortag_category = $color_blue;
  138. our $colortag_imgname = $color_purple;
  139. our $colortag_selection = $color_dark_red;
  140.  
  141. # Text used for the static variable tags;
  142. our $online_label = "AVAILABLE";
  143. our $offline_label = "UNAVAILABLE";
  144. our $warning_label = "WARNING";
  145. our $error_label = "ERROR";
  146. our $pretend_label = "PRETEND";
  147. our $exists_label = "FOUND";
  148. our $exec_label = "EXEC";
  149. our $abort_label = "ABORT";
  150. our $yes_label = "y";
  151. our $no_label = "n";
  152. our $category_label = "CATEGORY";
  153. our $vid_label = "VID FILE";
  154.  
  155. # Initial self awareness for this script
  156. my @ScriptPath=split(/\//,$0);
  157. our $script_name=$ScriptPath[$#ScriptPath];
  158.  
  159. # Required commands used by this script
  160. our @Required=("$mplayer","grep");
  161.  
  162. #-------------------------------------------------------------------------------------------------------#
  163. &Init; ## END CONFIGURABLE OPTIONS : YOU SHOULDN'T NEED TO EDIT ANYTHING BELOW THIS POINT
  164. #-------------------------------------------------------------------------------------------------------#
  165.  
  166. sub GlobalVars {
  167.  
  168.     if ($debug == 1) {
  169.         print qq| <Enter Sub> GlobalVars\n|;
  170.     }
  171.  
  172.     our $mplayer = $main::mplayer;
  173.     our $mplayer_opts = $main::mplayer_opts;
  174.     our $volume_level = $main::volume_level;
  175.     our $image_viewer = $main::image_viewer;
  176.     our $version = $main::version;
  177.     our @Collections = @main::Collections;
  178.     our @Videos = @main::Videos;
  179.     our @Images = @main::Images;
  180.     our @Rejected = @main::Rejected;
  181.     our @Supported_videos = @main::Supported_videos;
  182.     our @Supported_images = @main::Supported_images;
  183.     our @AlreadyPicked=@main::AlreadyPicked;
  184. }
  185.  
  186. sub Init {
  187.  
  188.     # Set & Get some initial requirements
  189.     &GlobalVars;
  190.  
  191.     print qq|\n|;
  192.  
  193.     if (@ARGV) {
  194.         &CheckArgs;
  195.     }
  196.    
  197.     if ($debug == 1) {
  198.         print qq| <Enter Sub> Init\n|;
  199.     }
  200.  
  201.     # swap out colors
  202.     if ($use_colors == 1) {
  203.         $online_label = $colortag_online . "$online_label" . $colortag_default;
  204.         $offline_label = $colortag_offline . "$offline_label" . $colortag_default;
  205.         $warning_label = $colortag_error . "$warning_label" . $colortag_default;
  206.         $error_label = $colortag_error . "$error_label" . $colortag_default;
  207.         $pretend_label = $colortag_pretend . "$pretend_label" . $colortag_default;
  208.         $exists_label = $colortag_pretend . "$exists_label" . $colortag_default;
  209.         $exec_label = $colortag_exec . "$exec_label" . $colortag_default;
  210.         $abort_label = $colortag_abort . "$abort_label" . $colortag_default;
  211.         $yes_label = $color_bold . "$yes_label" . $colortag_default;
  212.         $no_label = $color_bold . "$no_label" . $colortag_default;
  213.         $vid_label = $colortag_vidlabel . $vid_label . $colortag_default;
  214.         $script_name = $color_bold . $script_name . $colortag_default;
  215.         #$category_label = $colortag_category . "$category_label" . $colortag_default;
  216.     }
  217.    
  218.     if ($autoplay == 1) {
  219.         our $do_exec = 1;
  220.     }
  221.  
  222.     # Check some command dependancies
  223.     &DepCheck;
  224.    
  225.     # If one of the args is a directory, play file from requested dir
  226.     if ($custom_dir == 1) {
  227.         our $dir=$main::user_dir;
  228.        
  229.         my $dirlabel = $color_bold . "USING DIR" . $colortag_default;
  230.         print qq| [$dirlabel]: $dir\n\n|;
  231.        
  232.         if ($search == 1) {
  233.             &Search;
  234.         }
  235.         else {
  236.             #Draw random file from user dir (will inherit dir)
  237.             &BeginFlow;
  238.         }
  239.     }
  240.     else {
  241.         # Default Program flow; Play random file from collections
  242.         &BeginFlow;
  243.     }  
  244. }
  245.  
  246. sub CheckArgs {
  247.  
  248.     # Process arguments before action
  249.  
  250.     if ($debug == 1) {
  251.         print qq| <Enter Sub> CheckArgs\n|;
  252.     }
  253.  
  254.     my $args=0;
  255.     my $pass_opt_check=0;
  256.     my $next;
  257.    
  258.     foreach my $arg (@ARGV) {  
  259.        
  260.         if ($arg =~/^\-q$/) {
  261.             $vol_muted = 1;
  262.         }
  263.         elsif ($arg =~/^\-qq$/) {
  264.             $nosound = 1;
  265.         }
  266.         elsif ($arg =~/^\-i$/) {
  267.             our $cover = 1;
  268.         }
  269.         elsif ($arg =~/^\-h$|^-{1,2}help$/) {
  270.             &Usage;
  271.         }
  272.         elsif ($arg =~/^\-v$/) {
  273.             our $verbose = 1;
  274.         }
  275.         elsif ($arg =~/^-vv$/) {
  276.             our $verbose = 1;
  277.             our $very_verbose = 1;
  278.         }
  279.         elsif ($arg =~/^-{1,2}debug$/) {
  280.             our $debug = 1;
  281.         }
  282.         elsif ($arg =~/^\-a$/) {
  283.             our $autoplay = 1;
  284.             our $do_exec = 1;
  285.         }
  286.         elsif ($arg =~/^\-l$/) {
  287.             our $listing = 1;
  288.         }
  289.         elsif ($arg =~/^\-z$/) {
  290.             our $list_everything = 1;
  291.             our $listing = 1;
  292.         }
  293.         elsif ($arg =~/^\-c$/) {
  294.            
  295.             if ($use_colors == 1) {
  296.                 our $use_colors = 0;
  297.             }
  298.             else {
  299.                 our $use_colors = 1;
  300.             }
  301.         }
  302.         elsif ($arg =~/^\-o$/) {
  303.            
  304.             if ($sort_order == 1) {
  305.                 our $sort_order = 0;
  306.             }
  307.             else {
  308.                 our $sort_order = 1;
  309.             }
  310.         }
  311.         elsif ($arg =~/^\-k$/) {
  312.             our $kill_players = 1;
  313.            
  314.             chomp(my $mplayer_pid=`pidof mplayer`);
  315.            
  316.             if ($mplayer_pid) {
  317.                 system("kill -s $kill_signal $mplayer_pid");
  318.             }
  319.         }
  320.         elsif ($arg =~/^\-p$/) {
  321.             our $pretend = 1;
  322.         }
  323.         elsif ($arg =~ /^\-fs$/) {
  324.             our $fullscreen = 1;
  325.         }
  326.         elsif ($arg =~ /^\-m$/) {
  327.             our $mplayer_output = 1;
  328.         }
  329.         elsif ($arg =~/^\-t$/) {
  330.            
  331.             # Limit results by time logic;
  332.  
  333.             our $limit_recent = 1;
  334.            
  335.             if ($auto_sort == 1) {
  336.                 our $sort_order = 1;
  337.             }
  338.  
  339.             my $next=$ARGV[$args+1];
  340.            
  341.             unless ($next) {
  342.                 print qq|[$error_label]: With -t, You must specify a time period.\n\n|;
  343.                 sleep 1;
  344.                 &Usage;
  345.             }      
  346.                    
  347.             unless ($next=~/^-(\w+)/) {
  348.                 $limit_time = $next;
  349.             }
  350.            
  351.             if ($limit_time=~/^(\+?)(\d+)(\w?)$/) {
  352.                
  353.                 $pass_opt_check=1;
  354.                
  355.                 our $old_or_new = $1;
  356.                 my $number = $2;
  357.                 my $amount = $3;
  358.                
  359.                 if ($amount) {
  360.                     if ($amount eq 'd') {
  361.                         if ($old_or_new) {
  362.                             $number = $number - 1; 
  363.                         }
  364.                         $limit_time = $number * 1;
  365.                     }
  366.                     elsif ($amount eq 'w') {
  367.                         $limit_time = $number * 7;
  368.                     }
  369.                     elsif ($amount eq 'm') {
  370.                         $limit_time = $number * 31;
  371.                     }
  372.                     elsif ($amount eq 'y') {
  373.                         $limit_time = $number * 365;
  374.                     }
  375.                     else {
  376.                         print qq|Recent Limit: $limit_time - "$amount" is not a valid time period... must be either d,w,m,y\n|;
  377.                         exit;
  378.                     }
  379.                 }
  380.             }
  381.         }
  382.         elsif (($arg =~ /^\-s$/) || ($arg=~ /^-e$/)) {
  383.  
  384.             # grab search term
  385.            
  386.             if ($arg =~/^\-s$/) {
  387.                 our $search = 1;
  388.             }
  389.             elsif ($arg =~/^\-e$/) {
  390.                 our $search = 1;
  391.                 our $listing = 1;
  392.                 our $test_exists = 1;
  393.             }
  394.            
  395.             my $next=$ARGV[$args+1];
  396.  
  397.             if ($next) {
  398.                
  399.                 unless ($next=~/^-(\w+)/) {
  400.                     $search_term = $next;
  401.                 }
  402.                 if ($search_term=~/^((\w+)|(\*)|(\.))/g) {
  403.                     $pass_opt_check=1;
  404.                 }
  405.             }
  406.             else {
  407.                 $search_term = "";
  408.             }
  409.         }
  410.         elsif ($arg =~ /^\-x$/) {
  411.  
  412.             our $null_term = 1;
  413.            
  414.             my $next=$ARGV[$args+1];
  415.  
  416.             if ($next) {    
  417.                 unless ($next=~/^-(\w+)/) {
  418.                     $exclude_term = $next;
  419.                 }
  420.                 if ($exclude_term=~/^((\w+)|(\*)|(\.))/g) {
  421.                     $pass_opt_check=1;
  422.                 }
  423.             }
  424.             else {
  425.                 $exclude_term = "";
  426.             }
  427.         }
  428.         elsif ($arg =~ /^\-n$/) {
  429.  
  430.             our $specific_result = 1;
  431.  
  432.             my $wrong_number="[$error_label]: With -n, You must specify the number of a search result to play.\n";
  433.             my $next = $ARGV[$args+1];
  434.  
  435.             if ($next) {
  436.                
  437.                 unless ($next=~/^(\d+)$/) {
  438.                     print qq|$wrong_number\n|;
  439.                     sleep 1;
  440.                     &Usage;
  441.                 }
  442.                 else {
  443.                     $search_request = $next;
  444.                 }
  445.                 if ($search_request=~/^(\d+)/) {
  446.                     $pass_opt_check=1;
  447.                 }
  448.             }
  449.             else {
  450.                 print qq|$wrong_number\n|;
  451.                 sleep 1;
  452.                 &Usage;
  453.             }
  454.         }  
  455.         elsif ($arg =~ /^\-r$/) {
  456.  
  457.             our $repeat = 1;           
  458.             $repeat_range = "$default_repeat";
  459.            
  460.             my $next=$ARGV[$args+1];
  461.  
  462.             if ($next) {
  463.                
  464.                 # unless next var is another option, assign it as a var
  465.                 unless ($next=~/^-(\w+)/) {
  466.                    
  467.                     unless (-d $next) {
  468.                         $repeat_range = $next;
  469.                     }
  470.                 }
  471.                
  472.                 if ($repeat_range=~/^((\d+)|all)$/g) {
  473.                    
  474.                     my $range_limit=$mplayer_max + $default_repeat;
  475.                    
  476.                     if (($repeat_range=~/^\d+/) && ($repeat_range > $range_limit)) {
  477.                        
  478.                         unless ($fork_bomb_protect == 1) {
  479.                        
  480.                             &PromptUser("WARNING: $repeat_range is over $range_limit processes. Continue?");
  481.                         }
  482.                     }
  483.                    
  484.                     $pass_opt_check=1;
  485.                 }
  486.             }
  487.  
  488.             $range_request = $repeat_range;
  489.         }
  490.         elsif ($arg =~/^\-j$/) {
  491.             our $timejump = 1;
  492.            
  493.             my $next=$ARGV[$args+1];
  494.            
  495.             if ($next) {
  496.                 if ($next=~/^(\d+)$/) {
  497.                     our $jumptime = $1;
  498.                     $pass_opt_check=1;
  499.                 }
  500.             }
  501.             else {
  502.                 #$jumptime = $jumptime;
  503.             }
  504.         }
  505.         elsif ((-d "$arg")||(-l "$arg")) {
  506.             our $custom_dir = 1;
  507.             our $user_dir=$arg;
  508.             $user_dir=~s/\/$//;
  509.         }
  510.         else {
  511.             # if an option has been validated, don't complain
  512.             unless ($pass_opt_check == 1) {
  513.                
  514.                 print qq|[$error_label]: Unknown Argument: "$arg"\n\n|;
  515.                
  516.                 sleep 1;
  517.                
  518.                 &Usage;
  519.                 exit;
  520.             }
  521.             $pass_opt_check=0;
  522.         }
  523.         $args++;
  524.     }
  525.     return;
  526. }
  527.  
  528. sub BeginFlow {
  529.    
  530.     # Silence errors of subcommands, unless ...
  531.  
  532.     unless (($very_verbose == 1) || ($debug == 1)) {
  533.         open(STDERR, ">/dev/null") or die "Can't redirect stderr: $!";
  534.     }
  535.    
  536.     if ($debug == 1) {
  537.         print qq| <Enter Sub> BeginFlow\n|;
  538.     }
  539.    
  540.     &CheckStorage;     
  541.     &GetSysInfo;
  542.    
  543.     if (($search == 1) || ($test_exists == 1)) {
  544.         &Search;
  545.     }
  546.     else {
  547.         &SelectFile;
  548.     }
  549.  
  550.     print qq|OOPS! You should not be here.\n|;
  551.  
  552.     exit;
  553. }
  554.  
  555. sub GetSysInfo {
  556.  
  557.     # Alter commands per OS;
  558.     my $this_os="$^O";
  559.    
  560.     # MAC OSX
  561.     if ($this_os =~/^(darwin)$/i) {
  562.        
  563.         # grab default for image viewer
  564.         unless ($image_viewer) {
  565.             $image_viewer = $def_image_viewer_osx;
  566.         }
  567.        
  568.         # If repeating, and resolution hasn't been grabbed yet... we need it to determine window layouts
  569.         if ($repeat == 1) {
  570.            
  571.             unless ($resolution) {
  572.  
  573.                 my $getrez_cmd="system_profiler SPDisplaysDataType | grep Resolution";
  574.                 chomp($resolution=`$getrez_cmd`);
  575.                
  576.                 $resolution=~s/^\s+//g;
  577.                 $resolution=~s/Resolution: //g;
  578.                
  579.                 # Pull x & Y variables from result
  580.                 ($screen_res_x,$screen_res_y)=split(/\ x\ /,$resolution);
  581.             }
  582.         }
  583.     }
  584.     elsif ($this_os =~/^(linux)$/i) {
  585.        
  586.         # grab default for image viewer
  587.         unless ($image_viewer) {
  588.             $image_viewer = $def_image_viewer_linux;
  589.         }
  590.        
  591.         # Same process as above..
  592.         if ($repeat == 1) {
  593.             unless($resolution) {
  594.                
  595.                 my $getrez_cmd="xdpyinfo | grep dimensions | awk '{print \$2}' | awk -Fx '{print \$1, \$2}'";
  596.                 chomp($resolution=`$getrez_cmd`);
  597.                
  598.                 # Pull x & Y variables from result 
  599.                 ($screen_res_x,$screen_res_y)=split(/\ /,$resolution);
  600.             }
  601.         }
  602.     }
  603.     else {
  604.         print qq|Unsupported OS: some things may not work as expected.\n|;
  605.     }
  606.  
  607.     if ($debug == 1) { print qq| Screen Resolution: "$resolution"\n|; };
  608. }
  609.  
  610. sub CheckStorage {
  611.    
  612.     # Consider multiple sources, check for availability
  613.  
  614.     if ($debug == 1) {
  615.         print qq| <Enter Sub> CheckStorage\n|;
  616.     }
  617.    
  618.     our @Available;
  619.     our @Unavailable;
  620.  
  621.     my $count;
  622.  
  623.     # Check storage for availability   
  624.     foreach my $csellection (@Collections) {
  625.         $count++;
  626.         chomp $csellection;
  627.        
  628.         if (-d "$csellection") {
  629.             push(@Available,$csellection);
  630.         }
  631.         else {
  632.             push(@Unavailable,$csellection);
  633.         }
  634.     }
  635.    
  636.     # if no collections available, print error -- unless user specified a directory to use 
  637.     my $X;
  638.     my $Y;
  639.     my $storage_info="";
  640.    
  641.     unless ($#Available == -1) {
  642.  
  643.         if ($very_verbose == 1) {
  644.  
  645.             $storage_info .= qq| [COLLECTIONS]:\n\n|;
  646.  
  647.             foreach my $avail (@Available) {
  648.                 $storage_info .= qq|  [$online_label]: $avail\n|;
  649.             }
  650.             foreach my $unavail (@Unavailable) {
  651.                 $storage_info .= qq|  [$offline_label]: $unavail\n|;
  652.             }
  653.             print qq|$storage_info\n|;
  654.         }
  655.         else {
  656.             $Y=0;
  657.  
  658.             foreach my $unavail (@Unavailable) {
  659.                
  660.                 if ($verbose == 1) {
  661.                    
  662.                     print qq|[$warning_label]: $unavail is currently unavailable.\n\n|;
  663.                    
  664.                     if ($Y == $#Unavailable) {
  665.                         print qq|  Consider editing the \@Collections array.\n\n|;
  666.                     }
  667.                 }
  668.                 $Y++;
  669.             }
  670.             unless ($#Unavailable < 0) {
  671.                 #print qq|\n|;
  672.             }
  673.         }
  674.     }
  675.     else {
  676.         unless ($custom_dir == 1) {
  677.  
  678.             # Display this message if no available collections
  679.  
  680.             $storage_info .= qq|[$error_label]: No collections currently available?\n\n|;
  681.  
  682.             $X=0;
  683.  
  684.             foreach my $unavail (@Unavailable) {
  685.                 $X++;
  686.                 $storage_info .= qq|[$offline_label]: $unavail\n|;
  687.             }
  688.  
  689.             $storage_info .= qq|\n You may need to edit the list of \@Collections in this script,\n|;
  690.             $storage_info .= qq| or otherwise specify a directory to select a file from:\n|;
  691.             $storage_info .= qq|\n $script_name ~/path/to/videos\n|;
  692.  
  693.             print qq|$storage_info\n|;
  694.  
  695.             exit;
  696.         }
  697.     }
  698.     return;
  699. }
  700.  
  701. sub DepCheck {
  702.  
  703.     # Ensure required commands exist
  704.  
  705.     if ($debug == 1) {
  706.         print qq| <Enter Sub> DepCheck\n|;
  707.     }
  708.    
  709.     foreach my $command (@Required) {  
  710.        
  711.         chomp(my $which=`which $command`);     
  712.        
  713.         unless (-e "$which") {
  714.        
  715.             print qq|[$error_label]: "$command" command not found!\n\n|;
  716.            
  717.             if ($command =~/mplayer$/) {
  718.                 print qq|This script is just a wrapper for command line mplayer.\n|;
  719.                 print qq|Please ensure mplayer is compiled & installed properly.\n|;
  720.                 print qq|http://www.mplayerhq.hu/design7/dload.html\n\n|;
  721.             }
  722.  
  723.             exit;
  724.         }
  725.     }
  726. }
  727.  
  728. sub BuildLists {
  729.  
  730.     # Filter unsupported file types and build list of available files.
  731.  
  732.     if ($debug == 1) {
  733.         print qq| <Enter Sub> BuildLists\n|;
  734.     }
  735.    
  736.     our $location;
  737.     my $Y=0;
  738.  
  739.     my $mtime;
  740.     my %mtime;
  741.     my $supported_videos;
  742.     my $supported_images;
  743.     my @AllFiles;
  744.     my @FileList;
  745.        
  746.     # Build List from a collection directory, or user-specified path
  747.     if ($custom_dir == 1) {
  748.         $location = &PrepPath("$main::user_dir");
  749.         @main::Available = $main::user_dir;
  750.     }
  751.     else {
  752.        
  753.         $location="";
  754.        
  755.         foreach my $item (@main::Available) {
  756.        
  757.             chomp $item;
  758.            
  759.             $location .= &PrepPath("$item");
  760.  
  761.             if ($#main::Available > 0) {
  762.                 $location = $location . " ";
  763.             }
  764.         }
  765.     }
  766.    
  767.     if ($debug == 1) { print qq| <FIND AND SORT FILES>\n|; }
  768.    
  769.     # FILE FIND: IF sorting by oder, find files in all available paths & sort by mtime (-l -o)
  770.     if ($sort_order == 1 && $limit_recent == 0) {
  771.        
  772.         find(sub {$mtime{$File::Find::name} = -M _ if -f;}, @main::Available);
  773.         @AllFiles = sort {$mtime{$b} <=> $mtime{$a}} keys %mtime;
  774.        
  775.     }
  776.     # FILE FIND: (-l -o -t [x]): selective population of the $mtime{} hash for sorting, based on mtime vs $limit_time
  777.     elsif ($sort_order == 1 && $limit_recent == 1) {
  778.        
  779.         unless ($repetition) {
  780.        
  781.             unless ($old_or_new eq '+') {
  782.                 $old_or_new = "-";
  783.             }
  784.             $limit_time = $old_or_new . $limit_time;
  785.         }
  786.        
  787.         # File::Find in action;
  788.         find(
  789.             sub {  
  790.                 if ($old_or_new eq '+') {
  791.        
  792.                     if (-f && -M >= $limit_time) {
  793.                         $mtime{$File::Find::name} = -M _;
  794.                     }
  795.                 }
  796.                 elsif ($old_or_new eq '-') {
  797.        
  798.                     $limit_time=~s/\-//;
  799.        
  800.                     if (-f && $limit_time >= -M) {
  801.                         $mtime{$File::Find::name} = -M _;
  802.                     }
  803.                 }  
  804.             }, @main::Available);
  805.  
  806.         @AllFiles = sort { $mtime{$b} <=> $mtime{$a} } keys %mtime;
  807.        
  808.     }
  809.     # FIND FILE: Limit file list to time period (-l -t [x])
  810.     elsif ($sort_order == 0 && $limit_recent == 1) {
  811.        
  812.         # THIS CONDITION IS UNREACHABLE IF $sort_order =1 is defined under -t option -- or $auto_sort = 1|;
  813.         #@AllFiles=`find $location -type f -mtime $limit_time`;
  814.        
  815.         unless ($repetition) {
  816.        
  817.             unless ($old_or_new eq '+') {
  818.                 $old_or_new = "-";
  819.             }
  820.             $limit_time = $old_or_new . $limit_time;
  821.         }
  822.        
  823.         find(
  824.             sub {  
  825.                 if ($old_or_new eq '+') {
  826.                     if (-f && -M >= $limit_time) {
  827.                         push(@AllFiles, $File::Find::name); ### FIX THIS SHIT CONDITIONAL
  828.                     }
  829.                 }
  830.                 elsif ($old_or_new eq '-') {
  831.    
  832.                     $limit_time=~s/\-//;
  833.    
  834.                     if (-f && $limit_time >= -M) {
  835.                         push(@AllFiles, $File::Find::name);
  836.                     }
  837.                 }  
  838.             }, @main::Available);
  839.                            
  840.     }
  841.     # IF NOT sorting, no need for mtime check (just -l), slight speedup
  842.     else {
  843.         #@AllFiles=`find $location -type f`;
  844.         find(sub { push(@AllFiles, $File::Find::name) if -f }, @main::Available);
  845.     }
  846.    
  847.     # SEARCH FILTER: Now we'll use a secondary list for parsed search results
  848.     if ($search == 1) {
  849.                    
  850.         my @search_words=split(/\,/,$search_term);
  851.        
  852.         foreach my $search_word (@search_words) {
  853.  
  854.             $search_word=~s/\,\ /\,/g;
  855.             $search_word=~s/\./\(\\W+\)/g;
  856.             #$search_word=~s/\./\(\(\\W+\)|\(\\S+\)\)/g;
  857.            
  858.             # Must-have for simple search
  859.             $search_word=~s/\ /\./g;
  860.             #$search_word=~s/\ /\(\\W+\)/g;
  861.            
  862.             # Expand search if wildcard, else this will not split and var is still useable
  863.    
  864.             my @sub_words=(split(/\*/,"$search_word"));
  865.  
  866.             # Now, actually populate @FileList if file matches search terms
  867.             foreach my $sub_word (@sub_words) {
  868.                
  869.                 $sub_word=~s/^\.//g;
  870.  
  871.                 foreach my $item (@AllFiles) {
  872.                     chomp $item;
  873.                    
  874.                     # .. unless it matches an -x exclusion_term, put it in the list
  875.                     unless (($null_term == 1 )&& ($exclude_term ne "") && ($item=~/$exclude_term/ig)) {
  876.                        
  877.                         if ($item=~/$search_word/ig) {         
  878.                             push(@FileList,$item);
  879.                         }
  880.                    
  881.                         if ($item=~/$sub_word/ig) {
  882.                             push(@FileList,$item);
  883.                         }
  884.                     }
  885.                 }
  886.             }
  887.         }
  888.     }
  889.     else {
  890.         # If not searching, use the complete list
  891.         @FileList = @AllFiles;
  892.     }
  893.    
  894.     # Determine Supported file types by creating a filter
  895.  
  896.     $Y=0;
  897.  
  898.     foreach my $type (@Supported_videos) {
  899.  
  900.         $supported_videos .= "\.$type\$";
  901.  
  902.         unless ($Y == $#Supported_videos) {
  903.             $supported_videos .= "|";
  904.         }
  905.         $Y++;
  906.     }
  907.  
  908.     # Same style filter image types
  909.  
  910.     $Y=0;
  911.  
  912.     foreach my $type (@Supported_images) {
  913.  
  914.         $supported_images .= "\.$type\$";
  915.  
  916.         unless ($Y == $#Supported_images) {
  917.             $supported_images .= "|";
  918.         }
  919.         $Y++;
  920.     }
  921.  
  922.     # Isolate specific file types into arrays for later access
  923.  
  924.     foreach my $item (@FileList) {
  925.  
  926.         chomp $item;
  927.  
  928.         if ($item =~/$supported_videos/i) {
  929.             push (@main::Videos,$item);
  930.             our $total_videos++;
  931.         }
  932.         elsif ($item=~/$supported_images/i) {
  933.             push (@main::Images,$item);
  934.             our $total_images++;
  935.         }
  936.         else {
  937.             # Store all other files as rejected
  938.             push (@main::Rejected,$item);
  939.             our $total_rejected++;
  940.         }
  941.     }
  942.    
  943.     # Strip out duplicates.
  944.     my %unique;
  945.  
  946.     undef %unique;
  947.         @unique{@main::Videos} = ();
  948.  
  949.         my @Videos = keys %unique;
  950.    
  951.     unless ($sort_order == 1) {
  952.         #NOTE: Don't sort this list, it should already be sorted
  953.         @main::Videos=sort(@Videos);
  954.     }
  955.     else {
  956.         # Strip duplicates;
  957.         @main::Videos = grep(!$unique{$_}++, @main::Videos);       
  958.     }
  959.    
  960.         undef %unique;
  961.     @unique{@main::Images} = ();
  962.  
  963.     my @Images = keys %unique;
  964.  
  965.     @main::Images = sort(@Images);
  966.  
  967.     undef %unique;
  968.     @unique{@main::Rejected} = ();
  969.    
  970.     my @Rejected = keys %unique;
  971.     @main::Rejected =  sort(@Rejected);
  972.    
  973.     my $zero;
  974.  
  975.     if ($total_videos == 0) {
  976.         if ($use_colors == 1) {
  977.             $zero = $color_red . "0" . $colortag_default;
  978.         }
  979.         else {
  980.             $zero = "0";
  981.         }
  982.        
  983.         if ($search == 1 && $limit_recent == 0) {
  984.             print qq|[$error_label]: $zero results found for "$main::search_input" in: $location\n\n|;
  985.         }
  986.         elsif ($search == 1 && $limit_recent == 1) {
  987.    
  988.             my $result_text="";
  989.    
  990.             if ($limit_time =~/^\-/) {
  991.                 $result_text = "results NEWER than $limit_time days";
  992.             }
  993.             elsif ($limit_time =~/^\+/) {
  994.                 $result_text = "results OLDER than $limit_time days";
  995.             }
  996.    
  997.             print qq|[$error_label]: $zero $result_text found for "$main::search_input" in: $location\n\n|;
  998.         }
  999.         else {
  1000.             print qq|[$error_label:] $zero results found in: $location\n\n|;
  1001.         }  
  1002.         exit;
  1003.     }
  1004.  
  1005.     return;
  1006. }
  1007.  
  1008. sub Search {
  1009.  
  1010.     if ($debug == 1) {
  1011.         print qq| <Enter Sub> Search: \"$main::search_term\"\n|;
  1012.     }
  1013.    
  1014.     # Gather Search input if not specified on the command line
  1015.     unless ($main::search_term) {
  1016.  
  1017.         print qq|[SEARCH]: |;
  1018.  
  1019.         chomp($search_input=<STDIN>);
  1020.  
  1021.         print qq|\n|;
  1022.  
  1023.     }
  1024.     else {
  1025.         unless (-d "$main::search_term") {
  1026.             $search_input=$main::search_term;
  1027.         }
  1028.         else {
  1029.             if ($debug == 1) {
  1030.                 print qq|<DEBUG>Search $main::search_term is a dir.\n|;
  1031.             }
  1032.  
  1033.             $main::search_term = "";
  1034.  
  1035.             print qq|[SEARCH]: |;
  1036.  
  1037.             chomp($search_input=<STDIN>);
  1038.  
  1039.             print qq|\n|;
  1040.         }
  1041.     }
  1042.    
  1043.     my $search_char=length($search_input);
  1044.    
  1045.     # if empty search input, default to random selection, else format a regex based on input
  1046.     if ($search_char == 0) {
  1047.        
  1048.         print qq|[NOTICE]: No Search terms specified, selecting random file...\n\n|;
  1049.  
  1050.         $main::search = 0;
  1051.  
  1052.         &SelectFile;
  1053.         exit;
  1054.     }
  1055.     elsif ($search_char < $main::search_char_min ) {
  1056.         print qq|[$error_label]: $search_input is too short ($search_char of $main::search_char_min min).\n\n|;
  1057.         exit;  
  1058.     }
  1059.     else {
  1060.         # Now that input is validated, Search
  1061.         $search_term="$search_input";
  1062.  
  1063.         &SelectFile;
  1064.         exit;
  1065.     }
  1066. }
  1067.  
  1068. sub SelectFile {
  1069.  
  1070.     if ($debug == 1) {
  1071.         print qq| <Enter Sub> SelectFile\n|;
  1072.     }
  1073.  
  1074.     # Only build the list once
  1075.     unless ($repetition) {
  1076.         &BuildLists;   
  1077.     }
  1078.  
  1079.     my $count;
  1080.     my $display_name;
  1081.     my $selected;
  1082.     my $selected_movie_raw_path;
  1083.     my $unique_videos=$#main::Videos+1;
  1084.    
  1085.    
  1086.     # If the range is 'all', play in order (avoid dupes) by dropping to 1st request, and jumping back to top of &SelectFile for full increment
  1087.     if (($repeat == 1) && ($range_request =~/^all$/)) {
  1088.        
  1089.         $specific_result = 1;
  1090.         $search_request = 1;
  1091.        
  1092.         $range_request = $total_videos;
  1093.         $repeat_range = $range_request;
  1094.        
  1095.         # Reset counter    
  1096.         $total_videos = "";
  1097.        
  1098.         # Start over;      
  1099.         &SelectFile;
  1100.     }
  1101.    
  1102.     # If a user specifies the file from a list, we already know it's number. Else draw randomly.
  1103.     if ($specific_result == 1) {
  1104.    
  1105.         my $result_summary;
  1106.         my $req_orig = $search_request;
  1107.    
  1108.         $selected = $search_request;
  1109.        
  1110.         # Alter user request to align with array
  1111.         unless ($search_request == 0) {
  1112.             $search_request = ($search_request - 1);
  1113.         }
  1114.            
  1115.         if ($search_request > $#main::Videos) {
  1116.            
  1117.             if ($total_videos == 1) {
  1118.                 $result_summary = qq|only 1 result for "$search_term" ... |;
  1119.             }
  1120.             else {
  1121.                 $result_summary = qq|only $unique_videos Videos found |;
  1122.                 if ($search == 1) {
  1123.                     $result_summary .= qq|for "$search_term" |;
  1124.                 }
  1125.                 $result_summary .= qq |...|;
  1126.             }
  1127.            
  1128.             print qq|[$error_label]: $req_orig is out of bounds, $result_summary\n\n|;
  1129.             exit;
  1130.         }
  1131.         chomp($selected_movie_raw_path=$main::Videos[$search_request]);
  1132.     }
  1133.     else {
  1134.         # THE WHEEL OF FATE SPINS!
  1135.         my $rand=int rand ($#main::Videos+1);
  1136.         $selected = $rand;
  1137.        
  1138.         chomp($selected_movie_raw_path=$main::Videos[$rand]);
  1139.        
  1140.         unless ($selected == 0) {
  1141.             $selected = ($selected + 1);
  1142.         }
  1143.        
  1144.         # ..but try to avoid dupes
  1145.         if ($repeat == 1) {
  1146.            
  1147.             foreach my $past_select (@main::AlreadyPicked) {
  1148.                
  1149.                 # If this selection has been drawn before...
  1150.                 if ($past_select == $selected) {
  1151.                    
  1152.                     if ($debug == 1) {
  1153.                         print qq| PICKED $selected but ALREADY PLAYED $#main::AlreadyPicked $#main::Videos\n|;
  1154.                     }
  1155.                    
  1156.                     # exit if we've gone through the full list, else roll again
  1157.                     if ($#main::AlreadyPicked >= $#main::Videos) {
  1158.                         exit;
  1159.                     }
  1160.                     else {
  1161.                         &SelectFile;
  1162.                     }
  1163.                 }
  1164.             }
  1165.            
  1166.             # Keep track of drawn numbers
  1167.             push (@main::AlreadyPicked,$selected);
  1168.         }
  1169.     }
  1170.  
  1171.     if (($selected)&&($debug == 1)) {
  1172.         print qq| <SELECTED:> "$selected"\n|;
  1173.         print qq| <FILENAME: $selected_movie_raw_path\n|;
  1174.     }
  1175.  
  1176.     # Mangle the path to seperate the $file_name from the raw $file_folder_path
  1177.     my $playable_path=&PrepPath("$selected_movie_raw_path");   
  1178.     my $file_folder_path=$selected_movie_raw_path;
  1179.    
  1180.     foreach my $item (@main::Available) {
  1181.         $file_folder_path=~s/^$item//g;
  1182.     }
  1183.    
  1184.     # Extract file name from path and determine generic name of file (without extension)
  1185.        
  1186.     my $file_path=$file_folder_path;
  1187.     my @folders=split(/\//,$file_folder_path);
  1188.    
  1189.     our $file_name = $folders[$#folders];
  1190.        
  1191.     # if $file_name contains invalid characters it gets treated as a nested regex, escape, then replace
  1192.     $file_name =~s/\?/\\\?/g;
  1193.     $file_name =~s/\[/\\\[/g;
  1194.     $file_name =~s/\]/\\\]/g;
  1195.    
  1196.     $file_path=~s/$file_name//g;
  1197.    
  1198.     $file_name =~s/\\\?/\?/g;
  1199.     $file_name =~s/\\\[/\[/g;
  1200.     $file_name =~s/\\\]/\]/g;
  1201.  
  1202.     # Strip extension for a generic name to find images with
  1203.     our $generic_name = $file_name;
  1204.     $generic_name =~s/\.(\w{3})$//i;
  1205.    
  1206.     # Ok, NOW PRINT list if -l
  1207.     if ($listing == 1) {   
  1208.    
  1209.         if ($total_videos > 0) {
  1210.             print qq| [VIDEO FILES]:|;
  1211.    
  1212.             if ($search == 1) {
  1213.                 $total_videos = $unique_videos;
  1214.                 print qq| $total_videos results for "$search_input" ... \n\n|;
  1215.             }
  1216.             elsif ($limit_recent == 1) {
  1217.            
  1218.                 my $result_text="";
  1219.  
  1220.                 if ($limit_time =~/^\-/) {
  1221.                     $result_text = "results NEWER than $limit_time days";
  1222.                 }
  1223.                 elsif ($limit_time =~/^\+/) {
  1224.                     $result_text = "results OLDER than $limit_time days";
  1225.                 }
  1226.        
  1227.                 print qq| $total_videos $result_text\n\n|;
  1228.             }
  1229.             else {
  1230.                 print qq| $total_videos videos available.\n\n|;
  1231.             }
  1232.            
  1233.             $count=0;
  1234.            
  1235.             # Loop through and print list
  1236.             foreach my $item (@main::Videos) {
  1237.            
  1238.                 $count++;
  1239.                 $display_name=$item;
  1240.                    
  1241.                 # Strip source name from file to help categorize
  1242.                 unless ($list_full_paths == 1) {
  1243.                     foreach my $avail (@main::Available) {
  1244.                         $display_name=~s/^$avail\///g;
  1245.                     }
  1246.                 }
  1247.            
  1248.                 # Colorize search-term hits
  1249.                 if (($search == 1) && ($use_colors == 1)) {
  1250.            
  1251.                     my $search_word;
  1252.                    
  1253.                     # Split seperated terms
  1254.                     my @search_breakdown2=split(/\,/,$search_term);
  1255.            
  1256.                     foreach my $seperate_term (@search_breakdown2) {
  1257.                    
  1258.                         #$search_term=~s/\,\ /\,/g;
  1259.                         my @search_breakdown=split(/\ |\,|\.|\*/,$search_term);
  1260.                    
  1261.                         # Break the search phrase down into individual words for matching results
  1262.                         foreach my $search_word (@search_breakdown) {      
  1263.            
  1264.                             my @matches = $display_name =~/($search_word)/ig;
  1265.            
  1266.                             foreach my $match (@matches) {
  1267.                            
  1268.                                 my $highlighted=$colortag_search . "$match" . $colortag_default;
  1269.                                 $display_name=~s/$match/$highlighted/g;
  1270.                             }
  1271.                         }
  1272.                     }
  1273.                 }
  1274.                
  1275.                 # Include mtime info ?
  1276.                 my $mtime="";
  1277.                
  1278.                 if (($verbose == 1) || ($limit_recent == 1) || ($sort_order == 1)) {
  1279.  
  1280.                     $mtime = scalar localtime stat("$item")->mtime;
  1281.                    
  1282.                     # format only useful data
  1283.                     $mtime =~s/\ \ /\ /g;
  1284.                     (my $day,my $month,my $date,my $time,my $year)=split(/\ /,$mtime);
  1285.                     $mtime = "$year $month $date";
  1286.                     $mtime = " ($mtime)";
  1287.  
  1288.                     if ($use_colors == 1) {
  1289.                         $mtime = $colortag_mtime . $mtime . $colortag_default;
  1290.                     }
  1291.                 }
  1292.                 my $number;
  1293.                 if ($use_colors == 1) {
  1294.                     $number = $colortag_number . $count . $colortag_default;
  1295.                 }
  1296.                 else {
  1297.                     $number = $count;
  1298.                 }
  1299.                 # Finally display list item
  1300.                 print qq|  [$number]:$mtime $display_name \n|;
  1301.                
  1302.             }
  1303.             print qq|\n|;
  1304.         }
  1305.         $count=0;
  1306.     }
  1307.        
  1308.     if ($list_everything == 1) {
  1309.  
  1310.         print qq| [IMAGES]:\n\n|;
  1311.  
  1312.         foreach my $item (@main::Images) {
  1313.             $count++;
  1314.             print qq|  [$count]: $item\n|;
  1315.         }
  1316.  
  1317.         print qq|\n|;
  1318.         $count=0;
  1319.  
  1320.         print qq| [OTHER FILES]:\n\n|;
  1321.  
  1322.         foreach my $item (@main::Rejected) {
  1323.             $count++;
  1324.             print qq|  [$count]: $item\n|;
  1325.         }
  1326.  
  1327.         print qq|\n|;
  1328.         $count=0;
  1329.  
  1330.         print qq| [VIDEOS]: $total_videos\n|;
  1331.         print qq| [IMAGES]: $total_images\n|;
  1332.         print qq| [OTHER]: $total_rejected\n|;
  1333.  
  1334.         print qq|\n|;
  1335.         exit;
  1336.     }
  1337.    
  1338.     if ($test_exists == 1) {
  1339.  
  1340.         $pretend = 1;
  1341.  
  1342.         if ($total_videos > 1) {
  1343.             print qq| [$exists_label] $total_videos matches for "$search_term".\n\n|;
  1344.         }
  1345.         elsif ($total_videos == 1) {
  1346.             print qq| [$exists_label] File "$file_name" matches.\n\n|;
  1347.         }
  1348.         exit;      
  1349.     }
  1350.    
  1351.     # If repeating, report itteration
  1352.     if ($repeat == 1) {
  1353.                    
  1354.         #keep track of repetitions (after earlier reset)
  1355.         $repetition++;
  1356.  
  1357.         # If we've opened too many windows, bind to terminal to prevent fork bombing the system
  1358.         if ($fork_bomb_protect == 1) {
  1359.            
  1360.             if ($repetition > $mplayer_max) {
  1361.                
  1362.                 $target_x = 0;
  1363.                 $target_y = 0;
  1364.                 $mplayer_output = 1;
  1365.             }
  1366.         }
  1367.        
  1368.         # Turn off listing for repititions
  1369.         $listing = 0;
  1370.        
  1371.         #if user requests 4, but there's only 3 vids, drop range to match total_videos
  1372.         if ($range_request >= $total_videos) {
  1373.             $range_request = $total_videos;
  1374.         }
  1375.        
  1376.         print qq| [INSTANCE]: $repetition of $range_request\n|;
  1377.     }
  1378.    
  1379.     # Determine selection # of total
  1380.     if ($selected == 0) {
  1381.         $selected = 1;
  1382.     }
  1383.    
  1384.     my $file_info="";
  1385.     my $selected_label = $selected;
  1386.    
  1387.     if ($use_colors == 1) {
  1388.         $selected_label = $colortag_selection . $selected_label . $colortag_default;
  1389.     }
  1390.  
  1391.     $file_info .= qq| [SELECTED]: File \# $selected_label of $unique_videos\n|;
  1392.    
  1393.     # Display some useful info about the file if verbose
  1394.     if ($#Collections >= 1) {      
  1395.  
  1396.         foreach my $item (@main::Available) {
  1397.  
  1398.             if ($selected_movie_raw_path=~/^$item/) {
  1399.  
  1400.                 my $csellection = $item;
  1401.  
  1402.                 if ($use_colors == 1) {
  1403.                     #$csellection .= $colortag_category . $csellection . $colortag_default;
  1404.                 }
  1405.                 $file_info .= qq| [SOURCE]: $csellection\n|;
  1406.             }
  1407.         }
  1408.     }          
  1409.     # Unless custom dir, list some path info as 'category' - it's up to you to organize your files though
  1410.     unless (($custom_dir == 1) || ($#folders == 1)) {      
  1411.  
  1412.         $file_info .= qq| [$category_label]: |;
  1413.  
  1414.         if ($use_colors == 1) {
  1415.             $file_info .= $colortag_category;
  1416.         }
  1417.        
  1418.         for (my $i=0; $i < $#folders; $i++) {  
  1419.            
  1420.             unless ($folders[$i] =~"^\/") {
  1421.  
  1422.                 $file_info .= qq|$folders[$i]|;    
  1423.  
  1424.                 unless ($i == 0) {
  1425.                     $file_info .= qq|/ |;
  1426.                 }
  1427.             }
  1428.         }
  1429.         if ($use_colors == 1) {
  1430.             $file_info .= $colortag_default;
  1431.         }
  1432.         $file_info .= qq|\n|;      
  1433.     }
  1434.    
  1435.     if ($verbose == 1) {
  1436.  
  1437.         # Additional date
  1438.         my $mtime = scalar localtime stat("$selected_movie_raw_path")->mtime;
  1439.  
  1440.         # format only useful data
  1441.         $mtime =~s/\ \ /\ /g;
  1442.         (my $day,my $month,my $date,my $time,my $year)=split(/\ /,$mtime);
  1443.         $mtime = "$month $date $year";
  1444.    
  1445.         if ($use_colors == 1) {
  1446.             $mtime = $colortag_mtime . $mtime . $colortag_default;
  1447.         }
  1448.         $file_info .= qq| [VID DATE]: $mtime\n|;
  1449.     }
  1450.    
  1451.     # Color label for filename?
  1452.     my $filename_label = $file_name;
  1453.     my $orig_total = $total_videos;
  1454.  
  1455.     if ($use_colors == 1) {
  1456.         $filename_label = $colortag_name . $file_name . $colortag_default;
  1457.         $total_videos = $color_red . $total_videos . $colortag_default;
  1458.     }
  1459.     else {
  1460.         # Bold if no color
  1461.         $filename_label = $color_bold . $file_name . $colortag_default;
  1462.         $total_videos = $color_bold . $total_videos . $colortag_default;
  1463.     }
  1464.  
  1465.     $file_info .= qq| [$vid_label]: $filename_label\n\n|;
  1466.    
  1467.     # Finally print the $file_info we've formatted
  1468.     if (($file_info_banner == 1) || ($verbose == 1)) {
  1469.  
  1470.         unless (($#ARGV == 0)&&($listing == 1)) {
  1471.             print qq|$file_info|;
  1472.         }
  1473.         else {
  1474.             # Exit after -l is given
  1475.             print qq| $total_videos videos in your collection.\n\n|;
  1476.             exit;
  1477.         }
  1478.     }
  1479.    
  1480.     $total_videos = $orig_total;
  1481.        
  1482.     # Handle repitition requests
  1483.     if ($repeat == 1) {
  1484.        
  1485.         # Determine geometries for multiple window layouts, unless remaining attached
  1486.         unless ($mplayer_output == 1) {
  1487.        
  1488.             my $last_vid_x = $target_x;
  1489.             my $last_vid_y = $target_y;
  1490.        
  1491.             # Only move across if user has played previous file, or autoplay
  1492.             unless ($user_ok eq "n") {
  1493.                 $target_x=$target_x + $video_width;
  1494.             }
  1495.            
  1496.             #$target_y= $target_y + $video_height;
  1497.        
  1498.             # Get video resolution
  1499.             my $mplayer_info_cmd="mplayer -vo null -ao null -frames 0 -identify $playable_path 2>/dev/null | grep ^ID_VIDEO";
  1500.             my @vid_info=`$mplayer_info_cmd`;
  1501.            
  1502.             foreach my $info_line (@vid_info) {
  1503.  
  1504.                 chomp $info_line;
  1505.  
  1506.                 if ($info_line =~/^ID_VIDEO_WIDTH=/) {
  1507.                     $video_width=$info_line;
  1508.                     $video_width=~s/^ID_VIDEO_WIDTH=//;
  1509.                 }
  1510.                 if ($info_line =~/^ID_VIDEO_HEIGHT=/) {
  1511.                     $video_height=$info_line;
  1512.                     $video_height=~s/^ID_VIDEO_HEIGHT=//;
  1513.                 }
  1514.             };
  1515.        
  1516.             # Determine next geometry, and if breaching far edge, drop down to new row.
  1517.             my $next_x = $target_x + $video_width;
  1518.             my $next_y = $target_y + $video_height;
  1519.            
  1520.             if ($next_x >= $screen_res_x) {
  1521.                 $target_x = 0;
  1522.                 $target_y= $target_y + $video_height;
  1523.             }
  1524.            
  1525.             if ($next_y >= $screen_res_y) {
  1526.                 #$target_y = 0;
  1527.             }
  1528.        
  1529.             if ($debug == 1) {
  1530.                 print qq| vidX: $video_width : $target_x of $screen_res_x : $next_x ($resolution)\n|;
  1531.                 print qq| vidY: $video_height : $target_y of $screen_res_y : $next_y ($resolution)\n|;
  1532.             }
  1533.            
  1534.             # Set next windows' mplayer geometry
  1535.             $mplayer_opts_geo = " -geometry $target_x:$target_y";
  1536.            
  1537.         }
  1538.        
  1539.         # Return to center if we've stacked too many
  1540.         if ($repetition > $mplayer_max) {
  1541.             $mplayer_opts_geo = "";
  1542.         }
  1543.        
  1544.         ## IF -n $search_request, array needs alignment elsewhere (-1), so to increment the range to +1, we must actually +2
  1545.         if ($search_request) {
  1546.             $search_request = $search_request +2;
  1547.         }
  1548.         # If the file #1 is requested, var was = 0, so previous test fails, so we need to bump to 2 to equal back to 0 to allow file +1
  1549.         else {
  1550.             $search_request = 2;
  1551.         }
  1552.        
  1553.         # if repeat range has more cycles,
  1554.         if ($repeat_range > 1) {
  1555.  
  1556.             # remove a cycle from requested repetitions,
  1557.             $repeat_range--;
  1558.            
  1559.             # and unless this is the last cycle, spin another video
  1560.             unless ($repetition >= $total_videos) {
  1561.                 #sleep 1;
  1562.                 &PlayFile("$playable_path");
  1563.                 &SelectFile;
  1564.             }  
  1565.         }  
  1566.     }
  1567.    
  1568.     # Under regular operation, finally open file;
  1569.     &PlayFile("$playable_path");
  1570.    
  1571.     if (($verbose == 1) || ($debug == 1)) {
  1572.         &GetStats;
  1573.     }  
  1574.     exit;
  1575. }
  1576.  
  1577. sub PlayFile {
  1578.    
  1579.     chomp(my $play_file="$_[0]");
  1580.    
  1581.     if ($debug == 1) {
  1582.         print qq| <Enter Sub> PlayFile $play_file\n|;
  1583.     }  
  1584.    
  1585.     # Form the actual mplayer command
  1586.     my $cmd = "$mplayer $mplayer_opts -title \"$main::file_name\"";
  1587.     my $silent_output="1>/dev/null 2>&1";
  1588.    
  1589.     # Append mplayer options before command is formed
  1590.     if ($mplayer_opts_geo) {
  1591.         $cmd .= " $mplayer_opts_geo";
  1592.     }
  1593.     if ($timejump == 1) {
  1594.         $cmd .=" -ss $jumptime";
  1595.     }
  1596.     if ($fullscreen == 1)  {
  1597.         $cmd .=" -fs";
  1598.     }
  1599.     if ($vol_muted == 1) {
  1600.         $cmd .=" -volume 00";
  1601.     }
  1602.     elsif ($nosound == 1) {
  1603.         $cmd .=" -nosound";
  1604.     }
  1605.     else {
  1606.         $cmd .= " $volume_level";
  1607.     }
  1608.  
  1609.     # Feed file to command
  1610.     $cmd = $cmd . " $play_file";
  1611.    
  1612.     # Unless attaching, silence output
  1613.     unless ($mplayer_output == 1) {
  1614.         $cmd="$cmd $silent_output";    
  1615.     }
  1616.    
  1617.     # Added Ability to open an image, even if -p
  1618.     if ($cover == 1 && $pretend == 1) {
  1619.  
  1620.         &GetRelatedImages;
  1621.  
  1622.         if ($#main::Related_images >= 1) {
  1623.  
  1624.             &PromptUser("Open image only?");
  1625.  
  1626.             foreach my $item (@main::Related_images) {
  1627.                
  1628.                 # Possible to be called and return nothing, so only act on tangible items
  1629.                 unless ($item =~/^$/) {
  1630.                     &OpenImage("$item");
  1631.                 }
  1632.             }
  1633.         }
  1634.     }
  1635.  
  1636.     unless ($pretend == 1) {
  1637.  
  1638.         # Build a List
  1639.         if ($cover == 1) {
  1640.             &GetRelatedImages;
  1641.         }
  1642.        
  1643.         unless ($do_exec == 1) {
  1644.  
  1645.             # SAFETY; confirmation prompt before playing the video;
  1646.             print qq|[$warning_label]: Always wise to double-check before exec ... ('-a' to override)\n\n|;
  1647.  
  1648.             &PromptUser("Play file?");
  1649.         }
  1650.        
  1651.         # Now that a user will have confirmed, open all related images
  1652.         if ($cover == 1) {
  1653.             if ($do_exec == 1) {
  1654.                 foreach my $item (@main::Related_images) {
  1655.                    
  1656.                     # Possible to be called and return nothing, so only act on tangible items
  1657.                     unless ($item =~/^$/) {
  1658.                         &OpenImage("$item");
  1659.                     }
  1660.                 }
  1661.             }
  1662.         }
  1663.  
  1664.         # NOW we can finally launch mplayer
  1665.         unless ($mplayer_output == 1) {    
  1666.            
  1667.             if ($do_exec == 1) {   
  1668.                    
  1669.                 system("$cmd \&");
  1670.                
  1671.                 # Unless auto = 1, reset so it prompts again
  1672.                 unless ($autoplay == 1) {
  1673.                     $do_exec = 0;
  1674.                 }
  1675.             }
  1676.         }
  1677.         else {
  1678.             print qq|Mplayer output:\n--\n|;
  1679.             system("$cmd");
  1680.         }
  1681.     }
  1682.     else {
  1683.         print qq| [$pretend_label]: no exec ...\n\n|;
  1684.         unless ($repeat == 1) {
  1685.             exit;
  1686.         }
  1687.     }  
  1688.     if ($very_verbose == 1) {
  1689.         print qq|\n [$exec_label]: $cmd\n\n|;
  1690.     }
  1691.     return;
  1692. }
  1693.  
  1694. sub GetRelatedImages {
  1695.  
  1696.     # Find Associated Images;
  1697.    
  1698.     if ($debug == 1) {
  1699.         print qq| <Enter Sub> GetRelatedImages for "$main::generic_name" in $main::location\n|;
  1700.     }
  1701.    
  1702.     # Reset;
  1703.     our @Related_images="";
  1704.     our $path_to_image;
  1705.  
  1706.     my $image;
  1707.     my $image_file="";
  1708.     my $images_found="";
  1709.     my $generic_name=$main::generic_name;
  1710.    
  1711.     # strip non-word characters into regex, strip "part X" for multi-part video labels
  1712.     $generic_name =~s/part((\s+)*)(\d+)/\.\*/ig;
  1713.     $generic_name =~s/(\W+)/\.\*/g;
  1714.    
  1715.     # Go through all images we found and find matches for the selected video, set them aside
  1716.     foreach my $item (@main::Images) {
  1717.  
  1718.         chomp $item;
  1719.  
  1720.         if ($item=~/$generic_name/g) {
  1721.             push (@Related_images,$item);
  1722.            
  1723.         }
  1724.     }
  1725.  
  1726.     # If we have some related image results, make use of them - but don't pass to OpenImage yet
  1727.     unless ($#Related_images == -1) {
  1728.         my $X;
  1729.         foreach my $image (@Related_images) {
  1730.             $X++;
  1731.             chomp $image;
  1732.  
  1733.             my @image_path=split(/\//,$image);
  1734.             $image_file=$image_path[$#image_path];
  1735.            
  1736.             unless ($image =~/^$/) {
  1737.                
  1738.                 if ($use_colors == 1) {
  1739.                     $image_file = $colortag_imgname . $image_file . $colortag_default;
  1740.                 }
  1741.                 print qq| [IMAGE]: $image_file\n|;
  1742.                
  1743.                 # Format image file list correct, by adding space if it's the last one
  1744.                 if ($#Related_images < $X) {
  1745.                     print qq|\n|;
  1746.                 }
  1747.             }
  1748.         }  
  1749.        
  1750.     }
  1751.     else {
  1752.         print qq| [NOTICE]: No images found for "$generic_name"\n\n|;
  1753.     }
  1754.     return;
  1755. }
  1756.    
  1757. sub OpenImage {
  1758.  
  1759.     # Open Associated Image(s)
  1760.  
  1761.     chomp(my $imagepath=$_[0]);
  1762.     $imagepath=&PrepPath("$imagepath");
  1763.  
  1764.     my $image_command = "$image_viewer $imagepath 1>/dev/null 2>&1";
  1765.    
  1766.     my @image_path=split(/\//,$imagepath);
  1767.     my $image_name=$image_path[$#image_path];
  1768.    
  1769.     if ($debug == 1) {
  1770.         print qq| <OpenImageExec>: "$image_command"\n\n|;
  1771.     }
  1772.    
  1773.     unless (($main::user_ok eq 'n') || ($imagepath =~/^$/)) {
  1774.         system("$image_command \&");
  1775.     }
  1776.  
  1777.     return;
  1778. }
  1779.  
  1780. sub PromptUser {
  1781.  
  1782.     # Unless otherwise stated, prompt before blatantly opening a video.
  1783.    
  1784.     if ($debug == 1) {
  1785.         print qq| <PromptUser:>\n|;
  1786.     }
  1787.  
  1788.     my $prompt_msg = "$_[0]";
  1789.      
  1790.     unless ($autoplay == 1) {
  1791.  
  1792.         print qq|$prompt_msg [$yes_label/$no_label|;
  1793.         if ($repeat == 1) {
  1794.             print $color_bold . qq|/q| . $colortag_default;
  1795.         }
  1796.         print qq|] ($yes_label)|;
  1797.        
  1798.         chomp($main::user_ok=<STDIN>);
  1799.  
  1800.         if ($user_ok =~/^y$/i) {
  1801.             $do_exec = 1;
  1802.             #return;
  1803.         }
  1804.         elsif ($user_ok eq "") {
  1805.             $do_exec = 1;
  1806.             #return;
  1807.         }
  1808.         elsif ($user_ok =~/^n$/i) {
  1809.             print qq|\n [$abort_label]: Not Launching.\n\n|;
  1810.             #exit;
  1811.         }
  1812.         elsif ($user_ok =~/^q$|^quit$|^exit$/) {
  1813.             print qq|\n [$abort_label]: Aborted.\n\n|;
  1814.             exit;
  1815.         }
  1816.         else {
  1817.             &PromptUser("$prompt_msg");
  1818.         }
  1819.        
  1820.         print qq|\n|;
  1821.     }
  1822. }
  1823.  
  1824. sub PrepPath {
  1825.  
  1826.     # Sanitize path for command executions
  1827.  
  1828.     if ($debug == 1) {
  1829.         print qq| <PrepPath:> "$_[0]"\n|;
  1830.     }
  1831.    
  1832.     my $esc_path;
  1833.     chomp($esc_path=$_[0]);
  1834.    
  1835.     $esc_path=~s/\ /\\\ /g;
  1836.     $esc_path=~s/\&/\\&/g;
  1837.     $esc_path=~s/\[/\\[/g;
  1838.     $esc_path=~s/\]/\\]/g;
  1839.     $esc_path=~s/\(/\\(/g;
  1840.     $esc_path=~s/\)/\\)/g;
  1841.     $esc_path=~s/\'/\\'/g; 
  1842.     $esc_path=~s/\!/\\!/g;
  1843.     $esc_path=~s/\;/\\;/g;
  1844.     return $esc_path;
  1845. }
  1846.  
  1847. sub GetStats {
  1848.  
  1849.     # Time this scripts execution time
  1850.    
  1851.     if (($verbose == 1)||($debug == 1)) {  
  1852.    
  1853.         my $time = time - $^T;
  1854.         my $decimal=$time/60;
  1855.         my $minutes;
  1856.         my $fraction;
  1857.         my $time_report;
  1858.         ($minutes,$fraction)=split(/\./,$decimal);
  1859.  
  1860.         # Square off time into minutes, subtract from overall time to get additional seconds
  1861.         my $min_seconds=($minutes*60);
  1862.         my $seconds=($time-$min_seconds);
  1863.  
  1864.         # If over an hour, break down into additional minutes
  1865.         if ($minutes >= 60) {
  1866.             my $decimal2 = $minutes/60;
  1867.             my $hours;
  1868.             ($hours,$fraction)=split(/\./,$decimal2);
  1869.  
  1870.             my $hour_minutes=($hours*60);
  1871.             my $extramins=($minutes - $hour_minutes);
  1872.  
  1873.             $time_report = qq|$hours hours $extramins minutes $seconds seconds.\n|;
  1874.         }
  1875.         elsif ($minutes >= 1) {
  1876.             $time_report = qq|$minutes minutes $seconds seconds.\n|;
  1877.         }
  1878.         else {
  1879.             $time_report = qq|$seconds seconds.\n|;
  1880.         }
  1881.         print qq|$script_name runtime: $time_report|;
  1882.     }  
  1883. }
  1884.  
  1885. sub Usage {
  1886.    
  1887.     if ($debug == 1) {
  1888.         print qq| <Enter Sub> Usage\n|;
  1889.     }
  1890.    
  1891.     if ($use_colors == 1) {
  1892.         $script_name = $color_bold . $script_name . $colortag_default;
  1893.     }
  1894.    
  1895.     print qq| $script_name [options] [dir]\n (v.$version)\n\n|;
  1896.     print qq|   -h\t\tThis Help. \n|;
  1897.     print qq|   -p\t\tPretend Only. No execution.\n|;
  1898.     print qq|   -q\t\tStart with volume = 0.0\n|;
  1899.     print qq|   -qq\t\tMute completely, no sound loaded.\n|;
  1900.     print qq|   -a\t\tAutoplay. Bypass confirmation prompt.\n|;
  1901.     print qq|   -l\t\tList available videos.\n|;
  1902.     print qq|   -o\t\tSort listing by file modification times.\n|;
  1903.     print qq|   -n [#]\tPlay Nth numbered result. (As numbered by the "-l" option)\n|;
  1904.     print qq|   -e [TERM]\tQuick check against collection and exit. Shorter than '-s -p'\n|;
  1905.     print qq|   -s [TERM]\tSearch files using keywords.\n\t\t ("." = wildcard, "," = expanded search terms)\n|;
  1906.     print qq|   -x [TERM]\tExclude a term from search results.\n|;
  1907.     print qq|   -t [#x]\tOnly list files newer than [Xx]. +X for 'older than' X.\n\t\t x = (d/w/m/y). Ex: 5d / 2w / 1m / 1y\n|;
  1908.     print qq|   -r [#][all]\tRepeat selection process X amount of times. default: $default_repeat\n\t\t Will increment to n+X if starting point specified with -n\n|;
  1909.     print qq|   -j [x]\tJump player to start X seconds in to file.\n|;
  1910.     print qq|   -i\t\tOpen any images related to selection, if found.\n|;
  1911.     print qq|   -fs\t\tFull Screen.\n|;
  1912.     print qq|   -m\t\tAttach MPlayer output, do not fork to background.\n|;
  1913.     print qq|   -k\t\tKill any existing mplayer instances before starting new ones.\n|;
  1914.     print qq|   -c\t\tToggle \$use_colors on/off.\n|;
  1915.     print qq|   -v\t\tVerbose information about the selected file. (file date)\n|;
  1916.     print qq|   -vv\t\tVery verbose: even more info.\n|;
  1917.     print qq|   --debug\tInclude script execution debug info.\n|;
  1918.     #print qq|   -z\t\tList Every file parsed from storage locations\n|;
  1919.    
  1920.     print qq|\n\n Example Usages:\n\n|;
  1921.    
  1922.     print qq|  Play a random file from the locations set in \@Collections array:\n|;
  1923.     print qq|  (\@Collections = "@Collections")\n|;
  1924.     print qq|\t$script_name\n\n|;
  1925.  
  1926.     print qq|  List files and play a random file from another directory:\n|;
  1927.     print qq|\t$script_name -l ~/Downloads\n\n|;
  1928.  
  1929.     print qq|  Order listing by mtime, select 3rd video from list:\n|;
  1930.     print qq|\t$script_name -l -o -n 3\n\n|;
  1931.  
  1932.     print qq|  Open multiple videos, no prompt. If not given, \$default_repeat = $default_repeat:\n|;
  1933.     print qq|\t$script_name -r 3 -a\n\n|;
  1934.  
  1935.     print qq|  List and play $default_repeat videos from the past month, muted, kill any already running:\n|;
  1936.     print qq|\t$script_name -q -l -t 1m -r -k\n\n|;
  1937.  
  1938.     print qq|  Starting at first vid, sequential play all videos that match search term:\n|;
  1939.     print qq|\t$script_name -l -o -s "star wars" -n 1 -r all\n\n|;
  1940.    
  1941.     print qq|\n|;
  1942.    
  1943.     exit;
  1944. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement