mirror of https://github.com/AxioDL/amuse.git
More UI bindings, metadata management
This commit is contained in:
parent
9ae92313e3
commit
62ece61cb2
|
@ -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>
|
||||
|
|
|
@ -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__
|
|
@ -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[])
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue