LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Articles > Technical
User Name
Password

Notices

By stomfi at 2006-03-16 08:38
Power to the Users. Shell Scripting & GUI interfacing for Desktop Users. By Stomfi © 2006

Part 6 - Continuing Story Board Scripting

In this part you will create and copy the image script, and write more Transcripts and shell scripts for the activities the story board performs.

Many of the Runtime Revolution scripts call Linux shell scripts using these three basic commands:
  1. put ($HOME & "/SB/bin/dowork.sh" && quote & ARGSTRING1 & quote && ARGSTRING2) into DUWORK
  2. replace return with empty in DUWORK
  3. put the shell of DUWORK into DUNWORK

If ARGSTRING1 contains "filename1 filename2" and ARGSTRING2 contains "45", the first command creates a shell command string that looks like this:

Code:
/home/stomfi/SB/bin/dowork.sh "filename1 filename2" 45
The brackets are handy tokens for telling RunRev where a string of words starts and finishes. The $HOME token is a RunRev variable and is not enclosed in quotes as if it were part of a Linux shell path name. The single & token concatenates two strings together without any spaces. The && token does the same with a space. Because RunRev interprets the " token itself, to add a space separated string as one Linux shell variable, the quote token is used.

The second command makes sure that RunRev hasn't split a long string with a carriage return.

The third command runs the shell command and put the result into DUNWORK. Even if there is no output from the shell script, it is a good idea to do it this way as you can see if there are any shell script errors with the variable watcher when you set the RunRev script debug mode.

The other way RunRev scripts in this application call shell commands is like this.

put the shell of ("ls" && MYFLDR && "|wc -l") into FLDRLINES
replace return with empty in FLDRLINES

In this case the Linux shell command returned a value to RunRev. Because the Linux shell adds a carriage return, we have to get rid of it otherwise RunRev sees it as two lines, one containing the value and one a blank.

These simple constructions allow you to seamlessly integrate Runtime Revolution GUI interfaces with Linux shell scripts and commands.

Now it is time to write the script for the image "Im1". We will use the button "button 1" to copy this script to the other 48 images on the story board.

I've added some extra functionality to the images which we shall implement as the story board is developed. The two extra areas are Sound and Zoom. Sound lets you create a sound or add a sound which is associated with the chosen image. Zoom lets you zoom a picture a large as all the thumbnail pictures. To make this work you will have to add a new image starting at the top left of thumbnail "Im1" and ending at the bottom right of thumbnail "Im49". The name of this image is "ZOOM". Here is the size and position property inspector. Make sure its size and position are locked.

Picture of Property Inspector for Image ZOOM:
[img=640x480]http://images.linuxquestions.org/articles/zoom.jpg[/img]

RunRev scripts take actions designated by action handlers. In the Button 1 script the handler we used was "on mouseUp" which performed the actions when the mouse button was released. In the next script we are using the handler "on mouseDown" which performs the actions when a mouse button is pressed down.

Here is the script for image "Im1" which lots of explanatory comments. Right click on the thumbnail "Im1" in Pointer Mode to bring up the object menu and select "edit script" to enter the following.

Code:
on mouseDown
  #set a global variable that can be used in other scripts or contain
  #values set by other scripts
  global PPROG
  #me is a special RunRev variable in this case containing the object name of
  #the clicked object i.e. The image name 
  put me into CPIC
  put the filename of image me into CIMAGE
  #Check that this image field contains a source image
  #<> means "not equal to" 
  if CIMAGE <> empty
  then
    #Ask the user what they want to do.
    #The order of options after the with statement is the reverse of the order
    #of the button placement in to answer pop up window. The first item "Move"
    #will be highlighted and activated by the Enter key. You can change this
    #order to suit your preferences.
    answer "Move, Zoom, Edit, Remove Picture or Add Sound" with "Cancel" or "Sound" or "Remove" or "Edit" or "Zoom" or "Move"
    #The special RunRev variable "it" contains the last value input.  
    put it into MANSWER
    #Take action based on the input value
    switch MANSWER
      case "Cancel"
        #Break out of the switch
        break
    
      case "Move"
        #Set some variables
        global MUVIT
        global MUVPIC
        global MUVFILE
        #Give a message to click an empty thumbnail
        put "Click OK, then click on an empty picture square" into MASK
        answer MASK
        put "YES" into MUVIT
        put CPIC into MUVPIC
        put CIMAGE into MUVFILE
        break
                   
      case "Zoom"
        #load the ZOOM image with the clicked picture
        set the filename of image "ZOOM" to CIMAGE
        #Move this image in front of all the other images
        set the layer of image "ZOOM" to top
        #Hopefully the user will read the howto and click this image
        #to unzoom it
        break
      
      case "Edit"
        global PDIR
        global PPROG
        answer "Edit with TUX or the GIMP" with "Cancel" or "GIMP" or"TUX"
        put it into PPROG
        if PPROG <> "Cancel"
        then
          #Call a shell command script 
          put ($HOME & "/SB/bin/editpic.sh" && CIMAGE && PPROG) into DUEDIT
          replace return with empty in DUEDIT
          put the shell of DUEDIT into DUNEDIT
          #Refresh the image
          set the filename of image CPIC to empty
          set the filename of image CPIC to CIMAGE
        end if
        break
      
      case "Remove"
        set the filename of image CPIC to empty
        break
      
      case "Sound"
        #Add a sound for this picture and rename it to the 
        #picture name and save it in its folder where it will 
        #be loaded with the picture next time
        answer file "Select a sound to go with this picture" with ($HOME & "/SB/work/sounds")
        put it into NEWSND
        #Run some Linux shell commands
        #basename cuts of the preceding path.
        put the shell of ("basename"  && CIMAGE) into IMNAME
        put the shell of ("dirname" && CIMAGE) into IMDIR
        #Do not have to get rid of return as it is done next 
        put ("cp" && NEWSND && IMDIR & "/" & IMNAME) into CPSND
        replace return with empty in CPSND
        put the shell of CPSND into DUNCPSND
        break
    
    end switch
  else
    #This is an empty thumbnail so check if it is a square to move
    #a picture to
    if MUVIT = "YES"
    then
      #CPIC is the empty image field
      set the filename of image CPIC to MUVFILE
      #MUVPIC is a global variable containing the image name to be moved
      set the filename of image MUVPIC to empty
      #Clear the moving variable 
      put "NO" into MUVIT
    end if
  end if
end mouseDown
Save the script with the "Apply" button and replace and apply the script in "Button 1" with this one.

Code:
on mouseUp
  put 2 into PCOUNT
  put the script of image "Im1" into MSCRIPT 
  repeat for 48 times
    put ("Im" & PCOUNT) into PIC
    set the script of image PIC to MSCRIPT
    add 1 to PCOUNT
  end repeat
end mouseUp
Select "Browse Mode" from the menu or tool box and click "Button 1". Return to "Pointer Mode" and right click thumbnail "Im49" to check edit script happened as planned and the script was copied successfully to all of them.

You can right click and cut Button 1 as you shouldn't need it any more.

IMPORTANT MESSAGE
Save the stack after every big change, to help negate Murphy's Law.

The CLICK ME menu button is developed next so that you can load some pictures and at least move them around. This is the script. It is the longest one in the project. If you think of each menu item as another button, it doesn't seem so big.

The object action handler is called "on menuPick", "theMenuItem" can be any meaningful name not already used by RunRev. Since I added some more choices to the menu here is a new picture.

Picture of CLICK ME menu:
[img=640x480]http://images.linuxquestions.org/articles/click2.jpg)[/img]

Add SOUNDS and Manage Files to the objects Property Inspector. Both these items will eventually be used to create some new sub stacks, although sounds will be used from the existing stack.

Here is the CLICK ME menu script

Code:
on menuPick theMenuItem
  global NUMPICS
  global PDIR
  global MYPICDIR
  put ($HOME & "/SB/work/pics/") into MYPICDIR
  #The default folder is where RunRev goes to open folders 
  set the defaultFolder to MYPICDIR
  #Turn off animation if going
  set the filename of image "ANIM" to $HOME & "/SB/sclblue.gif"
  #The visible property is used to hide or show objects
  set the visible of button "ANIMCTRL" to false
  set the visible of button "PSOUND" to false
  #Perform actions for each menu item
  switch theMenuItem

    case "NEW PROJECT"
      #Make directory
      ask "Enter one word project Name"
      put it into NDIR
      put ($HOME & "/SB/work/pics/" & NDIR) into PDIR
      put the shell of ("mkdir" && PDIR) into DUNDIR
      #Test there is room for more pictures
      if NUMPICS < 49
      then
        set the visible of button "NEWPIC" to true
      else
        put "Cannot add any more pictures" after field "MESG"
      end if
      break

    case "LOAD PROJECT"
      #Load all picture  files in a folder 
      #Get name from list
      global MYPICDIR
      global NUMPICS
      answer folder "Select Project Folder" with MYPICDIR
      put it into PDIR
   
      #Fill the pics. The second set of brackets inside the quotes
      #make the shell commands run in a sub shell, first changing to
      #the folder PDIR, then running the file command on this folder
      #which outputs the file path name followed by a colon followed
      #by the file type. This output is piped into the grep command
      #to select only those of type "image". Finally the output from
      #grep is piped into the cut command with the field delimiter set
      #to the colon, returning a list of file path names.
      put ("(cd" && PDIR  && "; file * |  grep image | cut -d: -f1 )" ) into DUIFILES
      replace return with empty in DUIFILES
      put the shell of DUIFILES into IFILES
      #IFILES is a list of image file path names, one per line.
      if IFILES <> empty
      then
        #This is a repeat loop inside a repeat loop
        put 0 into ALLPICS
        #Loop round each file name
        repeat for each line thisLine in IFILES
          put "NO" into PSAVED
          #put each picture thisLine into empty thumbnail by looping round
          #thumbnails until the flag PSAVED is not equal to NO 
          repeat while ALLPICS < 49 and PSAVED = "NO"
            add 1 to ALLPICS
            put "Im" & ALLPICS into THISPIC
            if the filename of image THISPIC <> empty
            then
              #Skip it
            else
              put the filename of image THISPIC into THISPFILE
              set the filename of image THISPIC to  (PDIR & "/" & thisLine)
              add 1 to NUMPICS
              #Set inner repeat loop exit flag
              put "YES" into PSAVED
              #Put a message into MESG
              put return & "Added pic" && NUMPICS && "as" && thisLine after field "MESG"
            end if
            #In case we have run out of empty thumbnails 
            if ALLPICS > 49
            then
              put NUMPICS && "Is more than 49 pics" after field "MESG"
              exit repeat
            end if
          #End of inner repeat loop
          end repeat
        #End of outer repeat loop  
        end repeat
        put return & "Pic Count" && NUMPICS after field "MESG"
        #Make sure number of pics is not more than 49
        if NUMPICS > 49
        then
          put 49 into NUMPICS
        end if
        #Show add pic button if there are empty thumbnails
        if NUMPICS < 49
        then
          set the visible of button "NEWPIC" to true
        end if
        #Put the project directory path into PMESG
        put PDIR & return after field "PMESG"
        #Allow the user to make an animation of loaded pictures
        set the visible of button "ANIMTEST" to true
      else
        put return & "No image files in" && PDIR after field "MESG"
        put empty into PDIR
      end if
      break
  
    case "LOAD PICTURE"
      #Load a single picture. This can also be a repeat picture from a
      #loaded project folder
      #Get name from list
      global MYPICDIR
      global NUMPICS
      put "NO" into TSAVED
      #The with statement sets the folder to start looking for files
      answer file "Select Project Picture" with MYPICDIR
      put it into PFILE
      if PFILE <> empty
      then
        #This is the same inner loop and if conditions 
        #as in the load project case item
        #with the variable names changed 
        repeat while ALLPICS < 49 and TSAVED = "NO"
        add 1 to ALLPICS
          put "Im" & ALLPICS into THISPIC
          if the filename of image THISPIC <> empty
          then
            #Skip it
          else
            put the filename of image THISPIC into THISPFILE
            set the filename of image THISPIC to  PFILE
            add 1 to NUMPICS
            put "YES" into TSAVED
            put return & "Added pic" && NUMPICS && "as" && PFILE after field "MESG"
          end if
          if ALLPICS > 49
          then
            put NUMPICS && "Is more than 49 pics" after field "MESG"
            exit repeat
          end if
        end repeat
      end  if
      if NUMPICS > 49
      then
        put 49 into NUMPICS
      end if
      if NUMPICS < 49
      then
        set the visible of button "NEWPIC" to true
      end if
      if NUMPICS > 2
      then
        set the visible of button "ANIMTEST" to true
      end if
      break
        
    case "CLEAR BOARD"
      global NUMPICS
      answer "Clear the Story Board of all current pictures" with "Cancel" or "WIPE"
      put it into CRACT
      if CRACT = "Cancel"
      then
        break
      end if 
      if CRACT = "WIPE"
      then
        put 1 into CLPICS
        #A repeat until loop just to show you how it is done
        #We need to have one more than the number of pictures
        #To make the loop stop at this point
        repeat until CLPICS = 50
          put "Im" & CLPICS into CLRPIC
          set the filename of image CLRPIC to empty
          add 1 to CLPICS
        end repeat
        #Clear out picture count, project path names, and hide
        #action buttons
        put 0 into NUMPICS
        put empty into field "PMESG"
        set the visible of button "NEWPIC" to false
        set the visible of button "ANIMTEST" to false
        set the visible  of button "ANIMCTRL" to false
      end if
      break
      
    case "SOUNDS"
      answer "Create New Sound or Add Existing Sound to Layout" with "Cancel" or "Create" or "Add"
      put  it into SANS
      if SANS <> "Cancel"
      then
        switch SANS
          case "Create"
            #This is an easy case as we just choose a tool for creating
            answer "Use Audacity or Simple Recorder" with "Audacity" or "Recorder"
            put it into RECS
            global NEWSND
            ask "Enter a one word name for your new sound"
            put it into NSND
            put  ($HOME & "/SB/work/sounds/" & NSND & ".wav") into NEWSND
            if RECS = "Audacity"
            then
              put ($HOME & "/SB/bin/donewsnd.sh" && NEWSND) into DUNEW
              replace return with empty in DUNEW
              put the shell of DUNEW into DUNNEW
            else
              #Use the new recorder stack.
              go  card "SOUND" of stack "SB"
            end if
            break
          case "Add"
            #A more difficult case as the sound needs to be identified
            #as belonging to an animation so that it can be played back 
            #when the animation is being displayed.
            answer file "Choose a wav sound for the whole layout" with ( $HOME & "/SB/work/sounds/")  
            global LAYSND
            put it into LAYSND
            #To be more general sound formats other than "wav" should be
            #allowed or converted, but at this point of development it 
            #doesn't happen, (Maybe later) so we had better test the name 
            #to make sure it is a wav format file.
            put the shell of ("basename" && LAYSND && "|cut -d. -f2") into STYPE
            if STYPE <> "wav"
            then
               #Give the user a message
               put "Sound not wav format" into field "MESG"
               #Break out of the case
               break
            end if 
            #Create a layout folder, save the pictures and rename the sound to the folder name
            #Make sure layout folder exists
            put  ($HOME & "/SB/work/layouts") into LAYDIR
            put the shell of ("mkdir" && LAYDIR)  into DUNMK
            #Check the layout folder doesn't exist or overwrite it
            put "NO" into GOTFLDR
            #This loop will keep asking for a name until GOTFLDR = YES
            #Or it breaks out of the case
            repeat until GOTFLDR = "YES"
              ask "Enter a one word name for your layout"
              put it into LAYNAME
              if LAYNAME = "Cancel"
              then
                break
              end if
              put (LAYDIR & "/" & LAYNAME) into LAYFLDR
              #This tests for the existence of a folder
              if there is a folder LAYFLDR
              then
                answer "Overwrite existing layout" with "Yes" or "No"
                put it into OLAY
                if OLAY = "Yes"
                then
                  put "YES" into GOTFLDR
                else
                  break
                end  if
              else
                put "YES" into GOTFLDR
              end if
            end repeat
            #Even if there is an existing folder, existing files can't 
            #be removed in case the current story board layout is
            #using files from this layout folder which will be the case
            #when trying out more new sounds, or if pictures have been modified
            #after trying out a sound. With this scenario, copy (cp) won't        
            #copy a file to itself, but will leave existing or modified files
            #in place and return an error message. 
            #   
            #Create the layout folder whether it exists or not
            put the shell of ("mkdir" && LAYFLDR) into DUFLDR
            #Copy the layout files into new folder
            #Collect non empty image filenames and their image numbers
            #The lists are used to restore the original storyboard if the
            #user requests this option. This is so that a layout that
            #contains spaces which the user may want to fill after the
            #sound has be tested, can be restored.  
            global LAYPICS
            put empty into LAYPICS
            global NOLAY
            put empty into NOLAY
            put 1 into PICCOUNT
            repeat for NUMPICS times
              put "Im" & PICCOUNT  into LPIC
              put the filename of image LPIC into TPIC
              if TPIC <> empty
              then
                put TPIC & space after LAYPICS
                put PICCOUNT & space after NOLAY
              end if
              add 1 to PICCOUNT
            end repeat
            #Load them into LAYFLDR
            put the shell of ("cp" && LAYPICS && LAYFLDR) into CPLAY
            #Rename and copy the sound. 
            put  (LAYNAME & ".wav") into LAYBASE
            put ("cp" && LAYSND && LAYFLDR & "/" & LAYBASE) into CPSND
            replace return with empty in CPSND
            put the shell of CPSND into DUNCPSND
            #Replace the current layout with the newly saved layout
            #Clear board, pic count and hide buttons
            put 1 into CLPICS
            repeat until CLPICS = 50
              put "Im" & CLPICS into CLRPIC
              set the filename of image CLRPIC to empty
              add 1 to CLPICS
            end repeat
            put 0 into NUMPICS
            put empty into field "PMESG"
            set the visible of button "NEWPIC" to false
            set the visible of button "ANIMTEST" to false
            set the visible  of button "ANIMCTRL" to false
            #Load the layout
            put ("(cd" && LAYFLDR  && "; file * |  grep image | cut -d: -f1 )" ) into DULFILES
            replace return with empty in DULFILES
            put the shell of DULFILES into LFILES
            if LFILES <> empty
            then
              put 0 into ALLPICS
              repeat for each line thisLine in LFILES
                add 1 to ALLPICS
                put "Im" & ALLPICS into THISPIC
                set the filename of image THISPIC to  (LAYFLDR & "/" & thisLine)
                add 1 to NUMPICS
              end repeat
            end  if
            #Put new layout folder name into PMESG
            put LAYFLDR into field "PMESG"
            #Ask whether to replace or keep new layout and save the answer
            #into a global to be used by the end animation action object 
            answer "Keep or Replace new layout when finished Animation testing" with "Replace" or "Keep"
            global REPLAYOUT
            put it into REPLAYOUT
            set the visible of button "ANIMTEST" to true
            break
          end switch
        end if
        break
        
    case "Refresh Project List"
      #Replaces multiple occurrences of the same project path with one.
      global NUMPICS
      put empty into field "PMESG"
      put empty into RLDIR
      put 1 into RLCOUNT
      repeat until RLCOUNT >= NUMPICS
        put "Im" & RLCOUNT into RLPIC
        put the filename of image RLPIC into RLPICFILE
        put return & RLPICFILE after field "MESG" 
        if RLPICFILE <> empty
        then
          #Cut off the folder path part
          put the shell of ("dirname" && RLPICFILE) into RLDIR 
          #Check its not in the lines of PMESG
          put "NO" into RLMATCH
          if field "PMESG" <> empty
          then
            put field "PMESG" into ALLPDIRS
            repeat for each line RLLINE in ALLPDIRS
              if RLLINE <> empty
              then
                #This RunRev test checks for a text match just like the shell
                #command grep does.
                if matchText ( RLDIR, RLLINE)
                then
                  put "YES" into RLMATCH
                  #exit the repeat loop
                  exit repeat 
                else
                  put "NO" into RLMATCH
                end if
              end if
            end repeat 
          end if # PMESG This comment is to see which if this end if belongs.
          if RLMATCH = "NO"
          then
            put RLDIR  after field "PMESG"
          end if
        end if # <> RLPICFILE
        add 1 to RLCOUNT
      end repeat # NUMPICS
      break
    
  end switch
end menuPick
Although this is a big long script, nearly all the constructs are repeated over and over again, some nested inside others to achieve the desired actions, but mostly all are very simple, which is what programming and scripting are all about. They mainly consist of mundane testing and looping constructs, but the end result lets you create exciting programs like this one.

Apply this script and save the stack.

The last script to enter for this week is the one for the ZOOM image, so that you can click a thumbnail to zoom and click ZOOM to unzoom.

Code:
on mouseDown
  set the filename of image "ZOOM" to empty
  set the layer of image "ZOOM" to bottom
end mouseDown
Apply this script, save the stack, enter Browse Mode, load some picture files and click on the thumbnails to move them around, zoom and unzoom and clear the board. You won't be able to test functions which use Linux shell scripts in $HOME/SB/bin until they have been written. So you'll just have to wait until the next article won't ya.


  



All times are GMT -5. The time now is 10:55 PM.

Main Menu

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration