From 2c86d5b439486089541224dadd466ff57555c07b Mon Sep 17 00:00:00 2001 From: djdiskmachine <110535302+djdiskmachine@users.noreply.github.com> Date: Sun, 15 Jan 2023 01:23:00 +0100 Subject: [PATCH] Add save as (#12) Save As option in Project page --- sources/Application/AppWindow.cpp | 18 ++- sources/Application/AppWindow.h | 2 + .../Application/Views/BaseClasses/ViewEvent.h | 4 +- .../ModalDialogs/SelectProjectDialog.cpp | 12 +- sources/Application/Views/ProjectView.cpp | 105 ++++++++++++++++-- sources/Application/Views/ProjectView.h | 1 + sources/System/Errors/Result.h | 3 +- sources/System/FileSystem/FileSystem.cpp | 37 ++++++ sources/System/FileSystem/FileSystem.h | 5 + 9 files changed, 170 insertions(+), 17 deletions(-) diff --git a/sources/Application/AppWindow.cpp b/sources/Application/AppWindow.cpp index 026f901b..76dd5611 100644 --- a/sources/Application/AppWindow.cpp +++ b/sources/Application/AppWindow.cpp @@ -77,6 +77,7 @@ AppWindow::AppWindow(I_GUIWindowImp &imp):GUIWindow(imp) { _mixerView=0 ; _grooveView=0 ; _closeProject=0 ; + _loadAfterSaveAsProject=0 ; _lastA=0 ; _lastB=0 ; _mask=0 ; @@ -263,10 +264,11 @@ void AppWindow::Flush() { } ; void AppWindow::LoadProject(const Path &p) { - + Trace::Log("LoadProject","%s\n", p.GetPath().c_str()); _root=p ; _closeProject=false ; + _loadAfterSaveAsProject=false; PersistencyService *persist=PersistencyService::GetInstance() ; @@ -449,6 +451,11 @@ bool AppWindow::onEvent(GUIEvent &event) { CloseProject() ; _isDirty=true ; } + if(_loadAfterSaveAsProject) { + CloseProject(); + _isDirty=true; + LoadProject(_newProjectToLoad); + } #ifdef _SHOW_GP2X_ Redraw() ; #else @@ -534,6 +541,15 @@ void AppWindow::Update(Observable &o,I_ObservableData *d) { LoadProject(name) ; break ; } */ + + case VET_SAVEAS_PROJECT: + { + char *name=(char*)ve->GetData() ; + _loadAfterSaveAsProject=true; + strcpy(_newProjectToLoad,name); + break ; + } + case VET_QUIT_PROJECT: { // defer event to after we got out of the view diff --git a/sources/Application/AppWindow.h b/sources/Application/AppWindow.h index 4cbf52c1..704a4eea 100644 --- a/sources/Application/AppWindow.h +++ b/sources/Application/AppWindow.h @@ -77,11 +77,13 @@ class AppWindow:public GUIWindow,I_Observer,Status { bool _isDirty ; bool _closeProject ; + bool _loadAfterSaveAsProject ; bool _shouldQuit ; unsigned short _mask ; unsigned long _lastA ; unsigned long _lastB ; char _statusLine[80] ; + char _newProjectToLoad[80]; unsigned char _charScreen[1200] ; unsigned char _charScreenProp[1200] ; unsigned char _preScreen[1200] ; diff --git a/sources/Application/Views/BaseClasses/ViewEvent.h b/sources/Application/Views/BaseClasses/ViewEvent.h index afa04325..4035f8fe 100644 --- a/sources/Application/Views/BaseClasses/ViewEvent.h +++ b/sources/Application/Views/BaseClasses/ViewEvent.h @@ -5,8 +5,8 @@ enum ViewEventType { VET_SWITCH_VIEW, - VET_PLAYER_POSITION_UPDATE, - VET_LIST_SELECT, + VET_PLAYER_POSITION_UPDATE, + VET_SAVEAS_PROJECT, VET_QUIT_PROJECT, VET_UPDATE, VET_QUIT_APP diff --git a/sources/Application/Views/ModalDialogs/SelectProjectDialog.cpp b/sources/Application/Views/ModalDialogs/SelectProjectDialog.cpp index c7a29af4..218050f4 100644 --- a/sources/Application/Views/ModalDialogs/SelectProjectDialog.cpp +++ b/sources/Application/Views/ModalDialogs/SelectProjectDialog.cpp @@ -234,15 +234,15 @@ Path SelectProjectDialog::GetSelection() { Result SelectProjectDialog::OnNewProject(std::string &name) { Path path = currentPath_.Descend(name); - Trace::Log("TMP","creating project at %s",path.GetPath().c_str()); - selection_=path ; + Trace::Log("TMP","creating project at %s",path.GetPath().c_str()); + selection_ = path ; Result result = FileSystem::GetInstance()->MakeDir(path.GetPath().c_str()) ; - RETURN_IF_FAILED_MESSAGE(result,"Failed to create project dir"); + RETURN_IF_FAILED(result, ("Failed to create project dir for '%s", path.GetPath().c_str())); - path= path.Descend("samples"); - Trace::Log("TMP","creating samples dir at %s",path.GetPath().c_str()); + path = path.Descend("samples"); + Trace::Log("TMP","creating samples dir at %s",path.GetPath().c_str()); result = FileSystem::GetInstance()->MakeDir(path.GetPath().c_str()) ; - RETURN_IF_FAILED_MESSAGE(result,"Failed to create samples dir"); + RETURN_IF_FAILED(result, ("Failed to create samples dir for '%s'", path.GetPath().c_str())); EndModal(1) ; return Result::NoError; diff --git a/sources/Application/Views/ProjectView.cpp b/sources/Application/Views/ProjectView.cpp index 573b9406..2d689e37 100644 --- a/sources/Application/Views/ProjectView.cpp +++ b/sources/Application/Views/ProjectView.cpp @@ -6,13 +6,80 @@ #include "System/System/System.h" #include "Services/Midi/MidiService.h" #include "Application/Views/ModalDialogs/MessageBox.h" - -#define ACTION_PURGE MAKE_FOURCC('P','U','R','G') -#define ACTION_SAVE MAKE_FOURCC('S','A','V','E') -#define ACTION_LOAD MAKE_FOURCC('L','O','A','D') -#define ACTION_QUIT MAKE_FOURCC('Q','U','I','T') +#include "Application/Views/ModalDialogs/NewProjectDialog.h" +#include "Application/Views/ModalDialogs/SelectProjectDialog.h" + +#define ACTION_PURGE MAKE_FOURCC('P','U','R','G') +#define ACTION_SAVE MAKE_FOURCC('S','A','V','E') +#define ACTION_SAVE_AS MAKE_FOURCC('S','V','A','S') +#define ACTION_LOAD MAKE_FOURCC('L','O','A','D') +#define ACTION_QUIT MAKE_FOURCC('Q','U','I','T') #define ACTION_PURGE_INSTRUMENT MAKE_FOURCC('P','R','G','I') -#define ACTION_TEMPO_CHANGED MAKE_FOURCC('T','E','M','P') +#define ACTION_TEMPO_CHANGED MAKE_FOURCC('T','E','M','P') + +static void SaveAsProjectCallback(View &v,ModalView &dialog) { + + FileSystemService FSS; + NewProjectDialog &npd=(NewProjectDialog &)dialog; + + if (dialog.GetReturnCode()>0) { + std::string str_dstprjdir; + std::string str_dstsmpdir; + #ifdef PLATFORM_PSP + str_dstprjdir = npd.GetName(); + str_dstsmpdir = npd.GetName() + "/samples/"; + #else + std::string up = "../"; + str_dstprjdir = up + npd.GetName(); + str_dstsmpdir = up + npd.GetName() + "/samples/"; + #endif + + Path path_dstprjdir = Path(str_dstprjdir); + Path path_dstsmpdir = Path(str_dstsmpdir); + Path path_srcprjdir("project:"); + Path path_srcsmpdir("project:samples"); + + Path path_srclgptdatsav = path_srcprjdir.GetPath() + "/lgptsav.dat"; + Path path_dstlgptdatsav = path_dstprjdir.GetPath() + "/lgptsav.dat"; + + if (path_dstprjdir.Exists()) { Trace::Log("ProjectView", "Dst Dir '%s' Exist == true", + path_dstprjdir.GetPath().c_str()); } + else { + Result result = FileSystem::GetInstance()->MakeDir(path_dstprjdir.GetPath().c_str()); + if (result.Failed()) { + Trace::Log("ProjectView", "Failed to create dir '%s'", path_dstprjdir.GetPath().c_str()); + return; + }; + + result = FileSystem::GetInstance()->MakeDir(path_dstsmpdir.GetPath().c_str()) ; + + if (result.Failed()) { + Trace::Log("ProjectView", "Failed to create sample dir '%s'", path_dstprjdir.GetPath().c_str()); + return; + }; + + FSS.Copy(path_srclgptdatsav,path_dstlgptdatsav); + + I_Dir *idir_srcsmpdir=FileSystem::GetInstance()->Open(path_srcsmpdir.GetPath().c_str()); + if (idir_srcsmpdir) { + idir_srcsmpdir->GetContent("*"); + idir_srcsmpdir->Sort(); + IteratorPtrit(idir_srcsmpdir->GetIterator()); + for (it->Begin();!it->IsDone();it->Next()) { + Path ¤t=it->CurrentItem(); + if (current.IsFile()) + { + Path dstfile = Path((str_dstsmpdir+current.GetName()).c_str()); + Path srcfile = Path(current.GetPath()); + FSS.Copy(srcfile.GetPath(),dstfile.GetPath()); + } + } + } + + ((ProjectView &)v).OnSaveAsProject((char*)str_dstprjdir.c_str()); + } + } +} static void LoadCallback(View &v,ModalView &dialog) { if (dialog.GetReturnCode()==MBL_YES) { @@ -75,10 +142,15 @@ ProjectView::ProjectView(GUIWindow &w,ViewData *data):FieldView(w,data) { a1->AddObserver(*this) ; T_SimpleList::Insert(a1) ; + position._y+=1 ; + a1=new UIActionField("Save Song As",ACTION_SAVE_AS,position) ; + a1->AddObserver(*this) ; + T_SimpleList::Insert(a1) ; + v=project_->FindVariable(VAR_MIDIDEVICE) ; NAssert(v) ; position._y+=2 ; - UIIntVarField *f3=new UIIntVarField(position,*v,"midi: %s",0,MidiService::GetInstance()->Size(),1,1) ; + UIIntVarField *f3=new UIIntVarField(position,*v,"MIDI: %s",0,MidiService::GetInstance()->Size(),1,1) ; T_SimpleList::Insert(f3) ; position._y+=2 ; @@ -169,6 +241,19 @@ void ProjectView::Update(Observable &,I_ObservableData *data) { DoModal(mb) ; } break ; + case ACTION_SAVE_AS: + if (!player->IsRunning()) { + PersistencyService *service=PersistencyService::GetInstance() ; + service->Save() ; + NewProjectDialog *mb=new NewProjectDialog(*this) ; + DoModal(mb,SaveAsProjectCallback) ; + + } else { + MessageBox *mb=new MessageBox(*this,"Not while playing",MBBF_OK) ; + DoModal(mb) ; + } + break ; + case ACTION_LOAD: { if (!player->IsRunning()) { @@ -211,6 +296,12 @@ void ProjectView::OnLoadProject() { NotifyObservers(&ve) ; } ; +void ProjectView::OnSaveAsProject(char * data) { + ViewEvent ve(VET_SAVEAS_PROJECT,data) ; + SetChanged(); + NotifyObservers(&ve) ; +} ; + void ProjectView::OnQuit() { ViewEvent ve(VET_QUIT_APP) ; SetChanged(); diff --git a/sources/Application/Views/ProjectView.h b/sources/Application/Views/ProjectView.h index d48a1d7f..1f9474cf 100644 --- a/sources/Application/Views/ProjectView.h +++ b/sources/Application/Views/ProjectView.h @@ -21,6 +21,7 @@ class ProjectView: public FieldView,public I_Observer { void Update(Observable &,I_ObservableData *) ; void OnLoadProject() ; + void OnSaveAsProject(char * data) ; void OnPurgeInstruments(bool removeFromDisk) ; void OnQuit() ; diff --git a/sources/System/Errors/Result.h b/sources/System/Errors/Result.h index 596cf387..3882a820 100644 --- a/sources/System/Errors/Result.h +++ b/sources/System/Errors/Result.h @@ -20,6 +20,7 @@ class Result { Result &operator=(const Result &) ; static Result NoError ; + protected: Result() ; private: @@ -29,5 +30,5 @@ class Result { mutable Result *child_ ; } ; -#define RETURN_IF_FAILED_MESSAGE(r,m) if (r.Failed()) { return Result(r,m) ; } +#define RETURN_IF_FAILED(r,m) if (r.Failed()) {Result(r,m);} #define LOG_IF_FAILED(r,m) if (r.Failed()) { Trace::Log(m) ; Trace::Log(r.GetDescription().c_str()); } \ No newline at end of file diff --git a/sources/System/FileSystem/FileSystem.cpp b/sources/System/FileSystem/FileSystem.cpp index 81200ca4..f64436b5 100644 --- a/sources/System/FileSystem/FileSystem.cpp +++ b/sources/System/FileSystem/FileSystem.cpp @@ -179,3 +179,40 @@ void Path::Alias::SetAliasName(const char *alias) { void Path::Alias::SetPath(const char *path) { path_=path ; } ; + +int FileSystemService::Copy(const Path &src,const Path &dst) +{ + int bufsize=4096; + char buffer[bufsize]; + int count=0; + int nbwrite=-1; + + FileSystem * fs=FileSystem::GetInstance() ; + I_File * isrc=fs->Open(src.GetPath().c_str(),"r"); + I_File * idst=fs->Open(dst.GetPath().c_str(),"w"); + + Trace::Log("FS","FileSystemService::Copy %s to %s", + src.GetPath().c_str(), dst.GetPath().c_str()); + if (isrc) + Trace::Log("FS","src open ok"); + else { + Trace::Log("FS","src open fail"); + return nbwrite; + } + if (idst) + Trace::Log("FS","dst open ok"); + else { + Trace::Log("FS","dst open fail"); + return nbwrite; + } + + while (count=isrc->Read(buffer,sizeof(char),bufsize)) + { + idst->Write(buffer,sizeof(char),count); + nbwrite++; + } + + isrc->Close(); + idst->Close(); + return nbwrite; +} \ No newline at end of file diff --git a/sources/System/FileSystem/FileSystem.h b/sources/System/FileSystem/FileSystem.h index 10bbf958..a915ffc8 100644 --- a/sources/System/FileSystem/FileSystem.h +++ b/sources/System/FileSystem/FileSystem.h @@ -108,4 +108,9 @@ class FileSystem: public T_Factory { #define FS_FOPEN(a,b) FileSystem::GetInstance()->Open(a,b) +class FileSystemService { + public: + int Copy(const Path &src,const Path &dst); +}; + #endif