load files into of application on macosx?

Is there a way to easily open up a dialogue to load files from your harddrive into an OF app. It does not need to be cross platform but for Macosx. Any way of doing this?

The search didn’t really tell me anything about it.

that would be a great addon actually –

there is some different ways to do this i saw as a poked around, but nothing as simple as the windows.

here’s what I found,
http://www.xsquawkbox.net/info/src/PlatformUtils.mac.c

that I threw into testApp.cpp (at the top) like this:

  
  
#include "testApp.h"  
#include <Carbon/Carbon.h>  
#include <string.h>  
  
static	OSErr		FSSpecToPathName(const FSSpec * inFileSpec, char * outPathname);  
static	DialogPtr	sDialog = NULL;  
int		GetFilePathFromUser(const char * inPrompt, char * outFileName);  
  
  
/* Get FilePathFromUser puts up a nav services dialog box and converts the results  
 to a C string path. */  
  
int		GetFilePathFromUser(const char * inPrompt, char * outFileName)  
{  
	OSErr				err;  
	NavReplyRecord		reply;  
	NavDialogOptions	options;  
	FSSpec				fileSpec;  
	  
	reply.version = kNavReplyRecordVersion;  
	err = NavGetDefaultDialogOptions(&options);  
	if (err != noErr)  
		return 0;  
	  
	options.message[0] = strlen(inPrompt);  
	memcpy(options.message+1,inPrompt, options.message[0]);  
	memcpy(options.actionButtonLabel, "\pConvert", 8);  
	options.dialogOptionFlags &= ~kNavAllowMultipleFiles;  
	  
	err = NavGetFile(NULL, &reply, &options, NULL, NULL, NULL, NULL, NULL);  
	if ((err != noErr) && (err != userCanceledErr))  
		return 0;  
	  
	if (!reply.validRecord)  
		goto bail;  
	  
	/* Convert the result from an AEDesc to a Mac file spec. */  
	err = AEGetNthPtr(&reply.selection, 1, typeFSS, NULL, NULL, &fileSpec, sizeof(fileSpec), NULL);  
	if (err != noErr)  
		goto bail;  
	  
	/* Then convert the FSSpec to a full path. */  
	err = FSSpecToPathName(&fileSpec, outFileName);  
	if (err != noErr)  
		goto bail;  
	  
	NavDisposeReply(&reply);  
	return 1;  
	  
bail:  
	NavDisposeReply(&reply);  
	return 0;  
	  
	  
}  
  
void	DoUserAlert(const char * inMsg)  
{  
	Str255	p1;  
	size_t	sl;  
	  
	sl = strlen(inMsg);  
	if (sl > 255)   
		sl = 255;  
	  
	p1[0] = sl;  
	memcpy(p1+1, inMsg, sl);  
	  
	StandardAlert(kAlertStopAlert, p1, "\p", NULL, NULL);  
}  
  
void	ShowProgressMessage(const char * inMsg)  
{  
	Handle	item;  
	Str255	pStr;  
	Rect	r;  
	DialogItemType	t;  
	  
	pStr[0] = strlen(inMsg);  
	memcpy(pStr+1, inMsg, pStr[0]);  
	  
	if (sDialog == NULL)  
	{  
		/* If our dialog isn't up, put it up. */  
		sDialog = GetNewDialog(128, NULL, (WindowRef) -1L);  
		ShowWindow(GetDialogWindow(sDialog));  
	}  
	  
	GetDialogItem(sDialog, 1, &t, &item, &r);  
	SetDialogItemText(item, pStr);  
}  
  
int		ConfirmMessage(const char * inMsg, const char * proceedBtn, const char * cancelBtn)  
{  
	Str255					pStr, proStr, clcStr;  
	AlertStdAlertParamRec	params;  
	short					itemHit;  
	  
	pStr[0] = strlen(inMsg);  
	memcpy(pStr+1,inMsg,pStr[0]);  
	proStr[0] = strlen(proceedBtn);  
	memcpy(proStr+1, proceedBtn, proStr[0]);  
	clcStr[0] = strlen(cancelBtn);  
	memcpy(clcStr+1, cancelBtn, clcStr[0]);  
	  
	params.movable = false;  
	params.helpButton = false;  
	params.filterProc = NULL;  
	params.defaultText = proStr;  
	params.cancelText = clcStr;  
	params.otherText = NULL;  
	params.defaultButton = 1;  
	params.cancelButton = 2;  
	params.position = kWindowDefaultPosition;  
	  
	StandardAlert(kAlertCautionAlert, pStr, "\p", &params, &itemHit);  
	  
	return (itemHit == 1);		  
}  
  
/*  
 * FSSpecToPathName  
 *  
 * This routine builds a full path from a file spec by recursing up the directory  
 * tree to the route, prepending each directory name.  
 *  
 */  
  
OSErr	FSSpecToPathName(const FSSpec * inFileSpec, char * outPathname)  
{  
	short			vRefNum = inFileSpec->vRefNum;  
	long			startDirID = inFileSpec->parID;  
	  
	CInfoPBRec		paramRec;  
	Str255			dirName;	/* This will contain the name of the directory we get info about. */  
	OSErr 			err = noErr;  
	  
	paramRec.dirInfo.ioCompletion = nil;  
	paramRec.dirInfo.ioNamePtr = (StringPtr)(&dirName);  
	paramRec.dirInfo.ioDrParID = startDirID;  
	  
	/* Start by putting a directory separator and the file name on the path. */  
	outPathname[0] = ':';  
	memcpy(outPathname+1, inFileSpec->name+1, inFileSpec->name[0]);  
	outPathname[inFileSpec->name[0]+1] = 0;  
	  
	do {  
		paramRec.dirInfo.ioVRefNum = vRefNum;  
		paramRec.dirInfo.ioFDirIndex = -1;  
		paramRec.dirInfo.ioDrDirID = paramRec.dirInfo.ioDrParID;  
		  
		if (!(err = PBGetCatInfoSync(&paramRec)))   
		{  
			/* For each directory we get info about, prepend a : and the directory name.  
			 But for the root directory, do NOT prepend the colon. */  
			short	newPart = dirName[0] + ((paramRec.dirInfo.ioDrDirID != fsRtDirID) ? 1 : 0);  
			memmove(outPathname+newPart, outPathname, strlen(outPathname)+1);  
			if (paramRec.dirInfo.ioDrDirID != fsRtDirID)  
			{  
				outPathname[0] = ':';  
				memcpy(outPathname+1, dirName+1, dirName[0]);  
			} else   
				memcpy(outPathname, dirName+1, dirName[0]);  
		}  
	} while ((err == noErr) && (paramRec.dirInfo.ioDrDirID != fsRtDirID));  
	return err;  
}  
  

then to use:

  
  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
	  
	char path[1024];  
	if (GetFilePathFromUser("please pick a file", path)){  
		printf("user picked: %s \n", path);  
	} else {  
		printf("user cancelled \n");  
	}  
}  
  
  

currently I am getting back mac paths, like

user picked: Macintosh HD:Users:zach:Downloads:myLine2.cpp

but I guess that you could either change that to be a unix path by hand, or by altering “FSSpecToPathName”

hope that helps!

best,
zach

thanks zach, I will check that out. It would be a great addon indeed!

I will propably use this to load images. can I only replace the “:” in the mac path to “/” so of will understand it? does ofImage support paths anyways?

EDIT: Okay I just got it. A unix path to something on my desktop would be:

/Users/matthiasdorfelt/Desktop/blubb.jpg

it also works with ofImage, great!

here is another post with some solutions for an open dialog in os x.
http://forum.openframeworks.cc/t/file-dialog/955/0

Does anybody have similar code for saving files to the harddrive?

nobody?

edit:

just found something in the other thread:

http://forum.openframeworks.cc/t/file-dialog/955/0

Questions over questions:

I would like to tell the open Dialogue only to accept .jpg and .png files. Right now I would just check it afterwards. Is there a way to tell it to only accept certain file types?

And what would I have to change to be able to select multiple files at once?

Thanks!

Okay, I figgured it out myself. Was quite alot of pain since apples documentation is pretty bad (especially the search function ):

this function allows me to select multiple images at once and return me the according paths so I can load the via OFs loadImage:

  
struct path{  
	char p[1024];  
};  
vector<path> GetOpenFilesFromUser()  
{  
	NavDialogCreationOptions dialogOptions;  
	NavDialogRef dialog;  
	NavReplyRecord replyRecord;  
	vector<FSRef> fileAsFSRef;  
	vector<path> files;  
	OSStatus status;  
	  
	// Get the standard set of defaults  
	status = NavGetDefaultDialogCreationOptions(&dialogOptions);  
	require_noerr( status, CantGetNavOptions );  
	  
	// Make the window app-wide modal  
	dialogOptions.modality = kWindowModalityAppModal;  
	  
	// Create the dialog  
	status = NavCreateGetFileDialog(&dialogOptions, NULL, NULL, NULL, NULL, NULL, &dialog);  
	require_noerr( status, CantCreateDialog );  
	  
	// Filter, so you can only select .jpg or .png  
	CFMutableArrayRef identifiers = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);  
	CFArrayAppendValue(identifiers, kUTTypeJPEG);  
	CFArrayAppendValue(identifiers, kUTTypePNG);  
	CFArrayAppendValue(identifiers, kUTTypeTIFF);  
  
	status = NavDialogSetFilterTypeIdentifiers(dialog, identifiers);  
	require_noerr( status, CantRunDialog );  
	  
	// Show it  
	status = NavDialogRun(dialog);  
	require_noerr( status, CantRunDialog );  
	  
	// Get the reply  
	status = NavDialogGetReply(dialog, &replyRecord);  
	require( ((status == noErr) || (status == userCanceledErr)), CantGetReply );  
	  
	// If the user clicked "Cancel", just bail  
	if ( status == userCanceledErr ) goto UserCanceled;  
	  
	// Get File Count  
	long numFiles;  
	AECountItems(&(replyRecord.selection), &numFiles);  
	  
	// Get the files  
	for(int i=0; i<numFiles; i++){  
		FSRef f;  
		path p;  
  
		fileAsFSRef.push_back(f);  
	    status = AEGetNthPtr(&(replyRecord.selection), i+1, typeFSRef, NULL, NULL, &fileAsFSRef.at(i), sizeof(FSRef), NULL);  
		  
		//Convert to Path  
		FSRefMakePath( &fileAsFSRef.at(i), ( UInt8 * ) p.p, sizeof( p ) );  
		files.push_back(p);  
		//cout<<files.back().p<<endl;  
	}  
	  
	require_noerr( status, CantExtractFSRef );  
	  
	// Cleanup  
CantExtractFSRef:  
UserCanceled:  
	verify_noerr( NavDisposeReply(&replyRecord) );  
CantGetReply:  
CantRunDialog:  
	NavDialogDispose(dialog);  
CantCreateDialog:  
CantGetNavOptions:  
	return files;  
}  

I am pretty sure that this is not the best way but it works fast and good for me.

Very useful! Works great in 0.06 too.

It would be good to get this going cross platform, but I hate COM! Anyone with any experience?

Cheers,

JGL

I’ve been playing around with this kind of Cocoa dialog for a while, and the problem I have is that it jams the rest of the application while it’s running…

I’d like to be able to use the standard Mac dialog to open video files, but I don’t want it to stop a video that is already playing.

Has anyone had any luck getting a dialog box to open in a thread?

From what I can see this isn’t as simple as using the ofxThread method, as Cocoa requires it’s own threading (NSThread) and memory management (NSAutoReleasePool)…???

Any suggestions would be most welcome.

I’ve had this issues as well. It has something to do with the runloop/clock system in OSX. There are 3 different clocks that come in to play depending on what “mode” the application is in.

  
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode];   
		[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSModalPanelRunLoopMode];   
		[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];   

I forget exactly what NSEventTrackingRunLoopMode means, but NSDefaultRunLoopMode is during standard operation, NSModalPanelRunLoopMode is the one you’re actually looking for as it kicks in when the open file panel shows up. As for how to get this to drive the GLUT/OF timer, I can’t say but this is certainly where you should start looking.