From e231ae835ddab6fbe9b103b80c2f8ee2ddf68a8a Mon Sep 17 00:00:00 2001 From: bill-auger Date: Oct 21 2018 11:16:14 +0000 Subject: sq clips --- diff --git a/Source/Constants/GuiConstants.cpp b/Source/Constants/GuiConstants.cpp index 0c551e9..dce705f 100644 --- a/Source/Constants/GuiConstants.cpp +++ b/Source/Constants/GuiConstants.cpp @@ -30,12 +30,13 @@ const uint8 GUI::STROKE_W = 1 ; const float GUI::FONT_SIZE = 16.0 ; // MainWindow -const uint8 GUI::BORDERS_W = 2 ; -const uint8 GUI::TITLEBAR_H = 24 ; -const uint16 GUI::WINDOW_W = 768 - BORDERS_W ; // jucer 766 -const uint16 GUI::WINDOW_H = 768 - BORDERS_W - TITLEBAR_H ; // jucer 742 -const Colour GUI::WINDOW_BG_COLOR = Colour(0xFF404040) ; -const int GUI::TITLEBAR_BTNS = DocumentWindow::allButtons ; +const uint8 GUI::BORDERS_W = 2 ; +const uint8 GUI::TITLEBAR_H = 24 ; +const uint16 GUI::WINDOW_W = 768 - BORDERS_W ; // jucer 766 +const uint16 GUI::WINDOW_H = 768 - BORDERS_W - TITLEBAR_H ; // jucer 742 +const Colour GUI::WINDOW_BG_COLOR = Colour(0xFF404040) ; +const int GUI::TITLEBAR_BTNS = DocumentWindow::allButtons ; +const float GUI::DASH_LENGTHS[N_DASH_LENGTHS] = { 8.0f , 8.0f } ; // Waveform const uint16 GUI::CACHE_N_THUMBS = 512 ; @@ -75,10 +76,11 @@ const Colour GUI::BROWSER_SELECTED_FG_COLOR = Colour(0xFF40FF40) ; // clips/compilations TreeViewItems const String GUI::FILE_ITEM_LABEL = "Source: " ; const String GUI::BEGIN_ITEM_LABEL = "Beginning: " ; -const String GUI::ENT_ITEM_LABEL = "Ending: " ; +const String GUI::END_ITEM_LABEL = "Ending: " ; // user messages const String GUI::DEVICE_ERROR_TITLE = "Audio Device Error" ; const String GUI::DEVICE_ERROR_MSG = "Audio Device Error\n\nCan not find a usable audio playback device" ; const String GUI::FILESYSTEM_WRITE_ERROR_MSG = "I/O Error\n\nCan not write to filesystem" ; const String GUI::STORAGE_WRITE_ERROR_MSG = "I/O Error\n\nCan not write: " ; +const String GUI::ID_COLLISION_ERROR_MSG = "ID Collision\n\nCan not create an entry for this file. The path/file name is ambiguous with another entry." ; diff --git a/Source/Constants/GuiConstants.h b/Source/Constants/GuiConstants.h index d0f7bed..1799563 100644 --- a/Source/Constants/GuiConstants.h +++ b/Source/Constants/GuiConstants.h @@ -44,6 +44,8 @@ public: static const uint16 WINDOW_H ; static const Colour WINDOW_BG_COLOR ; static const int TITLEBAR_BTNS ; + static const int N_DASH_LENGTHS = 2 ; // ASSERT: number of floats defiend in DASH_LENGTHS + static const float DASH_LENGTHS[N_DASH_LENGTHS] ; // Waveform static const uint16 CACHE_N_THUMBS ; @@ -83,11 +85,12 @@ public: // clips/compilations TreeViewItems static const String FILE_ITEM_LABEL ; static const String BEGIN_ITEM_LABEL ; - static const String ENT_ITEM_LABEL ; + static const String END_ITEM_LABEL ; // user messages static const String DEVICE_ERROR_TITLE ; static const String DEVICE_ERROR_MSG ; static const String FILESYSTEM_WRITE_ERROR_MSG ; static const String STORAGE_WRITE_ERROR_MSG ; + static const String ID_COLLISION_ERROR_MSG ; } ; diff --git a/Source/Constants/StorageConstants.cpp b/Source/Constants/StorageConstants.cpp index 7769517..20c6e79 100644 --- a/Source/Constants/StorageConstants.cpp +++ b/Source/Constants/StorageConstants.cpp @@ -55,6 +55,7 @@ const Identifier STORE::COMPILATIONS_ID = "compilations" ; const Identifier STORE::CONFIG_VERSION_KEY = "config-version" ; // clips/compilations IDs +const Identifier STORE::LABEL_TEXT_KEY = "label-text"; const Identifier STORE::FILENAME_KEY = "master-filename"; const Identifier STORE::BEGIN_TIME_KEY = "begin-time" ; const Identifier STORE::END_TIME_KEY = "end-time" ; diff --git a/Source/Constants/StorageConstants.h b/Source/Constants/StorageConstants.h index 6f55cac..40d5b93 100644 --- a/Source/Constants/StorageConstants.h +++ b/Source/Constants/StorageConstants.h @@ -102,6 +102,7 @@ public: static const Identifier CONFIG_VERSION_KEY ; // clips/compilations IDs + static const Identifier LABEL_TEXT_KEY ; static const Identifier FILENAME_KEY ; static const Identifier BEGIN_TIME_KEY ; static const Identifier END_TIME_KEY ; diff --git a/Source/Models/AudioTagTooStore.cpp b/Source/Models/AudioTagTooStore.cpp index 1a74d9b..20723f8 100644 --- a/Source/Models/AudioTagTooStore.cpp +++ b/Source/Models/AudioTagTooStore.cpp @@ -384,38 +384,60 @@ DEBUG_TRACE_SET_CONFIG return is_valid ; } +ValueTree AudioTagTooStore::getChildNodeById(ValueTree root_store , Identifier node_id) +{ + ValueTree child_node ; + + if ((child_node = root_store.getChildWithName(node_id)).isValid()) + return child_node ; + else for (int master_n = 0 ; master_n < root_store.getNumChildren() ; ++master_n) + if ((child_node = root_store.getChild(master_n).getChildWithName(node_id)).isValid()) + return child_node ; + + return ValueTree::invalid ; +} + bool AudioTagTooStore::createClip(String audio_filename , double begin_time , double end_time) { - Identifier master_id = STORE::FilterId(audio_filename) ; - Identifier clip_id = STORE::FilterId(audio_filename + '-' + - String(begin_time) + '-' + - String(end_time ) ) ; - - ValueTree master_store = this->clips.getChildWithName(master_id) ; - bool is_new_master = !master_store.isValid() ; - var master_filename = master_store.getProperty(STORE::FILENAME_KEY) ; - bool is_id_collision = !is_new_master && STRING(master_filename) != audio_filename ; - master_store = (is_new_master) ? ValueTree(master_id) : master_store ; - ValueTree clip_store = ValueTree(clip_id) ; + Identifier master_id = STORE::FilterId(audio_filename) ; + Identifier clip_id = STORE::FilterId(audio_filename + '-' + + String(begin_time) + '-' + + String(end_time ) ) ; + ValueTree master_node = this->clips.getChildWithName(master_id) ; + bool is_new_master = !master_node.isValid() ; + String master_filename = STRING(master_node[STORE::FILENAME_KEY]) ; + bool is_id_collision = !is_new_master && master_filename != audio_filename ; + master_node = (is_new_master) ? ValueTree(master_id) : master_node ; + String master_label_text = File(audio_filename).getFileName() ; + String clip_label_text = String(begin_time , 6) + " - " + String(end_time , 6) ; + ValueTree clip_node = ValueTree(clip_id) ; DEBUG_TRACE_CREATE_CLIP - bool is_valid = !is_id_collision && - setProperty(master_store , STORE::FILENAME_KEY , audio_filename) && - setProperty(clip_store , STORE::FILENAME_KEY , audio_filename) && - setProperty(clip_store , STORE::BEGIN_TIME_KEY , begin_time ) && - setProperty(clip_store , STORE::END_TIME_KEY , end_time ) ; +#ifdef HAS_MAIN_CONTROLLER + if (is_id_collision) AudioTagToo::Warning(GUI::ID_COLLISION_ERROR_MSG) ; +#else // HAS_MAIN_CONTROLLER + if (is_id_collision) Trace::TraceError(GUI::ID_COLLISION_ERROR_MSG) ; +#endif // HAS_MAIN_CONTROLLER + + bool is_valid = !is_id_collision && + setProperty(master_node , STORE::LABEL_TEXT_KEY , master_label_text) && + setProperty(master_node , STORE::FILENAME_KEY , audio_filename ) && + setProperty(clip_node , STORE::LABEL_TEXT_KEY , clip_label_text ) && + setProperty(clip_node , STORE::FILENAME_KEY , audio_filename ) && + setProperty(clip_node , STORE::BEGIN_TIME_KEY , begin_time ) && + setProperty(clip_node , STORE::END_TIME_KEY , end_time ) ; if (is_valid) { - master_store.appendChild(clip_store , nullptr) ; - this->clips.appendChild(master_store , nullptr) ; + master_node.appendChild(clip_node , nullptr) ; + this->clips.appendChild(master_node , nullptr) ; STORE::IdComparator id_comparator ; - this->clips .sort(id_comparator , nullptr , false) ; - master_store.sort(id_comparator , nullptr , false) ; + this->clips.sort(id_comparator , nullptr , false) ; + master_node.sort(id_comparator , nullptr , false) ; -// DEBUG_TRACE_DUMP_STORE(master_store , "master_store") +DEBUG_TRACE_DUMP_STORE(master_node , "master_node") } return is_valid ; diff --git a/Source/Models/AudioTagTooStore.h b/Source/Models/AudioTagTooStore.h index 48618b2..1370469 100644 --- a/Source/Models/AudioTagTooStore.h +++ b/Source/Models/AudioTagTooStore.h @@ -36,20 +36,20 @@ class AudioTagTooStore : ValueTree::Listener public: - ~AudioTagTooStore() ; + ~AudioTagTooStore(void) ; private: // initialization - AudioTagTooStore() ; - bool initialize() ; - void teardown() ; + AudioTagTooStore(void) ; + bool initialize(void) ; + void teardown(void) ; // validations - void verifyConfig() ; - void verifyRoot () ; - void sanitizeRoot() ; + void verifyConfig(void) ; + void verifyRoot (void) ; + void sanitizeRoot(void) ; // validation/sanitization helpers void verifyChildNode (ValueTree store , Identifier node_id) ; @@ -65,7 +65,7 @@ private: void sanitizeComboProperty(ValueTree store , Identifier key , StringArray options) ; // persistence - void loadConfig () ; + void loadConfig (void) ; bool storeConfig(XmlElement* device_state_xml) ; // event handlers @@ -80,10 +80,11 @@ private: void valueTreeRedirected (ValueTree& /*redirected_node*/ ) override {} // getters/setters - bool isKnownProperty(ValueTree node , const Identifier& key) ; - bool setProperty (ValueTree node , const Identifier& key , const var value) ; - bool setConfig (ValueTree config_node , const Identifier& key , const var value) ; - bool createClip (String audio_filename , double begin_time , double end_time) ; + bool isKnownProperty (ValueTree node , const Identifier& key) ; + bool setProperty (ValueTree node , const Identifier& key , const var value) ; + bool setConfig (ValueTree config_node , const Identifier& key , const var value) ; + ValueTree getChildNodeById(ValueTree root_store , Identifier node_id) ; + bool createClip (String audio_filename , double begin_time , double end_time) ; // configuration/persistence File storageFile ; diff --git a/Source/Views/MainContent.cpp b/Source/Views/MainContent.cpp index 0f736d8..bb2245b 100644 --- a/Source/Views/MainContent.cpp +++ b/Source/Views/MainContent.cpp @@ -87,7 +87,6 @@ MainContent::MainContent () clipButton.reset (new TextButton (String())); addAndMakeVisible (clipButton.get()); clipButton->setButtonText (TRANS("Clip")); - clipButton->addListener (this); tailButton.reset (new TextButton (String())); addAndMakeVisible (tailButton.get()); @@ -153,6 +152,7 @@ MainContent::MainContent () this->headButton ->addListener (this); this->transportButton ->addListener (this); + this->clipButton ->addListener (this); this->tailButton ->addListener (this); this->deviceManager .addAudioCallback (&audioSourcePlayer) ; this->deviceManager .addChangeListener(this) ; @@ -186,14 +186,17 @@ MainContent::~MainContent() this->transportSource .setSource(nullptr) ; this->audioSourcePlayer.setSource(nullptr) ; - this->headButton ->removeListener (this); - this->transportButton->removeListener (this); - this->tailButton ->removeListener (this); - this->deviceManager .removeAudioCallback (&audioSourcePlayer) ; - this->deviceManager .removeChangeListener(this) ; - this->transportSource .removeChangeListener(this) ; - this->fileBrowser ->removeListener (this) ; - this->storage->root .removeListener (this) ; + this->headButton ->removeListener (this); + this->transportButton ->removeListener (this); + this->clipButton ->removeListener (this); + this->tailButton ->removeListener (this); + this->deviceManager .removeAudioCallback (&audioSourcePlayer) ; + this->deviceManager .removeChangeListener(this) ; + this->clipWaveform ->removeChangeListener(this) ; + this->transportSource .removeChangeListener(this) ; + this->fileBrowser ->removeListener (this) ; + this->storage->clips .removeListener (this) ; + this->storage->compilations.removeListener (this) ; this->storage = nullptr ; @@ -261,6 +264,7 @@ void MainContent::resized() } + //[MiscUserCode] You can add your own definitions of your custom methods or any other code here... /* getters/setters */ @@ -341,10 +345,9 @@ void MainContent::setTailMarker() void MainContent::createClip() { - if (!this->storage->createClip(this->audioFilename , - this->fullWaveform->getHeadTime() , - this->fullWaveform->getHeadTime() )) - ; // TODO: collision alert + this->storage->createClip(this->audioFilename , + this->fullWaveform->getHeadTime() , + this->fullWaveform->getTailTime() ) ; } @@ -358,38 +361,40 @@ TreeViewItem* MainContent::getViewItemFor(ValueTree root_store) TreeViewItem* MainContent::newMasterItem(ValueTree master_node) { - String master_id = STRING(master_node.getType()) ; - String master_filename = STRING(master_node[STORE::FILENAME_KEY]) ; - String master_label = File(master_filename).getFileName() ; - TreeViewItem* new_master = new ClipItem(master_id , master_label) ; + String master_id = STRING(master_node.getType()) ; + String master_filename = STRING(master_node[STORE::FILENAME_KEY ]) ; + String master_label_text = STRING(master_node[STORE::LABEL_TEXT_KEY]) ; + TreeViewItem* master_item = new ClipItem(master_id , master_label_text , master_node) ; DEBUG_TRACE_NEW_MASTER_ITEM -// Trace::DumpStore(master_node , "master_node") ; - return new_master ; + return master_item ; } TreeViewItem* MainContent::newClipItem(ValueTree clip_node) { - String clip_id = STRING(clip_node.getType()) ; - String file_id = clip_id + "-filename" ; - String begin_id = clip_id + "-begin_time" ; - String end_id = clip_id + "-end_time" ; - String filename = STRING( clip_node[STORE::FILENAME_KEY ]) ; - String begin_time = String(double(clip_node[STORE::BEGIN_TIME_KEY]) , 6) ; - String end_time = String(double(clip_node[STORE::END_TIME_KEY ]) , 6) ; - String clip_label = begin_time + " - " + end_time ; - String file_label = GUI::FILE_ITEM_LABEL + filename ; - String begin_label = GUI::BEGIN_ITEM_LABEL + begin_time ; - String end_label = GUI::ENT_ITEM_LABEL + end_time ; - TreeViewItem* new_clip = new ClipItem(clip_id , clip_label) ; - new_clip->addSubItem( new ClipItem(file_id , file_label , false) , 0) ; - new_clip->addSubItem( new ClipItem(begin_id , begin_label , false) , 1) ; - new_clip->addSubItem( new ClipItem(end_id , end_label , false) , 2) ; + String clip_id = STRING(clip_node.getType()) ; + String file_id = clip_id + "-filename" ; + String begin_id = clip_id + "-begin_time" ; + String end_id = clip_id + "-end_time" ; + String filename = STRING( clip_node[STORE::FILENAME_KEY ]) ; + String begin_time = String(double(clip_node[STORE::BEGIN_TIME_KEY]) , 6) ; + String end_time = String(double(clip_node[STORE::END_TIME_KEY ]) , 6) ; + String clip_label_text = STRING( clip_node[STORE::LABEL_TEXT_KEY]) ; + String file_label_text = GUI::FILE_ITEM_LABEL + filename ; + String begin_label_text = GUI::BEGIN_ITEM_LABEL + begin_time ; + String end_label_text = GUI::END_ITEM_LABEL + end_time ; + TreeViewItem* clip_item = new ClipItem(clip_id , clip_label_text , clip_node) ; + TreeViewItem* filename_item = new ClipItem(file_id , file_label_text ) ; + TreeViewItem* begin_time_item = new ClipItem(begin_id , begin_label_text ) ; + TreeViewItem* end_time_item = new ClipItem(end_id , end_label_text ) ; + clip_item->addSubItem(filename_item , 0) ; + clip_item->addSubItem(begin_time_item , 1) ; + clip_item->addSubItem(end_time_item , 2) ; DEBUG_TRACE_NEW_CLIP_ITEM - return new_clip ; + return clip_item ; } void MainContent::createMasterItem(ValueTree root_store , ValueTree master_node) @@ -405,7 +410,6 @@ void MainContent::createMasterItem(ValueTree root_store , ValueTree master_node) DEBUG_TRACE_CREATE_MASTER_ITEM for (int clip_n = 0 ; clip_n < master_node.getNumChildren() ; ++clip_n) -// master_item->addSubItem(newClipItem(master_node.getChild(clip_n)) , -1) ; createClipItem(root_store , master_node.getChild(clip_n)) ; } @@ -547,38 +551,24 @@ DEBUG_TRACE_STORAGE_REDIRECTED if (root_item != nullptr) { - ValueTree master_node ; - ValueTree clip_node ; + while (root_item->getNumSubItems() > 0) root_item->removeSubItem(0) ; // clearSubItems() - while (root_item->getNumSubItems() > 0) root_item->removeSubItem(0) ; - // clearSubItems() for (int master_n = 0 ; master_n < root_store.getNumChildren() ; ++master_n) - { - master_node = root_store.getChild(master_n) ; - createMasterItem(root_store , master_node) ; - - for (int clip_n = 0 ; clip_n < master_node.getNumChildren() ; ++clip_n) - { - clip_node = master_node.getChild(clip_n) ; - createClipItem(root_store , clip_node) ; - } - } + createMasterItem(root_store , root_store.getChild(master_n)) ; } } void MainContent::valueTreeChildAdded(ValueTree& parent_node , ValueTree& new_node) { - bool is_master_clips_node = parent_node == this->storage->clips ; - bool is_clip_clips_node = parent_node.getParent() == this->storage->clips ; - bool is_master_compilations_node = parent_node == this->storage->compilations ; - bool is_clip_compilations_node = parent_node.getParent() == this->storage->compilations ; + bool is_master_node = parent_node == this->storage->clips || + parent_node == this->storage->compilations ; + bool is_clip_node = parent_node.getParent() == this->storage->clips || + parent_node.getParent() == this->storage->compilations ; DEBUG_TRACE_STORAGE_CHILD_ADDED - if (is_master_clips_node ) createMasterItem(this->storage->clips , new_node) ; - else if (is_clip_clips_node ) createClipItem (this->storage->clips , new_node) ; - else if (is_master_compilations_node) createMasterItem(this->storage->compilations , new_node) ; - else if (is_clip_compilations_node ) createClipItem (this->storage->compilations , new_node) ; + if (is_master_node) createMasterItem(parent_node , new_node) ; + else if (is_clip_node ) createClipItem (parent_node.getParent() , new_node) ; } void MainContent::valueTreeChildRemoved(ValueTree& parent_node , ValueTree& deleted_node , diff --git a/Source/Views/MainContent.h b/Source/Views/MainContent.h index d13fd0b..c6f8032 100644 --- a/Source/Views/MainContent.h +++ b/Source/Views/MainContent.h @@ -24,6 +24,7 @@ //[Headers] -- You can add your own extra header files here -- #include "../../JuceLibraryCode/JuceHeader.h" +#include "../Constants/StorageConstants.h" #include "../Models/AudioTagTooStore.h" #include "Statusbar.h" #include "Waveform.h" @@ -122,49 +123,40 @@ private: void browserRootChanged(const File& ) override {} - class ClipItem : public TreeViewItem + class ClipItem : public TreeViewItem , private Label::Listener { public: - ClipItem(String _item_id , String _label , bool _accepts_sub_items = true ) : - item_id(_item_id) , label(_label) , accepts_sub_items(_accepts_sub_items) { } + ClipItem(String _item_id , String _label , ValueTree _store = ValueTree::invalid) : + item_id(_item_id) , label(_label) , store(_store) { } - String getUniqueName () const override { return this->item_id ; } - bool mightContainSubItems() override { return this->accepts_sub_items ; } - int getItemHeight () const override { return 22 ; } -// Component* createItemComponent () override { return new Label(id) ; } - void paintItem(Graphics& g , int width , int height) override + // TreeViewItem implementation + String getUniqueName () const override { return this->item_id ; } + bool mightContainSubItems() override { return this->store.isValid() ; } + int getItemHeight () const override { return 24 ; } + Component* createItemComponent () override { - g.setFont(Font(height * 0.7f , Font::bold)) ; - g.setColour(GUI::FILENAME_FG_COLOR) ; - g.drawText(this->label , 2 , 0 , width - 2 , height , Justification::centredLeft , true) ; + Label* item_label = new Label(this->item_id , this->label) ; + + item_label->setEditable(this->store.isValid()) ; + item_label->addListener(this) ; + + return item_label ; } - void itemOpennessChanged(bool is_open) override + // Label event handler + void labelTextChanged(Label* a_label) { -DBG("ClipsTreeViewItem::itemOpennessChanged()=" + String(is_open ? "is_open" : "is_closed")) ; -/* - if (isNowOpen) - { - if (getNumSubItems() == 0) - for (auto command : owner.getCommandManager().getCommandsInCategory (categoryName)) - if (owner.shouldCommandBeIncluded (command)) - addSubItem (new MappingItem (owner, command)); - } - else - { - clearSubItems(); - } -*/ + this->store.setProperty(STORE::LABEL_TEXT_KEY , a_label->getText() , nullptr) ; } private: - String item_id ; - String label ; - bool accepts_sub_items ; + String item_id ; + String label ; + ValueTree store ; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ClipItem)