tkPlayMediaFilesInPlaylist - a front-end for multiple media-players

uniquename - 2014mar06

On 2014mar02, I contributed code at tkShowImageFilesInPlaylist - a front-end for multiple image viewers that uses several image viewers ('display', 'ffplay', 'eog') in making a 'show-image-files-in-a-playlist' Tk-script utility.

That page mentioned that another utility would follow --- a utility to show 'media' (movie and/or audio) files, named in a 'playlist' file --- using media-players such as

  • mplayer
  • ffplay
  • totem
  • gnome-mplayer
  • VLC
  • smplayer
  • gmplayer

That 'play-media-files-in-a-playlist' utility is the subject of this page.


One Way to Build the Media Playlist

These two 'show/play-files-in-a-PLAYLIST' utilities are follow-up's to two corresponding 'batch' 'find-and-show/play-files-in-a-DIRECTORY-HIERARCHY' utilities. Those two utilities were published in 2013dec at

- tkImageViewer - for Mask-Selecting Images from a Directory Hierarchy

and

- tkMediaPlayer - to Batch-Select-and-Play Movie & Audio files in a Directory Hierarchy.

The first provides a Tk GUI 'front end' to a combination of the 'find' command and a user-selectable image viewer command/program.

The second provides a Tk GUI 'front end' to a combination of the 'find' command and a user-selectable media-player command/program.

These two 'batch-find' utilities have GUI's that were designed to offer the user the ability to 'automatically' select image/media files within a DIRECTORY HIERARCHY --- according to criteria such as filename-mask, file-size, file-age, and file-type --- and show the image/media files in a sequence --- with a choice from several image-viewer/media-player programs.

(It is quite easy to switch out any of these viewer/player programs/commands to replace them with another viewer/player that is available in a user's operating environment.)

Each of these two 'Batch-Find' utilities was implemented as a Tk script and 2 shell scripts. As such, they should be implementable with very few changes in various Linux/BSD/Mac/Unix operating system environments.

An intended use of the 'batch-image-viewer' and 'batch-media-player' utilities was to allow for quickly surveying image/media files that may be scattered throughout a directory hierarchy --- such as sub-directories of a web site --- OR sub-directories of a home directory --- OR sub-directories on multiple disk drives mounted on a computer --- OR sub-directories of a removable storage device mounted on a computer.

However, two drawbacks are that (1) the files are viewed in a fixed order (according to a filename sort), and (2) the user may encounter many files that they are not so interested in seeing.

On the other hand, the 'batch-image-viewer' and 'batch-media-player' utilities have a 'show-selected-files' button-option that lists the files selected via the search criteria (filename-mask, file-size, file-age, and/or file-type). The list is shown in a popup window, in a Tk 'text' widget.

So the list of files could be pasted in a text-editor window --- and the user could change the ORDER of the files and ELIMINATE files that the user does not want to view/play, for this particular group of files.

In other words, the user could rather easily make a 'playlist' of files to be viewed with a 'light-weight' image-viewer program --- or a playlist of movie/audio files to be played with a 'media-player' program.

If I were to prepare a playlist file of movie/audio files, I just needed a utility to 'play' the files --- preferably a low-cost (like free) utility that is easily enhanced/modified/fixed.

That is the purpose of the 'play-media-files-in-a-playlist' utility whose Tcl-Tk code is presented below.

---

PLAYERS FOR MOVIE FILES --- in Tk

It is conceivable that a person could make an image viewer with Tcl-Tk --- one that reads image files named in a 'playlist' --- by using the 'photo image' reading capability of Tk along with the Tk 'canvas' widget capabilites.

However, it is not so feasible to make a movie player with Tcl-Tk --- one that reads movie files named in a 'playlist' and displays each movie on a Tk 'canvas' widget --- because there is no (efficient) 'movie' reading capability built into Tk.

(Another problem is that there are so many different video and audio formats. An overview of these formats is provided at the bottom of this page.)

BUT, one could make a movie/audio player --- for filenames in a 'playlist' file --- by using existing media-players, such as the ones listed above.

And that is the type of utility presented on this page --- a utility that reads a 'media playlist' file and uses some 'external' media-players to play the media.

In other words, the Tk GUI utility on this page is a 'front end' for

1) reading a media playlist file (containing names of movie and/or audio files)

and

2) playing the sequence of files in the playlist, using 'external' media-players.

---

THE GOALS

My goals for the Tcl-Tk script were:

  - provide a GUI for selecting a 'playlist' of movie/audio files.

  - allow the user to select an media-player program from among multiple choices.

  - allow the user to select a 'fullscreen'-size or 'default'-size mode of display.

  - provide a 'Launch' button to start showing the media files, in the order of the
    filenames within the playlist file.

  - provide a 'Stop' button for 'interrupting' the display of a (long) sequence
    of media files.

  - like on the 'batch-find-and-imageView' and 'batch-find-and-mediaPlay' utilities,
    provide 'Count' and 'List' buttons on the GUI to allow for quickly counting
    and displaying the (full) filenames of the media files in the playlist file.

---

THE GUI LAYOUT

Like for the 'show-image-files-in-a-playlist' 'slideshow' utility, I made a 'text-sketch' for the GUI for this 'play-media-files-in-a-playlist' utility:

  --------------------------------------------------------------------------------------------
  Play *Media* Files of a *Playlist* ...  with a choice of media-players
  [window title]
  --------------------------------------------------------------------------------------------

  {Exit} {Help} {LaunchPlayerJob} {Stop (no more files)}    {CountMediaFiles} {ShowMediaFilenames}

  Playlist Filename: ____________________________________________________________  {Browse...}

  Player Program:  O 1 mplayer   O 2 ffplay   O 3 totem   O 4 gmplayer   O 5 VLC   O 6 smplayer

  Display Size: O Default   O Fullscreen

  --------------------------------------------------------------------------------------------

where

   Square brackets indicate a comment (not to be placed on the GUI).
   Braces indicate a Tk 'button' widget.
   Underscores indicate a Tk 'entry' widget.
   A colon indicates that the text before the colon is on a 'label' widget.
   Capital-O indicates a Tk 'radiobutton' widget.
   Capital-X indicates a Tk 'checkbutton' widget (if any).

---

GUI Components

From the GUI 'sketch' above, it is seen that the GUI consists of about

   -  7 button widgets
   -  3 label widgets
   -  1 entry widget
   -  8 radiobutton widgets in 2 groups
   -  0 checkbutton widgets
   -  0 scale widgets
   -  0 listbox widgets

THE PLAYLIST FILE FORMAT

The intent of this utility is to allow the user to easily specify media files to be played ... by building a simple 'playlist'.

The playlist file for this utility contains three types of lines:

  1 - Comment lines may be indicated in the file by a # sign
      in column 1.

  2 - Lines that contain a fully-qualified directory name.
      Examples:  /data/images/tennis2013  or
                 $env(HOME)/tennis2013   or
                 /home/fred/tennis2013
      These lines must start with either slash (/) or $.

  3 - Lines that contain a relative filename (relative to the
      previous directory name)
      Example: Federer_vs_Nadal_2013.mp4
      These lines DO NOT start with either slash (/) or $ or #.

The first non-comment line of the playlist file should be a directory name.

There can be more than one directory name in the file.

Each directory-name-line is followed by names of image files that are in the specified directory.

A SAMPLE media playlist file:

 # A description of this file could go here.
 #
 # First directory:
 $env(HOME)/tennis2013
 Federer_vs_Nadal_2013.mp4
 Djokovic_vs_Murray_2013.flv
 #
 # Second directory:
 /data/sports/tennis/movies/1972
 McEnroe_vs_Connors_1972.mpg

FRONT END FOR OPTIONS FOR THE MEDIA PLAYERS

This 'Front End' Tk script is essentially a 'front end' for the media-player programs that are offered via radiobuttons on the GUI.

A second set of radiobuttons allow for running the several media-players in 'fullscreen' mode, instead of a 'default' mode. The 'default' mode may vary, depending on the player chosen, but it is typically play-a-movie-at-its-original-size- unless-it-is-too-large-for-the-screen.

In the future, if there are some 'either-or' options (of at least one of the media-players) that would seem nice to implement, then additional widgets could be added to the GUI to support those choices.

---

I should point out here that I was not especially interested in coming up with a 'beautiful utility'. I just wanted a utility that would make playing media files that are specified in a playlist file (with a very simple format) --- and with several different choices of media-player --- an easy process (a small set of mouse clicks).

I am certainly interested in making pretty GUI's --- as I have expressed on my 'bio' page at uniquename, and as my pages at Experiments in making embellished GUI's and Version 2 of a demo of THEMES for Tk GUI's, using images and colors have indicated.

But at this time, I am satisfied to implement the 'functionality', and let the 'beauty' go for a later date (when I have more beauty tools/code at hand).


SCREENSHOT OF THE GUI

On the basis of the GUI-layout sketch above, I ended up with the GUI seen in the following image.

tkPlayMediaFilesInPlaylist_initial_screenshot_809x144.jpg

Note that there are several radiobuttons that allow you to choose the media-player to use --- and a couple of radiobuttons to choose fullscreen-mode, or not.

---

TYPICAL SEQUENCE OF OPERATIONS WITH THE GUI

You can use the 'Browse...' button to retrieve a full filename to the filename entry field.

Before clicking on the 'LaunchPlayerJob' button, you can also change radiobutton settings as needed --- for

- a player program

and

- display size ('fullscreen' or the 'default-size' used by the player).

*NOTE*: Closing the player window causes the next media file to be played.

---

Optionally, if you want to check the number or names of the media files specified in the 'playlist' file, then, after selecting a playlist file, click on the 'CountMediaFiles' or 'ShowMediaFilenames' button.

---

BREADTH AND FLEXIBILITY FEATURES OF THIS UTILITY

Note that this utility has the flexibility of a 'playlist' approach. The user is given an opportunity to SELECT the files to be shown and is given the opportunity to choose the ORDER in which the selected image files are shown.

This utility is oriented toward playing movie/audio files which may be scattered throughout various PARENT DIRECTORIES and THEIR SUB-DIRECTORIES --- in a play-back ORDER DETERMINED BY THE USER (that is, determined by the order of directories and files in the playlist file).


The code

Below, I provide the Tk script code for this 'play-media-files-in-a-playlist' utility.

I follow my usual 'canonical' structure for Tk code for this Tk script:

  0) Set general window & widget parms (win-name, win-position,
     win-color-scheme, fonts-for-widgets, widget-geometry-parms,
     text-array-for-labels-etc, win-size-control).

  1a) Define ALL frames (and sub-frames, if any).
  1b) Pack   ALL frames and sub-frames.

  2) Define & pack all widgets in the frames, frame by frame.
              Within each frame, define ALL the widgets.
              Then pack the widgets.

  3) Define keyboard and mouse/touchpad/touch-sensitive-screen action
     BINDINGS, if needed.

  4) Define PROCS, if needed.

  5) Additional GUI initialization (typically with one or more of
     the procs), if needed.

This Tk coding structure is discussed in more detail on the page A Canonical Structure for Tk Code --- and variations.

This structure makes it easy for me to find code sections --- while generating and testing a Tk script, and when looking for code snippets to include in other scripts (code re-use).

I call your attention to step-zero. One thing that I started doing in 2013 is use of a text-array for text in labels, buttons, and other widgets in the GUI. This can make it easier for people to internationalize my scripts. I will be using a text-array like this in most of my scripts in the future.


Experimenting with the GUI

As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus scripts, so far), I provide the four main pack parameters --- '-side', '-anchor', '-fill', '-expand' --- on all of the 'pack' commands for the frames and widgets.

That helps me when I am initially testing the behavior of a GUI (the various widgets within it) as I resize the main window.

I think that I have used a pretty nice choice of the 'pack' parameters. The label and button and radiobutton widgets stay fixed in size and relative-location if the window is re-sized --- while the entry widget expands/contracts horizontally whenever the window is re-sized horizontally.

You can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various frames and widgets --- to get the widget behavior that you want.

___

Additional experimentation: You might want to change the fonts used for the various GUI widgets. For example, you could change '-weight' from 'bold' to 'normal' --- or '-slant' from 'roman' to 'italic'. Or change font families.

In fact, you may NEED to change the font families, because the families I used may not be available on your computer --- and the default font that the 'wish' interpreter chooses may not be very pleasing.

I use variables to set geometry parameters of widgets --- parameters such as border-widths and padding. And I have included the '-relief' parameter on the definitions of frames and widgets. Feel free to experiment with those 'appearance' parameters as well.

If you find the gray 'palette' of the GUI is not to your liking, you can change the value of the RGB parameter supplied to the 'tk_setPalette' command near the top of the code.

---

In fact, here are images from a couple of experiments with the variable-width fonts used for text on Tk 'label' and 'button' and 'radiobutton' widgets --- and experimentation with the color 'palette' of the Tk window.

tkPlayMediaFilesInPlaylist_fontTimesNewRoman_beige_screenshot_690x128.jpg

The image above uses the rather staid 'Times New Roman' font --- and a brownish palette (to blend with the brownish desktop background image that came with my Ubuntu 9.10 Gnome 2.28 desktop system).

tkPlayMediaFilesInPlaylist_fontZachary_blue_screenshot_801x126.jpg

The image above uses the not-so-staid 'Zachary' font (modeled on the hand-writing of the son of a font-maker) --- and a bluish palette.


Some features in the code

That said, here's the code --- with plenty of comments to describe what most of the code-sections are doing.

You can look at the top of the PROCS section of the code to see a list of the procs used in this script, along with brief descriptions of how they are called and what they do.

The main procs are

  'get_playlist_filename'   - called by the 'Browse...' button
                              next to the filename entry field

  'count_media_files'       - called by the 'CountMediaFiles' button.

  'show_media_filenames'    - called by the 'ShowMediaFilenames' button.

  'play_media_files'        - called by the 'LaunchPlayerJob' button.

  'popup_msgVarWithScroll' - called by 'Help' button to show HELPtext var.
                                    Also called via the 'CountMediaFiles' and
                                    and 'ShowMediaFilenames' buttons

Like with the 'batch-find-and-imageViewer' and 'batch-find-and-mediaPlayer' and 'show-images-of-a-playlist' Tk GUI utilities, I used the following statement to allow the GUI to be expanded in the x-direction, but NOT the y-direction.

   wm resizable . 1 0

---

To get the 'Stop' button to work, I used the technique that I used for the 'show-images-of-a-playlist' utility.

I could not use the Tcl 'exec' command to start the 'external' player(s) in a 'foreground' mode, because that would 'lock up' the Tk GUI while a media file was being played by the 'external' player.

Instead, I use the 'exec' command to start the media-player in a 'background' mode. Example:

   catch {eval exec $PLAYERcommand "$MEDIAfilename" &} PlayerPID

Thus I had a PID (process ID) for the media-player process.

Then I used a 'while' loop, including an 'after 500' statement to occasionally check, with the 'ps' command, whether the process was still running --- thanks to a code snippet seen at http://stackoverflow.com/questions/16012040/how-do-i-check-for-spawn-id-thats-alive-tcl .

Based on that example, I used the following simple loop

   while {1} {
      update
      after 500
      if {[catch {exec ps $PlayerPID} CatchMsg] != 0} {break} 
   }

The 'update' command is to allow for checking whether the 'Stop' button was pressed --- as the 'play_media_files' proc was playing (or proceeding to play) a media file. (The Stop button sets a stop-variable to 1 rather than 0.)

Only the one 'catch-exec-ps-break' line was needed to determine whether the user had closed the media-player window and it was now time to play the next media file (and check whether the Stop button had been pressed).


It is my hope that the copious comments in the code will help Tcl-Tk coding 'newbies' get started in making GUI's like this.

Without the comments, potential young Tcler's might be tempted to return to their iPhones and iPads and iPods --- to watch videos of Russian helicopters flying over a highway into the Crimea (apparently as captured on the smartPhone of a Ukrainian motorist).


 Code for Tk script 'playMediaFilesInPlaylist_FrontEnd.tk' :
#!/usr/bin/wish -f
##
## Tk SCRIPT NAME: playMediaFilesInPlaylist_FrontEnd.tk
##
##+#######################################################################
## PURPOSE:  This Tk script provides a GUI for selecting a 'playlist' of
##           media files. The media (movie or audio) files may be scattered
##           throughout various directories -- such as sub-directories of a
##           web site --- OR sub-directories of a home directory --- OR
##           sub-directories on multiple disk drives mounted on a computer ---
##           OR sub-directories of a removable storage device mounted on
##           a computer.
##
##           Besides selecting the playlist file, this utility
##           allows the user to select a media-player program from among
##           multiple choices --- and allows the user to specify a
##           fullscreen-size or 'default'-size display mode.
##
##           Then the user can click on a 'Launch' button to start playing
##           the media files, in the order of the filenames within the
##           playlist file.
##
##           Some examples of media-player programs:
##                - mplayer
##                - ffplay
##                - totem
##                - gnome-mplayer
##                - VLC
##                - smplayer
##                - gmplayer
##
##           The player program is chosen via radiobutton widgets on the GUI.
##           This code can be changed to allow for additional or other
##           media players.
##
##           The GUI is intended to make the user aware of the main
##           (most useful) options available without the user needing
##           to reference the 'man mplayer'/'man ffplay'/'man totem'/...
##           commands and other 'mplayer'/'ffplay'/'totem'/... documentation,
##           for example, via web searches.
##
##           The intent of this utility is to allow the user to easily
##           specify files to be played ... by building a simple 'playlist'.
##
##           The playlist file contains three types of lines:
##
##             1 - Comment lines may be indicated in the file by a # sign
##                 in column 1.
##
##             2 - Lines that contain a fully-qualified directory name
##                 or a 'dot' directory name.
##                 Examples: /data/movies/tennis2013 or
##                           $env(HOME)/tennis2013  or
##                           /home/fred/tennis2013  or
##                           .                      or
##                           ./USopen
##                 These lines must start with either slash(/) or $ or dot(.).
##
##                 The dot can be used to represent the directory in which
##                 the playlist file lies. This useful when putting the playlist
##                 file in a directory of media files and using the dot to
##                 represent the directory of the media files. The directory of
##                 media files may have sub-directories of media files, as indicated
##                 by the last example. The dot allows for moving/copying the
##                 media files (with the playlist file) to different directories
##                 without having to change the internals of the playlist file.
##
##             3 - Lines that contain a relative filename (relative to the
##                 previous directory name)
##                 Example: Federer_vs_Nadal_2013.mp4
##                 These lines DO NOT start with either slash (/) or $ or #.
##
##           The first non-comment line of the playlist file should be a
##           directory name.
##
##           There can be more than one directory name in the file.
##
##           Each directory-name-line is followed by names of media files
##           that are in the specified directory.
##
## NOTEWORTHY FEATURES OF THIS UTILITY:
##
##           NOTE that some media-players, like 'totem' and 'VLC', support
##           selecting media files to play, from a playlist. But each of
##           these players typically have their own playlist format that
##           is somewhat different from the playlist format used by
##           other players.
##
##           Furthermore, some simple media-players, like 'ffplay',
##           do not support a playlist feature.
##
##           This utility is oriented toward using a simple, 'open', common
##           playlist format that can be used with any of these media-players
##           --- via this Tk GUI script.
##
##           Note that in building the playlist file, the user can SELECT
##           media files which may be scattered throughout various PARENT
##           DIRECTORIES and THEIR SUB-DIRECTORIES --- and place the filenames
##           in a play-back ORDER DETERMINED BY THE USER (that is, determined
##           by the order of directories and files in the playlist file). 
##            
##+##########################
## NOTES ON THE MEDIA-PLAYERS:
##
##     See notes in the 'play_media_files' proc, on seven media-players:
##         - mplayer        ('man' page is about 100+ pages)
##         - ffplay         (comes with the 'ffmpeg' command)
##         - totem          (uses Gstreamer)
##         - gnome-mplayer  (bugs -- used gmplayer instead)
##         - gmplayer       (comes with the 'mplayer' command)
##         - VLC            ('man' page is about 50+ pages)
##         - smplayer       (uses Qt rather than Gtk to program the GUI)
##
##+#################
## THE GUI WIDGETS:
##
##           The options available to the user are compactly indicated
##           by the following 'sketch' of the GUI:
##
##  ---------------------------------------------------------------------------
## Play *Media* Files of a *Playlist* ...  with a choice of media-players
## [window title]
## --------------------------------------------------------------------------------
## 
## {Exit} {Help} {LaunchPlayerJob} {Stop (no more files)}    {CountMediaFiles} {ShowMediaFilenames}
## 
## Playlist Filename: _____________________________________________________  {Browse...}
## 
## Player Program:  O 1 mplayer   O 2 ffplay   O 3 totem   O 4 gnome-mplayer   O 5 VLC
## 
## Display Size: O Default   O Fullscreen
## 
## --------------------------------------------------------
##
## In the above sketch of the GUI:
##
## Square brackets indicate a comment (not to be placed on the GUI).
## Braces indicate a Tk 'button' widget.
## Underscores indicate a Tk 'entry' widget.
## A colon indicates that the text before the colon is on a 'label' widget.
## Capital-O indicates a Tk 'radiobutton' widget.
## Capital-X indicates a Tk 'checkbutton' widget (if any).
##
##+##############
## GUI components:
##
## From the GUI 'sketch' above, it is seen that the GUI consists of
## about
##     
##   -  7 button widgets
##   -  3 label widgets
##   -  1 entry widget
##   -  7 radiobutton widgets in 2 groups
##   -  0 checkbutton widget
##   -  0 scale widgets
##   -  0 listbox widgets
##
##+#####################################################################
## CALLED BY:  This script could be put in a sub-directory of the
##             user's home directory, such as $HOME/apps/tkPlayMediaInPlaylist.
##
##             Then the user can use their desktop system (such as
##             Gnome or KDE) to set up the script as an icon on the
##             desktop. Then the user can click on the icon to
##             startup the script.
##+########################################################################
## STRUCTURE OF THIS CODE:
##
##  0) Set general window parms (win-name, win-position, win-color-scheme,
##     fonts-for-widgets, widget-geom-parms, text-array-for-labels-etc,
##     win-size-control).
##
##  1a) Define ALL frames (and sub-frames, if any).
##  1b) Pack the frames.
##
##  2) Define & pack all widgets in the frames, frame by frame.
##     After all the widgets for a frame are defined, pack them in the frame.
##
##  3) Define keyboard and/or mouse/touchpad/touch-sensitive-screen 'event'
##     BINDINGS, if needed.
##  4) Define PROCS, if needed.
##  5) Additional GUI INITIALIZATION (typically with one or more of
##     the procs), if needed.
##
## In more detail:
##
##  1a) Define ALL frames -- and sub-frames:
## 
##   Top-level :
##       'fRbuttons'     for Exit, Help, Launch, ... buttons
##       'fRfile'        for a playlist (directory-and-filename) entry field
##       'fRdisplayPgm'  for several radiobuttons, with a label
##       'fRdisplaySize' for 2 radiobuttons, with a label 
##
##  1b) Pack ALL frames, including sub-frames (if any).
##
##  2) Define & pack all widgets in the frames -- basically going through
##     frames & their interiors in  left-to-right, top-to-bottom order:
##
##  3) Define bindings:  See BINDINGS section below.
##
##  4) Define procs:
##
##    'get_playlist_filename' - called by the 'Browse...' button
##
##    'count_media_files'     - called by the 'CountMediaFiles' button.
##
##    'show_media_filenames'  - called by the 'ShowMediaFilenames' button.
##
##    'play_media_files'      - called by the 'LaunchPlayerJob' button.              
##
##   'popup_msgVarWithScroll' - called by 'Help' button to show HELPtext var.
##                                         Also used via the 'CountMediaFiles'
##                                         and 'ShowMediaFilenames' buttons.
##
##     For other procs, see the PROCS section below.
##
##  5) Additional GUI initialization:  See this section at the bottom
##                                     of this script.
##+#######################################################################
## DEVELOPED WITH: Tcl-Tk 8.5 on Ubuntu 9.10 (2009-october, 'Karmic Koala')
##
##   $ wish
##   % puts "$tcl_version $tk_version"
##
## showed
##     8.5 8.5
## but this script should work in most previous 8.x versions, and probably
## even in some 7.x versions (if font handling is made 'old-style').
##+########################################################################
## MAINTENANCE HISTORY:
## Started by: Blaise Montandon 2014mar03 Started development, on Ubuntu 9.10,
##                                        based on the code of some Tk scripts
##                                        of mine that contained most of the
##                                        widgets needed.
## Updated by: Blaise Montandon 2014apr14 Added 'file exists' and RETcode checks 
##                                        in proc 'play_media_files'.
## Updated by: Blaise Montandon 2014apr21 Added capability to use "." at the
##                                        start of any directory name in the
##                                        playlist file --- to represent the
##                                        directory in which the playlist file
##                                        lies. Changed <KeyPress> to <KeyRelease>
##                                        in binding on filename entry field.
## Updated by: Blaise Montandon 2014may22 Added 'catch' to 3 close-file statements.
## Updated by: Blaise Montandon 2014may26 1) Replaced var 'fileID' occurences by
##                                           'fileIDcount','fileIDshow','fileIDplay'.
##                                        2) Added 'eval' to a 'set' statement in proc
##                                           'show_media_filenames' and to a 'set'
##                                           statement in proc 'play_media_files'.
##+#######################################################################

##+######################################################
## Set WINDOW TITLE and POSITION.
##+######################################################

wm title    . "Play *Media* Files of a *Playlist* ... with a choice of media-players"

wm iconname . "tkMediaPlaylist"

# wm geometry . +15+30
# wm geometry . +250+285
wm geometry . -10-10


##+######################################################
## Set the COLOR SCHEME for the window and its widgets ---
## such as listbox and entry field background color.
##+######################################################

tk_setPalette "#e0e0e0"


  set entryBKGD "#ffffff"
  set textBKGD  "#f0f0f0"
  set radbuttBKGD  "#ffffff"
# set chkbuttBKGD  "#ffffff"
# set scaleBKGD   "#f0f0f0"
# set listboxBKGD "#f0f0f0"


##+########################################################
## DEFINE (temporary) FONT NAMES.
##
## We use a VARIABLE-WIDTH font for text on LABEL and
## BUTTON widgets.
##
## We use a FIXED-WIDTH font for LISTBOX lists,
## for text in ENTRY fields --- and often for text in
## TEXT widgets.
##+########################################################

font create fontTEMP_varwidth \
   -family {comic sans ms} \
   -size -14 \
   -weight bold \
   -slant roman

font create fontTEMP_SMALL_varwidth \
   -family {comic sans ms} \
   -size -12 \
   -weight bold \
   -slant roman

## Some other possible (similar) variable width fonts:
##  Arial
##  Bitstream Vera Sans
##  DejaVu Sans
##  Droid Sans
##  FreeSans
##  Liberation Sans
##  Nimbus Sans L
##  Trebuchet MS
##  Verdana


font create fontTEMP_fixedwidth  \
   -family {liberation mono} \
   -size -14 \
   -weight bold \
   -slant roman

font create fontTEMP_SMALL_fixedwidth  \
   -family {liberation mono} \
   -size -12 \
   -weight bold \
   -slant roman

## Some other possible fixed width fonts (esp. on Linux):
##  Andale Mono
##  Bitstream Vera Sans Mono
##  Courier 10 Pitch
##  DejaVu Sans Mono
##  Droid Sans Mono
##  FreeMono
##  Nimbus Mono L
##  TlwgMono


##+###########################################################
## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS.
## (e.g. width and height of canvas, and padding for Buttons)
##+###########################################################

## LABEL widget geom settings:

set PADXpx_label 0
set PADYpx_label 0
set BDwidthPx_label 2


## BUTTON widget geom settings:

set PADXpx_button 0
set PADYpx_button 0
set BDwidthPx_button 2


## ENTRY widget geom settings:

set BDwidthPx_entry 2


## RADIOBUTTON widget geom settings:

set PADXpx_radbutton 0
set PADYpx_radbutton 0
set BDwidthPx_radbutt 2


## CHECKBUTTON widget geom settings:

set PADXpx_chkbutton 0
set PADYpx_chkbutton 0
set BDwidthPx_chkbutton 2

## TEXT widget geom settings:

set BDwidthPx_text 2


## SCALE widget geom parameters:

# set BDwidthPx_scale 2
# set scaleThicknessPx 10

##+##############################################################
## Set a TEXT-ARRAY to hold text for buttons & labels on the GUI.
##     NOTE: This can aid INTERNATIONALIZATION. This array can
##           be set according to a nation/region parameter.
##+##############################################################

## if { "$VARlocale" == "en"}

## For '.fRbuttons' frame:

set aRtext(buttonEXIT)    "Exit"
set aRtext(buttonHELP)    "Help"
set aRtext(buttonLAUNCH)  "LaunchPlayerJob"
set aRtext(buttonSTOP1)   "Stop (no more files)"
set aRtext(buttonSTOP2)   "Stop indicator was SET"

set aRtext(buttonCOUNT)  "CountMediaFiles"
set aRtext(buttonPRINT)  "ShowMediaFilenames"

## For '.fRfile' frame:

set aRtext(labelFILENAME) "Playlist Filename:"
set aRtext(buttonBROWSE)  "Browse..."


## For '.fRdisplayPgm' frame:

set aRtext(labelDISPLAYPGM)   "Player Program:"
set aRtext(radbuttDPGM1) "1 - mplayer"
set aRtext(radbuttDPGM2) "2 - ffplay"
set aRtext(radbuttDPGM3) "3 - totem"
# set aRtext(radbuttDPGM4) "4 - gnome-mplayer"
set aRtext(radbuttDPGM4) "4 - gmplayer"
set aRtext(radbuttDPGM5) "5 - VLC"
set aRtext(radbuttDPGM6) "6 - smplayer"

## For '.fRdisplaySize' frame:

set aRtext(labelDISPLAYSIZE)  "Display size:"
set aRtext(radbuttDSIZEFULL)    "FULLSCREEN"
set aRtext(radbuttDSIZEDEFAULT) "DEFAULT-image-size (up to fullscreen)"

## END OF  if { "$VARlocale" == "en"}


##+######################################################################
## Set a MIN-SIZE of the window (roughly).
##
## For WIDTH, allow for the min-width of the '.fRbuttons' frame.
##
## For HEIGHT, allow for the stacked frames:
##      1 char   high for the '.fRbuttons'     frame
##      1 char   high for the '.fRfile'        frame
##      1 char   high for the '.fRdisplayPgm'  frame
##      1 char   high for the '.fRdisplaySize' frame
##    --------
##      4 chars  high for the 4 frames
##+#####################################################################

## FOR WIDTH: (allow for widgets in the '.fRbuttons' frame)

set minWidthPx [font measure fontTEMP_varwidth \
   " $aRtext(buttonEXIT) $aRtext(buttonHELP) $aRtext(buttonLAUNCH) \
 $aRtext(buttonSTOP1) $aRtext(buttonCOUNT) $aRtext(buttonPRINT)"]

## We add some pixels to account for right-left-size of
## window-manager decoration (~8 pixels) and some pixels for
## frame/widget borders (~5 widgets x 4 pixels/widget = 20 pixels).

set minWinWidthPx [expr {28 + $minWidthPx}]


## For HEIGHT --- for
##      1 char   high for the '.fRbuttons'     frame
##      1 char   high for the '.fRfile'        frame
##      1 char   high for the '.fRdisplayPgm'  frame
##      1 char   high for the '.fRdisplaySize' frame
##    --------
##      4 chars  high for the 4 frames

set charHeightPx [font metrics fontTEMP_varwidth -linespace]

set minWinHeightPx [expr {4 * $charHeightPx}]


## Add about 20 pixels for top-and-bottom window decoration --
## and some pixels for top-and-bottom of frame/widget borders
## (~4 widgets x 4 pixels/widget = 16 pixels).

set minWinHeightPx [expr {36 + $minWinHeightPx}]


## FOR TESTING:
#   puts "minWinWidthPx = $minWinWidthPx"
#   puts "minWinHeightPx = $minWinHeightPx"

wm minsize . $minWinWidthPx $minWinHeightPx


## We may allow the window to be resizable.  We pack the canvases
## (and the frames that contain them) with '-fill both -expand 1'
## so that the canvases can be enlarged by enlarging the window.

## If you want to make the window un-resizable, 
## you can use the following statement.
#   wm resizable . 0 0

## We fix the y-size of the window, but allow the x-size to vary.
wm resizable . 1 0



##+####################################################################
##+####################################################################
## DEFINE *ALL* THE FRAMES:
##
##   Top-level :
##       'fRbuttons'     for Exit, Help, Launch, ... buttons
##       'fRfile'        for a playlist filename entry field
##       'fRdisplayPgm'  for several radiobuttons, with a label
##       'fRdisplaySize' for 2 radiobuttons, with a label
##+####################################################################
##+####################################################################

## FOR TESTING of expansion of frames (esp. during window expansion):

# set feRELIEF_frame raised
# set feBDwidth_frame 2

 set feRELIEF_frame flat
 set feBDwidth_frame 0

frame .fRbuttons     -relief $feRELIEF_frame  -bd $feBDwidth_frame

  frame .fRfile        -relief $feRELIEF_frame  -bd $feBDwidth_frame
# frame .fRfile        -relief raised           -bd 2

frame .fRdisplayPgm  -relief raised           -bd 2

  frame .fRdisplaySize  -relief $feRELIEF_frame  -bd $feBDwidth_frame
# frame .fRdisplaySize  -relief raised           -bd 2


##+########################################################
## PACK *ALL* the FRAMES.
##+########################################################

pack .fRbuttons \
   -side top \
   -anchor nw \
   -fill x \
   -expand 0

pack .fRfile \
   -side top \
   -anchor nw \
   -fill x \
   -expand 0

pack .fRdisplayPgm \
   -side top \
   -anchor nw \
   -fill x \
   -expand 0

pack .fRdisplaySize \
   -side top \
   -anchor nw \
   -fill x \
   -expand 0


##+################################################################
##+################################################################
## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. 
##+################################################################
##+################################################################

##+########################################################
## IN THE '.fRbuttons' frame -- DEFINE several buttons
## --- Exit, Help, Launch.
##+########################################################

button .fRbuttons.buttEXIT \
   -text "$aRtext(buttonEXIT)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {exit}

button .fRbuttons.buttHELP \
   -text "$aRtext(buttonHELP)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {popup_msgVarWithScroll .topHelp "$HELPtext"}

button .fRbuttons.buttLAUNCH \
   -text "$aRtext(buttonLAUNCH)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {play_media_files}

set STOPvar0or1 0

button .fRbuttons.buttSTOP \
   -text "$aRtext(buttonSTOP1)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {set STOPvar0or1 1 ; \
     .fRbuttons.buttSTOP configure -text "$aRtext(buttonSTOP2)"}

button .fRbuttons.buttCOUNT \
   -text "$aRtext(buttonCOUNT)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {count_media_files}

button .fRbuttons.buttPRINT \
   -text "$aRtext(buttonPRINT)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {show_media_filenames}

##+########################################
## Pack the widgets in the 'fRbuttons' frame
##+########################################

pack .fRbuttons.buttEXIT \
     .fRbuttons.buttHELP \
     .fRbuttons.buttLAUNCH \
     .fRbuttons.buttSTOP \
   -side left \
   -anchor w \
   -fill none \
   -expand 0

pack .fRbuttons.buttPRINT \
     .fRbuttons.buttCOUNT \
   -side right \
   -anchor e \
   -fill none \
   -expand 0


##+########################################################
## IN THE '.fRfile' frame -- DEFINE 1 LABEL widget,
## 1 ENTRY widget, and 1 BUTTON widget.
##+########################################################

label .fRfile.labelFILENAME \
   -text "$aRtext(labelFILENAME)" \
   -font fontTEMP_varwidth \
   -justify left \
   -anchor w \
   -relief  flat \
   -bd $BDwidthPx_label

entry .fRfile.entryFILENAME \
   -textvariable ENTRYfilename \
   -bg $entryBKGD \
   -font fontTEMP_fixedwidth \
   -relief sunken \
   -bd $BDwidthPx_entry

## Set an initial value for the entry var.

set curDIR "$env(HOME)"
# set curDIR "$env(HOME)/MyMoviePlaylists"
# set curDIR "$env(HOME)/MyAudioPlaylists"
# set curDIR "/data/playlists/movies"
# set curDIR "/data/playlists/audio"

## FOR TESTING:
     set curDIR [pwd]

set ENTRYfilename "$curDIR/media_playlist.lis"

## Put the end of the filename in view.

.fRfile.entryFILENAME xview end


button .fRfile.buttBROWSE \
   -text "$aRtext(buttonBROWSE)" \
   -font fontTEMP_varwidth \
   -padx $PADXpx_button \
   -pady $PADYpx_button \
   -relief raised \
   -bd $BDwidthPx_button \
   -command {get_playlist_filename}

## PACK the widgets in the 'fRfile' frame.

pack  .fRfile.labelFILENAME \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 

pack .fRfile.entryFILENAME \
   -side left \
   -anchor w \
   -fill x \
   -expand 1 

pack .fRfile.buttBROWSE \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 


##+########################################################
## IN THE '.fRdisplayPgm' frame -- DEFINE
## severak RADIOBUTTONS, preceded by a LABEL widget.
##+########################################################

label .fRdisplayPgm.labelDISPLAYPGM \
   -text "$aRtext(labelDISPLAYPGM)" \
   -font fontTEMP_varwidth \
   -justify left \
   -anchor w \
   -relief  flat \
   -bd $BDwidthPx_label

## DEFINE Radiobuttons for player programs :

radiobutton  .fRdisplayPgm.radbuttDPGM1 \
   -text "$aRtext(radbuttDPGM1)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaypgm \
   -value "1" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

radiobutton  .fRdisplayPgm.radbuttDPGM2 \
   -text "$aRtext(radbuttDPGM2)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaypgm \
   -value "2" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

radiobutton  .fRdisplayPgm.radbuttDPGM3 \
   -text "$aRtext(radbuttDPGM3)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaypgm \
   -value "3" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

radiobutton  .fRdisplayPgm.radbuttDPGM4 \
   -text "$aRtext(radbuttDPGM4)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaypgm \
   -value "4" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

radiobutton  .fRdisplayPgm.radbuttDPGM5 \
   -text "$aRtext(radbuttDPGM5)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaypgm \
   -value "5" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

radiobutton  .fRdisplayPgm.radbuttDPGM6 \
   -text "$aRtext(radbuttDPGM6)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaypgm \
   -value "6" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

## RADVARdisplaypgm is the var for these several radiobuttons.
## Set an initial value.
  set RADVARdisplaypgm "1"
# set RADVARdisplaypgm "2"
# set RADVARdisplaypgm "3"
# set RADVARdisplaypgm "4"
# set RADVARdisplaypgm "5"
# set RADVARdisplaypgm "6"

## PACK the widgets in the 'fRdisplayPgm' frame.

pack  .fRdisplayPgm.labelDISPLAYPGM \
      .fRdisplayPgm.radbuttDPGM1 \
      .fRdisplayPgm.radbuttDPGM2 \
      .fRdisplayPgm.radbuttDPGM3 \
      .fRdisplayPgm.radbuttDPGM4 \
      .fRdisplayPgm.radbuttDPGM5 \
      .fRdisplayPgm.radbuttDPGM6 \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 


##+########################################################
## IN THE '.fRdisplaySize' frame -- DEFINE
## 2 RADIOBUTTONS, preceded by a LABEL widget.
##+########################################################

label .fRdisplaySize.labelDISPLAYSIZE \
   -text "$aRtext(labelDISPLAYSIZE)" \
   -font fontTEMP_varwidth \
   -justify left \
   -anchor w \
   -relief  flat \
   -bd $BDwidthPx_label

## DEFINE Radiobuttons for display sizes :

radiobutton  .fRdisplaySize.radbuttDSIZEDEFAULT \
   -text "$aRtext(radbuttDSIZEDEFAULT)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaysize \
   -value "default" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt

radiobutton  .fRdisplaySize.radbuttDSIZEFULL \
   -text "$aRtext(radbuttDSIZEFULL)" \
   -font fontTEMP_varwidth \
   -anchor w \
   -variable RADVARdisplaysize \
   -value "fullscreen" \
   -selectcolor "$radbuttBKGD" \
   -relief flat \
   -bd $BDwidthPx_radbutt


## RADVARdisplaysize is the var for these 2 radiobuttons.
## Set an initial value.
   set RADVARdisplaysize "default"
#  set RADVARdisplaysize "fullscreen"

## PACK the widgets in the 'fRdisplaySize' frame.

pack  .fRdisplaySize.labelDISPLAYSIZE \
      .fRdisplaySize.radbuttDSIZEDEFAULT \
      .fRdisplaySize.radbuttDSIZEFULL \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 


##+#####################################################################
## END OF SECTION TO DEFINE AND PACK THE GUI WIDGETS.
##+#####################################################################

##+#####################################################################
##+#####################################################################
## DEFINE BINDINGS:  button1-release bindings on some widgets ???
##                   Return-key bindings on some entry widgets ???
##+#####################################################################

# bind .fR?????.???widget???  <ButtonRelease-1>  {??proc??}
# bind .fR?????.???widget???  <Return>  {??proc??}

## As the user types in the filename entry field (KeyRelease events), make sure
## the area near the insertion cursor or the character entry is showing.
## (Strange? 'KeyRelease' works, but 'KeyPress' leaves the insert cursor at the
## end of the field and ALWAYS slightly out of view to the right. It's as if
## a backspace occurs after the KeyPress.)

bind .fRfile.entryFILENAME <KeyRelease> \
   {.fRfile.entryFILENAME xview insert}

## FOR TESTING:
#   bind .fRfile.entryFILENAME <KeyPress> {
#      set entFILENAMExview [.fRfile.entryFILENAME xview]
#      puts ".fRfile.entryFILENAME 'offset' and 'span': $entFILENAMExview"
#   }

## An alternative?
# bind .fRfile.entryFILENAME <KeyRelease> \
#     {.fRfile.entryFILENAME xview moveto 1.0}


##+#####################################################################
##+#####################################################################
## DEFINE PROCEDURES:
##
##  'get_playlist_filename'   - called by the 'Browse...' button
##                              next to the filename entry field
##
##  'count_media_files'       - called by the 'CountMediaFiles' button.
##
##  'show_media_filenames'    - called by the 'ShowMediaFilenames' button.
##
##  'play_media_files'        - called by the 'LaunchPlayerJob' button.
##
##  'popup_msgVarWithScroll' - called by 'Help' button to show HELPtext var.
##                                    Also called via the 'CountMediaFiles' and
##                                    and 'ShowMediaFilenames' buttons.
##+#####################################################################
##+#####################################################################

##+#####################################################################
## Proc 'get_playlist_filename'
##
## PURPOSE: To get the fully-qualified name of a file and put the
##          name into global var 'ENTRYfilename'.
##
##    Note: The user may change the filename (after the end of the
##          directory name) to change it to a different filename
##          in the same directory. For example: change playlist1.lis
##          to playlist2.lis.
##
##          Furthermore, the user may completely change both
##          the directory name and the filename by editing
##          the text in the entry field. 
##
## CALLED BY: the '-command' option of the 'Browse ...' button.
##+#####################################################################

proc get_playlist_filename {} {

   global ENTRYfilename env curDIR

   #############################################
   ## Get a 'media-playlist' file name.
   #############################################

   set fName [tk_getOpenFile -parent .  \
      -title "Select Directory-and-Filename - of a media playlist-file" \
      -initialdir "$curDIR" ]

   ## FOR TESTING:
   #   puts "fName : $fName"

   ################################
   ## Check if fName var is empty.
   ################################

   if {"$fName" == ""} {return}

   #####################################################
   ## Put $fName in ENTRYfilename. Reset the curDIR var.
   #####################################################

   if {[file exists "$fName"]} {
      set ENTRYfilename "$fName"

      ## Put the end of the filename in view.
      .fRfile.entryFILENAME xview end

      set curDIR [ get_chars_before_last / in "$ENTRYfilename" ]
   }
   ## END OF if directory-exists

}
## END OF proc 'get_playlist_filename'


##+###################################################################
## Proc 'get_chars_before_last'
##+###################################################################
## INPUT:  A character and a string.
##         Note: The "in" parameter is there only for clarity.
##
## OUTPUT: Returns all of the characters in the string "strng" that
##         are BEFORE the last occurence of the characater "char".
##
## CALLED BY: proc 'get_img_filename' and 3 'media' procs below.
##
##+##################################################################

proc get_chars_before_last { char in strng } {

   set lastIDX [ expr [string last $char $strng ] - 1 ]
   set output [ string range "$strng" 0 $lastIDX ]

   ## FOR TESTING:
   # puts "From 'get_chars_before_last' proc:"
   # puts "STRING: $strng"
   # puts "CHAR: $char"
   # puts "RANGE up to LAST CHAR - start: 0   lastIDX: $lastIDX"

   return $output

}
## END OF 'get_chars_before_last' PROCEDURE


##+###################################################################
## Proc 'get_chars_after_last'
##+###################################################################
## INPUT:  A character and a string.
##         Note: The "in" parameter is there only for clarity.
##
## OUTPUT: Returns all of the characters in the string "strng" that
##         are AFTER the last occurence of the characater "char".
##
## CALLED BY: 3 'media' procs below
##+##################################################################

proc get_chars_after_last { char in strng } {

   set lastIDX [ expr [string last $char $strng ] + 1 ]
   set output [ string range "$strng" $lastIDX end ]

   ## FOR TESTING:
   # puts "From 'get_chars_before_last' proc:"
   # puts "STRING: $strng"
   # puts "CHAR: $char"
   # puts "RANGE up to LAST CHAR - start: 0   lastIDX: $lastIDX"

   return $output

}
## END OF 'get_chars_after_last' PROCEDURE



##+#############################################################
## proc count_media_files
##
## PURPOSE: For a given playlist file, counts the
##          media filenames in the playlist file ---
##          by counting the non-empty lines that do NOT
##          start with slash (/) or $ or #.
##
## CALLED BY: the 'CountMediaFiles'  button
##+#############################################################

proc count_media_files {} {

   global ENTRYfilename env

   ## DUMMY OUT THIS PROC (during development)
   #   return

   #######################################################
   ## Remove trailing and leading blanks (if any) from the
   ## user entry in the filename 'entry' widget.
   #######################################################

   set ENTRYfilename [string trim "$ENTRYfilename"]

   if {![file exists "$ENTRYfilename"]} {
      popup_msgVarWithScroll .topCount \
         "Filename in entry field does not exist."
      return
   }

   ###############################################################
   ## 'count' logic goes here.
   ###############################################################
   ## Prepare for counting media files in the playlist file.
   ###############################################################

   set fileIDcount [open $ENTRYfilename]

   set Nmediafiles 0

   ################################################################
   ## START OF WHILE-LOOP for the 'gets' file-READING.
   ## The while-test below is equivalent to 'while {![eof $fileIDcount]}'.
   ################################################################

   while {[eof $fileIDcount] == 0} {

      ############################################################
      ## GET THE NEXT LINE (up to a line feed) --- and, optionally,
      ## get its length.
      ############################################################

      # set lineLen [gets $fileIDcount line]

      gets $fileIDcount line

      ###########################
      ## GET FIRST CHAR of line.
      ###########################

      set FIRSTchar [string index "$line" 0]

      ##############################################################
      ## IF A COMMENT LINE, SKIP THIS LINE ... i.e. read next line.
      ##############################################################

      if { "$FIRSTchar" == "#" } {continue}

      #################################################################
      ## IF A DIRECTORY LINE, (set the tempDIR var and) read next line.
      #################################################################

      if { "$FIRSTchar" == "/" || "$FIRSTchar" == "$" || \
           "$FIRSTchar" == "." } {
         # set tempDIR "[string trim $line]"
         continue
      }

      #################################################################
      ## IF A RELATIVE-FILENAME LINE, INCREMENT COUNT & read next line.
      #################################################################

      set EMPTYLINEcheck "[string trim $line]"

      if { "$EMPTYLINEcheck" == "" } {continue}

      incr Nmediafiles

   }
   ## END OF  while {[eof $fileIDcount] == 0}

   catch {close $fileIDcount}

   ###############################################################
   ## DISPLAY THE COUNT in a small popup Tk window.
   ###############################################################

   popup_msgVarWithScroll .topCount \
      "$Nmediafiles media filenames are in the playlist file ---
[get_chars_after_last "/" in "$ENTRYfilename"]
in directory
[get_chars_before_last "/" in "$ENTRYfilename"]"

}
## END OF proc 'count_media_files'


##+#############################################################
## proc show_media_filenames
##
## PURPOSE: For a given playlist file, shows the
##          media filenames in the playlist file ---
##          in a Tk popup window with a scrollable text widget.
##
## CALLED BY: the 'ShowMediaFilenames'  button
##+#############################################################

proc show_media_filenames {} {

   global ENTRYfilename env

   ## DUMMY OUT THIS PROC (during development)
   #  return

   #######################################################
   ## Remove trailing and leading blanks (if any) from the
   ## user entry in the filename 'entry' widget.
   #######################################################

   set ENTRYfilename [string trim "$ENTRYfilename"]

   if {![file exists "$ENTRYfilename"]} {
      popup_msgVarWithScroll .topCount \
         "Filename in entry field does not exist."
      return
   }

   ######################################################
   ## Store the directory of this playlist file, to use
   ## below in place of "." in a directory-name line.
   ######################################################

   set thisDIR [file dirname "$ENTRYfilename"]


   ###############################################################
   ## Logic goes here to SHOW THE MEDIA FILENAMES of
   ## the 'playlist file'.
   ###############################################################
   ## Prepare for getting media filenames in the playlist file.
   ###############################################################

   set fileIDshow [open $ENTRYfilename]

   set Nmediafiles 0

   set TEXTfilenames ""

   ################################################################
   ## START OF WHILE-LOOP for the 'gets' file-READING.
   ## The while-test below is equivalent to 'while {![eof $fileIDshow]}'.
   ################################################################

   while {[eof $fileIDshow] == 0} {

      ############################################################
      ## GET THE NEXT LINE (up to a line feed) --- and, optionally,
      ## get its length.
      ############################################################

      # set lineLen [gets $fileIDshow line]

      gets $fileIDshow line

      ###########################
      ## GET FIRST CHAR of line.
      ###########################

      set FIRSTchar [string index "$line" 0]

      ##############################################################
      ## IF A COMMENT LINE, SKIP THIS LINE ... i.e. read next line.
      ##############################################################

      if { "$FIRSTchar" == "#" } {continue}

      #################################################################
      ## IF A DIRECTORY LINE starting with "/" or "$",
      ## SET THE 'tempDIR' VAR and read next line.
      #################################################################

      if { "$FIRSTchar" == "/" || "$FIRSTchar" == "$"  } {
         set tempDIR "[string trim $line]"
         continue
      }

      #################################################################
      ## IF A DIRECTORY LINE starting with ".",
      ## SET THE 'tempDIR' VAR and read next line.
      #################################################################

      if { "$FIRSTchar" == "."  } {
         set lengthOFline [string length "$line"]
         if {$lengthOFline > 1} {
            set restOFline [string range "$line" 1 $lengthOFline]
            set tempDIR "${thisDIR}$restOFline"
         } else {
            set tempDIR "$thisDIR"
         }
         continue
      }


      #################################################################
      ## IF A RELATIVE-FILENAME LINE, add the full filename to the
      ## 'TEXTfilenames' var ... and read next line.
      ##       We need the 'eval' on the 'set' statement to convert
      ##       $env(HOME), if it is used, to a directory name.
      #################################################################

      set EMPTYLINEcheck "[string trim $line]"

      if { "$EMPTYLINEcheck" == "" } {continue}

      eval set MEDIAfilename "$tempDIR/$EMPTYLINEcheck"

      set TEXTfilenames "$TEXTfilenames
$MEDIAfilename"

      incr Nmediafiles

   }
   ## END OF  while {[eof $fileIDshow] == 0}

   catch {close $fileIDshow}


   ###############################################################
   ## DISPLAY THE MEDIA FILENAMES in a popup Tk window.
   ###############################################################

   popup_msgVarWithScroll .topList \
      "For the playlist file
[get_chars_after_last "/" in "$ENTRYfilename"]
in directory
[get_chars_before_last "/" in "$ENTRYfilename"],

the $Nmediafiles full-filenames of the media files in the playlist file 
are as follows:

$TEXTfilenames"

}
## END OF proc 'show_media_filenames'
 

##+#############################################################
## proc play_media_files
##
## PURPOSE: For a given playlist file, plays the media files indicated
##          by directory names and 'relative' media filenames in
##          the playlist file.
##
##          Uses the display program indicated by the variable
##          $RADVARdisplaypgm.
##
##          Uses other variables, such as $RADVARdisplaysize,
##          to determine options for playing the media files.
##
## CALLED BY: the 'LaunchPlayerJob'  button
##+#############################################################

proc play_media_files {} {

   ## DUMMY OUT THIS PROC (during development)
   #   return

   global ENTRYfilename env RADVARdisplaypgm RADVARdisplaysize \
      STOPvar0or1 aRtext

   ## FOR TESTING:
   #  puts "Started proc 'play_media_files'."

   #####################################################
   ## Reset the 'stop' variable in case it was set to 1
   ## to stop a previous display sequence.
   #####################################################

   set STOPvar0or1 0
   .fRbuttons.buttSTOP configure -text "$aRtext(buttonSTOP1)"

   #######################################################
   ## Remove trailing and leading blanks (if any) from the
   ## user entry in the filename 'entry' widget.
   #######################################################

   set ENTRYfilename [string trim "$ENTRYfilename"]

   if {![file exists "$ENTRYfilename"]} {
      popup_msgVarWithScroll .topCount \
         "Filename in entry field does not exist."
      return
   }
   
   ######################################################
   ## Store the directory of this playlist file, to use
   ## below in place of "." in a directory-name line.
   ######################################################

   set thisDIR [file dirname "$ENTRYfilename"]


   ###############################################################
   ## Logic goes here to read the playlist file and
   ## PLAY THE MEDIA FILES.
   ###############################################################
   ## Prepare for playing the media files in the playlist file ...
   ## mainly, open the file and set a player command.
   ###############################################################

   set fileIDplay [open "$ENTRYfilename"]

   set Nmediafiles 0

   ###################################################################
   ## Some 'mplayer' COMMAND-LINE options:
   ##                 (from 'man mplayer', over 8500 lines, ~100+ pages)
   ##
   ##  -fs  Fullscreen  playback  (centers movie, and paints black bands
   ##       around it).  Not supported by all video output drivers.
   ##  Note:
   ##  "Every 'flag' option has a 'noflag' counterpart, e.g. the opposite
   ##  of the -fs option is -nofs."
   ##
   ##  -geometry x[%][:y[%]] or [WxH][+x+y]
   ##      Adjust where the output is on the screen initially.  The x and y
   ##      specifications  are  in pixels measured from the top-left of the
   ##      screen to the top-left of the image being displayed, however  if
   ##      a percentage sign is given after the argument it turns the value
   ##      into a percentage of the screen size in that direction.  It also
   ##      supports the standard X11 -geometry option format.  If an exter-
   ##      nal window is specified using the -wid option, then the x and  y
   ##      coordinates  are relativeto the top-left corner of the window
   ##      rather than the screen.
   ##      NOTE: This option is only supported by the x11, xmga, xv,  xvmc,
   ##      xvidix, gl, gl2, directx, fbdev and tdfxfb video output drivers.
   ##
   ##      EXAMPLEs:
   ##        50:40      Places the window at x=50, y=40.
   ##        50%:50%    Places the window in the middle of the screen.
   ##        100%       Places the window at the middle of the right edge of
   ##                   the screen.
   ##        100%:100%  Places the window at the bottom right corner of the
   ##                   screen.
   ##      
   ##  -loop <number>   Loops movie playback <number> times.  0 means forever.
   ##
   ##  -menu (OSD menu only)  Turn on OSD menu support.
   ##  -(no)gui         Enable  or  disable the GUI interface (default depends
   ##                   on binary name).  Only works as the first argument on
   ##                   the command line.
   ##  -quiet           Make console output less verbose; in particular,
   ##                   prevents the status line
   ##                   (i.e. A:   0.7 V:   0.6 A-V:  0.068 ...)
   ##                   from being displayed.
   ##  -really-quiet    Display even less output and status messages than
   ##                   with -quiet. Also suppresses the GUI error message boxes.
   ##
   ##  -idle            Makes MPlayer wait idly instead of quitting when
   ##                   there is no file to play.
   ##
   ##  -sstep <sec>     Skip  <sec>  seconds after every frame.  The normal
   ##                   framerate of the movie is kept, so playback is accelerated.
   ##                    Since MPlayer can only seek to the next keyframe this may be inexact.
   ##
   ##  -speed <0.01-100>  Slow down or speed up playback by the factor given
   ##                     as parameter.
   ##
   ##  -border          Play movie with window border and decorations.  Since
   ##                   this is on by default, use -noborder to disable the
   ##                   standard window decorations.
   ##
   ##
   ##############################################
   ## Some 'mplayer' INTERACTIVE keyboard controls while playing:
   ##
   ##  q or ESC         Stop playing and quit.
   ##  f                Toggle fullscreen.
   ##  p or SPACE       Pause (pressing again unpauses).
   ##  <- and ->        Seek backward/forward 10 seconds.
   ##  up and down      Seek forward/backward 1 minute.
   ##  pgup and pgdown  Seek forward/backward 10 minutes.
   ##  .                Step  forward.  Pressing once will pause movie,
   ##                   every consecutive press will play one frame and
   ##                   then go into pause mode again (any other key unpauses).
   ##  [ and ]          Decrease/increase current playback speed by 10%.
   ##  \{ and \}        Halve/double current playback speed.
   ##  backspace        Reset playback speed to normal.
   ##  + and -          Adjust audio delay by +/- 0.1 seconds.
   ##  / and *          Decrease/increase volume.
   ##  9 and 0          Decrease/increase volume.
   ##  ( and )          Adjust audio balance in favor of left/right channel.
   ##  m                Mute sound.
   ##  I                Show filename on the OSD.
   ###################################################################

   if {"$RADVARdisplaypgm" == "1"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {

         ## Set 'mplayer' to start in fullscreen mode.
         set VARcommand "/usr/bin/mplayer -fs "

         ## AN ALTERNATIVE, in case '-fs' is not desirable.
         ## NOT USED, yet.
         ## Get screen size.
         # set SCREENwidthPx  [winfo screenwidth .]
         # set SCREENheightPx [winfo screenheight .]
         ## Set heightheight/width to allow for desktop 'panels'
         ## at top-bottom/left-right of screen.
         # set MAXwidthPx  [expr {int(0.90 * $SCREENwidthPx)}]
         # set MAXheightPx [expr {int(0.90 * $SCREENheightPx)}]
         ## Set 'mplayer' to start in 'near-fullscreen' mode.
         # set VARcommand "/usr/bin/mplayer -geometry ${MAXwidthPx}x$MAXheightPx"

      } else {
         ## Set 'mplayer' to start in 'default' (non-fullscreen) mode.
         set VARcommand "/usr/bin/mplayer -nofs -geometry 15:30 "
      }
   }
 
   ###################################################################
   ## Some 'ffplay' COMMAND-LINE options:
   ##                              (from 'man ffplay' and 'ffplay -h')
   ##   -x width       Force displayed width.
   ##   -y height      Force displayed height.
   ##   -s size        Set frame size (WxH or abbreviation). Needed for
   ##                  videos which don't contain a header with the
   ##                  frame size, like raw YUV.
   ##   -fs            Force full screen
   ##   -an            Disable audio.
   ##   -vn            Disable video.
   ##   -nodisp        Disable graphical display.
   ##   -stats         Show the stream duration, the codec parameters,
   ##                  the current position in the stream and the
   ##                  audio/video synchronisation drift.
   ##   -threads count Set the thread count.
   ##
   ##############################################
   ## Some 'ffplay' INTERACTIVE keyboard controls while playing:
   ##   q or ESC       Quit.
   ##   f              Toggle full screen.
   ##   p or SPC       Pause.
   ##   left/right     Seek backward/forward 10 seconds.
   ##   down/up        Seek backward/forward 1 minute.
   ##   mouse click    Seek to percentage in file corresponding to fraction of width.
   ##   w              Show audio waves.
   ##   a              Cycle audio channel
   ##   v              Cycle video channel
   ##   t              Cycle subtitle channel
   ##
   ## NOTE: 'ffplay' nicely centers the media image within the width
   ##       and height area requested by the '-x' and '-y' parms
   ##       of the 'fullscreen' mode.
   ##       In the 'default' (non-fullscreen) mode, the 'ffplay'
   ##       window seems to always locate at the top-left of the desktop.
   ###################################################################

   if {"$RADVARdisplaypgm" == "2"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {
         ## Set 'ffplay' to start in fullscreen mode.
         set VARcommand "ffplay -fs "

         ## AN ALTERNATIVE way of getting 'near-fullscreen':
         ## Get screen size.
         # set SCREENwidthPx  [winfo screenwidth .]
         # set SCREENheightPx [winfo screenheight .]
         ## Set parms for '-x' and '-y'.
         # set MAXwidthPx  [expr {int(0.90 * $SCREENwidthPx)}]
         # set MAXheightPx [expr {int(0.90 * $SCREENheightPx)}]
         ## Set a 'fullscreen' version of the 'ffplay' command.
         # set VARcommand "ffplay -x $SCREENwidthPx -y $SCREENheightPx "
         ## OR
         # set VARcommand "ffplay -x $MAXwidthPx -y $MAXheightPx "

      } else {
         ## Set 'ffplay' to start in 'default' (non-fullscreen) mode.
         set VARcommand "ffplay "
      }
   }

   ###################################################################
   ## Some 'totem' COMMAND-LINE options:   (from 'man totem')
   ##
   ##  --fullscreen       Tell [an already-running instance of] Totem
   ##                     to toggle fullscreen mode.
   ##
   ##############################################
   ## Some 'totem' INTERACTIVE keyboard controls while playing:
   ##
   ##  q                    Quit.
   ##  Esc                  Exit full screen mode.
   ##  f                    Toggle full screen.
   ##  p                    Toggle between play and pause.
   ##  h                    Toggle display of on-screen controls.
   ##  0                    Resize window to 50% original size.
   ##  1                    Resize window to 100% original size.
   ##  2                    Resize window to 200% original size.
   ##  r                    Zoom in the video.
   ##  t                    Zoom out the video.
   ##  Left-arrow           Skip back 15 seconds
   ##  Right-arrow          Skip forward 60 seconds
   ##  Shift+Left-arrow     Skip back 5 seconds
   ##  Shift+Right-arrow    Skip forward 15 seconds
   ##  Ctrl+Left-arrow      Skip back 3 minutes
   ##  Ctrl+Right arrow     Skip forward 10 minutes
   ##  Up-arrow             Increase volume by 8%
   ##  Down-arrow           Decrease volume by 8%
   ##
   ####################################################################

   if {"$RADVARdisplaypgm" == "3"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {
         ## Set 'totem' to start in fullscreen mode.
         set VARcommand "totem --fullscreen "
      } else {
         ## Set 'totem' to start in 'default' (non-fullscreen) mode.
         set VARcommand "totem "
      }
   }

   ###################################################################
   ## Some 'gnome-mplayer' COMMAND-LINE options:  (from 'man gnome-mplayer')
   ##
   ##  --fullscreen                 Start in fullscreen mode.
   ##  -w, --width=X                Width of window to embed in.
   ##  -h, --height=Y               Height of window to embed in.
   ##  --showcontrols=[0|1]         Show the controls in window.
   ##  --loop                       Play [all files on the playlist] forever.
   ##  -q, --quit_on_complete       Quit application when last file [on playlist]
   ##                               is played.
   ##  --showdetails                Start with details visible.
   ##  --single_instance            Only allow one instance.
   ##  --disable_cover_art_fetch    Don't fetch new cover art images.
   ##  --large_buttons              Show interface with bigger icons. Useful
   ##                               for touchscreens.
   ##  --always_hide_after_timeout  Control bar will always slide away. Useful
   ##                               for small screens.
   ##  --keep_on_top                Keep window on top.
   ##  --volume                     Set initial volume percentage.
   ##
   #####################################################
   ## Some 'gnome-mplayer' INTERACTIVE keyboard controls while playing:
   ##
   ##  ???  TBD - from keyboard 'shortcuts' on toolbar menus.
   ####################################################################

   if {"$RADVARdisplaypgm" == "4000"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {
         ## Set 'gnome-mplayer' to start in fullscreen mode.
         # set VARcommand "gnome-mplayer --fullscreen "

         ## The '--fullscreen' option does not seem to work with
         ## 'gnome-mplayer'. Bug?
         ##
         ## AN ALTERNATIVE way of getting 'near-fullscreen':

         ## Get screen size.
         set SCREENwidthPx  [winfo screenwidth .]
         set SCREENheightPx [winfo screenheight .]
         ## Set parms for '-w' and '-h'.
         set MAXwidthPx  [expr {int(0.90 * $SCREENwidthPx)}]
         set MAXheightPx [expr {int(0.90 * $SCREENheightPx)}]
         ## Start 'gnome-mplayer' with '-w' and '-h'.
         set VARcommand "gnome-mplayer --width=$MAXwidthPx --height=$MAXheightPx "

      } else {
         ## Set 'gnome-mplayer' to start in 'default' (non-fullscreen) mode.
         set VARcommand "gnome-mplayer  "
      }
   }

   ###################################################################
   ## WE USE 'gmplayer' IN PLACE OF 'gnome-mplayer' ---
   ## since 'gnome-mplayer' has problems with '--fullscreen' and
   ## '--width' and '--height'.
   ##
   ## The ouput of 'man gmplayer' is the same as 'man mplayer'.
   ## I.e. the 'man' help for gmplayer is embedded in the HUGE
   ## 'man' help for mplayer.
   ##
   ## So we turn to 'gmplayer -h' for help.
   ####################################################################
   ## Some 'gmplayer' COMMAND-LINE options:  (from 'gmplayer -h')
   ## 
   ##  -fs              fullscreen playback (or -vm, -zoom, details in the man page)
   ##  -x <x> -y <y>    set display resolution (for use with -vm or -zoom)
   ##  -framedrop       enable frame dropping (for slow machines)
   ##  -vid x -aid y    select video (x) and audio (y) stream to play
   ##  -fps x -srate y  change video (x fps) and audio (y Hz) rate
   ##  -pp <quality>    enable postprocessing filter (details in the man page)
   ##  -nosound         do not play sound
   ##
   #####################################################
   ## Some 'gnome-mplayer' INTERACTIVE keyboard controls while playing:
   ## 
   ##  q or ESC         stop playing and quit program
   ##  p or SPACE       pause movie (press any key to continue)
   ##  <-  or  ->       seek backward/forward 10 seconds
   ##  down or up       seek backward/forward  1 minute
   ##  pgdown or pgup   seek backward/forward 10 minutes
   ##  + or -           adjust audio delay by +/- 0.1 second
   ##  * or /           increase or decrease PCM (audio) volume
   ##  x or z           adjust subtitle delay by +/- 0.1 second
   ##  r or t           adjust subtitle position up/down, also see -vf expand
   ##  o                cycle OSD mode:  none / seekbar / seekbar + timer
   ##                   (OSD = OnScreenDisplay info)
   ###################################################################

   if {"$RADVARdisplaypgm" == "4"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {
         ## Set 'gmplayer' to start in fullscreen mode.
         set VARcommand "gmplayer -fs -really-quiet "

         ## AN ALTERNATIVE way of getting 'near-fullscreen':

         ## Get screen size.
         # set SCREENwidthPx  [winfo screenwidth .]
         # set SCREENheightPx [winfo screenheight .]
         ## Set parms for '-geometry'.
         # set MAXwidthPx  [expr {int(0.90 * $SCREENwidthPx)}]
         # set MAXheightPx [expr {int(0.90 * $SCREENheightPx)}]
         ## Start 'mplayer' with '-geometry'.
         # set VARcommand "gmplayer -geometry ${MAXwidthPx}x${MAXheightPx}+15+30 "

      } else {
         ## Set 'gmplayer' to start in 'default' (non-fullscreen) mode.
         set VARcommand "gmplayer -really-quiet "
      }
   }


   ###################################################################
   ## Some 'VLC' COMMAND-LINE options:
   ##                     (from 'vlc -H', over 4,000 lines, ~50+ pages)
   ##
   ##  -f, --fullscreen       Start video in fullscreen mode. (Default: disabled)
   ##  --no-fullscreen
   ##  -L, --loop             VLC will keep playing [the playlist] indefinitely.
   ##                         (Default: disabled)
   ##  --no-loop
   ##  -R, --repeat           VLC will keep playing the current [playlist] item.
   ##                         (Default: disabled)
   ##  --no-repeat
   ##  --grayscale            Output video in grayscale. As the color
   ##                         information aren't decoded, this can save
   ##                         some processing power. (Default: disabled)
   ##  --no-grayscale
   ##  --skip-frames          Enables framedropping on MPEG2 stream.
   ##                         Framedropping occurs when your computer is
   ##                         not powerful enough. (Default: enabled)
   ##  --no-skip-frames
   ##  --drop-late-frames     This drops frames that are late (arrive to
   ##                         the video output after their intended display
   ##                         date). (Default: enabled)
   ##  --no-drop-late-frames
   ##  --video-on-top         Always place the video window on top of
   ##                         other windows. (Default: disabled)
   ##  --no-video-on-top
   ##  --disable-screensaver  Disable the screensaver during video playback.
   ##                         (Default: enabled)
   ##  --no-disable-screensaver
   ##   --video-title-show    Display the title of the video on top of the
   ##                         movie. (Default: enabled)
   ##  --no-video-title-show
   ##  --video-title-timeout <integer>   Show the video title for n milliseconds,
   ##                                    default is 5000 ms (5 sec.)
   ##  --video-title-position  Position of video title. 0 (Center),
   ##                          1 (Left), 2 (Right), 4 (Top), 8 (Bottom),
   ##                          5 (Top-Left), 6 (Top-Right), 9 (Bottom-Left),
   ##                          10 (Bottom-Right)
   ##
   ##  --width <integer>       Video width. You can enforce the video width
   ##                          By default (-1) VLC will adapt to the video
   ##                          characteristics.
   ##  --height <integer>      Video height. You can enforce the video height.
   ##                          By default (-1) VLC will adapt to the video
   ##                          characteristics.
   ##  --video-x <integer>     Video X coordinate. You can enforce the position
   ##                          of the top left corner of the video window
   ##                          (X coordinate).
   ##  --video-y <integer>     Video Y coordinate. You can enforce the position
   ##                          of the top left corner of the video window
   ##                          (Y coordinate).
   ##
   ##  --play-and-exit         Exit if there are no more items [in the playlist].
   ##                          (Default: disabled)
   ##  --no-play-and-exit
   ##  --play-and-stop         Stop [the playlist] after each played [playlist]
   ##                          item. (Default: disabled)
   ##  --no-play-and-stop
   ##  -q, --quiet             Turn off all warning and information messages.
   ##                          (Default: disabled)
   ##  --no-quiet 
   ##
   #####################################################
   ## Some 'VLC' INTERACTIVE keyboard controls while playing:
   ##
   ##  ???  TBD - from keyboard 'shortcuts' on toolbar menus.
   ## 
   ####################################################################

   if {"$RADVARdisplaypgm" == "5"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {
         ## Set 'vlc' to start in fullscreen mode.
         set VARcommand "vlc --fullscreen --quiet "
      } else {
         ## Set 'vlc' to start in 'default' (non-fullscreen) mode.
         set VARcommand "vlc --no-fullscreen --quiet "
      }
   }


   ###################################################################
   ## Some 'smplayer' COMMAND-LINE options:
   ##                     (from 'smplayer -h')
   ##
   ##  -fullscreen       The video will be played in fullscreen mode.
   ##  -no-fullscreen    The video will be played in window mode.
   ##
   ##  -close-at-end     The main window will be closed when the
   ##                    file/playlist finishes.
   ##  -no-close-at-end  The main window won't be closed when the
   ##                    file/playlist finishes.
   ##
   ##  -minigui          Opens the mini gui instead of the default one.
   ##  -mpcgui           Opens the mpc gui.
   ##  -defaultgui       Opens the default gui.
   ##  -actions          action_list is a list of actions separated by spaces.
   ##                    The actions will be executed just after loading
   ##                    the file (if any) in the same order you entered.
   ##                    For checkable actions you can pass true or false
   ##                    as parameter. Example:
   ##                       -actions "fullscreen compact true"
   ##                    Quotes are necessary in case you pass more than
   ##                    one action.
   ##
   #####################################################
   ## Some 'smplayer' INTERACTIVE keyboard controls while playing:
   ##
   ##  ???  TBD - from keyboard 'shortcuts' on toolbar menus.
   ## 
   ####################################################################

   if {"$RADVARdisplaypgm" == "6"} {
      if {"$RADVARdisplaysize" == "fullscreen"} {
         ## Set 'smplayer' to start in fullscreen mode.
         set VARcommand "smplayer -fullscreen "
      } else {
         ## Set 'smplayer' to start in 'default' (non-fullscreen) mode.
         set VARcommand "smplayer -no-fullscreen "
      }
   }

   ################################################################
   ## START OF WHILE-LOOP for the 'gets' file-READING.
   ## The while-test below is equivalent to 'while {![eof $fileIDplay]}'.
   ################################################################

   while {[eof $fileIDplay] == 0} {

      ############################################################
      ## GET the next line (up to a line feed).
      ## (We could get the line-length in the same statement.)
      ############################################################

      # set lineLen [gets $fileIDplay line]

      gets $fileIDplay line

      ## FOR TESTING:
      #  puts "line: $line"

      ###########################
      ## Get first char of line.
      ###########################

      set FIRSTchar [string index "$line" 0]

      ##############################################################
      ## If a comment line, skip this line ... i.e. read next line.
      ##############################################################

      if { "$FIRSTchar" == "#" } {continue}

      #################################################################
      ## If a directory line starting with "/" or "$",
      ## SET THE tempDIR VAR and read next line.
      #################################################################

      if { "$FIRSTchar" == "/" || "$FIRSTchar" == "$"  } {
         set tempDIR "[string trim "$line"]"
         continue
      }

      #################################################################
      ## IF A DIRECTORY LINE starting with ".",
      ## SET THE 'tempDIR' VAR and read next line.
      #################################################################

      if { "$FIRSTchar" == "."  } {
         set lengthOFline [string length "$line"]
         if {$lengthOFline > 1} {
            set restOFline [string range "$line" 1 $lengthOFline]
            set tempDIR "${thisDIR}$restOFline"
         } else {
            set tempDIR "$thisDIR"
         }
         continue
      }

      #################################################################
      ## At this point, we have eliminated 2 line types --- comment
      ## lines and directory-name lines. So this line must be a
      ## relative-filename line.
      ##
      ## If the relative-filename line is empty, return to the top
      ## of this 'while' loop to read the next media filename.
      #################################################################

      set EMPTYLINEcheck "[string trim $line]"

      if { "$EMPTYLINEcheck" == "" } {continue}

      incr Nmediafiles

      ##################################################################
      ## Set the fully-qualified name of the 'media' file and
      ## check if it exists.
      ##       We need 'eval' on the 'set' statement to convert
      ##       $env(HOME), if it is used, to a directory name.
      ##################################################################

      eval set MEDIAfilename "$tempDIR/$EMPTYLINEcheck"

      ## FOR TESTING:
      #   puts "MEDIAfilename: $MEDIAfilename"

      if {![file exists "$MEDIAfilename"]} {continue}


      ###################################################################
      ## At this point the relative-filename line appears to be OK, so we
      ## PLAY THE MEDIA FILE.
      ####################################################################
      ## SOME SYNTAX NOTES on running the player program via a Tcl 'exec':
      ####################################################################
      ## On page 105 of the 4th edition of 'Practical Programming in Tcl & Tk',
      ## is the following quote on the Tcl 'exec' command:
      ##
      ## "The 'exec' command runs programs from your Tcl script. For example:
      ##      set d [exec date]
      ## The standard output of the program is returned as the value of
      ## the 'exec' command. However, if the program writes to its standard
      ## error channel or exits with a nonzero status code, then 'exec'
      ## raises an error. If you do not care about the exit status, or you
      ## use a program that insists on writing to standard error, then you
      ## can use 'catch' to mask the errors:
      ##   catch {exec program arg arg} result"
      ##
      ## Unfortunately, running a player program in 'foreground' mode
      ## like this makes the button widgets on the GUI unavailable ---
      ## in particular, the 'Stop' button ... and the 'Help' button.
      #######################################################################
      ## On page 107 of the 4th edition of 'Practical Programming in Tcl & Tk',
      ## is the following quote on the Tcl 'exec' command and 'background' mode:
      ##
      ## "A trailing '&' causes the program to run in the background.
      ##  In this case, the process identifier is returned by the 'exec'
      ##  command. Otherwise, the 'exec' command blocks during execution
      ##  of the program, and the standard output of the program is the
      ##  return code of 'exec'."
      ##
      ## Page 83 of the same book says:
      ## "'catch' returns zero if there was no error caught,
      ##   or a nonzero error code if it did catch an error."
      ####################################################################
      ## A couple of examples of using a PID (process ID) with Tcl:
      ##
      ## catch {eval exec $feREADER_text \"$FULFILname\"  &} ViewerPID
      ##
      ## set RETcode [ catch {eval exec ${feDIR}/tkGUIs/shofil.tk \
      ##    "$FULFILname" &} ViewerPID ]
      ##
      ####################################################################
      ## An alternative form of trying 'exec':
      ##    exec  /bin/sh -c "$...."
      ####################################################################

      ## A 'foreground' run per page 105.
      ## NOT USED, because it 'locks up' the GUI.

      # catch {eval exec $VARcommand "$MEDIAgilename"} CatchMsg


      ###############################################################
      ## A 'background' run per page 105.
      ## (Better for implementing the 'Stop' feature via a button
      ##  on this GUI.)
      ## We use 'eval' to avoid a 'not found' error when we append
      ## some parms (or a space) to the player command.
      ###############################################################

      set RETcode [ catch {eval exec $VARcommand "$MEDIAfilename" &} ViewerPID ]

      if {$RETcode != 0} {
         set ERRtext \
"Proc 'play_media_files' encountered an error on trying to show file
$EMPTYLINEcheck
in directory
$tempDIR
using command '$VARcommand'.

RETcode: $RETcode
Message: $ViewerPID
Stopping processing."
         popup_msgVarWithScroll .topErr "$ERRtext"
         return
      }

      ## FOR TESTING:
      if {0} {
          puts ""
          puts "***********************"
          puts "VARcommand: $VARcommand"
          puts "tempDIR (directory)      :    $tempDIR"
          puts "EMPTYLINEcheck (filename): $EMPTYLINEcheck"
          puts "ViewerPID: $ViewerPID"
          puts "***********************"
          puts ""
      }

      ##########################################################
      ## About every 500 millisecs, use 'update' to check
      ## the GUI for any events --- esp. a click on the 'Stop'
      ## button --- or a click on the 'Help' button ---
      ## and break out of this loop if the PID no longer exists
      ## (i.e. if the user has closed the player window).
      ##
      ## After we break out of this PID-check loop, we check if the
      ## 'Stop' button has been clicked (via whether its variable
      ## STOPvar0or1 is set to 1). If not, then we go on to play
      ## the next media file, if any.
      ##########################################################
      ## Reference: web page
      ## http://stackoverflow.com/questions/16012040/how-do-i-check-for-spawn-id-thats-alive-tcl
      ## which showed sample code using the Linux/Mac 'ps' command
      ## to check if a process with process-ID $pid is still running:
      ##
      ##   if {[catch {exec ps $pid} std_out] == 0} { 
      ##      puts "Alive"
      ##   } else {
      ##      puts "It's dead, Jim"
      ##   }
      ##############################################################
 
      while {1} {
         update
         after 500
         if {[catch {exec ps $ViewerPID} CatchMsg] != 0} {break} 
      }
      ## END OF 'while {1}' LOOP

      ############################################################
      ## CHECK TO SEE IF THE DISPLAY SEQUENCE SHOULD STOP.  I.e.,
      ## break out of the media-file-reading 'while' loop,
      ## if STOPvar0or1 is set to 1.
      ############################################################

      if { $STOPvar0or1 == 1 } {break}

   }
   ## END OF  'while {[eof $fileIDplay] == 0}' LOOP

   #######################################################
   ## Close the playlist file when the while loop is done.
   #######################################################

   catch {close $fileIDplay}

   #########################################################
   ## In case the 'stop' button was used,
   ## reset the 'stop' button message, to indicate the 'stop'
   ## button is ready to handle another display sequence.
   ########################################################

   set STOPvar0or1 0
   .fRbuttons.buttSTOP configure -text "$aRtext(buttonSTOP1)"

   ###############################################################
   ## DISPLAY THE COUNT OF MEDIA-FILES-PLAYED in a small popup Tk window.
   ##   (If the user finds this annoying, this could be
   ##    deactivated by setting 1 to 0 in the 'if' statement.
   ##    Or we could show this only if Nmediafiles were greater than
   ##    25, say. That is, replace '1' by  '$Nmediafiles > 25'.)
   ###############################################################

   if {1} {
      popup_msgVarWithScroll .topCount \
         "$Nmediafiles media files were shown --- from the playlist file ---
[get_chars_after_last "/" in "$ENTRYfilename"]
in directory
[get_chars_before_last "/" in "$ENTRYfilename"]"
   }
   ## END OF 'if {1}'

}
## END OF proc 'play_media_files'


##+########################################################################
## PROC 'popup_msgVarWithScroll'
##+########################################################################
## PURPOSE: Report help or error conditions to the user.
##
##       We do not use focus,grab,tkwait in this proc,
##       because we use it to show help when the GUI is idle,
##       and we may want the user to be able to keep the Help
##       window open while doing some other things with the GUI
##       such as putting a filename in the filename entry field
##       or clicking on a radiobutton.
##
##       For a similar proc with focus-grab-tkwait added,
##       see the proc 'popup_msgVarWithScroll_wait' in a
##       3DterrainGeneratorExaminer Tk script.
##
## REFERENCE: page 602 of 'Practical Programming in Tcl and Tk',
##            4th edition, by Welch, Jones, Hobbs.
##
## ARGUMENTS: A toplevel frame name (such as .fRhelp or .fRerrmsg)
##            and a variable holding text (many lines, if needed).
##
## CALLED BY: 'help' button
##+########################################################################
## To have more control over the formatting of the message (esp.
## words per line), we use this 'toplevel-text' method, 
## rather than the 'tk_dialog' method -- like on page 574 of the book 
## by Hattie Schroeder & Mike Doyel,'Interactive Web Applications
## with Tcl/Tk', Appendix A "ED, the Tcl Code Editor".
##+########################################################################

proc popup_msgVarWithScroll { toplevName VARtext } {

   ## global fontTEMP_varwidth #; Not needed. 'wish' makes this global.
   ## global env

   # bell
   # bell
  
   #################################################
   ## Set VARwidth & VARheight from $VARtext.
   #################################################
   ## To get VARheight,
   ##    split at '\n' (newlines) and count 'lines'.
   #################################################
 
   set VARlist [ split $VARtext "\n" ]

   ## For testing:
   #  puts "VARlist: $VARlist"

   set VARheight [ llength $VARlist ]

   ## For testing:
   #  puts "VARheight: $VARheight"


   #################################################
   ## To get VARwidth,
   ##    loop through the 'lines' getting length
   ##     of each; save max.
   #################################################

   set VARwidth 0

   #############################################
   ## LOOK AT EACH LINE IN THE LIST.
   #############################################
   foreach line $VARlist {

      #############################################
      ## Get the length of the line.
      #############################################
      set LINEwidth [ string length $line ]

      if { $LINEwidth > $VARwidth } {
         set VARwidth $LINEwidth 
      }

   }
   ## END OF foreach line $VARlist

   ## For testing:
   #    puts "VARwidth: $VARwidth"


   ###############################################################
   ## NOTE: VARwidth works for a fixed-width font used for the
   ##       text widget ... BUT the programmer may need to be
   ##       careful that the contents of VARtext are all
   ##       countable characters by the 'string length' command.
   ###############################################################


   #####################################
   ## SETUP 'TOP LEVEL' HELP WINDOW.
   #####################################

   catch {destroy $toplevName}
   toplevel  $toplevName

   # wm geometry $toplevName 600x400+100+50

   wm geometry $toplevName +100+50

   wm title     $toplevName "Note"
   # wm title   $toplevName "Note to $env(USER)"

   wm iconname  $toplevName "Note"


   #####################################
   ## In the frame '$toplevName' -
   ## DEFINE THE TEXT WIDGET and
   ## its two scrollbars --- and
   ## DEFINE an OK BUTTON widget.
   #####################################

   if {$VARheight > 10 || $VARwidth > 100} {
      text $toplevName.text \
         -wrap none \
         -font fontTEMP_fixedwidth \
         -width  $VARwidth \
         -height $VARheight \
         -bg "#f0f0f0" \
         -relief raised \
         -bd 2 \
         -yscrollcommand "$toplevName.scrolly set" \
         -xscrollcommand "$toplevName.scrollx set"

      scrollbar $toplevName.scrolly \
         -orient vertical \
         -command "$toplevName.text yview"

      scrollbar $toplevName.scrollx \
         -orient horizontal \
         -command "$toplevName.text xview"
   } else {
      text $toplevName.text \
         -wrap none \
         -font fontTEMP_fixedwidth \
         -width  $VARwidth \
         -height $VARheight \
         -bg "#f0f0f0" \
         -relief raised \
         -bd 2 
   }

   button $toplevName.butt \
      -text "OK" \
      -font fontTEMP_varwidth \
      -command  "destroy $toplevName"

   ###############################################
   ## PACK *ALL* the widgets in frame '$toplevName'.
   ###############################################

   ## Pack the bottom button BEFORE the
   ## bottom x-scrollbar widget,

   pack  $toplevName.butt \
      -side bottom \
      -anchor center \
      -fill none \
      -expand 0


   if {$VARheight > 10 || $VARwidth > 100} {
      ## Pack the scrollbars BEFORE the text widget,
      ## so that the text does not monopolize the space.

      pack $toplevName.scrolly \
         -side right \
         -anchor center \
         -fill y \
         -expand 0

      ## DO NOT USE '-expand 1' HERE on the Y-scrollbar.
      ## THAT ALLOWS Y-SCROLLBAR TO EXPAND AND PUTS
      ## BLANK SPACE BETWEEN Y-SCROLLBAR & THE TEXT AREA.
                
      pack $toplevName.scrollx \
         -side bottom \
         -anchor center \
         -fill x  \
         -expand 0

      ## DO NOT USE '-expand 1' HERE on the X-scrollbar.
      ## THAT KEEPS THE TEXT AREA FROM EXPANDING.

      pack $toplevName.text \
         -side top \
         -anchor center \
         -fill both \
         -expand 1
   } else {
      pack $toplevName.text \
         -side top \
         -anchor center \
         -fill both \
         -expand 1
   }


   #####################################
   ## LOAD MSG INTO TEXT WIDGET.
   #####################################

   ##  $toplevName.text delete 1.0 end
 
   $toplevName.text insert end $VARtext
   
   $toplevName.text configure -state disabled
  
}
## END OF PROC 'popup_msgVarWithScroll'


##+########################
## END of PROC definitions.
##+########################
## Set HELPtext var.
##+########################


set HELPtext "\
\ \ ** HELP for this utility to 'Play Media Files in a Playlist File' **

    ** essentially a 'front end' for multiple media player programs **

This utility provides a GUI for selecting a 'playlist' of media files.
The media (movie and/or audio) files may be scattered throughout
various directories --- such as sub-directories that store the
files for a web site --- OR sub-directories of a home directory ---
OR sub-directories on multiple disk drives mounted on a computer ---
OR sub-directories on a removable storage device mounted on a computer.

Besides selecting the playlist file, this utility allows
the user to select a media-player program from among
multiple choices --- and allows the user to select a
'fullscreen'-size or 'default'-size display mode.

Then the user can click on a 'Launch' button to start playing the
media files, in the order of the filenames within the playlist file.

This utility also provides for 'interrupting' the display of
the sequence of media files --- via a 'Stop' button on the GUI.
This is handy in the cases where the playlist file contains
the names of MANY media files.

Some examples of the media-player program:
     - mplayer
     - ffplay
     - totem
     - gnome-mplayer
     - gmplayer
     - VLC
     - smplayer

The player program is chosen via radiobutton widgets on the GUI.

The code for the Tk script that constitutes this utility can be
esaily changed to allow for additional or other media players.

The GUI is intended to make the user aware of the main
(most useful) options available without the user needing
to reference the 'man mplayer'/'man ffplay'/'man totem'/... commands
and other 'mplayer'/'ffplay'/'totem'/... documentation, for example,
via web searches.

The intent of this utility is to allow the user to easily
specify files to be played ... by building a simple 'playlist'.

The playlist file contains three types of lines:

  1 - Comment lines may be indicated in the file by a # sign
      in column 1.

  2 - Lines that contain a fully-qualified directory name
      or a 'dot' directory name.
      Examples:  /data/movies/tennis2013  or
                 \$env(HOME)/tennis2013   or
                 /home/fred/tennis2013    or
                 .                        or
                 ./USopen
      These lines must start with either slash (/) or $ or dot(.).

      The dot can be used to represent the directory in which
      the playlist file lies. This useful when putting the playlist
      file in a directory of media files and using the dot to
      represent the directory of the media files. The directory of
      media files may have sub-directories of media files, as indicated
      by the last example.  The dot allows for moving/copying the
      media files (with the playlist file) to different directories
      without having to change the internals of the playlist file.

  3 - Lines that contain a relative filename (relative to the
      previous directory name)
      Example: Federer_vs_Nadal_2013.mp4

      These lines SHOULD NOT start with either slash(/) or $ or dot(.)
      or # --- although # could be used to comment out a filename.


The first non-comment line of the playlist file should be a
directory name.

There can be more than one directory name in the file.

Each directory-name-line is followed by names of media files
that are in the specified directory.


***************************
HOW TO CHANGE MEDIA PLAYERS:
***************************

A different media player program could be used in place of any of the
current media-players by some simple label-text changes in the Tk script
--- 'playMediaFilesInPlaylist_FrontEnd.tk' --- and, additionally, a few
coding changes in the proc 'play_media_files' of that Tk script.


***************
THE GUI WIDGETS:
***************

The GUI consists of about

  -  3 label widgets
  -  7 button widgets
  -  1 entry widget
  -  7 radiobutton widgets in 2 groups
  -  0 checkbutton widgets
  -  0 scale widgets
  -  0 listbox widgets

The button, entry, and radiobutton widgets are the control widgets
of the GUI --- so there are bout 15 control options.


*************
TYPICAL USAGE:
*************

You can use the 'Browse...' button to retrieve a full filename
to the filename entry field.

Before clicking on the 'LaunchPlayerJob' button,
you can also change *radiobutton* settings as needed --- for

- a player program

and

- display size ('fullscreen' or the 'default' size used by the player).

*NOTE*:
Closing the player window causes the next media file to be played.

In the future, additional options may be added to the GUI, via adding
a few widgets, to allow for

   - user specification of the location of the upper-left-corner of
     the player-window on the 'desktop'

   - 'stepping back' to previously played media files (There are many
      ways that this could be implemented --- some using much
      more computer memory than others --- an array for ALL of the
      media filenames or an array for no more than 10 filenames, say.)


***************************************************************
FILE-TYPE CONSIDERATIONS:
***************************************************************

Note that this utility will play whatever media file types
are supported by the media player that is chosen.

Most of these media players, listed above, support most of the
common types of movie files. However, in some cases, they may
fail to play a media file --- especially if a needed 'decoder'
library is not available on the user's computer.

In case of failures, it will probably be good to know a little
about the 'nature' of movie and audio files.

Basically, a movie file involves THREE different formats:
   - the container format
   - the format for the video stream(s)
   - the format for the audio stream(s).


***********************
Movie Container Formats
***********************

The Linux/Unix 'file' command, when applied to a movie file,
typically reports on the 'container' format of the movie file.

Example output from the 'file' command:

Typical movie suffix    'find' output
--------------------    -----------------------------------------

mp4                     ISO Media, MPEG v4 system, version 1
mpg or mpeg             MPEG sequence, v1, system multiplex
flv                     Macromedia Flash Video
mov                     ISO Media, Apple QuickTime movie
wmv                     Microsoft ASF
avi (with DivX video)   RIFF (little-endian) data, AVI, 640 x 480, 30.00 fps,
                           video: DivX 3 Fast-Motion
avi (with Xvid video)   RIFF (little-endian) data, AVI, 640 x 480, 30.00 fps,
                           video: XviD
avi (w. Cinepak video)  RIFF (little-endian) data, AVI, 160 x 120, 10.00 fps,
                           video: Cinepak, audio: uncompressed PCM (mono, 8000 Hz)

  MPEG = Motion Picture Experts Group
  ASF = Advanced Systems Format
  RIFF = Resource Interchange File Format
  AVI = Audio Video Interleave

The 'mp4' and 'flv' container formats are commonly used in recent times
(2010-2014).

The 'mpg/mpeg', 'mov', 'wmv', and 'avi' container formats are formats that
are getting rather 'long in the tooth'.


******************
Audio-only Formats
******************

'file' returns text strings like the following on AUDIO files:

Typical
suffix  'find' output
------- -----------------------------------------

mp3     MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
wav     RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, mono 22050 Hz

  ADTS = Audio Data Transport Stream

These are audio 'encoding' formats --- not 'container' formats.

Note that 'layer III' indicates the popular 'mp3' audio file format.


********************************************
Video-and-Audio Formats in Container Formats
********************************************

Some of the popular video-and-audio 'encodings' seen in various movie
'container' files --- via applying the 'ffmpeg -i' command to the movie file
or using the File Properties option of the Gnome2-Nautilus file manager:

Container format    Video-Audio encodings typically found in the container format
----------------   -------------------------------------------------------------

mp4                 h264-aac
flv (a.k.a. Flash)  vp6f-mp3 , flv(Sorensen)-mp3, h264-aac , flv(Sorensen)-adpcm_swf
mpg or mpeg         mpeg1video-mp2 , mpeg4-mp3
mov                 mpeg4-aac , cinepak-adpcm_ima_qt , svq3(Sorensen)-mp3, svq3-qdm2 , h263-qcelp
wmv (a.k.a. asf)    wmv3-wmav2 , wmv2-wmav2 ,  wmv1-wmav2 , msmpeg4-wmav2
avi                 mpeg4-pcm_s16le , msmpeg4-none , cinepak-pcm_u8

Note that there are a 'mess' of video-audio combinations out there.


*********************************************************************
THE MEDIA-PLAYERS INFO:
*********************************************************************

*************************************************
FEATURES & IDIOSYNCRACIES OF THE 'mplayer' PLAYER:
*************************************************

The 'man' page for the 'mplayer' command is more than 8,000 lines
long (100-plus pages). There are a confusing number of
command-line options for 'mplayer'. The '-fs' (fullscreen) option
is the main one that we have implemented in this Tk script utility.

Here are some of the keyboard controls that you can use
when the 'mplayer' display window comes up:

  q or ESC         Stop playing and quit.
  f                Toggle fullscreen.
  p or SPACE       Pause (pressing again unpauses).
  <- and ->        Seek backward/forward 10 seconds.
  up and down      Seek forward/backward 1 minute.
  pgup and pgdown  Seek forward/backward 10 minutes.
  .                Step  forward.  Pressing once will pause movie,
                   every consecutive press will play one frame and
                   then go into pause mode again (any other key unpauses).
  \[ and \]        Decrease/increase current playback speed by 10%.
  \{ and \}        Halve/double current playback speed.
  backspace        Reset playback speed to normal.
  + and -          Adjust audio delay by +/- 0.1 seconds.
  / and *          Decrease/increase volume.
  9 and 0          Decrease/increase volume.
  ( and )          Adjust audio balance in favor of left/right channel.
  m                Mute sound.
  I                Show filename on the OSD.

You can consult the 'man mplayer' info for more information
on controlling 'mplayer' as a media file is played.


************************************************
FEATURES & IDIOSYNCRACIES OF THE 'ffplay' PLAYER:
************************************************

Although the 'ffplay' command (which is usually packaged with
the 'ffmpeg' command) does not have nearly as many parameter
options as the 'mplayer' command, the 'ffplay' command may be
handy to try if 'mplayer' fails to play a media file.

'ffplay' does not have any control options in a GUI.
But there a few keyboard controls:

   q or ESC       Quit.
   f              Toggle full screen.
   p or SPC       Pause.
   left/right     Seek backward/forward 10 seconds.
   down/up        Seek backward/forward 1 minute.
   mouse click    Seek to percentage in file corresponding to fraction of width.
   w              Show audio waves.
   a              Cycle audio channel
   v              Cycle video channel
   t              Cycle subtitle channel
 
'ffplay' automatically expands each media file image to fit in the
'ffplay' window when it is 'fullscreen'. However, for media files
with small image size, the scale-up may result in crude-looking
images (frames).


***********************************************
FEATURES & IDIOSYNCRACIES OF THE 'totem' PLAYER:
***********************************************

'totem' has a pretty elaborate GUI for controlling the
display of a media file.

In addition, it has a rather plentiful set of keyboard
control options, including:

  q                    Quit.
  Esc                  Exit full screen mode.
  f                    Toggle full screen.
  p                    Toggle between play and pause.
  h                    Toggle display of on-screen controls.
  0                    Resize window to 50% original size.
  1                    Resize window to 100% original size.
  2                    Resize window to 200% original size.
  r                    Zoom in the video.
  t                    Zoom out the video.
  Left-arrow           Skip back 15 seconds
  Right-arrow          Skip forward 60 seconds
  Shift+Left-arrow     Skip back 5 seconds
  Shift+Right-arrow    Skip forward 15 seconds
  Ctrl+Left-arrow      Skip back 3 minutes
  Ctrl+Right arrow     Skip forward 10 minutes
  Up-arrow             Increase volume by 8%
  Down-arrow           Decrease volume by 8%


*******************************************************
FEATURES & IDIOSYNCRACIES OF THE 'gnome-mplayer' PLAYER:
*******************************************************

The 'gnome-mplayer' program seems to have some bugs (that are
confirmed by searches on the internet). The '--fullscreen' parameter
does not seem to work --- nor the '--width' and --'height'
parameters. This made it impossible to offer a fullscreen mode
(at least for the version of 'gnome-mplayer' on the test computer
--- version 0.8.8, 2008, lead developer: Kevin DeKorte).

So instead of offering 'gnome-mplayer' on this GUI, I have
offered the 'gmplayer' program (which was delivered with
the  version of 'mplayer' on the test computer ---
version 4.4.1, 2009).

**************************************************
FEATURES & IDIOSYNCRACIES OF THE 'gmplayer' PLAYER:
**************************************************

'gmplayer' offers a small subset of the 'mplayer' command line
options as comand line options for 'gmplayer'. The '-fs'
(fullscreen) option is the main one that we have implemented
in this Tk script utility.

The 'gmplayer' program offers a small, minimal GUI ---
with buttons to control things like
   - pause/play
   - return-to-start
   - advance/retreat
and two slider bars to
   - set audio volume
   - indicate time range and display current play position.

As an alternative (and augmentation) of those controls, 'gmplayer'
has the following keyboard control options:

  q or ESC         stop playing and quit program
  p or SPACE       pause movie (press any key to continue)
  <-  or  ->       seek backward/forward 10 seconds
  down or up       seek backward/forward  1 minute
  pgdown or pgup   seek backward/forward 10 minutes
  + or -           adjust audio delay by +/- 0.1 second
  * or /           increase or decrease PCM (audio) volume
  x or z           adjust subtitle delay by +/- 0.1 second
  r or t           adjust subtitle position up/down, also see -vf expand
  o                cycle OSD mode:  none / seekbar / seekbar + timer
                   (OSD = OnScreenDisplay info)


*********************************************
FEATURES & IDIOSYNCRACIES OF THE 'VLC' PLAYER:
*********************************************

The 'man' page for the 'vlc' command is more than 4,500 lines
long (50-plus pages). There are a confusing number of
command-line options for 'vlc'. The 'fullscreen' option
is the main one that we have implemented with this utility.

'vlc' has a rather elaborate GUI. You can determine most of
its keyboard shortcuts from the items on the toolbar drop-down menus.


**************************************************
FEATURES & IDIOSYNCRACIES OF THE 'smplayer' PLAYER:
**************************************************

'smplayer' has a rather simple GUI --- like 'gmplayer'.
You can determine most of its keyboard shortcuts from the
items on the toolbar drop-down menus.

The GUI of 'smplayer' has a little different 'look' versus the
GUI of 'gmplayer' --- because 'smplayer' was programmed
using the Qt library to build the GUI, while the Gtk
library was used to build the 'gmplayer' GUI.


***********************************************
SETTING UP THIS UTILITY FOR EASY ICON-CLICK USE:
***********************************************

The set of files for this utility (a single Tk script)
could be put in a sub-directory of the user's home
directory, such as \$HOME/apps/tkPlayMediaFilesInPlaylist.

Then the user can use their desktop system (such as
Gnome or KDE) to set up the Tk script as an icon on the
desktop (or in a desktop 'panel').

Then, whenever the user wants to start the
'play-media-files-in-a-playlist' GUI, the user can
click on the desktop icon to startup the Tk script.


*****************
STARTUP DIRECTORY:
*****************

If you want the playlist filename to start at a
different directory, in the Tk script, you can look for
the line
    
    set curDIR \"\$env(HOME)\"

and change it according to nearby examples.
"


##+######################################################
## ADDITIONAL GUI INITIALIZATION section.
##+######################################################

##+###########################################
## Disable/enable widgets according to initial
## GUI settings. (NOT IMPLMENTED, yet)
##+##########################################

# disable_enable_widgets


INSTALLING THE SCRIPT:

I used two auxiliary shell scripts, in addition to a Tk script, to implement the 'batch-find-and-imageView' and 'batch-find-and-mediaPlay' utilities. So those two utilities involved the installation of THREE scripts.

However, for this 'playlist' utility, a SINGLE Tk script can be put in a sub-directory of the user's home directory, such as $HOME/apps/tkPlayMediaInPlaylist.

Then the user can use their desktop system (such as Gnome or KDE) to set up the Tk script as an icon on the desktop. Then the user can click on the icon to startup the 'front end'.

In fact, here is an image of the 4 icons that I set up on an Ubuntu 9.10 Gnome 2.28 desktop for the 4 utilities published at

* tkImageViewer - for Mask-Selecting Images from a Directory Hierarchy

* tkMediaPlayer - to Batch-Select-and-Play Movie & Audio files in a Directory Hierarchy

* tkShowImageFilesInPlaylist - a front-end for multiple image viewers

and

* this page

iconsFour_2ImgViewer_2MediaPlay_screenshot_316x135.jpg


SOME POSSIBLE ENHANCEMENTS

This Tk script adds another 'Front End' utility at the bottom of my 'bio' page at uniquename --- in the 'CFE' (Code for Front Ends) group.

I plan to work on other 'front ends' --- for commands with many command-line optons --- such as 'mplayer', 'xrandr', 'ffmpeg', 'find-and-copy', and several other commands (or combinations of commands).

But I may return to this 'play-media-files-in-a-playlist' Tk script to provide some enhancements.

Additional options may be added to the GUI, via adding a few widgets, to allow for

   - auto-media-play-advance (with a small or zero wait-time before
     starting to play the next media file)

   - user specification of the location of the upper-left-corner of
     the player-window on the 'desktop'

   - 'stepping back' to previously shown media files (There are many
      ways that this could be implemented --- some using much
      more computer memory than others --- for ALL the media filenames
      or just 10 of the filenames, say.)

---

FILE FORMATS for MOVIES and AUDIO

As I promised above, here is an overview of movie and audio file formats.

Note that this 'play-media-files-of-a-playlist' utility will play whatever media file types are supported by the media player that is chosen.

Most of these media players, listed above, support most of the common types of movie files. However, in some cases, they may fail to play a media file --- especially if a needed 'decoder' library is not available on the user's computer.

In case of failures, it will probably be good to know a little about the 'nature' of movie and audio files.

Basically, a movie file involves THREE different formats:

   - the container format
   - the format for the video stream(s)
   - the format for the audio stream(s).

---

Movie Container Formats

The Linux/Unix 'file' command, when applied to a movie file, typically reports on the 'container' format of the movie file.

Example output from the 'file' command:

  Typical movie suffix    'find' output
  --------------------    -----------------------------------------

  mp4                     ISO Media, MPEG v4 system, version 1
  mpg or mpeg             MPEG sequence, v1, system multiplex
  flv                     Macromedia Flash Video
  mov                     ISO Media, Apple QuickTime movie
  wmv                     Microsoft ASF
  avi (with DivX video)   RIFF (little-endian) data, AVI, 640 x 480, 30.00 fps,
                             video: DivX 3 Fast-Motion
  avi (with Xvid video)   RIFF (little-endian) data, AVI, 640 x 480, 30.00 fps,
                             video: XviD
  avi (w. Cinepak video)  RIFF (little-endian) data, AVI, 160 x 120, 10.00 fps,
                             video: Cinepak, audio: uncompressed PCM (mono, 8000 Hz)

  MPEG = Motion Picture Experts Group
  ASF = Advanced Systems Format
  RIFF = Resource Interchange File Format
  AVI = Audio Video Interleave

The 'mp4' and 'flv' container formats are commonly used in recent times (2010-2014).

The 'mpg/mpeg', 'mov', 'wmv', and 'avi' container formats are formats that are getting rather 'long in the tooth'.

---

Audio-only Formats

'file' returns text strings like the following on AUDIO files:

  Typical
  suffix  'find' output
  ------- -----------------------------------------

  mp3     MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, Stereo
  wav     RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, mono 22050 Hz

  ADTS = Audio Data Transport Stream

These are audio 'encoding' formats --- not 'container' formats.

Note that 'layer III' indicates the popular 'mp3' audio file format.

---

Video-and-Audio Formats in Container Formats

Some of the popular video-and-audio 'encodings' seen in various movie 'container' files --- via applying the 'ffmpeg -i' command to the movie file or using the File Properties option of the Gnome2-Nautilus file manager:

  Container format    Video-Audio encodings typically found in the container format
  ----------------   -------------------------------------------------------------

  mp4                 h264-aac
  flv (a.k.a. Flash)  vp6f-mp3 , flv(Sorensen)-mp3, h264-aac , flv(Sorensen)-adpcm_swf
  mpg or mpeg         mpeg1video-mp2 , mpeg4-mp3
  mov                 mpeg4-aac , cinepak-adpcm_ima_qt , svq3(Sorensen)-mp3, svq3-qdm2 , h263-qcelp
  wmv (a.k.a. asf)    wmv3-wmav2 , wmv2-wmav2 ,  wmv1-wmav2 , msmpeg4-wmav2
  avi                 mpeg4-pcm_s16le , msmpeg4-none , cinepak-pcm_u8

Note that there are a 'mess' of video-audio combinations out there.


INFO on the MEDIA-PLAYERS

---

FEATURES & IDIOSYNCRACIES OF THE 'mplayer' PLAYER:

The 'man' page for the 'mplayer' command is more than 8,000 lines long (100-plus pages). There are a confusing number of command-line options for 'mplayer'. The '-fs' (fullscreen) option is the main one that we have implemented in this Tk script utility.

Here are some of the keyboard controls that you can use when the 'mplayer' display window comes up:

  q or ESC         Stop playing and quit.
  f                Toggle fullscreen.
  p or SPACE       Pause (pressing again unpauses).
  <- and ->        Seek backward/forward 10 seconds.
  up and down      Seek forward/backward 1 minute.
  pgup and pgdown  Seek forward/backward 10 minutes.
  .                Step  forward.  Pressing once will pause movie,
                   every consecutive press will play one frame and
                   then go into pause mode again (any other key unpauses).
  [ and ]          Decrease/increase current playback speed by 10%.
  { and }          Halve/double current playback speed.
  backspace        Reset playback speed to normal.
  + and -          Adjust audio delay by +/- 0.1 seconds.
  / and *          Decrease/increase volume.
  9 and 0          Decrease/increase volume.
  ( and )          Adjust audio balance in favor of left/right channel.
  m                Mute sound.
  I                Show filename on the OSD (OnScreen Display).

You can consult the 'man mplayer' info for more information on controlling 'mplayer' as a media file is played.

---

FEATURES & IDIOSYNCRACIES OF THE 'ffplay' PLAYER:

Although the 'ffplay' command (which is usually packaged with the 'ffmpeg' command) does not have nearly as many parameter options as the 'mplayer' command, the 'ffplay' command may be handy to try if 'mplayer' fails to play a media file.

'ffplay' does not have any control options in a GUI. But there a few keyboard controls:

   q or ESC       Quit.
   f              Toggle full screen.
   p or SPC       Pause.
   left/right     Seek backward/forward 10 seconds.
   down/up        Seek backward/forward 1 minute.
   mouse click    Seek to percentage in file corresponding to fraction of width.
   w              Show audio waves.
   a              Cycle audio channel
   v              Cycle video channel
   t              Cycle subtitle channel

'ffplay' automatically expands each media file image to fit in the 'ffplay' window when it is 'fullscreen'. This can be convenient, however, for media files with small image size, the scale-up may result in crude-looking images (frames).

---

FEATURES & IDIOSYNCRACIES OF THE 'totem' PLAYER:

'totem' has a pretty elaborate GUI for controlling the display of a media file.

In addition, it has a rather plentiful set of keyboard control options, including:

  q                    Quit.
  Esc                  Exit full screen mode.
  f                    Toggle full screen.
  p                    Toggle between play and pause.
  h                    Toggle display of on-screen controls.
  0                    Resize window to 50% original size.
  1                    Resize window to 100% original size.
  2                    Resize window to 200% original size.
  r                    Zoom in the video.
  t                    Zoom out the video.
  Left-arrow           Skip back 15 seconds
  Right-arrow          Skip forward 60 seconds
  Shift+Left-arrow     Skip back 5 seconds
  Shift+Right-arrow    Skip forward 15 seconds
  Ctrl+Left-arrow      Skip back 3 minutes
  Ctrl+Right arrow     Skip forward 10 minutes
  Up-arrow             Increase volume by 8%
  Down-arrow           Decrease volume by 8%

---

FEATURES & IDIOSYNCRACIES OF THE 'gnome-mplayer' PLAYER:

The 'gnome-mplayer' program seems to have some bugs (that are confirmed by searches on the internet). The '--fullscreen' parameter does not seem to work --- nor the '--width' and --'height' parameters. This made it impossible to offer a fullscreen mode (at least for the version of 'gnome-mplayer' on the test computer --- version 0.8.8, 2008, lead developer: Kevin DeKorte).

So instead of offering 'gnome-mplayer' on this GUI, I have offered the 'gmplayer' program (which was delivered with the version of 'mplayer' on the test computer --- version 4.4.1, 2009).

FEATURES & IDIOSYNCRACIES OF THE 'gmplayer' PLAYER:

'gmplayer' offers a small subset of the 'mplayer' command line options as comand line options for 'gmplayer'. The '-fs' (fullscreen) option is the main one that we have implemented in this Tk script utility.

The 'gmplayer' program offers a small, minimal GUI --- with buttons to control things like

   - pause/play
   - return-to-start
   - advance/retreat

and two slider bars to

   - set audio volume
   - indicate time range (and display current play position).

As an alternative to (and augmentation of) those GUI controls, 'gmplayer' has the following keyboard control options:

  q or ESC         stop playing and quit program
  p or SPACE       pause movie (press any key to continue)
  <-  or  ->       seek backward/forward 10 seconds
  down or up       seek backward/forward  1 minute
  pgdown or pgup   seek backward/forward 10 minutes
  + or -           adjust audio delay by +/- 0.1 second
  * or /           increase or decrease PCM (audio) volume
  x or z           adjust subtitle delay by +/- 0.1 second
  r or t           adjust subtitle position up/down, also see -vf expand
  o                cycle OSD mode:  none / seekbar / seekbar + timer
                   (OSD = OnScreenDisplay info)

---

FEATURES & IDIOSYNCRACIES OF THE 'VLC' PLAYER:

The 'man' page for the 'vlc' command is more than 4,500 lines long (50-plus pages). There are a confusing number of command-line options for 'vlc'. The 'fullscreen' option is the main one that we have implemented with this utility.

'vlc' has a rather elaborate GUI. You can determine most of its keyboard shortcuts from the items on the toolbar drop-down menus.

---

FEATURES & IDIOSYNCRACIES OF THE 'smplayer' PLAYER:

'smplayer' has a rather simple GUI --- like 'gmplayer'. You can determine most of its keyboard shortcuts from the items on the toolbar drop-down menus.

The GUI of 'smplayer' has a little different 'look' versus the GUI of 'gmplayer' --- because 'smplayer' was programmed using the Qt library to build the GUI, while the Gtk library was used to build the 'gmplayer' GUI.


IN CONCLUSION

As I have said on several other code-donation pages on this wiki ...

There's a lot to like about a utility that is 'free freedom' --- that is, no-cost and open-source so that you can modify/enhance/fix it without having to wait for someone else to do it for you (which may be never).

A BIG THANK YOU to Ousterhout for starting Tcl-Tk, and a BIG THANK YOU to the Tcl-Tk developers and maintainers who have kept the simply MAH-velous 'wish' interpreter going.


uniquename UPDATE 2014apr22

In using this utility, I found a few changes were advisable:

1) Added a 'file exists' check to proc 'play_media_files' --- to handle cases when there may be non-existent filenames or filenames with syntax errors in the playlist file.

2) Added a 'RETcode' (return code) check to proc 'play_media_files' --- to handle cases where the player program cannot handle a specified media file.

3) Added the capability to use a dot (.) at the start of any directory name in the playlist file --- to represent the directory in which the playlist file lies. This useful when putting the playlist file in a directory of media files and we want to use the dot to represent the directory of the media files. The dot allows for moving/copying the media files (with the playlist file) to different directories without having to change the internals of the playlist file.

4) Changed <KeyPress> to <KeyRelease> in a binding on the playlist filename entry field.

The code above has been replaced with the updated code.


uniquename UPDATE 2014may28

In using this utility some more since I posted it here a few months ago, I found a couple of more changes were advisable. Namely:

I added 'eval' to a 'set' statement in the proc 'show_media_filenames', and I moved an 'eval' command to a 'set' statement in the proc 'play_media_files'. This was to properly implement the intended feature of allowing the use of environment variables in directory names of the playlist file. Example: $env(HOME)

The code above has been replaced with the updated code.