FE 'tkGooie' Utilities

'IMAGEtools' group

A Tk GUI to
Find-and-Play
a batch of
Animated-GIF files

(a 'front-end' for the 'find' command and
a user-selected animated-GIF viewer program)
(FE = Freedom Environment)

FE Home Page > FE Downloads Page >

FE 'tkGooies' Description Page >

FE 'tkGooies' 'IMAGEtools' MENU Page >

This
'Batch Find-and-Play Animated GIF files'
tkGooie Page

INTRODUCTION to Tcl-Tk script
'tkBatchFindAndPlay_AniGifs'

In the past six months (in Dec 2013 - March 2014), I contributed code to 'batch-find-and-play' and to 'play-from-a-playlist' either

  • image files (JPEG, PNG, GIF, etc.)

or

  • media files (movie or audio files)

on pages at the Tclers' Wiki (wiki.tcl.tk) web site.

The code for these utilities can be found, on this site, at pages with titles like:

A couple of months ago (2014 March), I contributed code to 'play-from-a-playlist' --- animated GIF files --- whose code is at a page on this site with a title like:

I had skipped providing a 'batch-find-and-play' utility for animated GIF files.

That is the subject of this page.


COMPARISON of this utility
(to the 'batch-find-and-play' utilities
mentioned above)

Like the 'batch-find-and-show/play' utilities for image files (JPEG, PNG, GIF, etc.) and for media files (video and audio), I wanted to provide a Tk GUI 'front end' to a combination of the 'find' command and a user-selectable animated-GIF 'player' command/program.

In this case, the GUI was designed to offer the user a choice from two animated-GIF-file 'player' programs:

  • ImageMagick 'animate'

    and

  • the 'gifview' program that usually comes packaged with the 'gifsicle' utility that can be used to make animated GIF files.

---

Like the 'batch-find-and-play' utilities for image files and for media files, this 'batch-find-and-play' utility for animated-GIF files has been implemented as a Tk script and 2 shell scripts.

As such, it should be implementable with very few changes in various Linux, BSD, Mac, and other Unix-like operating system environments.


The GUI LAYOUT

Like for the 'find-and-image-viewer' and 'find-and-media-player' utilities, I made a 'text-sketch' for the GUI for the 'find-and-aniGIF-player' utility:



 ---------------------------------------------------------------------------
 'find'-and-Animated-GIF-Viewers  Front End -  to find-and-view Animated GIFs
 [window title]
 ---------------------------------------------------------------------------------------
 
 {Exit} {Help} {LaunchPlayerJob} {Next N} {Stop (no more files)}    {CountAniGIFs} {ShowAniGIFfilenames}
 
 Full Filename Mask (for ani-GIFs): _______________________________________  {Browse...}
 
 Player Program:   O 1 - ImageMagick 'animate'   O 2 - Gifsicle 'gifview' 
 
 LayoutOnScreen: O 1x1(1)   O 2x1(2)  O 3x1(3)  O 2x2(4)  O 3x2(6)  O 3x3(9)  O 4x3(12)
 
 Search Levels for Mask:  O ONE  O ALL subdirectories of selected dir
 
 Case Sense for Mask Search:  O case-sensitive  O case-INsensitive
 
 Files Size (KiloBytes):  _____  O bigger-than  O smaller-than
 
 Files Age (Days) : ______ O older-than  O younger-than

 File Type: ___________   Example: 'GIF' or 'GIF image data' or 'version 89a'
 ----------------------------------------------------------------------------------------


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).


NOTE that only at the 'Player Program:' and 'LayoutOnScreen:' prompts are there parameters involving the aniGIF-player.

The other parameters (the majority of the parameters) are for the 'find' command.

---

GUI Components

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

  • 8 button widgets
  • 9 label widgets
  • 4 entry widgets
  • 17 radiobutton widgets in 6 groups
  • 0 checkbutton widgets
  • 0 scale widgets
  • 0 listbox widgets
  • 0 text widgets
  • 0 canvas widgets

All but the 'label' widgets provide operating parameters/options in this utility.

Hence there are about 8 + 4 + 17 = 29 user-specifiable options via the GUI of this utility.

There is one line added to this GUI, compared to the GUI for the 'find-images-and-view' utility:

  • a 'LayoutOnScreen' line of radiobuttons --- to allow for playing a 'group' of animated GIF files 'at a time' --- arranged in a rectangular array on the screen.

---

Front-End-for-Two-Commands

This 'Front End' Tk script is essentially a 'wrapper' for TWO commands:

  • the 'find' command
    that assembles the animated-GIF files to be 'played'

    and

  • an animated-GIF 'player' command
    (of the user's choice, from more than one).

NOTE that among the 8 'parameter-lines' of this GUI, only 2 have to do with the animated-GIF 'player':

  • the line of radiobuttons used to select the 'player'

and

  • the 'LayoutOnScreen' line of radiobuttons
    (1x1 , 2x1 , 3x1 , 2x2, ... ).

The other parameters (on 6 of the lines) are for the 'find' command.

---

The Ani-GIF Players

As far as choosing which animated-GIF player to use, both 'animate' and 'gifview' have their idiosyncracies.

The question of which one to use may come down to which one is already available --- or which one is easier to install on the user's operating system.

To avoid surprises, it may help for the user to know that if they click on an ImageMagick 'animate' player window, a menu of options pops up.

Typically, I find that when that happens, I simply want to close that popup window.


Beautification of the GUI

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 be able to sweep through a hierarchy of sub-directories and pick out animated-GIF files to 'play' based on a rather 'rich' set of selection capabilities --- such as 'file-mask' and/or 'file-size' and/or 'file-age'.

I am certainly interested in making pretty GUI's --- as I have expressed on pages titled:

and

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).


THE GUI
(and some discussion of how-to-use)

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

Note that there are a couple of radiobuttons that allow you to choose whether application of the file-mask is 'case-sensitive' or 'case-INsensitive'.

For example, if you chose 'case-INsensitive' and the mask were set to '*.gif', then files with the suffix '.GIF' would also be selected.

And there are a couple of radiobuttons that allow you to choose whether to do the 'mask-search' at the current directory level only --- or to sweep through all sub-directories of the current 'base' directory, looking for animated-GIF files that satisfy the criteria chosen via this GUI.

To help avoid accidentally triggering a 'find' search on a 'deep' directory (full of many, many files), the GUI is intially defaulted to a ONE-level search.

If the user is disappointed by a search that yielded zero animated-GIF files, the user may want to change the search to 'ALL-subdirectories'.

Here is a place where I MAY make a future enhancement:

I may change the 'ONE' radiobutton to an 'N-levels' radiobutton --- and if that radiobutton is selected, an entry field could be activated where the user can enter a choice of N (with the entry field being initialized with '1').

---

NOTE that most simple image-file 'players' are oriented toward 'playing' the files in a single directory.

This 'find-and-aniGIF-play' utility is oriented toward SELECTING 'aniGIF' files (based on criteria such as a file-mask, file-size, and/or file-age) from an ENTIRE HIERARCHY OF SUB-DIRECTORIES --- as well as allowing mask-search in a SINGLE directory.

This utility SORTS the found-files by filename and then starts a loop in which 'groups' of aniGIF files are shown by the user-selected 'player'.

So this utility does not have the flexibility of a 'playlist' approach.

The user is not given an opportunity to change the order in which the selected files are played.

    (That capability is offered by the 'play-from-a-playlist' utility that I have already made for aniGIF files.)

On the other hand, this utility offers the user the ability to quickly and auto-magically sweep through a directory hierarchy, selecting files by a 'rich' set of criteria, and 'play' the selected aniGIF files --- which may be scattered throughout that hierarchy.

By using the file-mask option (and file-age and file-size options), the user has quite a bit of selection ability.

The user can avoid a lot of 'manual' searching for files by letting the 'find' command find the desired files.

ALSO, note that this utility can be useful without even using any of the 'player' programs.

Say you want to know the NUMBER or NAMES of the animated-GIF files satisfying a set of criteria (file-mask, file-size, file-age).

Then set the criteria and click on the 'CountFilenames' or 'ShowFilenames' button.

IN FACT, by using the 'ShowFilenames' button you can get a list from which to build a 'playlist' file.

The filenames are shown in a popup Tk 'text' widget --- from which you can paste the names into a text-editor window of your choice.

---

Note also that this utility can be used to 'play' a single file.

Just select a full filename and do not change the last part of the filename to a mask.

Then click the 'LaunchPlayer' button.

    (Remember to unset any criteria which the selected file would not satisfy.

    Note that you can click on the 'CountFilenames' button to see if it returns a value of 1, rather than 0.)


DESCRIPTION OF THE CODE

Below, I provide the Tk script code for this 'multi-subdirectory tkBatchAniGIFsPlayer' 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, widget-geometry-parms, win-size-control,
     text-array-for-labels-etc).

  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 using a text-array --- named 'aRtext' --- 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 widgets expand/contract 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 with the GUI:

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.


Some features in the code

There are plenty of comments in the code, 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_filemask'             - called by the 'Browse...' button

  'get_chars_before_last'    - called by proc 'get_filemask'

  'check_for_criterion_change' - called by the following
                                 'findAniGIFs_forCriteria' proc

  'findAniGIFs_forCriteria'    - called by several procs below, namely
                                 - 'count_aniGIF_files'
                                 - 'show_aniGIF_filenames'
                                 - 'play_nextN_aniGIF_files' 

  'count_aniGIF_files'       - called by the 'CountAniGIFs' button.

  'show_aniGIF_filenames'    - called by the 'ShowAniGIFfilenames' button.

  +-------------------------------------
  For playing the 'found' aniGIF files:

  'set_player_command'       - called by button1-release bindings on the
                               player radiobuttons.

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

  'play_nextN_aniGIF_files'    - called by the 'start_playing_aniGIF_files'
                                 proc and the 'Next N' button.

  'set_window_positions'     - called by 'play_nextN_aniGIF_files' proc
                               to set the window positions according
                               to the current user-selected windows-layout.
  +-------------------------------------

   'popup_msgVarWithScroll' - called by 'Help' button to show HELPtext var.
                                         Also used via the 'CountFilenames'
                                         and 'ShowFilenames' buttons.


Like with the 'find-images-and-view' Tk GUI utility, 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


Lessons Learned
(and incorporated in this utility)

In using the 'tkBatchMediaPlayer' (for movie/audio files) on 'deep' directories --- that is, a 'find' search on about 200-plus subdirectories with 2,000-plus files in those subdirectories --- I found a few improvements that I needed to make in that Tk script and its 2 associated shell scripts.

I found the following 'needs'.

  • Put filenames in a temporary file

    When I used the 'CountFilenames' and 'ShowFilenames' and 'LaunchPlayerJob' buttons with the same 'find' criteria, the same long 'find' search would have to be repeated --- unnecessarily.

    I needed to save the 'found-filenames' in an output file, and work off of that list of files when the 'find' criteria had NOT been changed by the user.

  • Progress indicator

    On a long 'find' search, a 'progress indicator' was needed to let the user know if the 'find' command was doing its job --- and to let the user know how far/fast the search was proceeding.

To handle these needs, I put the following features into the 'find-aniGIFs' utility.

  • In the Tk script, I set the filename of a temporary file to be used to hold the names of animated-GIF files found by the 'find' search --- in variable 'outFILE'.

  • In the Tk script, I added 'PREV' variables to be used to hold about 8 parameter values of a previous 'find' search --- to be used to indicate when the user has changed a 'find' criterion.

  • In the Tk script, I created a proc called 'check_for_criterion_change' --- to determine if a criterion variable has been changed by the user.

  • In the Tk script, I run the 'findAniGIFfiles_forCriteria.sh' script only if one of the 'find' search criteria was changed by the user.

  • In the Tk script, I provided an 'xterm' window in the 'exec' statement for the 'findAniGIFfiles_forCriteria.sh' shell script, to allow for better visibility of how a lengthy 'find' is progressing.

    The 'find' command in the 'findAniGIFfiles_forCriteria.sh' shell script was devised to show directories being searched, as well as files being found --- in order to provide a better 'progress indicator'.


A fervent hope

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 that recent (2014) video of a Giant Panda pulling the jacket off of a guy who sat down against the fence enclosing the panda's turf.


The Tcl-Tk CODE

Here is a link to CODE for the Tk script

'find_and_AniGifViewers_FrontEnd.tk'.


Shell script #1
(called by the Tk script) :

And below is the code for the shell script called by this Tk script.

This is a 'wrapper script' for the 'find' command.

You can put this script in the same directory with the Tk script.

The Tk script includes some code (involving the 'argv0' variable) to determine the location of the shell script by extracting the name of the directory in which the Tk script lies.


Shell-script-1 CODE

Here is a link to CODE for the SHELL script

'findAniGIFfiles_forCriteria.sh'.


Shell script #2
(called by shell script #1) :

And below is the code for the shell script that selects out GIF files and distinguishes a non-animated GIF file from an animated-GIF file.

You can put this script in the same directory with the Tk script.

Shell script #1 includes some code (involving the '$0' variable) to determine the location of the directory containing this shell script (and all 3 scripts) by extracting the name of the directory in which shell-script-1 lies.


Shell-script-2 CODE

Here is a link to CODE for the SHELL script

'file-identify_aniGIF.sh'.


INSTALLING THESE SCRIPTS:

This set of 3 scripts could be put in a sub-directory of the user's home directory, such as

$HOME/apps/tkBatchAniGIFsPlayer

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

Then, whenever the user wants to search a directory hierarchy for animated-GIF files, the user can click on the icon to startup the Tk GUI script.

In fact, below is an image of the 6 icons that I set up on an Ubuntu 9.10 Gnome 2.28 desktop for the 3 'batch-find-and-play' and 3 'play-from-a-playlist' utilities that I mentioned at the top of this page.

    Later, I removed these icons, because I can get to all of these 'tkGooie' utilities via the 'IMAGEtools' and 'AUDIOtools' and 'VIDEOtools' toolchests of the FE 'tkGooies' system.

SOME POSSIBLE ENHANCEMENTS :

maxdepth N

I indicated near the top of this page that I may change (someday) the 'ONE' radiobutton to an 'N-levels' radiobutton.

If that radiobutton is selected, an entry field could be activated where the user can enter a choice of N (with the entry field being initialized with '1').

    Alternatively, a 'spinbox-like widget could be used to select integers --- with the spinbox entry field initialized to '1'.

This capability would be implemented via the '-maxdepth' parameter of the 'find' command.

    There is also a '-mindepth' parameter of the 'find' command.

    But I have never encountered a situation where I felt I needed to use that parameter.


prune

Probably, even more useful than the 'maxdepth' capability would be allowing on the GUI for use of the '-prune' parameter of the 'find' command.

To implement the '-prune' feature would require adding yet another 'entry' widget to the GUI --- to allow for entering one or more sub-directory names (or masks).

As I pointed out on the 'find-images-and-view' FrontEnd page, I found a simple example that verifies that the 'find' command can prune using 'masks' as well as complete directory names:

find   .   -type d   -name '.git*'   -prune \
-o   -type f   -print

This 'find' skips any directories whose names matcn the mask '.git*'. Otherwise, the name of any 'regular' file found is printed (sent to 'stdout').

---

I leave the 'N-levels' and '-prune' enhancement possiblities to a future date.

These two features are similar in that they allow the user to avoid 'dropping into' a sub-directory of image files which the user does not wish to process.

If I encounter a need for either of those features ('N-levels' or 'prune'), I may implement them and update the code on this page.

---

There are a lot of parameters available with the 'find' command, but I think I have probably implemented the ones that are most useful to use for this 'multiple-subdirectory aniGIF-file-select-and-display' utility.

That said, I will probably find a '-prune' capability to be quite desirable --- someday.


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.

Bottom of this page for
Batch-Find-and-Play
of Animated GIF files

--- a utility in the FE 'tkGooies' system,
in the 'IMAGEtools' group.

To return to a previously visited web page location, click on the Back button of your web browser a sufficient number of times. OR, use the History-list option of your web browser.
OR ...

< Go to Top of Page, above. >

Page history:

The code was created in 2014 --- and posted 2014 May 20 at http://wiki.tcl.tk/40060.

This FE web page was created 2014 May 28.
(as a backup and alternative to the wiki.tcl.tk page)

This page was changed 2015 Oct 05.
(Small changes.)

Page was changed 2019 Feb 25.
(Added css and javascript to try to handle text-size for smartphones, esp. in portrait orientation.)

Page was changed 2019 Jun 26.
(Specified image widths in percents to size the images according to width of the browser window.)


NOTE:
The code here MAY BECOME more 'up-to-date' than the code posted on the Tcler's Wiki ---
wiki.tcl-lang.org --- formerly wiki.tcl.tk.