More UI bindings, metadata management

This commit is contained in:
Jack Andersen 2016-06-04 12:38:55 -10:00
parent 9ae92313e3
commit 62ece61cb2
6 changed files with 277 additions and 101 deletions

View File

@ -19,6 +19,8 @@
<outlet property="dataOutline" destination="Vlv-Jw-A4U" id="Ggn-DC-cUY"/>
<outlet property="dataSearchField" destination="Huk-pR-ayq" id="MbL-0b-KGw"/>
<outlet property="mainWindow" destination="FDh-Mc-OFY" id="CQQ-Dm-Kv3"/>
<outlet property="removeDataButton" destination="eh8-gl-WoS" id="U9P-dt-tN5"/>
<outlet property="removeDataMenu" destination="pa3-QI-u2k" id="xnq-of-WvG"/>
<outlet property="samplesTable" destination="Frt-wZ-1ZI" id="riC-O4-JXo"/>
<outlet property="sfxTable" destination="4nw-rf-Dh4" id="ebY-ro-tqk"/>
</connections>
@ -78,12 +80,15 @@
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<menu key="submenu" title="Edit" autoenablesItems="NO" id="W48-6f-4Dl">
<items>
<menuItem title="Delete" id="pa3-QI-u2k">
<menuItem title="Delete" enabled="NO" id="pa3-QI-u2k">
<string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
<action selector="removeDataItem:" target="Y3H-Qy-a7C" id="aAl-Ko-LrT"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
@ -182,10 +187,13 @@
<constraints>
<constraint firstAttribute="width" constant="31" id="HLy-Rb-n4I"/>
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="edx-l4-aHD">
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" enabled="NO" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="edx-l4-aHD">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="removeDataItem:" target="Y3H-Qy-a7C" id="hau-zt-Ozz"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mpK-AK-Otf">
<rect key="frame" x="58" y="-1" width="486" height="32"/>
@ -213,7 +221,7 @@
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<buttonCell key="dataCell" type="check" title="CollectionTitle" bezelStyle="regularSquare" imagePosition="left" alignment="left" lineBreakMode="truncatingTail" inset="2" id="Lpp-wh-qX7">
<buttonCell key="dataCell" type="check" title="CollectionTitle" bezelStyle="regularSquare" imagePosition="left" alignment="left" lineBreakMode="truncatingTail" allowsMixedState="YES" inset="2" id="Lpp-wh-qX7">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
@ -255,11 +263,14 @@
<constraints>
<constraint firstAttribute="height" constant="22" id="uJy-eO-Y8o"/>
</constraints>
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" usesSingleLineMode="YES" bezelStyle="round" id="u9E-Ld-d6I">
<searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" usesSingleLineMode="YES" bezelStyle="round" sendsSearchStringImmediately="YES" id="u9E-Ld-d6I">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</searchFieldCell>
<connections>
<action selector="filterDataOutline:" target="Y3H-Qy-a7C" id="D8g-Qv-0QG"/>
</connections>
</searchField>
</subviews>
<constraints>

View File

@ -0,0 +1,48 @@
#ifndef __AMUSE_AUDIOUNIT_CONTAININGAPP_HPP__
#define __AMUSE_AUDIOUNIT_CONTAININGAPP_HPP__
#import <AppKit/AppKit.h>
#import "AudioGroupFilePresenter.hpp"
@interface DataOutlineView : NSOutlineView
{
@public
IBOutlet NSButton* removeDataButton;
IBOutlet NSMenuItem* deleteMenuItem;
}
@end
@interface SamplesTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate>
{
}
@end
@interface SFXTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate>
{
}
@end
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
IBOutlet NSWindow* mainWindow;
IBOutlet NSOutlineView* dataOutline;
IBOutlet NSSearchField* dataSearchField;
IBOutlet NSTableView* sfxTable;
IBOutlet NSTableView* samplesTable;
IBOutlet NSTextView* creditsView;
IBOutlet NSButton* removeDataButton;
IBOutlet NSMenuItem* removeDataMenu;
AudioGroupFilePresenter* groupFilePresenter;
SamplesTableController* samplesController;
SFXTableController* sfxController;
}
- (BOOL)importURL:(NSURL*)url;
- (void)outlineView:(DataOutlineView*)ov selectionChanged:(id)item;
@end
#endif // __AMUSE_AUDIOUNIT_CONTAININGAPP_HPP__

View File

@ -2,7 +2,7 @@
#import <AudioUnit/AudioUnit.h>
#import <CoreAudioKit/AUViewController.h>
#import "AudioUnitViewController.hpp"
#import "AudioGroupFilePresenter.hpp"
#import "AmuseContainingApp.hpp"
#include <amuse/amuse.hpp>
@class DataOutlineController;
@ -34,21 +34,19 @@
@end
@interface AppDelegate : NSObject <NSApplicationDelegate>
@implementation DataOutlineView
- (id)initWithFrame:(NSRect)frameRect
{
IBOutlet NSWindow* mainWindow;
IBOutlet NSOutlineView* dataOutline;
IBOutlet NSSearchField* dataSearchField;
IBOutlet NSTableView* sfxTable;
IBOutlet NSTableView* samplesTable;
IBOutlet NSTextView* creditsView;
AudioGroupFilePresenter* groupFilePresenter;
SamplesTableController* samplesController;
SFXTableController* sfxController;
self = [super initWithFrame:frameRect];
[self registerForDraggedTypes:@[(__bridge NSString*)kUTTypeData]];
return self;
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
{
return NO;
}
- (BOOL)importURL:(NSURL*)url;
@end
@interface MainTabView : NSTabView
@ -78,34 +76,6 @@
}
@end
@interface DataOutlineView : NSOutlineView
{
}
@end
@implementation DataOutlineView
- (id)initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
[self registerForDraggedTypes:@[(__bridge NSString*)kUTTypeData]];
return self;
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
{
}
@end
@interface SamplesTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate>
{
}
@end
@implementation SamplesTableController
@ -121,11 +91,6 @@
@end
@interface SFXTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate>
{
}
@end
@implementation SFXTableController
@ -199,6 +164,30 @@
}];
}
- (IBAction)filterDataOutline:(id)sender
{
[groupFilePresenter setSearchFilter:[sender stringValue]];
}
- (IBAction)removeDataItem:(id)sender
{
[groupFilePresenter removeSelectedItem];
}
- (void)outlineView:(DataOutlineView *)ov selectionChanged:(id)item
{
if ([item isKindOfClass:[AudioGroupCollectionToken class]])
{
removeDataButton.enabled = TRUE;
removeDataMenu.enabled = TRUE;
}
else
{
removeDataButton.enabled = FALSE;
removeDataMenu.enabled = FALSE;
}
}
@end
int main(int argc, const char * argv[])

View File

@ -55,6 +55,9 @@ struct AudioGroupDataCollection
AudioGroupDataCollection(const std::string& name, NSURL* proj, NSURL* pool, NSURL* sdir, NSURL* samp, NSURL* meta);
bool isDataComplete() const {return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;}
bool _attemptLoad(AudioGroupFilePresenter* presenter);
void enable(AudioGroupFilePresenter* presenter);
void disable(AudioGroupFilePresenter* presenter);
};
template <class T>
@ -90,12 +93,14 @@ struct AudioGroupCollection
NSURL* m_url;
AudioGroupCollectionToken* m_token;
std::map<std::string, AudioGroupDataCollection> m_groups;
std::experimental::optional<IteratorTracker<AudioGroupDataCollection>> m_iteratorTracker;
std::map<std::string, std::unique_ptr<AudioGroupDataCollection>> m_groups;
std::vector<std::map<std::string, std::unique_ptr<AudioGroupDataCollection>>::iterator> m_filterGroups;
//std::experimental::optional<IteratorTracker<std::unique_ptr<AudioGroupDataCollection>>> m_iteratorTracker;
AudioGroupCollection(NSURL* url);
void addCollection(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&& collection);
void update(AudioGroupFilePresenter* presenter);
bool doSearch(const std::string& str);
};
@interface AudioGroupDataToken : NSObject
@ -118,14 +123,18 @@ struct AudioGroupCollection
{
NSURL* m_groupURL;
NSOperationQueue* m_dataQueue;
std::map<std::string, AudioGroupCollection> m_audioGroupCollections;
std::map<std::string, std::unique_ptr<AudioGroupCollection>> m_audioGroupCollections;
std::vector<std::map<std::string, std::unique_ptr<AudioGroupCollection>>::iterator> m_filterAudioGroupCollections;
NSOutlineView* lastOutlineView;
NSString* searchStr;
std::experimental::optional<IteratorTracker<AudioGroupCollection>> m_iteratorTracker;
//std::experimental::optional<IteratorTracker<std::unique_ptr<AudioGroupCollection>>> m_iteratorTracker;
}
- (BOOL)addCollectionName:(std::string&&)name items:(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&&)collection;
- (void)update;
- (void)resetIterators;
- (void)setSearchFilter:(NSString*)str;
- (void)removeSelectedItem;
@end
#endif // __AMUSE_AUDIOUNIT_AUDIOGROUPFILEPRESENTER_HPP__

View File

@ -1,28 +1,31 @@
#include "AudioGroupFilePresenter.hpp"
#include <athena/FileReader.hpp>
#include <amuse/AudioGroupProject.hpp>
#import <AppKit/AppKit.h>
#import "AmuseContainingApp.hpp"
static std::string StrToLower(const std::string& str)
{
std::string ret = str;
std::transform(ret.begin(), ret.end(), ret.begin(), tolower);
return ret;
}
@implementation AudioGroupDataToken
- (id)initWithDataCollection:(AudioGroupDataCollection *)collection
{
self = [super init];
m_collection = collection;
return self;
}
@end
@implementation AudioGroupCollectionToken
- (id)initWithCollection:(AudioGroupCollection *)collection
{
self = [super init];
m_collection = collection;
return self;
}
@end
@implementation AudioGroupFilePresenter
@ -51,15 +54,15 @@ void AudioGroupCollection::addCollection(std::vector<std::pair<std::string, amus
if (search == m_groups.end())
{
search = m_groups.emplace(pair.first,
AudioGroupDataCollection{pair.first,
std::make_unique<AudioGroupDataCollection>(pair.first,
[collectionUrl URLByAppendingPathComponent:@"proj"],
[collectionUrl URLByAppendingPathComponent:@"pool"],
[collectionUrl URLByAppendingPathComponent:@"sdir"],
[collectionUrl URLByAppendingPathComponent:@"samp"],
[collectionUrl URLByAppendingPathComponent:@"meta"]}).first;
[collectionUrl URLByAppendingPathComponent:@"meta"])).first;
}
AudioGroupDataCollection& dataCollection = search->second;
AudioGroupDataCollection& dataCollection = *search->second;
dataCollection.m_projData.resize(dataIn.getProjSize());
memmove(dataCollection.m_projData.data(), dataIn.getProj(), dataIn.getProjSize());
@ -101,18 +104,32 @@ void AudioGroupCollection::update(AudioGroupFilePresenter* presenter)
std::string nameStr = path.lastPathComponent.UTF8String;
search =
m_groups.emplace(nameStr,
AudioGroupDataCollection{nameStr,
std::make_unique<AudioGroupDataCollection>(nameStr,
[path URLByAppendingPathComponent:@"proj"],
[path URLByAppendingPathComponent:@"pool"],
[path URLByAppendingPathComponent:@"sdir"],
[path URLByAppendingPathComponent:@"samp"],
[path URLByAppendingPathComponent:@"meta"]}).first;
search->second._attemptLoad(presenter);
[path URLByAppendingPathComponent:@"meta"])).first;
search->second->_attemptLoad(presenter);
}
}
}
}
bool AudioGroupCollection::doSearch(const std::string& str)
{
bool ret = false;
m_filterGroups.clear();
m_filterGroups.reserve(m_groups.size());
for (auto it = m_groups.begin() ; it != m_groups.end() ; ++it)
if (str.empty() || StrToLower(it->first).find(str) != std::string::npos)
{
m_filterGroups.push_back(it);
ret = true;
}
return ret;
}
AudioGroupDataCollection::AudioGroupDataCollection(const std::string& name, NSURL* proj, NSURL* pool,
NSURL* sdir, NSURL* samp, NSURL* meta)
: m_name(name), m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp), m_meta(meta),
@ -120,8 +137,6 @@ AudioGroupDataCollection::AudioGroupDataCollection(const std::string& name, NSUR
bool AudioGroupDataCollection::_attemptLoad(AudioGroupFilePresenter* presenter)
{
if (!isDataComplete())
return false;
if (m_metaData && m_loadedProj)
return true;
if (!loadProj(presenter))
@ -169,6 +184,40 @@ bool AudioGroupDataCollection::_attemptLoad(AudioGroupFilePresenter* presenter)
return false;
}
void AudioGroupDataCollection::enable(AudioGroupFilePresenter* presenter)
{
m_metaData->active = true;
NSFileCoordinator* coord = [[NSFileCoordinator alloc] initWithFilePresenter:presenter];
[coord coordinateWritingItemAtURL:m_meta options:0 error:nil
byAccessor:^(NSURL* newUrl)
{
FILE* fp = fopen(newUrl.path.UTF8String, "wb");
if (fp)
{
fwrite(&*m_metaData, 1, sizeof(*m_metaData), fp);
fclose(fp);
}
}];
}
void AudioGroupDataCollection::disable(AudioGroupFilePresenter* presenter)
{
m_metaData->active = false;
NSFileCoordinator* coord = [[NSFileCoordinator alloc] initWithFilePresenter:presenter];
[coord coordinateWritingItemAtURL:m_meta options:0 error:nil
byAccessor:^(NSURL* newUrl)
{
FILE* fp = fopen(newUrl.path.UTF8String, "wb");
if (fp)
{
fwrite(&*m_metaData, 1, sizeof(*m_metaData), fp);
fclose(fp);
}
}];
}
void AudioGroupDataCollection::moveURL(NSURL* oldUrl, NSURL* newUrl)
{
if (m_proj)
@ -319,9 +368,9 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
{
for (auto& pair : m_audioGroupCollections)
{
for (auto& pair2 : pair.second.m_groups)
for (auto& pair2 : pair.second->m_groups)
{
pair2.second.moveURL(oldUrl, newUrl);
pair2.second->moveURL(oldUrl, newUrl);
}
}
}
@ -330,27 +379,25 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
{
lastOutlineView = outlineView;
if (!item)
return m_audioGroupCollections.size();
return m_filterAudioGroupCollections.size();
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
return collection.m_groups.size();
return collection.m_filterGroups.size();
}
- (id)outlineView:(NSOutlineView*)outlineView child:(NSInteger)index ofItem:(nullable id)item
{
if (!item)
{
auto search = m_iteratorTracker->seekToIndex(index);
if (search == m_audioGroupCollections.end())
if (index >= m_filterAudioGroupCollections.size())
return nil;
return search->second.m_token;
return m_filterAudioGroupCollections[index]->second->m_token;
}
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
auto search = collection.m_iteratorTracker->seekToIndex(index);
if (search == collection.m_groups.end())
if (index >= collection.m_filterGroups.size())
return nil;
return search->second.m_token;
return collection.m_filterGroups[index]->second->m_token;
}
- (BOOL)outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item
@ -366,7 +413,18 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
{
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
return [NSNumber numberWithBool:true];
{
size_t totalOn = 0;
for (auto& pair : collection.m_groups)
if (pair.second->m_metaData->active)
++totalOn;
if (totalOn == 0)
return [NSNumber numberWithInt:NSOffState];
else if (totalOn == collection.m_groups.size())
return [NSNumber numberWithInt:NSOnState];
else
return [NSNumber numberWithInt:NSMixedState];
}
else if ([tableColumn.identifier isEqualToString:@"DetailsColumn"])
return [NSString stringWithFormat:@"%" PRISize " groups", collection.m_groups.size()];
}
@ -374,7 +432,7 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
{
AudioGroupDataCollection& data = *((AudioGroupDataToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
return [NSNumber numberWithBool:data.m_metaData->active];
return [NSNumber numberWithInt:data.m_metaData->active ? NSOnState : NSOffState];
else if ([tableColumn.identifier isEqualToString:@"DetailsColumn"])
{
if (!data.m_loadedProj)
@ -387,6 +445,43 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
return nil;
}
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(nullable id)object forTableColumn:(nullable NSTableColumn *)tableColumn byItem:(nullable id)item
{
bool dirty = false;
if ([item isKindOfClass:[AudioGroupCollectionToken class]])
{
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
{
NSInteger active = [object integerValue];
if (active)
for (auto& pair : collection.m_groups)
pair.second->enable(self);
else
for (auto& pair : collection.m_groups)
pair.second->disable(self);
dirty = true;
}
}
else if ([item isKindOfClass:[AudioGroupDataToken class]])
{
AudioGroupDataCollection& data = *((AudioGroupDataToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
{
NSInteger active = [object integerValue];
if (active)
data.enable(self);
else
data.disable(self);
dirty = true;
}
}
if (dirty)
[outlineView reloadItem:nil reloadChildren:YES];
}
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(nonnull id)cell forTableColumn:(nullable NSTableColumn *)tableColumn item:(nonnull id)item
{
if ([item isKindOfClass:[AudioGroupCollectionToken class]])
@ -403,6 +498,13 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
}
}
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
{
DataOutlineView* ov = notification.object;
id item = [ov itemAtRow:ov.selectedRow];
[(AppDelegate*)NSApp.delegate outlineView:ov selectionChanged:item];
}
- (BOOL)addCollectionName:(std::string&&)name items:(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&&)collection
{
NSFileCoordinator* coord = [[NSFileCoordinator alloc] initWithFilePresenter:self];
@ -410,49 +512,49 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
return false;
NSURL* dir = [m_groupURL URLByAppendingPathComponent:@(name.c_str())];
__block AudioGroupCollection& insert = m_audioGroupCollections.emplace(name, dir).first->second;
__block AudioGroupCollection& insert = *m_audioGroupCollections.emplace(name, std::make_unique<AudioGroupCollection>(dir)).first->second;
insert.addCollection(std::move(collection));
[coord coordinateWritingItemAtURL:m_groupURL options:0 error:nil
byAccessor:^(NSURL* newUrl)
{
for (std::pair<const std::string, AudioGroupDataCollection>& pair : insert.m_groups)
for (std::pair<const std::string, std::unique_ptr<AudioGroupDataCollection>>& pair : insert.m_groups)
{
NSURL* collectionUrl = [insert.m_url URLByAppendingPathComponent:@(pair.first.c_str())];
[[NSFileManager defaultManager] createDirectoryAtURL:collectionUrl withIntermediateDirectories:YES attributes:nil error:nil];
FILE* fp = fopen(pair.second.m_proj.path.UTF8String, "wb");
FILE* fp = fopen(pair.second->m_proj.path.UTF8String, "wb");
if (fp)
{
fwrite(pair.second.m_projData.data(), 1, pair.second.m_projData.size(), fp);
fwrite(pair.second->m_projData.data(), 1, pair.second->m_projData.size(), fp);
fclose(fp);
}
fp = fopen(pair.second.m_pool.path.UTF8String, "wb");
fp = fopen(pair.second->m_pool.path.UTF8String, "wb");
if (fp)
{
fwrite(pair.second.m_poolData.data(), 1, pair.second.m_poolData.size(), fp);
fwrite(pair.second->m_poolData.data(), 1, pair.second->m_poolData.size(), fp);
fclose(fp);
}
fp = fopen(pair.second.m_sdir.path.UTF8String, "wb");
fp = fopen(pair.second->m_sdir.path.UTF8String, "wb");
if (fp)
{
fwrite(pair.second.m_sdirData.data(), 1, pair.second.m_sdirData.size(), fp);
fwrite(pair.second->m_sdirData.data(), 1, pair.second->m_sdirData.size(), fp);
fclose(fp);
}
fp = fopen(pair.second.m_samp.path.UTF8String, "wb");
fp = fopen(pair.second->m_samp.path.UTF8String, "wb");
if (fp)
{
fwrite(pair.second.m_sampData.data(), 1, pair.second.m_sampData.size(), fp);
fwrite(pair.second->m_sampData.data(), 1, pair.second->m_sampData.size(), fp);
fclose(fp);
}
fp = fopen(pair.second.m_meta.path.UTF8String, "wb");
fp = fopen(pair.second->m_meta.path.UTF8String, "wb");
if (fp)
{
fwrite(&*pair.second.m_metaData, 1, sizeof(*pair.second.m_metaData), fp);
fwrite(&*pair.second->m_metaData, 1, sizeof(*pair.second->m_metaData), fp);
fclose(fp);
}
}
@ -468,7 +570,7 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
return;
NSError* coordErr;
__block NSError* managerErr;
__block std::map<std::string, AudioGroupCollection>& theMap = m_audioGroupCollections;
__block std::map<std::string, std::unique_ptr<AudioGroupCollection>>& theMap = m_audioGroupCollections;
__block AudioGroupFilePresenter* presenter = self;
[coord coordinateReadingItemAtURL:m_groupURL options:NSFileCoordinatorReadingResolvesSymbolicLink error:&coordErr
byAccessor:^(NSURL* newUrl)
@ -493,8 +595,8 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
auto search = theMap.find(path.lastPathComponent.UTF8String);
if (search == theMap.end())
{
search = theMap.emplace(path.lastPathComponent.UTF8String, path).first;
search->second.update(presenter);
search = theMap.emplace(path.lastPathComponent.UTF8String, std::make_unique<AudioGroupCollection>(path)).first;
search->second->update(presenter);
}
}
}
@ -505,12 +607,29 @@ bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
- (void)resetIterators
{
m_iteratorTracker.emplace(m_audioGroupCollections.begin(), m_audioGroupCollections.end());
for (auto& pair : m_audioGroupCollections)
pair.second.m_iteratorTracker.emplace(pair.second.m_groups.begin(), pair.second.m_groups.end());
std::string search;
if (searchStr)
search = searchStr.UTF8String;
m_filterAudioGroupCollections.clear();
m_filterAudioGroupCollections.reserve(m_audioGroupCollections.size());
for (auto it = m_audioGroupCollections.begin() ; it != m_audioGroupCollections.end() ; ++it)
if (it->second->doSearch(search) || !searchStr || StrToLower(it->first).find(search) != std::string::npos)
m_filterAudioGroupCollections.push_back(it);
[lastOutlineView reloadItem:nil reloadChildren:YES];
}
- (void)setSearchFilter:(NSString*)str
{
searchStr = [str lowercaseString];
[self resetIterators];
}
- (void)removeSelectedItem
{
}
- (id)init
{
m_groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.io.github.axiodl.Amuse.AudioGroups"];

View File

@ -48,7 +48,7 @@ if (APPLE AND (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VE
${CMAKE_CURRENT_SOURCE_DIR}/AmuseContainerMainMenu.xib
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/AmuseContainerMainMenu.xib
)
add_executable(amuse-au-container MACOSX_BUNDLE AmuseContainingApp.mm
add_executable(amuse-au-container MACOSX_BUNDLE AmuseContainingApp.hpp AmuseContainingApp.mm
AudioUnitBackend.hpp AudioUnitBackend.mm
AudioUnitViewController.hpp AudioUnitViewController.mm
AudioGroupFilePresenter.hpp AudioGroupFilePresenter.mm