1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-17 08:40:27 +02:00

Limit access to global array of open projects & simplify iterations

This commit is contained in:
Paul Licameli 2019-05-29 14:19:01 -04:00
parent 0ae542cf08
commit b25d3ad344
15 changed files with 203 additions and 185 deletions

View File

@ -466,9 +466,9 @@ static void QuitAudacity(bool bForce)
// BG: unless force is true
// BG: Are there any projects open?
//- if (!gAudacityProjects.empty())
//- if (!AllProjects{}.empty())
/*start+*/
if (gAudacityProjects.empty())
if (AllProjects{}.empty())
{
#ifdef __WXMAC__
Clipboard::Get().Clear();
@ -607,7 +607,7 @@ static gboolean save_yourself_cb(GnomeClient *client,
return TRUE;
}
if (gAudacityProjects.empty()) {
if (AllProjects{}.empty()) {
return TRUE;
}
@ -808,7 +808,7 @@ void AudacityApp::MacNewFile()
// This method should only be used on the Mac platform
// when no project windows are open.
if (gAudacityProjects.size() == 0) {
if (AllProjects{}.empty()) {
CreateNewAudacityProject();
}
}
@ -983,9 +983,9 @@ void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event))
if (MissingAliasFilesDialog::ShouldShow()) {
// find which project owns the blockfile
// note: there may be more than 1, but just go with the first one.
//size_t numProjects = gAudacityProjects.size();
//size_t numProjects = AllProjects{}.size();
auto marked = MissingAliasFilesDialog::Marked();
AProjectHolder offendingProject = marked.second;
auto offendingProject = marked.second;
wxString missingFileName = marked.first;
// if there are no projects open, don't show the warning (user has closed it)
@ -2085,7 +2085,7 @@ void AudacityApp::OnMenuNew(wxCommandEvent & event)
// this happens, and enable the same code to be present on
// all platforms.
if(gAudacityProjects.size() == 0)
if(AllProjects{}.empty())
CreateNewAudacityProject();
else
event.Skip();
@ -2101,7 +2101,7 @@ void AudacityApp::OnMenuOpen(wxCommandEvent & event)
// all platforms.
if(gAudacityProjects.size() == 0)
if(AllProjects{}.empty())
AudacityProject::OpenFiles(NULL);
else
event.Skip();
@ -2117,7 +2117,7 @@ void AudacityApp::OnMenuPreferences(wxCommandEvent & event)
// this happens, and enable the same code to be present on
// all platforms.
if(gAudacityProjects.size() == 0) {
if(AllProjects{}.empty()) {
GlobalPrefsDialog dialog(NULL /* parent */ );
dialog.ShowModal();
}
@ -2135,12 +2135,12 @@ void AudacityApp::OnMenuExit(wxCommandEvent & event)
// all platforms.
// LL: Removed "if" to allow closing based on final project count.
// if(gAudacityProjects.size() == 0)
// if(AllProjects{}.empty())
QuitAudacity();
// LL: Veto quit if projects are still open. This can happen
// if the user selected Cancel in a Save dialog.
event.Skip(gAudacityProjects.size() == 0);
event.Skip(AllProjects{}.empty());
}

View File

@ -95,7 +95,8 @@ _("This will close all project windows (without saving)\nand open the Audacity B
if (action != wxYES)
return;
CloseAllProjects();
for ( auto pProject : AllProjects{} )
GetProjectFrame( *pProject ).Close();
*/
BenchmarkDialog dlog(parent);

View File

@ -300,8 +300,8 @@ void DeviceManager::Rescan()
// If this was not an initial scan update each device toolbar.
// Hosts may have disappeared or appeared so a complete repopulate is needed.
if (m_inited) {
for (size_t i = 0; i < gAudacityProjects.size(); i++) {
auto &dt = DeviceToolBar::Get( *gAudacityProjects[i] );
for ( auto pProject : AllProjects{} ) {
auto &dt = DeviceToolBar::Get( *pProject );
dt.RefillCombos();
}
}

View File

@ -575,9 +575,8 @@ CommandFlag MenuManager::GetUpdateFlags
void MenuManager::ModifyAllProjectToolbarMenus()
{
AProjectArray::iterator i;
for (i = gAudacityProjects.begin(); i != gAudacityProjects.end(); ++i) {
auto &project = **i;
for (auto pProject : AllProjects{}) {
auto &project = *pProject;
MenuManager::Get(project).ModifyToolbarMenus(project);
}
}
@ -742,9 +741,7 @@ void MenuManager::UpdateMenus(AudacityProject &project, bool checkActive)
void MenuCreator::RebuildAllMenuBars()
{
for( size_t i = 0; i < gAudacityProjects.size(); i++ ) {
AudacityProject *p = gAudacityProjects[i].get();
for( auto p : AllProjects{} ) {
MenuManager::Get(*p).RebuildMenuBar(*p);
#if defined(__WXGTK__)
// Workaround for:

View File

@ -108,11 +108,10 @@ namespace MissingAliasFilesDialog {
{
Lock lock{ m_LastMissingBlockFileLock };
if (b) {
size_t numProjects = gAudacityProjects.size();
for (size_t ii = 0; ii < numProjects; ++ii) {
for ( auto pProject : AllProjects{} ) {
// search each project for the blockfile
if (DirManager::Get( *gAudacityProjects[ii] ).ContainsBlockFile(b)) {
m_LastMissingBlockFileProject = gAudacityProjects[ii];
if (DirManager::Get( *pProject ).ContainsBlockFile(b)) {
m_LastMissingBlockFileProject = pProject;
break;
}
}

View File

@ -170,25 +170,72 @@ scroll information. It also has some status flags.
wxDEFINE_EVENT(EVT_PROJECT_STATUS_UPDATE, wxCommandEvent);
size_t AllProjects::size() const
{
return gAudacityProjects.size();
}
auto AllProjects::begin() const -> const_iterator
{
return gAudacityProjects.begin();
}
auto AllProjects::end() const -> const_iterator
{
return gAudacityProjects.end();
}
auto AllProjects::rbegin() const -> const_reverse_iterator
{
return gAudacityProjects.rbegin();
}
auto AllProjects::rend() const -> const_reverse_iterator
{
return gAudacityProjects.rend();
}
auto AllProjects::Remove( AudacityProject &project ) -> value_type
{
ODLocker locker{ &Mutex() };
auto start = begin(), finish = end(), iter = std::find_if(
start, finish,
[&]( const value_type &ptr ){ return ptr.get() == &project; }
);
if (iter == finish)
return nullptr;
auto result = *iter;
gAudacityProjects.erase( iter );
return result;
}
void AllProjects::Add( const value_type &pProject )
{
ODLocker locker{ &Mutex() };
gAudacityProjects.push_back( pProject );
}
bool AllProjects::sbClosing = false;
bool AllProjects::sbWindowRectAlreadySaved = false;
bool AllProjects::Close( bool force )
{
ValueRestorer<bool> cleanup{ sbClosing, true };
if (gAudacityProjects.size())
if (AllProjects{}.size())
// PRL: Always did at least once before close might be vetoed
// though I don't know why that is important
SaveWindowSize();
while (gAudacityProjects.size())
while (AllProjects{}.size())
{
// Closing the project has global side-effect
// of deletion from gAudacityProjects
if ( force )
{
GetProjectFrame( *gAudacityProjects[0] ).Close(true);
GetProjectFrame( **AllProjects{}.begin() ).Close(true);
}
else
{
if (! GetProjectFrame( *gAudacityProjects[0] ).Close())
if (! GetProjectFrame( **AllProjects{}.begin() ).Close())
return false;
}
}
@ -204,14 +251,13 @@ void AllProjects::SaveWindowSize()
bool validWindowForSaveWindowSize = FALSE;
ProjectWindow * validProject = nullptr;
bool foundIconizedProject = FALSE;
size_t numProjects = gAudacityProjects.size();
for (size_t i = 0; i < numProjects; i++)
for ( auto pProject : AllProjects{} )
{
auto &window = ProjectWindow::Get( *gAudacityProjects[i] );
auto &window = ProjectWindow::Get( *pProject );
if (!window.IsIconized()) {
validWindowForSaveWindowSize = TRUE;
validProject = &window;
i = numProjects;
break;
}
else
foundIconizedProject = TRUE;
@ -236,7 +282,7 @@ void AllProjects::SaveWindowSize()
else
{
if (foundIconizedProject) {
validProject = &ProjectWindow::Get( *gAudacityProjects[0] );
validProject = &ProjectWindow::Get( **AllProjects{}.begin() );
bool wndMaximized = validProject->IsMaximized();
wxRect normalRect = validProject->GetNormalizedWindowState();
// store only the normal rectangle because the itemized rectangle
@ -274,7 +320,7 @@ void AllProjects::SaveWindowSize()
sbWindowRectAlreadySaved = true;
}
ODLock &AudacityProject::AllProjectDeleteMutex()
ODLock &AllProjects::Mutex()
{
static ODLock theMutex;
return theMutex;
@ -382,7 +428,7 @@ END_EVENT_TABLE()
//This is a pointer to the currently-active project.
static AudacityProject *gActiveProject;
//This array holds onto all of the projects currently open
AProjectArray gAudacityProjects;
AllProjects::Container AllProjects::gAudacityProjects;
/* Declare Static functions */
static void SetActiveProject(AudacityProject * project);
@ -656,15 +702,16 @@ AudacityProject *CreateNewAudacityProject()
// Create and show a NEW project
// Use a non-default deleter in the smart pointer!
gAudacityProjects.push_back( AProjectHolder {
auto sp = AllProjects::value_type {
safenew AudacityProject(
nullptr, -1,
wxDefaultPosition,
wxSize(wndRect.width, wndRect.height)
),
Destroyer< AudacityProject > {}
} );
const auto p = gAudacityProjects.back().get();
};
AllProjects{}.Add( sp );
auto p = sp.get();
auto &project = *p;
auto &window = GetProjectFrame( *p );
@ -697,27 +744,6 @@ AudacityProject *CreateNewAudacityProject()
return p;
}
void RedrawAllProjects()
{
size_t len = gAudacityProjects.size();
for (size_t i = 0; i < len; i++)
ProjectWindow::Get( *gAudacityProjects[i] ).RedrawProject();
}
void RefreshCursorForAllProjects()
{
size_t len = gAudacityProjects.size();
for (size_t i = 0; i < len; i++)
ProjectWindow::Get( *gAudacityProjects[i] ).RefreshCursor();
}
AUDACITY_DLL_API void CloseAllProjects()
{
size_t len = gAudacityProjects.size();
for (size_t i = 0; i < len; i++)
GetProjectFrame( *gAudacityProjects[i] ).Close();
}
// BG: The default size and position of the first window
void GetDefaultWindowRect(wxRect *defRect)
{
@ -861,7 +887,7 @@ void GetNextWindowPlacement(wxRect *nextRect, bool *pMaximized, bool *pIconized)
// IF projects empty, THEN it's the first window.
// It lands where the config says it should, and can straddle screen.
if (gAudacityProjects.empty()) {
if (AllProjects{}.empty()) {
if (*pMaximized || *pIconized) {
*nextRect = normalRect;
}
@ -899,12 +925,14 @@ void GetNextWindowPlacement(wxRect *nextRect, bool *pMaximized, bool *pIconized)
bool validWindowSize = false;
ProjectWindow * validProject = NULL;
size_t numProjects = gAudacityProjects.size();
for (int i = numProjects; i > 0 ; i--) {
if (!GetProjectFrame( *gAudacityProjects[i-1] ).IsIconized()) {
validWindowSize = true;
validProject = &ProjectWindow::Get( *gAudacityProjects[i-1] );
break;
for ( auto iter = AllProjects{}.rbegin(), end = AllProjects{}.rend();
iter != end; ++iter
) {
auto pProject = *iter;
if (!GetProjectFrame( *pProject ).IsIconized()) {
validWindowSize = true;
validProject = &ProjectWindow::Get( *pProject );
break;
}
}
if (validWindowSize) {
@ -2122,35 +2150,8 @@ void AudacityProject::HandleResize()
UpdateLayout();
}
// How many projects that do not have a name yet?
int AudacityProject::CountUnnamed()
{
int j = 0;
for ( size_t i = 0; i < gAudacityProjects.size(); i++) {
if ( gAudacityProjects[i] )
if ( gAudacityProjects[i]->GetProjectName().empty() )
j++;
}
return j;
}
void AudacityProject::RefreshAllTitles(bool bShowProjectNumbers )
{
for ( size_t i = 0; i < gAudacityProjects.size(); i++) {
if ( gAudacityProjects[i] ) {
if ( !GetProjectFrame( *gAudacityProjects[i] ).IsIconized() ) {
AudacityProject * p;
p = gAudacityProjects[i].get();
p->SetProjectTitle( bShowProjectNumbers ? p->GetProjectNumber() : -1 );
}
}
}
}
void AudacityProject::OnIconize(wxIconizeEvent &event)
{
int VisibleProjectCount = 0;
//JKC: On Iconizing we get called twice. Don't know
// why but it does no harm.
// Should we be returning true/false rather than
@ -2161,12 +2162,12 @@ void AudacityProject::OnIconize(wxIconizeEvent &event)
// VisibileProjectCount seems to be just a counter for debugging.
// It's not used outside this function.
for(i=0;i<gAudacityProjects.size();i++){
if(gAudacityProjects[i]){
if( !GetProjectFrame( *gAudacityProjects[i] ).IsIconized() )
VisibleProjectCount++;
auto VisibleProjectCount = std::count_if(
AllProjects{}.begin(), AllProjects{}.end(),
[]( const AllProjects::value_type &ptr ){
return !GetProjectFrame( *ptr ).IsIconized();
}
}
);
event.Skip();
// This step is to fix part of Bug 2040, where the BackingPanel
@ -2410,8 +2411,17 @@ void AudacityProject::OnMouseEvent(wxMouseEvent & event)
// TitleRestorer restores project window titles to what they were, in its destructor.
class TitleRestorer{
static void RefreshAllTitles(bool bShowProjectNumbers )
{
for ( auto pProject : AllProjects{} ) {
if ( !GetProjectFrame( *pProject ).IsIconized() ) {
pProject->SetProjectTitle(
bShowProjectNumbers ? pProject->GetProjectNumber() : -1 );
}
}
}
public:
TitleRestorer(AudacityProject * p ){
TitleRestorer(AudacityProject * p ) {
auto &window = GetProjectFrame( *p );
if( window.IsIconized() )
window.Restore();
@ -2421,10 +2431,15 @@ public:
sProjName = p->GetProjectName();
if (sProjName.empty()){
sProjName = _("<untitled>");
UnnamedCount=AudacityProject::CountUnnamed();
UnnamedCount = std::count_if(
AllProjects{}.begin(), AllProjects{}.end(),
[]( const AllProjects::value_type &ptr ){
return ptr->GetProjectName().empty();
}
);
if( UnnamedCount > 1 ){
sProjNumber.Printf( "[Project %02i] ", p->GetProjectNumber()+1 );
AudacityProject::RefreshAllTitles( true );
RefreshAllTitles( true );
}
} else {
UnnamedCount = 0;
@ -2432,11 +2447,11 @@ public:
};
~TitleRestorer() {
if( UnnamedCount > 1 )
AudacityProject::RefreshAllTitles( false );
RefreshAllTitles( false );
};
wxString sProjNumber;
wxString sProjName;
int UnnamedCount;
size_t UnnamedCount;
};
@ -2560,7 +2575,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
// DanH: If we're definitely about to quit, clear the clipboard.
// Doing this after Deref'ing the DirManager causes problems.
if ((gAudacityProjects.size() == 1) &&
if ((AllProjects{}.size() == 1) &&
(quitOnClose || AllProjects::Closing()))
Clipboard::Get().Clear();
@ -2606,21 +2621,14 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
// have been deleted before this.
DirManager::Destroy( project );
AProjectHolder pSelf;
{
ODLocker locker{ &AudacityProject::AllProjectDeleteMutex() };
auto end = gAudacityProjects.end();
auto it = std::find_if(gAudacityProjects.begin(), end,
[this] (const AProjectHolder &p) { return p.get() == this; });
wxASSERT( it != end );
pSelf = std::move( *it );
gAudacityProjects.erase(it);
}
// Remove self from the global array, but defer destruction of self
auto pSelf = AllProjects{}.Remove( *this );
wxASSERT( pSelf );
if (gActiveProject == this) {
// Find a NEW active project
if (gAudacityProjects.size() > 0) {
SetActiveProject(gAudacityProjects[0].get());
if ( !AllProjects{}.empty() ) {
SetActiveProject(AllProjects{}.begin()->get());
}
else {
SetActiveProject(NULL);
@ -2633,7 +2641,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event)
gAudioIO->SetListener(gActiveProject);
}
if (gAudacityProjects.empty() && !AllProjects::Closing()) {
if (AllProjects{}.empty() && !AllProjects::Closing()) {
#if !defined(__WXMAC__)
if (quitOnClose) {
@ -2773,18 +2781,18 @@ wxArrayString AudacityProject::ShowOpenDialog(const wxString &extraformat, const
bool AudacityProject::IsAlreadyOpen(const FilePath &projPathName)
{
const wxFileName newProjPathName(projPathName);
size_t numProjects = gAudacityProjects.size();
for (size_t i = 0; i < numProjects; i++)
{
if (newProjPathName.SameAs(gAudacityProjects[i]->mFileName))
{
wxString errMsg =
wxString::Format(_("%s is already open in another window."),
newProjPathName.GetName());
wxLogError(errMsg);
AudacityMessageBox(errMsg, _("Error Opening Project"), wxOK | wxCENTRE);
return true;
}
auto start = AllProjects{}.begin(), finish = AllProjects{}.end(),
iter = std::find_if( start, finish,
[&]( const AllProjects::value_type &ptr ){
return (newProjPathName.SameAs(wxFileNameWrapper{ ptr->mFileName }));
} );
if (iter != finish) {
wxString errMsg =
wxString::Format(_("%s is already open in another window."),
newProjPathName.GetName());
wxLogError(errMsg);
AudacityMessageBox(errMsg, _("Error Opening Project"), wxOK | wxCENTRE);
return true;
}
return false;
}
@ -4498,7 +4506,7 @@ For an audio file that will open in other apps, use 'Export'.\n");
// saved to disk, and we then need to check the destination file is not
// open in another window.
int mayOverwrite = (mFileName == fName)? 2 : 1;
for (auto p : gAudacityProjects) {
for ( auto p : AllProjects{} ) {
const wxFileName openProjectName(p->mFileName);
if (openProjectName.SameAs(fName)) {
mayOverwrite -= 1;
@ -5223,10 +5231,6 @@ void AudacityProject::SetSyncLock(bool flag)
}
}
int AudacityProject::GetOpenProjectCount() {
return gAudacityProjects.size();
}
bool AudacityProject::IsProjectSaved() {
auto &project = *this;
auto &dirManager = DirManager::Get( project );

View File

@ -83,22 +83,13 @@ class WaveClip;
AudacityProject *CreateNewAudacityProject();
AUDACITY_DLL_API AudacityProject *GetActiveProject();
void RedrawAllProjects();
void RefreshCursorForAllProjects();
AUDACITY_DLL_API void CloseAllProjects();
void GetDefaultWindowRect(wxRect *defRect);
void GetNextWindowPlacement(wxRect *nextRect, bool *pMaximized, bool *pIconized);
bool IsWindowAccessible(wxRect *requestedRect);
// Use shared_ptr to projects, because elsewhere we need weak_ptr
using AProjectHolder = std::shared_ptr< AudacityProject >;
using AProjectArray = std::vector< AProjectHolder >;
using WaveTrackArray = std::vector < std::shared_ptr < WaveTrack > >;
extern AProjectArray gAudacityProjects;
enum StatusBarField {
stateStatusBarField = 1,
@ -124,9 +115,45 @@ class ImportXMLTagHandler final : public XMLTagHandler
AudacityProject* mProject;
};
/// \brief an object of class AllProjects acts like a standard library
/// container, but refers to a global array of open projects. So you can
/// iterate easily over shared pointers to them with range-for :
/// for (auto pProject : AllProjects{}) { ... }
/// The pointers are never null.
class AllProjects
{
// Use shared_ptr to projects, because elsewhere we need weak_ptr
using AProjectHolder = std::shared_ptr< AudacityProject >;
using Container = std::vector< AProjectHolder >;
static Container gAudacityProjects;
public:
AllProjects() = default;
size_t size() const;
bool empty() const { return size() == 0; }
using const_iterator = Container::const_iterator;
const_iterator begin() const;
const_iterator end() const;
using const_reverse_iterator = Container::const_reverse_iterator;
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
using value_type = Container::value_type;
// If the project is present, remove it from the global array and return
// a shared pointer, else return null. This invalidates any iterators.
value_type Remove( AudacityProject &project );
// This invalidates iterators
void Add( const value_type &pProject );
/// In case you must iterate in a non-main thread, use this to prevent
/// changes in the set of open projects
static ODLock &Mutex();
// Return true if all projects do close (always so if force == true)
// But if return is false, that means the user cancelled close of at least
// one un-saved project.
@ -310,7 +337,6 @@ public:
// Timer Record Auto Save/Export Routines
bool SaveFromTimerRecording(wxFileName fnFile);
static int GetOpenProjectCount();
bool IsProjectSaved();
void ResetProjectToEmpty();
void ResetProjectFileIO();
@ -351,8 +377,6 @@ public:
// Other commands
int GetProjectNumber(){ return mProjectNo;};
static int CountUnnamed();
static void RefreshAllTitles(bool bShowProjectNumbers );
void UpdatePrefs() override;
void UpdatePrefsVariables();
void RedrawProject(const bool bForceWaveTracks = false);
@ -510,11 +534,6 @@ public:
std::shared_ptr<TrackList> mLastSavedTracks;
public:
///Prevents DELETE from external thread - for e.g. use of GetActiveProject
//shared by all projects
static ODLock &AllProjectDeleteMutex();
private:
bool mDirty{ false };

View File

@ -705,7 +705,8 @@ bool NyquistEffect::Process()
mProps += wxString::Format(wxT("(putprop '*SYSTEM-TIME* \"%s\" 'MONTH-NAME)\n"), now.GetMonthName(month));
mProps += wxString::Format(wxT("(putprop '*SYSTEM-TIME* \"%s\" 'DAY-NAME)\n"), now.GetWeekDayName(day));
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'PROJECTS)\n"), (int) gAudacityProjects.size());
mProps += wxString::Format(wxT("(putprop '*PROJECT* %d 'PROJECTS)\n"),
(int) AllProjects{}.size());
mProps += wxString::Format(wxT("(putprop '*PROJECT* \"%s\" 'NAME)\n"), project->GetProjectName());
int numTracks = 0;

View File

@ -676,9 +676,9 @@ bool Exporter::GetFilename()
// Also, this can only happen for uncompressed audio.
bool overwritingMissingAliasFiles;
overwritingMissingAliasFiles = false;
for (size_t i = 0; i < gAudacityProjects.size(); i++) {
for (auto pProject : AllProjects{}) {
AliasedFileArray aliasedFiles;
FindDependencies(gAudacityProjects[i].get(), aliasedFiles);
FindDependencies(pProject.get(), aliasedFiles);
for (const auto &aliasedFile : aliasedFiles) {
if (mFilename.GetFullPath() == aliasedFile.mFileName.GetFullPath() &&
!mFilename.FileExists()) {

View File

@ -179,9 +179,7 @@ void DoReloadPreferences( AudacityProject &project )
// LL: Moved from PrefsDialog since wxWidgets on OSX can't deal with
// rebuilding the menus while the PrefsDialog is still in the modal
// state.
for (size_t i = 0; i < gAudacityProjects.size(); i++) {
AudacityProject *p = gAudacityProjects[i].get();
for (auto p : AllProjects{}) {
MenuManager::Get(*p).RebuildMenuBar(*p);
// TODO: The comment below suggests this workaround is obsolete.
#if defined(__WXGTK__)
@ -1031,9 +1029,7 @@ void OnPreferences(const CommandContext &context)
// LL: Moved from PrefsDialog since wxWidgets on OSX can't deal with
// rebuilding the menus while the PrefsDialog is still in the modal
// state.
for (size_t i = 0; i < gAudacityProjects.size(); i++) {
AudacityProject *p = gAudacityProjects[i].get();
for (auto p : AllProjects{}) {
MenuManager::Get(*p).RebuildMenuBar(*p);
// TODO: The comment below suggests this workaround is obsolete.
#if defined(__WXGTK__)

View File

@ -94,16 +94,14 @@ void DoPlayStop(const CommandContext &context)
// old and start the NEW.
//find out which project we need;
AudacityProject* otherProject = NULL;
for(unsigned i=0; i<gAudacityProjects.size(); i++) {
if(gAudioIO->IsStreamActive(gAudacityProjects[i]->GetAudioIOToken())) {
otherProject=gAudacityProjects[i].get();
break;
}
}
auto start = AllProjects{}.begin(), finish = AllProjects{}.end(),
iter = std::find_if( start, finish,
[]( const AllProjects::value_type &ptr ){
return gAudioIO->IsStreamActive(ptr->GetAudioIOToken()); } );
//stop playing the other project
if(otherProject) {
if(iter != finish) {
auto otherProject = *iter;
auto &otherToolbar = ControlToolBar::Get( *otherProject );
otherToolbar.SetPlay(false); //Pops
otherToolbar.SetStop(true); //Pushes stop down
@ -407,7 +405,7 @@ void OnTimerRecord(const CommandContext &context)
// MY: Due to improvements in how Timer Recording saves and/or exports
// it is now safer to disable Timer Recording when there is more than
// one open project.
if (AudacityProject::GetOpenProjectCount() > 1) {
if (AllProjects{}.size() > 1) {
AudacityMessageBox(_("Timer Recording cannot be used with more than one open project.\n\nPlease close any additional projects and try again."),
_("Timer Recording"),
wxICON_INFORMATION | wxOK);

View File

@ -89,13 +89,13 @@ void OnMacBringAllToFront(const CommandContext &)
{
// Reall this de-miniaturizes all, which is not exactly the standard
// behavior.
for (const auto project : gAudacityProjects)
for (const auto project : AllProjects{})
GetProjectFrame( *project ).Raise();
}
void OnMacMinimizeAll(const CommandContext &)
{
for (const auto project : gAudacityProjects) {
for (const auto project : AllProjects{}) {
DoMacMinimize(project.get());
}
}

View File

@ -421,7 +421,7 @@ void ODManager::Start()
{
mNeedsDraw=0;
wxCommandEvent event( EVT_ODTASK_UPDATE );
ODLocker locker{ &AudacityProject::AllProjectDeleteMutex() };
ODLocker locker{ &AllProjects::Mutex() };
AudacityProject* proj = GetActiveProject();
if(proj)
GetProjectFrame( *proj )

View File

@ -129,13 +129,13 @@ void ODTask::DoSome(float amountWork)
ODManager::Instance()->AddTask(this);
//we did a bit of progress - we should allow a resave.
ODLocker locker{ &AudacityProject::AllProjectDeleteMutex() };
for(unsigned i=0; i<gAudacityProjects.size(); i++)
ODLocker locker{ &AllProjects::Mutex() };
for ( auto pProject : AllProjects{} )
{
if(IsTaskAssociatedWithProject(gAudacityProjects[i].get()))
if(IsTaskAssociatedWithProject(pProject.get()))
{
//mark the changes so that the project can be resaved.
UndoManager::Get( *gAudacityProjects[i] ).SetODChangesFlag();
UndoManager::Get( *pProject ).SetODChangesFlag();
break;
}
}
@ -153,16 +153,16 @@ void ODTask::DoSome(float amountWork)
wxCommandEvent event( EVT_ODTASK_COMPLETE );
ODLocker locker{ &AudacityProject::AllProjectDeleteMutex() };
for(unsigned i=0; i<gAudacityProjects.size(); i++)
ODLocker locker{ &AllProjects::Mutex() };
for ( auto pProject : AllProjects{} )
{
if(IsTaskAssociatedWithProject(gAudacityProjects[i].get()))
if(IsTaskAssociatedWithProject(pProject.get()))
{
//this assumes tasks are only associated with one project.
GetProjectFrame( *gAudacityProjects[i] )
GetProjectFrame( *pProject )
.GetEventHandler()->AddPendingEvent(event);
//mark the changes so that the project can be resaved.
UndoManager::Get( *gAudacityProjects[i] ).SetODChangesFlag();
UndoManager::Get( *pProject ).SetODChangesFlag();
break;
}
}

View File

@ -226,13 +226,15 @@ void ToolsToolBar::SetCurrentTool(int tool)
mCurrentTool=tool;
mTool[mCurrentTool]->PushDown();
}
//JKC: ANSWER-ME: Why is this RedrawAllProjects() line required?
//JKC: ANSWER-ME: Why is this required?
//msmeyer: I think it isn't, we leave it out for 1.3.1 (beta), and
// we'll see if anyone complains.
// RedrawAllProjects();
//for ( auto pProject : AllProjects{} )
// ProjectWindow::Get( *pProject ).RedrawProject();
//msmeyer: But we instruct the projects to handle the cursor shape again
RefreshCursorForAllProjects();
for ( auto pProject : AllProjects{} )
ProjectWindow::Get( *pProject ).RefreshCursor();
gPrefs->Write(wxT("/GUI/ToolBars/Tools/MultiToolActive"),
IsDown(multiTool));
@ -264,7 +266,8 @@ void ToolsToolBar::OnTool(wxCommandEvent & evt)
else
mTool[i]->PopUp();
RedrawAllProjects();
for ( auto pProject : AllProjects{} )
ProjectWindow::Get( *pProject ).RedrawProject();
gPrefs->Write(wxT("/GUI/ToolBars/Tools/MultiToolActive"),
IsDown(multiTool));