Bundling and accessing media files inside a .app package in OS X

#1

Hello,
first post!
I have an ofx app that loads some images from disk at runtime. I use ofImage::load() to load from a relative path. However this comes with the following disadvantages when I distribute the app (I am only interested in distributing for OSX):

  • Relying on a relative path means I have to ship the .app package AND a data/ folder containing the images. If the two are not in the same folder then image loading fails
  • on OS X > 10.12 , the “quarantine flag” and “translocation” mean that the relative path will always fail for apps downloaded from the internet (see, e.g.: here).

To solve both issues above, it would be great if I could bundle the images INSIDE the .app package. What is the best way of doing this with ofx?

Thanks,
Giulio

#2

Hi, it is quite simple.
use ofSetDataPathRoot
then move the files into the desired location within the .app bundle.
usually this would be the Resources folder.
You also can automate this by adding a script in the “run script” section in the build phases settings in xcode.
hope this helps.

#3

hi @giulio,

I wrote a blog post about this here:
http://nickhardeman.com/591/preparing-an-openframeworks-application-for-the-mac-app-store/

Quicktime is no longer included in OF I believe, so you can ignore that section.
Best,
Nick

#4

Thanks, I tried

ofSetDataPathRoot("../Resources/");
ofDirectory dir;
dir.listDir("");

however when I run it, it gives:

[ error ] ofDirectory: listDir:() source directory does not exist: ""../Resources/""
Loading images relative to:/Users/giulio/studiosimulation/of_v0.9.8_osx_release/project/Studio/StudioSimulation/bin/../Resources/

Now, /Users/giulio/studiosimulation/of_v0.9.8_osx_release/project/Studio/StudioSimulation/bin/ is where the StudioSimulation.app lives, so it is still looking for a path relative to the .app package and not to the binary which is in StudioSimulation.app/Contents/MacOS.

Am I doing something wrong?

#5

what do you get when you call the following?

cout << ofFilePath::getCurrentExePath() << endl;
cout << ofFilePath::getCurrentWorkingDirectory() << endl;

the following will change the data path to the resources folder, at least for me.

ofSetDataPathRoot(ofFilePath::getCurrentWorkingDirectory());

which OF version are you using?

#6
    cout << "Before exepath: " << ofFilePath::getCurrentExePath() << endl;
    cout << "Before cwd    : " << ofFilePath::getCurrentWorkingDirectory() << endl;
	ofSetDataPathRoot("../Resources/");
    cout << "After exepath:  " << ofFilePath::getCurrentExePath() << endl;
    cout << "After cwd:      " << ofFilePath::getCurrentWorkingDirectory() << endl;

gives :

Before exepath: /Users/giulio/studiosimulation/of_v0.9.8_osx_release/project/Studio/StudioSimulation/bin/StudioSimulation.app/Contents/MacOS/StudioSimulation
Before cwd    : /Users/giulio/studiosimulation/of_v0.9.8_osx_release/project/Studio/StudioSimulation/bin
After exepath:  /Users/giulio/studiosimulation/of_v0.9.8_osx_release/project/Studio/StudioSimulation/bin/StudioSimulation.app/Contents/MacOS/StudioSimulation
After cwd:      /Users/giulio/studiosimulation/of_v0.9.8_osx_release/project/Studio/StudioSimulation/bin

This is of_v0.9.8_osx_release

#7

I’m using the github master. something must have changed.
does it work if you call?

ofSetDataPathRoot(ofFilePath::getCurrentExeDir()"/../Resources/");

you can use the following to check the if it is correct

	cout << ofToDataPath("",true) << endl;
#8

Yes thanks that’s what I ended up doing in the end.