bool Exporter::CheckMix() { // Clean up ... should never happen if (mMixerSpec) { delete mMixerSpec; mMixerSpec = NULL; } // Detemine if exported file will be stereo or mono or multichannel, // and if mixing will occur. int downMix = gPrefs->Read(wxT("/FileFormats/ExportDownMix"), true); if (downMix) { if (mNumRight > 0 || mNumLeft > 0) { mChannels = 2; } else { mChannels = 1; } int numLeft = mNumLeft + mNumMono; int numRight = mNumRight + mNumMono; if (numLeft > 1 || numRight > 1) if (mChannels == 2) { ShowWarningDialog(mProject, wxT("MixStereo"), _("Your tracks will be mixed down to two stereo channels in the exported file.")); } else { ShowWarningDialog(mProject, wxT("MixMono"), _("Your tracks will be mixed down to a single mono channel in the exported file.")); } } else { ExportMixerDialog md(mProject->GetTracks(), mSelectedOnly, mPlugins[mFormat]->GetMaxChannels(), NULL, 1, _("Advanced Mixing Options")); if (md.ShowModal() != wxID_OK) { return false; } mMixerSpec = new MixerSpec(*(md.GetMixerSpec())); mChannels = mMixerSpec->GetNumChannels(); } return true; }
DirManager::DirManager() { wxLogDebug("DirManager: Created new instance"); mRef = 1; // MM: Initial refcount is 1 by convention numDirManagers++; projPath = ""; projName = ""; mLoadingTarget = NULL; hashTableSize = defaultHashTableSize; blockFileHash = new wxHashTable(wxKEY_STRING, hashTableSize); // Make sure there is plenty of space for temp files //BG: wxWindows 2.3.2 and higher claim to support this, //through a function called wxGetDiskSpace wxLongLong freeSpace; wxGetDiskSpace(temp, NULL, &freeSpace); if (freeSpace >= 0) { if (freeSpace < 1048576) { ShowWarningDialog(NULL, "DiskSpaceWarning", _("Warning: there is very little free disk space left on this " "volume. Please select another temporary directory in your " "preferences.")); } } }
DirManager::DirManager() { wxLogDebug(wxT("DirManager: Created new instance")); mRef = 1; // MM: Initial refcount is 1 by convention // this need not be strictly uniform or random, but it should give // unclustered numbers srand(time(0)); // Set up local temp subdir // Previously, Audacity just named project temp directories "project0", // "project1" and so on. But with the advent of recovery code, we need an // unique name even after a crash. So we create a random project index // and make sure it is not used already. This will not pose any performance // penalties as long as the number of open Audacity projects is much // lower than RAND_MAX. do { mytemp = globaltemp + wxFILE_SEP_PATH + wxString::Format(wxT("project%d"), rand()); } while (wxDirExists(mytemp)); numDirManagers++; projPath = wxT(""); projName = wxT(""); mLoadingTarget = NULL; mMaxSamples = -1; // toplevel pool hash is fully populated to begin { int i; for(i=0; i< 256; i++) dirTopPool[i]=0; } // Make sure there is plenty of space for temp files wxLongLong freeSpace = 0; { //create a temporary null log to capture the log dialog //that wxGetDiskSpace creates. It gets destroyed when //it goes out of context. //JKC: Please explain why. wxLogNull logNo; if (wxGetDiskSpace(globaltemp, NULL, &freeSpace)) { if (freeSpace < 1048576) { ShowWarningDialog(NULL, wxT("DiskSpaceWarning"), _("Warning: there is very little free disk space left on this volume.\nPlease select another temporary directory in your preferences.")); } } } }
/* * This first function contains the code common to both * Export() and ExportLossy() * * For safety, if the file already exists it stores the filename * the user wants in actualName, and returns a temporary file name. * The calling function should rename the file when it's successfully * exported. */ wxString ExportCommon( AudacityProject *project, wxString format, wxString defaultExtension, bool selectionOnly, double *t0, double *t1, int *numChannels, wxString &actualName, int maxNumChannels, MixerSpec **mixerSpec ) { TrackList *tracks = project->GetTracks(); /* First analyze the selected audio, perform sanity checks, and provide * information as appropriate. */ /* Tally how many are right, left, mono, and make sure at least one track is selected (if selectionOnly==true) */ int numSelected = 0, numLeft = 0, numRight = 0, numMono = 0; float earliestBegin = *t1; float latestEnd = *t0; TrackListIterator iter1(tracks); Track *tr = iter1.First(); while (tr) { if (tr->GetKind() == Track::Wave) { if (tr->GetSelected() || !selectionOnly) { numSelected++; if (tr->GetChannel() == Track::LeftChannel) numLeft++; else if (tr->GetChannel() == Track::RightChannel) numRight++; else if (tr->GetChannel() == Track::MonoChannel) { // It's a mono channel, but it may be panned float pan = ((WaveTrack*)tr)->GetPan(); if (pan == -1.0) numLeft++; else if (pan == 1.0) numRight++; else if (pan == 0) numMono++; else { // Panned partially off-center. Mix as stereo. numLeft++; numRight++; } } if(tr->GetOffset() < earliestBegin) earliestBegin = tr->GetOffset(); if(tr->GetEndTime() > latestEnd) latestEnd = tr->GetEndTime(); } } tr = iter1.Next(); } if(*t0 < earliestBegin) *t0 = earliestBegin; if(*t1 > latestEnd) *t1 = latestEnd; if (numSelected == 0 && selectionOnly) { wxMessageBox(_("No tracks are selected! Use Ctrl-A (Select All)\nChoose Export... to export all tracks."), _("Unable to export"), wxOK | wxICON_INFORMATION); return wxT(""); } /* Detemine if exported file will be stereo or mono or multichannel, and if mixing will occur */ bool downMix = (gPrefs->Read( wxT("/FileFormats/ExportDownMix" ), true ) !=0) ? true:false ; int channels; if( downMix || !mixerSpec ) { if (numRight > 0 || numLeft > 0) channels = 2; else channels = 1; numRight += numMono; numLeft += numMono; if (numLeft > 1 || numRight > 1) if (channels == 2) { ShowWarningDialog(project, wxT("MixStereo"), _("Your tracks will be mixed down to two stereo channels in the exported file.")); } else { ShowWarningDialog(project, wxT("MixMono"), _("Your tracks will be mixed down to a single mono channel in the exported file.")); } } else { ExportMixerDialog md( tracks, selectionOnly, maxNumChannels, NULL, 1, _( "Advanced Mixing Options" ) ); if( md.ShowModal() != wxID_OK ) return wxT( "" ); *mixerSpec = new MixerSpec( *( md.GetMixerSpec() ) ); channels = ( *mixerSpec )->GetNumChannels(); } /* Prepare and display the filename selection dialog */ wxString path = gPrefs->Read(wxT("/DefaultExportPath"), ::wxGetCwd()); wxString nameOnly; wxString extension; wxString defaultName = project->GetName(); wxString fName; wxString maskString; wxString endOfPathSep; #if 0 // this code shouldn't be here --dmazzoni //MERGE exercise exception if (defaultName == wxT("ThrowExceptionOnExport")) { //lda throw("Exercise exception"); } #endif if (defaultExtension.Left(1) == wxT(".")) defaultExtension = defaultExtension.Right(defaultExtension.Length()-1); maskString.Printf(wxT("%s files (*.%s)|*.%s|All files (*.*)|*.*"), format.c_str(), defaultExtension.c_str(), defaultExtension.c_str()); bool fileOkay; do { fileOkay = true; fName = defaultName + wxT(".") + defaultExtension; fName = wxFileSelector(wxString::Format(_("Save %s File As:"), format.c_str()), path, fName, // default file name defaultExtension, maskString, wxSAVE | wxOVERWRITE_PROMPT); if (fName.Length() >= 256) { wxMessageBox (_("Sorry, pathnames longer than 256 characters not supported.")); return wxT(""); } if (fName == wxT("")) return wxT(""); ::wxSplitPath(fName, &path, &nameOnly, &extension); // // Make sure the user doesn't accidentally save the file // as an extension with no name, like just plain ".wav". // if ((nameOnly.Left(1)==wxT(".") && extension==wxT("")) || (nameOnly==wxT("") && extension!=wxT(""))) { wxString prompt = _("Are you sure you want to save the file as \"")+ ::wxFileNameFromPath(fName)+wxT("\"?\n"); int action = wxMessageBox(prompt, wxT("Warning"), wxYES_NO | wxICON_EXCLAMATION, project); fileOkay = (action == wxYES); continue; } // // Check the extension - add the default if it's not there, // and warn user if it's abnormal. // wxString defaultExtension3 = defaultExtension; if (defaultExtension.Length() > 3) defaultExtension = defaultExtension.Left(3); if (extension == wxT("")) { #ifdef __WXMSW__ // Windows prefers 3-char uppercase extensions extension = defaultExtension; #else // Linux and Mac prefer lowercase extensions extension = defaultExtension.Lower(); #endif } else if (extension.Upper() != defaultExtension.Upper() && extension.Upper() != defaultExtension3.Upper()) { #ifdef __WXMSW__ // Windows prefers 3-char extensions defaultExtension3 = defaultExtension3; #endif wxString prompt; prompt.Printf(_("You are about to save a %s file with the name %s.\nNormally these files end in %s, and some programs will not open files with nonstandard extensions.\nAre you sure you want to save the file under this name?"), format.c_str(), (wxT("\"")+nameOnly+wxT(".")+extension+wxT("\"")).c_str(), (wxT("\".")+defaultExtension+wxT("\"")).c_str()); int action = wxMessageBox(prompt, wxT("Warning"), wxYES_NO | wxICON_EXCLAMATION, project); if (action == wxYES) fileOkay = true; else { fileOkay = false; defaultName = nameOnly + wxT(".") + extension; } } if (path.Length() > 0 && path.Last() == wxFILE_SEP_PATH) endOfPathSep = wxT(""); else endOfPathSep = wxFILE_SEP_PATH; fName = path + endOfPathSep + nameOnly + wxT(".") + extension; } while(!fileOkay); /* * Ensure that exporting a file by this name doesn't overwrite * one of the existing files in the project. (If it would * overwrite an existing file, DirManager tries to rename the * existing file.) */ if (!project->GetDirManager()->EnsureSafeFilename(wxFileName(fName))) return wxT(""); gPrefs->Write(wxT("/DefaultExportPath"), path); *numChannels = channels; /* * To be even MORE safe, return a temporary file name based * on this one... */ actualName = fName; int suffix = 0; while(::wxFileExists(fName)) { fName = path + endOfPathSep + nameOnly + wxString::Format(wxT("%d"), suffix) + wxT(".") + extension; suffix++; } return fName; }
/* * This first function contains the code common to both * Export() and ExportLossy() * * For safety, if the file already exists it stores the filename * the user wants in actualName, and returns a temporary file name. * The calling function should rename the file when it's successfully * exported. */ wxString ExportCommon(AudacityProject *project, wxString format, wxString defaultExtension, bool selectionOnly, double *t0, double *t1, bool *isStereo, wxString &actualName) { TrackList *tracks = project->GetTracks(); /* First analyze the selected audio, perform sanity checks, and provide * information as appropriate. */ /* Tally how many are right, left, mono, and make sure at least one track is selected (if selectionOnly==true) */ int numSelected = 0, numLeft = 0, numRight = 0, numMono = 0; float earliestBegin = *t1; float latestEnd = *t0; TrackListIterator iter1(tracks); Track *tr = iter1.First(); while (tr) { if (tr->GetKind() == Track::Wave) { if (tr->GetSelected() || !selectionOnly) { numSelected++; if (tr->GetChannel() == Track::LeftChannel) numLeft++; else if (tr->GetChannel() == Track::RightChannel) numRight++; else if (tr->GetChannel() == Track::MonoChannel) { // It's a mono channel, but it may be panned float pan = ((WaveTrack*)tr)->GetPan(); if (pan == -1.0) numLeft++; else if (pan == 1.0) numRight++; else if (pan == 0) numMono++; else { numLeft++; numRight++; } } if(tr->GetOffset() < earliestBegin) earliestBegin = tr->GetOffset(); if(tr->GetEndTime() > latestEnd) latestEnd = tr->GetEndTime(); } } tr = iter1.Next(); } if(*t0 < earliestBegin) *t0 = earliestBegin; if(*t1 > latestEnd) *t1 = latestEnd; if (numSelected == 0 && selectionOnly) { wxMessageBox(_("No tracks are selected!\n" "Choose Export... to export all tracks.")); return ""; } /* Detemine if exported file will be stereo or mono, and if mixing will occur */ bool stereo = false; if (numRight > 0 || numLeft > 0) stereo = true; numRight += numMono; numLeft += numMono; if (numLeft > 1 || numRight > 1) if (stereo) { ShowWarningDialog(project, "MixStereo", _("Your tracks will be mixed down to two " "stereo channels in the exported file.")); } else { ShowWarningDialog(project, "MixMono", _("Your tracks will be mixed down to a " "single mono channel in the exported file.")); } /* Prepare and display the filename selection dialog */ wxString path = gPrefs->Read("/DefaultExportPath", FROMFILENAME(::wxGetCwd())); wxString nameOnly; wxString extension; wxString defaultName = project->GetName(); wxString fName; wxString maskString; wxString endOfPathSep; if (defaultExtension.Left(1) == ".") defaultExtension = defaultExtension.Right(defaultExtension.Length()-1); maskString.Printf("%s files (*.%s)|*.%s|All files (*.*)|*.*", (const char *)format, (const char *)defaultExtension, (const char *)defaultExtension); bool fileOkay; do { fileOkay = true; fName = defaultName + "." + defaultExtension; fName = wxFileSelector(wxString::Format(_("Save %s File As:"), (const char *) format), path, fName, // default file name defaultExtension, maskString, wxSAVE | wxOVERWRITE_PROMPT); if (fName.Length() >= 256) { wxMessageBox (_("Sorry, pathnames longer than 256 characters not supported.")); return ""; } if (fName == "") return ""; ::wxSplitPath(fName, &path, &nameOnly, &extension); // // Make sure the user doesn't accidentally save the file // as an extension with no name, like just plain ".wav". // if ((nameOnly.Left(1)=="." && extension=="") || (nameOnly=="" && extension!="")) { wxString prompt = _("Are you sure you want to save the file as \"")+ ::wxFileNameFromPath(fName)+"\"?\n"; int action = wxMessageBox(prompt, "Warning", wxYES_NO | wxICON_EXCLAMATION, project); fileOkay = (action == wxYES); continue; } // // Check the extension - add the default if it's not there, // and warn user if it's abnormal. // wxString defaultExtension3 = defaultExtension; if (defaultExtension.Length() > 3) defaultExtension = defaultExtension.Left(3); if (extension == "") { #ifdef __WXMSW__ // Windows prefers 3-char uppercase extensions extension = defaultExtension; #else // Linux and Mac prefer lowercase extensions extension = defaultExtension.Lower(); #endif } else if (extension.Upper() != defaultExtension.Upper() && extension.Upper() != defaultExtension3.Upper()) { #ifdef __WXMSW__ // Windows prefers 3-char extensions defaultExtension3 = defaultExtension3; #endif wxString prompt; prompt.Printf(_("You are about to save a %s file with the name %s.\n" "Normally these files end in %s, and some programs " "will not open files with nonstandard extensions.\n" "Are you sure you want to save the file " "under this name?"), (const char *)format, (const char *)("\""+nameOnly+"."+extension+"\""), (const char *)("\"."+defaultExtension+"\"")); int action = wxMessageBox(prompt, "Warning", wxYES_NO | wxICON_EXCLAMATION, project); if (action == wxYES) fileOkay = true; else { fileOkay = false; defaultName = nameOnly + "." + extension; } } if (path.Length() > 0 && path.Last() == wxFILE_SEP_PATH) endOfPathSep = ""; else endOfPathSep = wxFILE_SEP_PATH; fName = path + endOfPathSep + nameOnly + "." + extension; } while(!fileOkay); /* * Ensure that exporting a file by this name doesn't overwrite * one of the existing files in the project. (If it would * overwrite an existing file, DirManager tries to rename the * existing file.) */ if (!project->GetDirManager()->EnsureSafeFilename(wxFileName(fName))) return ""; gPrefs->Write("/DefaultExportPath", path); *isStereo = stereo; /* * To be even MORE safe, return a temporary file name based * on this one... */ actualName = fName; int suffix = 0; while(::wxFileExists(FILENAME(fName))) { fName = path + endOfPathSep + nameOnly + wxString::Format("%d", suffix) + "." + extension; suffix++; } return fName; }