// OS specific results here. "" = cancel or something bad like can't load, can't save, etc... ofFileDialogResult ofFileLoadDialog(string windowTitle, bool bFolderSelection){ ofFileDialogResult results; //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ OSX //---------------------------------------------------------------------------------------- #ifdef TARGET_OSX CFURLRef cfUrl = GetOpenFileFromUser(bFolderSelection); CFStringRef cfString = NULL; if ( cfUrl != NULL ){ cfString = CFURLCopyFileSystemPath( cfUrl, kCFURLPOSIXPathStyle ); CFRelease( cfUrl ); // copy from a CFString into a local c string (http://www.carbondev.com/site/?page=CStrings+) const int kBufferSize = MAXPATHLEN; char fileUrl[kBufferSize]; Boolean bool1 = CFStringGetCString(cfString,fileUrl,kBufferSize,kCFStringEncodingMacRoman); //char fileName[kBufferSize]; //Boolean bool2 = CFStringGetCString(reply.saveFileName,fileName,kBufferSize,kCFStringEncodingMacRoman); // append strings together results.filePath = fileUrl; } #endif //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ windoze //---------------------------------------------------------------------------------------- #ifdef TARGET_WIN32 // TODO pc file choose dialog is now mega broken, please fix! if (bFolderSelection == false){ wchar_t szFileName[MAX_PATH] = L""; OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); HWND hwnd = WindowFromDC(wglGetCurrentDC()); ofn.hwndOwner = hwnd; ofn.lpstrFilter = _T("All Files (*.*)\0*.*\0"); ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = 0; if(GetOpenFileName(&ofn)) { results.filePath = convertWideToNarrow(szFileName); // TODO: name conversion, please!! } } else { BROWSEINFO bi; wchar_t wideCharacterBuffer[MAX_PATH]; LPITEMIDLIST pidl; LPMALLOC lpMalloc; // Get a pointer to the shell memory allocator if(SHGetMalloc(&lpMalloc) != S_OK){ //TODO: deal with some sort of error here? } bi.hwndOwner = NULL; bi.pidlRoot = NULL; bi.pszDisplayName = wideCharacterBuffer; bi.lpszTitle = _T("Select Directory"); bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS; bi.lpfn = NULL; bi.lParam = 0; if(pidl = SHBrowseForFolder(&bi)){ // Copy the path directory to the buffer if(SHGetPathFromIDList(pidl,wideCharacterBuffer)){ results.filePath = convertWideToNarrow(wideCharacterBuffer); } lpMalloc->Free(pidl); } lpMalloc->Release(); } //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ windoze //---------------------------------------------------------------------------------------- #endif //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ linux //---------------------------------------------------------------------------------------- #if defined( TARGET_LINUX ) && defined (OF_USING_GTK) if(bFolderSelection) results.filePath = gtkFileDialog(GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,windowTitle); else results.filePath = gtkFileDialog(GTK_FILE_CHOOSER_ACTION_OPEN,windowTitle); #endif //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- if( results.filePath.length() > 0 ){ results.bSuccess = true; results.fileName = ofFileUtils::getFilenameFromPath(results.filePath); } return results; }
ofFileDialogResult ofFileSaveDialog(string defaultName, string messageName){ ofFileDialogResult results; //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ OSX //---------------------------------------------------------------------------------------- #ifdef TARGET_OSX short fRefNumOut; FSRef output_file; OSStatus err; NavDialogCreationOptions options; NavGetDefaultDialogCreationOptions( &options ); options.optionFlags = kNavNoTypePopup + kNavSupportPackages + kNavAllowOpenPackages; options.modality = kWindowModalityAppModal; options.optionFlags = kNavDefaultNavDlogOptions; options.message = CFStringCreateWithCString(NULL, messageName.c_str(), kCFStringEncodingASCII);; options.saveFileName = CFStringCreateWithCString(NULL, defaultName.c_str(), kCFStringEncodingASCII); NavDialogRef dialog; err = NavCreatePutFileDialog(&options, '.mov', 'Moov', NULL, NULL, &dialog); //printf("NavCreatePutFileDialog returned %i\n", err ); err = NavDialogRun(dialog); //printf("NavDialogRun returned %i\n", err ); NavUserAction action; action = NavDialogGetUserAction( dialog ); //printf("got action %i\n", action); if (action == kNavUserActionNone || action == kNavUserActionCancel) { return results; } // get dialog reply NavReplyRecord reply; err = NavDialogGetReply(dialog, &reply); if ( err != noErr ) return results; if ( reply.replacing ) { printf("need to replace\n"); } AEKeyword keyword; DescType actual_type; Size actual_size; FSRef output_dir; err = AEGetNthPtr(&(reply.selection), 1, typeFSRef, &keyword, &actual_type, &output_dir, sizeof(output_file), &actual_size); //printf("AEGetNthPtr returned %i\n", err ); CFURLRef cfUrl = CFURLCreateFromFSRef( kCFAllocatorDefault, &output_dir ); CFStringRef cfString = NULL; if ( cfUrl != NULL ) { cfString = CFURLCopyFileSystemPath( cfUrl, kCFURLPOSIXPathStyle ); CFRelease( cfUrl ); } // copy from a CFString into a local c string (http://www.carbondev.com/site/?page=CStrings+) const int kBufferSize = 255; char folderURL[kBufferSize]; Boolean bool1 = CFStringGetCString(cfString,folderURL,kBufferSize,kCFStringEncodingMacRoman); char fileName[kBufferSize]; Boolean bool2 = CFStringGetCString(reply.saveFileName,fileName,kBufferSize,kCFStringEncodingMacRoman); // append strings together string url1 = folderURL; string url2 = fileName; string finalURL = url1 + "/" + url2; results.filePath = finalURL.c_str(); //printf("url %s\n", finalURL.c_str()); // cleanup dialog NavDialogDispose(dialog); #endif //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ windoze //---------------------------------------------------------------------------------------- #ifdef TARGET_WIN32 wchar_t fileName[MAX_PATH] = L""; char * extension; OPENFILENAME ofn; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); HWND hwnd = WindowFromDC(wglGetCurrentDC()); ofn.hwndOwner = hwnd; ofn.hInstance = GetModuleHandle(0); ofn.nMaxFileTitle = 31; ofn.lpstrFile = fileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFilter = _T("All Files (*.*)\0*.*\0"); ofn.lpstrDefExt = _T(""); // we could do .rxml here? ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; ofn.lpstrTitle = _T("Select Output File"); if (GetSaveFileName(&ofn)){ results.filePath = convertWideToNarrow(fileName); } #endif //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //------------------------------------------------------------------------------ linux //---------------------------------------------------------------------------------------- #if defined( TARGET_LINUX ) && defined (OF_USING_GTK) gtkFileDialog(GTK_FILE_CHOOSER_ACTION_SAVE, messageName,defaultName); #endif //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- if( results.filePath.length() > 0 ){ results.bSuccess = true; results.fileName = ofFileUtils::getFilenameFromPath(results.filePath); } return results; }
bool ofxVideoRecorder::setupCustomOutput(int w, int h, float fps, int sampleRate, int channels, string outputString, bool sysClockSync, bool silent) { if (bIsInitialized) { close(); } bIsSilent = silent; bSysClockSync = sysClockSync; bRecordAudio = (sampleRate > 0 && channels > 0); bRecordVideo = (w > 0 && h > 0 && fps > 0); bFinishing = false; videoFramesRecorded = 0; audioSamplesRecorded = 0; if (!bRecordVideo && !bRecordAudio) { ofLogWarning() << "ofxVideoRecorder::setupCustomOutput(): invalid parameters, could not setup video or audio stream.\n" << "video: " << w << "x" << h << "@" << fps << "fps\n" << "audio: " << "channels: " << channels << " @ " << sampleRate << "Hz\n"; return false; } videoPipePath = ""; audioPipePath = ""; pipeNumber = requestPipeNumber(); if (bRecordVideo) { width = w; height = h; frameRate = fps; #if defined( TARGET_OSX ) || defined( TARGET_LINUX ) // recording video, create a FIFO pipe videoPipePath = ofFilePath::getAbsolutePath("ofxvrpipe" + ofToString(pipeNumber)); ofStringReplace(videoPipePath, " ", "\\ "); if (!ofFile::doesFileExist(videoPipePath)) { string cmd = "bash --login -c 'mkfifo " + videoPipePath + "'"; system(cmd.c_str()); } #endif #ifdef TARGET_WIN32 char vpip[128]; int num = ofRandom(1024); sprintf(vpip, "\\\\.\\pipe\\videoPipe%d", num); vPipename = convertCharArrayToLPCWSTR(vpip); hVPipe = CreateNamedPipe( vPipename, // name of the pipe PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only PIPE_TYPE_BYTE, // send data as a byte stream 1, // only allow 1 instance of this pipe 0, // outbound buffer defaults to system default 0, // no inbound buffer 0, // use default wait time NULL // use default security attributes ); if (!(hVPipe != INVALID_HANDLE_VALUE)) { if (GetLastError() != ERROR_PIPE_BUSY) { ofLogError("Video Pipe") << "Could not open video pipe."; } // All pipe instances are busy, so wait for 5 seconds. if (!WaitNamedPipe(vPipename, 5000)) { ofLogError("Video Pipe") << "Could not open video pipe: 5 second wait timed out."; } } #endif } if (bRecordAudio) { this->sampleRate = sampleRate; audioChannels = channels; #if defined( TARGET_OSX ) || defined( TARGET_LINUX ) // recording video, create a FIFO pipe audioPipePath = ofFilePath::getAbsolutePath("ofxarpipe" + ofToString(pipeNumber)); ofStringReplace(audioPipePath, " ", "\\ "); if (!ofFile::doesFileExist(audioPipePath)) { string cmd = "bash --login -c 'mkfifo " + audioPipePath + "'"; system(cmd.c_str()); } #endif #ifdef TARGET_WIN32 char apip[128]; int num = ofRandom(1024); sprintf(apip, "\\\\.\\pipe\\videoPipe%d", num); aPipename = convertCharArrayToLPCWSTR(apip); hAPipe = CreateNamedPipe( aPipename, PIPE_ACCESS_OUTBOUND, // 1-way pipe -- send only PIPE_TYPE_BYTE, // send data as a byte stream 1, // only allow 1 instance of this pipe 0, // outbound buffer defaults to system default 0, // no inbound buffer 0, // use default wait time NULL // use default security attributes ); if (!(hAPipe != INVALID_HANDLE_VALUE)) { if (GetLastError() != ERROR_PIPE_BUSY) { ofLogError("Audio Pipe") << "Could not open audio pipe."; } // All pipe instances are busy, so wait for 5 seconds. if (!WaitNamedPipe(aPipename, 5000)) { ofLogError("Audio Pipe") << "Could not open pipe: 5 second wait timed out."; } } #endif } stringstream cmd; // basic ffmpeg invocation, -y option overwrites output file #if defined( TARGET_OSX ) || defined( TARGET_LINUX ) cmd << "bash --login -c '" << ffmpegLocation << (bIsSilent ? " -loglevel quiet " : " ") << "-y"; if (bRecordAudio) { cmd << " -acodec pcm_s16le -f s16le -ar " << sampleRate << " -ac " << audioChannels << " -i " << audioPipePath; } else { // no audio stream cmd << " -an"; } if (bRecordVideo) { // video input options and file cmd << " -r " << fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat << " -i " << videoPipePath << " -r " << fps; } else { // no video stream cmd << " -vn"; } cmd << " " + outputString + "' &"; //cerr << cmd.str(); ffmpegThread.setup(cmd.str()); // start ffmpeg thread, will wait for input pipes to be opened if (bRecordAudio) { audioThread.setup(audioPipePath, &audioFrames); } if (bRecordVideo) { videoThread.setup(videoPipePath, &frames); } #endif #ifdef TARGET_WIN32 //evidently there are issues with multiple named pipes http://trac.ffmpeg.org/ticket/1663 if (bRecordAudio && bRecordVideo) { bool fSuccess; // Audio Thread stringstream aCmd; aCmd << ffmpegLocation << " -y " << " -f s16le -acodec " << audioCodec << " -ar " << sampleRate << " -ac " << audioChannels; aCmd << " -i " << convertWideToNarrow(aPipename) << " -b:a " << audioBitrate << " " << outputString << "_atemp" << audioFileExt; ffmpegAudioThread.setup(aCmd.str()); ofLogNotice("FFMpeg Command") << aCmd.str() << endl; fSuccess = ConnectNamedPipe(hAPipe, NULL); if (!fSuccess) { LPTSTR errorText = NULL; FormatMessageW( // use system message tables to retrieve error text FORMAT_MESSAGE_FROM_SYSTEM // allocate buffer on local heap for error text | FORMAT_MESSAGE_ALLOCATE_BUFFER // Important! will fail otherwise, since we're not // (and CANNOT) pass insertion parameters | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorText, // output 0, // minimum size for output buffer NULL); // arguments - see note wstring ws = errorText; string error(ws.begin(), ws.end()); ofLogError("Audio Pipe") << "SetNamedPipeHandleState failed: " << error; } else { ofLogNotice("Audio Pipe") << "\n==========================\nAudio Pipe Connected Successfully\n==========================\n" << endl; audioThread.setup(hAPipe, &audioFrames); } // Video Thread stringstream vCmd; vCmd << ffmpegLocation << " -y " << " -r " << fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat; vCmd << " -i " << convertWideToNarrow(vPipename) << " -vcodec " << videoCodec << " -b:v " << videoBitrate << " " << outputString << "_vtemp" << movFileExt; ffmpegVideoThread.setup(vCmd.str()); ofLogNotice("FFMpeg Command") << vCmd.str() << endl; fSuccess = ConnectNamedPipe(hVPipe, NULL); if (!fSuccess) { LPTSTR errorText = NULL; FormatMessageW( // use system message tables to retrieve error text FORMAT_MESSAGE_FROM_SYSTEM // allocate buffer on local heap for error text | FORMAT_MESSAGE_ALLOCATE_BUFFER // Important! will fail otherwise, since we're not // (and CANNOT) pass insertion parameters | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorText, // output 0, // minimum size for output buffer NULL); // arguments - see note wstring ws = errorText; string error(ws.begin(), ws.end()); ofLogError("Video Pipe") << "SetNamedPipeHandleState failed: " << error; } else { ofLogNotice("Video Pipe") << "\n==========================\nVideo Pipe Connected Successfully\n==========================\n" << endl; videoThread.setup(hVPipe, &frames); } } else { cmd << ffmpegLocation << " -y "; if (bRecordAudio) { cmd << " -f s16le -acodec " << audioCodec << " -ar " << sampleRate << " -ac " << audioChannels << " -i " << convertWideToNarrow(aPipename); } else { // no audio stream cmd << " -an"; } if (bRecordVideo) { // video input options and file cmd << " -r " << fps << " -s " << w << "x" << h << " -f rawvideo -pix_fmt " << pixelFormat << " -i " << convertWideToNarrow(vPipename); } else { // no video stream cmd << " -vn"; } if (bRecordAudio) cmd << " -b:a " << audioBitrate; if (bRecordVideo) cmd << " -vcodec " << videoCodec << " -b:v " << videoBitrate; cmd << " " << outputString << movFileExt; ofLogNotice("FFMpeg Command") << cmd.str() << endl; ffmpegThread.setup(cmd.str()); // start ffmpeg thread, will wait for input pipes to be opened if (bRecordAudio) { //this blocks, so we have to call it after ffmpeg is listening for a pipe bool fSuccess = ConnectNamedPipe(hAPipe, NULL); if (!fSuccess) { LPTSTR errorText = NULL; FormatMessageW( // use system message tables to retrieve error text FORMAT_MESSAGE_FROM_SYSTEM // allocate buffer on local heap for error text | FORMAT_MESSAGE_ALLOCATE_BUFFER // Important! will fail otherwise, since we're not // (and CANNOT) pass insertion parameters | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorText, // output 0, // minimum size for output buffer NULL); // arguments - see note wstring ws = errorText; string error(ws.begin(), ws.end()); ofLogError("Audio Pipe") << "SetNamedPipeHandleState failed: " << error; } else { ofLogNotice("Audio Pipe") << "\n==========================\nAudio Pipe Connected Successfully\n==========================\n" << endl; audioThread.setup(hAPipe, &audioFrames); } } if (bRecordVideo) { //this blocks, so we have to call it after ffmpeg is listening for a pipe bool fSuccess = ConnectNamedPipe(hVPipe, NULL); if (!fSuccess) { LPTSTR errorText = NULL; FormatMessageW( // use system message tables to retrieve error text FORMAT_MESSAGE_FROM_SYSTEM // allocate buffer on local heap for error text | FORMAT_MESSAGE_ALLOCATE_BUFFER // Important! will fail otherwise, since we're not // (and CANNOT) pass insertion parameters | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&errorText, // output 0, // minimum size for output buffer NULL); // arguments - see note wstring ws = errorText; string error(ws.begin(), ws.end()); ofLogError("Video Pipe") << "SetNamedPipeHandleState failed: " << error; } else { ofLogNotice("Video Pipe") << "\n==========================\nVideo Pipe Connected Successfully\n==========================\n" << endl; videoThread.setup(hVPipe, &frames); } } } #endif bIsInitialized = true; bIsRecording = false; bIsPaused = false; startTime = 0; recordingDuration = 0; totalRecordingDuration = 0; return bIsInitialized; }