REBOL Quick Start: Part 5 - Files, Directories, and Playing Music
By Carl Sassenrath REBOL's Designer Updated 22-Feb-2007 Tutorial Home Page
The Plan
The prior tutorials were educational. Time to do something more
interesting.
So far, you've seen how to view and edit existing REBOL
source code, how to write your own scripts, and how to help yourself
when problems occur. This is useful info to know.
In this chapter, I will show you how to scan your system for MP3 and
other files, then play them on your media player. (I will show you this
for is Windows Media Player, but you can modify this example to use
whatever you want).
File Notation
REBOL uses a special notation for files and directories. For example:
do %demo.r
print read %readme.txt
data: load %business/contacts.r
dir: %"/c/documents and settings/Carl/"
dir: %/c/documents%20and%20settings/Carl/
Here's what to notice:
Files begin with a % (percent sign). This distinguishes them
from all other types of strings. Why? Because when you (or a script) scan a file or
other REBOL data, you can immediately recognize what values are files.
Directory paths use the / (forward slash) just like Web URLs.
This has been the international standard for 40 years. (Unfortunately,
Microsoft designers didn't know that and used the \ by accident. But, we
allow that in REBOL too.)
The file notation is the same on all computer systems.
That's why REBOL does not use the Windows format. You want your
scripts to work on OSX, Linux, your cell phone too... everywhere.
Use quotes if the file has spaces. You can also use the URL
format (percent-hex encoded).
A directory is just another name for "folder". Yep, you knew
that already.
Listing File Directories
To get a list of files within a directory, you can do this:
Notice that slash on the end of the %music/ directory.
We use that to show that it is a directory.
Later, we will show why that is important.
For this to work, the music directory must be found in the same location
as where you run REBOL. We call that location the "current directory".
To list files from other locations, you can use an absolute path such
as:
files: load %"/c/documents and settings/Carl/"
probe files
or, a relative path (go up two directories in this case):
files: load %../../music/
probe files
or, or you can change the current directory:
change-dir %"/c/documents and settings/carl/"
files: load %music/
probe files
On this last one take note: any file you now read or write will
use this directory location as the default.
A Note on File Security
If you try the above examples, REBOL will pop up a security alert.
It does that to protect you from scripts that could read, write, or
delete your files.
The default security is: don't let scripts mess with my files other
than those found in the REBOL directories. That is the safe thing
to do.
When the REBOL security requestor pops up, only answer YES or ALL if
you trust the script you are running.
Most scripts are safe, but you can never know that for sure, so be
careful. If necessary, look at the source for the script or ask
other REBOLers for advice.
Of course, if you are running your own scripts from your local disk, you
can safely do that. In fact, you can put the -s option in your REBOL
command line (or in your editor command that runs REBOL) to disable the
security for your own scripts.
For more information, read more about REBOL's the secure function.
It offers a range of file control and sandbox features.
Build A List of Files
You learned above that you can get a directory of files with:
Note the parens. Those are necessary if you write it this way!
A lot of us don't like typing parens, so we simply reverse the
expression to avoid them. But, either way works just fine.
A Variety of Files
Above, we just get mp3 files, but what if we also want to include
a few other types. Here's what you write:
The file types are just a block (a list) of file suffixes for music.
This is a handy method. For each file we check if the suffix is
in our file-types list.
Go ahead and add other music file types as needed.
Sorting Files
For some reason the Windows OS does not list directory files in
alphabetical order. This comes from the MSDOS days, but it just seems
plain wrong these days.
No problem, you can fix that by changing the line above to:
foreach file sort load %music/ [
Now the files will be sorted alphabetically for your search.
Adding Sub-directories
Let's expand the above code to get all matching files from all
sub-directories (directories that are in our directory). The easiest
way to do that is to create a function such as:
find-files: func [dir list /local files] [
files: sort load dir
; Get files that match the above types:
foreach file files [
if find file-types suffix? file [
append list dir/:file
]
]
; Search sub-directories:
foreach file files [
if find file "/" [find-files dir/:file list]
]
]
This function calls itself to get the next directory. It is
recursive. This is a very useful technique that you
will want to remember.
I go through the file list twice. The first time to collect
the music files; the second to scan of the subdirectories.
I use a special path notation dir/:file to join the directory and
file name. You can also use join but I wanted to introduce this
special method. Don't forget the ":" in that code. It's how you get
the value of the file variable, not just the word file.
Playing A Song
In Windows, there are various ways to play a song. Here, I will use
the Windows Media Player (WMP). I'm going to show you a general
method for calling other types of programs, not just the Windows
media player.
Find the icon for WMP and right click it to find the path to the
player. On my system it is:
"C:\Program Files\Windows Media Player\wmplayer.exe"
but, Windows will put in other places too.
To launch the player, you can simply write:
call "C:\Program Files\Windows Media Player\wmplayer.exe"
It should open on your screen. If not, then verify the path is correct.
To make this easier, we're going to use a variable for the WMP path:
player: "C:\Program Files\Windows Media Player\wmplayer.exe"
call player
Now, to play a song, you can provide the file for it, and form a
command line with it. Here's the code:
song: %rebol-song.mp3
call reform [player song]
It's really important to know how to debug this line because
if it does not work, you want to figure out why. So, to see what
is being called, just write:
The clean-path function joins the current directory to your file
name to create a full file path. We then convert that to local format
and add the quotes.
Play a User-Selected Song
To illustrate the above, here's how to make your script play a song
that you select from a directory listing:
file: request-file/only
if not file [quit]
call probe reform [player localize-file file]
The request-file opens a file requestor. The /only refinement
tells it to return only a single file (not a list of files).
Note that if the user clicked "cancel" then the program will quit.
It is always a good idea to do that.
Play a Pile of Songs
Now, let's tie it all together. Here is the complete script.
And, yes, I've tested it, and it works fine here.
I use comments to break the script into sections:
REBOL [Title: "Play a pile of songs"]
;--- 1. Setup (change this as needed)
music-dir: %/c/music/
file-types: [%.wma %.mp3 %.wav]
player: "C:\Program Files\Windows Media Player\wmplayer.exe"
;--- 2. Function that gathers all the files:
file-list: [] ; hold list of media files (rebol format)
find-files: func [dir list /local files] [
files: sort load dir
; Get files that match the above types:
foreach file files [
if find file-types suffix? file [
append list dir/:file
]
]
; Search sub-directories:
foreach file files [
if find file "/" [find-files dir/:file list]
]
]
find-files music-dir file-list
;--- 3. Convert the file list to local format:
localize-file: func [file] [
rejoin [{"} to-local-file clean-path file {"}]
]
play-list: [] ; hold list of media files (windows format)
foreach file file-list [
append play-list localize-file file
]
;--- 3. Play the list:
call probe reform [player play-list]
halt
When the script works properly, you can remove the probe function.
If you just want to play the first four songs, you can write:
call probe reform [player copy/part play-list 4]
That copies just part of the list and passes it to the player.
User Selected Directory
Finally, to select the directory to search for songs, you
can make this little change:
music-dir: request-dir
if not music-dir [quit]
If the user clicked "cancel" then the program will quit.
Next: Fun Graphics
The tutorial above talked about how to open the console and get help.
In the next tutorial, let's get back to having some fun by creating
a few graphical scripts in REBOL.
More to come... Check back soon for the next installment.