In class we discussed potential complications when loading external data files into your program automatically. We were talking about audio and image files, but it could be any file.
One question is what to do if the file cannot be found by your program or cannot be opened by your program. If you do detect a malfunction, you have to decide what to do about it: how to notify the user and how to recover from (or exit from) the error. The standard programmer’s way to deal with that is to check the value returned by the file-opening function, to ensure that it doesn’t contain an error warning (or an “exception”). If an error is detected, most often the program provides a warning to the user that the desired activity failed—providing enough information to actually be informative to the user. Then, if the program can’t proceed from there, the program should reset to a place where the user can try again in a different way, or should simply exit that function so that the user can try something completely different, or in extreme cases should quit the program entirely. In the case of being unable to find a file, the proper response action might be to open a file dialog window that will permit the user to browse and find the file manually.
First let’s address the problem of the program being unable to find a file. That might happen for one of two reasons. The file might not exist; the name was misspelled or the file is missing entirely. Or, the file might exist, but the program is not looking for it in the right place in the file system hierarchy. In Max, when the sfplay~ object can’t find the file you’ve tried to open or preload, it posts an error message in the Max window, “sfplay~: cant find file <filename>”, but does nothing more than that. If you want to handle that error in your patch somehow, you can use the error object, which sends error messages out its outlet, and you can use that message however you want (show it to the user, trigger other actions, etc.).
The Max application keeps a list of preferred search directories, which you can view and edit via the File Preferences… command in the Options menu. You can read about Max’s file search path in the documentation. However, those file search directories are stored in Max’s preferences for each user on that particular computer, so they won’t be guaranteed to be in effect on another computer. Max provides several objects to help you query the search path and construct a full pathname. Those objects are filepath to set or query the current path, absolutepath and relativepath to convert pathnames, and thispatcher to query the directory of the patch itself. There are also objects that help you construct messages, such as join, append, and prepend (which combine components of a message with spaces in between items), combine (which combines components with no space between items), and sprintf (which combines items in a C-like way).
One good approach can be to accompany your program with a folder full of the needed data files and name the folder something like “sounds” or “data” or whatever it contains. Then, as long as that folder is in the same folder as your Max patch, and nobody renames it, your program can find the files it needs regardless of what computer it’s on. You would query the thispatcher object by sending it a ‘path’ message, then combine that with the foldername and filename you want to use. You can make that into a subpatcher or abstraction that you use whenever you want to open a file, and you can then prepend the word ‘open’ or ‘preload’ or whatever selector you want, to make it into a message that will open the file successfully. I’ve posted an example of an abstraction that implements this path-construction technique and another example that demonstrates the use of the “providepath” abstraction in a main patch.