Skip to content
This repository has been archived by the owner on Dec 18, 2022. It is now read-only.

Commit

Permalink
Duplicate Project in ProjectWindows
Browse files Browse the repository at this point in the history
Patch imported by Audacity and adapted for Tenacity.

Original commit: 6477c9e0a6cb93b781c6c83153f1d036a7cc4c13

Signed-off-by: Panagiotis Vasilopoulos <[email protected]>
  • Loading branch information
Paul-Licameli authored and n0toose committed Oct 5, 2021
1 parent bc13feb commit 0843918
Show file tree
Hide file tree
Showing 2 changed files with 359 additions and 0 deletions.
172 changes: 172 additions & 0 deletions src/ProjectWindows.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Project.cpp
Dominic Mazzoni
Vaughan Johnson
*//*******************************************************************/


#include "Project.h"

#include "widgets/wxWidgetsBasicUI.h"

#include <wx/display.h>
#include <wx/filename.h>
#include <wx/frame.h>

wxDEFINE_EVENT(EVT_TRACK_PANEL_TIMER, 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
{
std::lock_guard<std::mutex> guard{ 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 )
{
if (!pProject) {
wxASSERT(false);
return;
}
std::lock_guard<std::mutex> guard{ Mutex() };
gAudacityProjects.push_back( pProject );
}

std::mutex &AllProjects::Mutex()
{
static std::mutex theMutex;
return theMutex;
}

int AudacityProject::mProjectCounter=0;// global counter.

/* Define Global Variables */
//This array holds onto all of the projects currently open
AllProjects::Container AllProjects::gAudacityProjects;

AudacityProject::AudacityProject()
{
mProjectNo = mProjectCounter++; // Bug 322
AttachedObjects::BuildAll();
// But not for the attached windows. They get built only on demand, such as
// from menu items.
}

AudacityProject::~AudacityProject()
{
}

void AudacityProject::SetFrame( wxFrame *pFrame )
{
mFrame = pFrame;
}

void AudacityProject::SetPanel( wxWindow *pPanel )
{
mPanel = pPanel;
}

const wxString &AudacityProject::GetProjectName() const
{
return mName;
}

void AudacityProject::SetProjectName(const wxString &name)
{
mName = name;
}

FilePath AudacityProject::GetInitialImportPath() const
{
return mInitialImportPath;
}

void AudacityProject::SetInitialImportPath(const FilePath &path)
{
if (mInitialImportPath.empty())
{
mInitialImportPath = path;
}
}

TENACITY_DLL_API wxFrame &GetProjectFrame( AudacityProject &project )
{
auto ptr = project.GetFrame();
if ( !ptr )
THROW_INCONSISTENCY_EXCEPTION;
return *ptr;
}

TENACITY_DLL_API const wxFrame &GetProjectFrame( const AudacityProject &project )
{
auto ptr = project.GetFrame();
if ( !ptr )
THROW_INCONSISTENCY_EXCEPTION;
return *ptr;
}

std::unique_ptr<const BasicUI::WindowPlacement>
ProjectFramePlacement( AudacityProject *project )
{
if (!project)
return std::make_unique<BasicUI::WindowPlacement>();
return std::make_unique<wxWidgetsWindowPlacement>(
&GetProjectFrame(*project));
}

TENACITY_DLL_API wxWindow &GetProjectPanel( AudacityProject &project )
{
auto ptr = project.GetPanel();
if ( !ptr )
THROW_INCONSISTENCY_EXCEPTION;
return *ptr;
}

TENACITY_DLL_API const wxWindow &GetProjectPanel(
const AudacityProject &project )
{
auto ptr = project.GetPanel();
if ( !ptr )
THROW_INCONSISTENCY_EXCEPTION;
return *ptr;
}

// Generate the needed, linkable registry functions
DEFINE_XML_METHOD_REGISTRY( ProjectFileIORegistry );
187 changes: 187 additions & 0 deletions src/ProjectWindows.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/**********************************************************************
Audacity: A Digital Audio Editor
Project.h
Dominic Mazzoni
**********************************************************************/

#ifndef __AUDACITY_PROJECT__
#define __AUDACITY_PROJECT__

#include "Identifier.h"

#include "ClientData.h" // to inherit

#include <memory>
#include <mutex>
#include <wx/weakref.h> // member variable
#include <wx/window.h> // MSVC wants this

class wxFrame;
class wxWindow;
namespace BasicUI { class WindowPlacement; }

class AudacityProject;

//! Like a standard library container of all open projects.
//! @invariant pointers accessible through the iterators are not null
/*!
So you can iterate easily over shared pointers to them with range-for :
for (auto pProject : AllProjects{}) { ... }
The pointers are never null.
However iterators will be invalid if addition or deletion of projects occur
during traversal.
*/
class TENACITY_DLL_API 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
/*!
@pre pProject is not null
*/
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 std::mutex &Mutex();
};

// Container of various objects associated with the project, which is
// responsible for destroying them
using AttachedProjectObjects = ClientData::Site<
AudacityProject, ClientData::Base, ClientData::SkipCopying, std::shared_ptr
>;
// Container of pointers to various windows associated with the project, which
// is not responsible for destroying them -- wxWidgets handles that instead
using AttachedProjectWindows = ClientData::Site<
AudacityProject, wxWindow, ClientData::SkipCopying, ClientData::BarePtr
>;

wxDECLARE_EXPORTED_EVENT(TENACITY_DLL_API,
EVT_TRACK_PANEL_TIMER, wxCommandEvent);

///\brief The top-level handle to an Audacity project. It serves as a source
/// of events that other objects can bind to, and a container of associated
/// sub-objects that it treats opaquely. It stores a filename and a status
/// message and a few other things.
/// There is very little in this class, most of the intelligence residing in
/// the cooperating attached objects.
class TENACITY_DLL_API AudacityProject final
: public wxEvtHandler
, public AttachedProjectObjects
, public AttachedProjectWindows
, public std::enable_shared_from_this<AudacityProject>
{
public:
using AttachedObjects = ::AttachedProjectObjects;
using AttachedWindows = ::AttachedProjectWindows;

AudacityProject();
virtual ~AudacityProject();

wxFrame *GetFrame() { return mFrame; }
const wxFrame *GetFrame() const { return mFrame; }
void SetFrame( wxFrame *pFrame );

wxWindow *GetPanel() { return mPanel; }
const wxWindow *GetPanel() const { return mPanel; }
void SetPanel( wxWindow *pPanel );

int GetProjectNumber(){ return mProjectNo;}

// Project name can be either empty or have the name of the project.
//
// If empty, it signifies that the project is empty/unmodified or
// that the project hasn't yet been saved to a permanent project
// file.
//
// If a name has been assigned, it is merely used to identify
// the project and should not be used for any other purposes.
const wxString &GetProjectName() const;
void SetProjectName(const wxString &name);

// Used exclusively in batch mode, this allows commands to remember
// and use the initial import path
FilePath GetInitialImportPath() const;
void SetInitialImportPath(const FilePath &path);

private:

// The project's name
wxString mName;

static int mProjectCounter;// global counter.
int mProjectNo; // count when this project was created.

FilePath mInitialImportPath;

public:
bool mbBusyImporting{ false }; // used to fix bug 584
int mBatchMode{ 0 };// 0 means not, >0 means in batch mode.

private:
wxWeakRef< wxFrame > mFrame{};
wxWeakRef< wxWindow > mPanel{};
};

///\brief Get the top-level window associated with the project (as a wxFrame
/// only, when you do not need to use the subclass ProjectWindow)
TENACITY_DLL_API wxFrame &GetProjectFrame( AudacityProject &project );
TENACITY_DLL_API const wxFrame &GetProjectFrame( const AudacityProject &project );

///\brief Get a pointer to the window associated with a project, or null if
/// the given pointer is null.
inline wxFrame *FindProjectFrame( AudacityProject *project ) {
return project ? &GetProjectFrame( *project ) : nullptr;
}
inline const wxFrame *FindProjectFrame( const AudacityProject *project ) {
return project ? &GetProjectFrame( *project ) : nullptr;
}

//! Make a WindowPlacement object suitable for `project` (which may be null)
/*! @post return value is not null */
TENACITY_DLL_API std::unique_ptr<const BasicUI::WindowPlacement>
ProjectFramePlacement( AudacityProject *project );

///\brief Get the main sub-window of the project frame that displays track data
// (as a wxWindow only, when you do not need to use the subclass TrackPanel)
TENACITY_DLL_API wxWindow &GetProjectPanel( AudacityProject &project );
TENACITY_DLL_API const wxWindow &GetProjectPanel(
const AudacityProject &project );

// Generate a registry for serialized data attached to the project
#include "XMLMethodRegistry.h"
class AudacityProject;
using ProjectFileIORegistry = XMLMethodRegistry<AudacityProject>;
DECLARE_XML_METHOD_REGISTRY( TENACITY_DLL_API, ProjectFileIORegistry );

#endif

0 comments on commit 0843918

Please sign in to comment.