Work on AudioUnit data UI

This commit is contained in:
Jack Andersen 2016-06-03 16:34:35 -10:00
parent 81bd897ec1
commit 9ae92313e3
9 changed files with 715 additions and 264 deletions

View File

@ -17,6 +17,7 @@
<connections>
<outlet property="creditsView" destination="AWS-Zd-8ha" id="O75-15-wzr"/>
<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="samplesTable" destination="Frt-wZ-1ZI" id="riC-O4-JXo"/>
<outlet property="sfxTable" destination="4nw-rf-Dh4" id="ebY-ro-tqk"/>
@ -69,7 +70,7 @@
<items>
<menuItem title="Import…" keyEquivalent="i" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
<action selector="importFile:" target="Y3H-Qy-a7C" id="j6G-7T-YiQ"/>
</connections>
</menuItem>
</items>
@ -149,7 +150,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="283" y="305" width="544" height="367"/>
<rect key="screenRect" x="0.0" y="0.0" width="1366" height="745"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="9Rk-3e-xVS">
<rect key="frame" x="0.0" y="0.0" width="544" height="367"/>
<autoresizingMask key="autoresizingMask"/>
@ -166,121 +167,75 @@
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Alc-jx-Z3v">
<rect key="frame" x="0.0" y="-1" width="30" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="QjK-Fn-bKW"/>
<constraint firstAttribute="width" constant="30" id="kSj-a9-U8v"/>
</constraints>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" image="NSAddTemplate" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="1BM-r8-8er">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="importFile:" target="Y3H-Qy-a7C" id="bBJ-EO-41Y"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="eh8-gl-WoS">
<rect key="frame" x="29" y="-1" width="31" height="31"/>
<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">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mpK-AK-Otf">
<rect key="frame" x="59" y="-1" width="485" height="32"/>
<rect key="frame" x="58" y="-1" width="486" height="32"/>
<buttonCell key="cell" type="smallSquare" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" lineBreakMode="truncatingTail" refusesFirstResponder="YES" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="JwG-gw-HOj">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XHK-NM-ZAP">
<scrollView autohidesScrollers="YES" horizontalLineScroll="22" horizontalPageScroll="10" verticalLineScroll="22" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XHK-NM-ZAP">
<rect key="frame" x="0.0" y="28" width="544" height="339"/>
<clipView key="contentView" id="cFf-wa-ZPx">
<clipView key="contentView" drawsBackground="NO" id="cFf-wa-ZPx">
<rect key="frame" x="1" y="0.0" width="542" height="338"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" headerView="jN4-UQ-VfT" viewBased="YES" indentationPerLevel="16" outlineTableColumn="DlG-iE-h1a" id="Vlv-Jw-A4U" customClass="DataOutlineView">
<outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" alternatingRowBackgroundColors="YES" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="22" headerView="jN4-UQ-VfT" indentationPerLevel="14" outlineTableColumn="DlG-iE-h1a" id="Vlv-Jw-A4U" customClass="DataOutlineView">
<rect key="frame" x="0.0" y="0.0" width="542" height="315"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="intercellSpacing" width="3" height="0.0"/>
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="116" minWidth="40" maxWidth="1000" id="DlG-iE-h1a">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<tableColumn identifier="CollectionColumn" width="193" minWidth="100" maxWidth="1000" id="DlG-iE-h1a">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Collection">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="nfQ-a8-ezY">
<buttonCell key="dataCell" type="check" title="CollectionTitle" bezelStyle="regularSquare" imagePosition="left" alignment="left" lineBreakMode="truncatingTail" inset="2" id="Lpp-wh-qX7">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</buttonCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView id="1eD-qr-jb9">
<rect key="frame" x="1" y="1" width="116" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="cAp-67-fuc">
<rect key="frame" x="0.0" y="0.0" width="100" height="17"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="n5E-QL-7SS">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="cAp-67-fuc" firstAttribute="centerY" secondItem="1eD-qr-jb9" secondAttribute="centerY" id="5cE-qL-mGq"/>
<constraint firstItem="cAp-67-fuc" firstAttribute="leading" secondItem="1eD-qr-jb9" secondAttribute="leading" constant="2" id="WPE-2V-xp9"/>
<constraint firstAttribute="trailing" secondItem="cAp-67-fuc" secondAttribute="trailing" constant="18" id="tKa-Es-CKH"/>
</constraints>
<connections>
<outlet property="textField" destination="cAp-67-fuc" id="oYq-0I-143"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn width="420" minWidth="40" maxWidth="1000" id="alh-ut-BoX">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<tableColumn identifier="DetailsColumn" width="343" minWidth="40" maxWidth="1000" id="alh-ut-BoX">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" title="Details">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="ywm-jc-RPk">
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" allowsUndo="NO" title="Text Cell" id="ywm-jc-RPk">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="textColor" name="disabledControlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews>
<tableCellView misplaced="YES" id="REu-Qt-X84">
<rect key="frame" x="120" y="1" width="420" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="zPc-LM-WxA">
<rect key="frame" x="0.0" y="0.0" width="100" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="96" id="hKb-R5-AZg"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="wy9-p6-MVa">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="zPc-LM-WxA" firstAttribute="centerY" secondItem="REu-Qt-X84" secondAttribute="centerY" id="HWb-8H-JTZ"/>
<constraint firstAttribute="trailing" secondItem="zPc-LM-WxA" secondAttribute="trailing" constant="-58" id="pfE-FE-k76"/>
<constraint firstItem="zPc-LM-WxA" firstAttribute="leading" secondItem="REu-Qt-X84" secondAttribute="leading" constant="2" id="qPe-rp-KwI"/>
</constraints>
<connections>
<outlet property="textField" destination="zPc-LM-WxA" id="XMS-Lt-7aA"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
</tableColumns>
</outlineView>
</subviews>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<nil key="backgroundColor"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="ZGl-Ws-7HQ">
<rect key="frame" x="1" y="19" width="158" height="15"/>
@ -298,7 +253,7 @@
<searchField wantsLayer="YES" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Huk-pR-ayq">
<rect key="frame" x="65" y="4" width="474" height="22"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="bta-rr-Rjn"/>
<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">
<font key="font" metaFont="system"/>
@ -308,24 +263,23 @@
</searchField>
</subviews>
<constraints>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="top" secondItem="GKx-9K-n29" secondAttribute="top" id="11d-cK-KTn"/>
<constraint firstAttribute="trailing" secondItem="Huk-pR-ayq" secondAttribute="trailing" constant="5" id="1Bp-rN-FgN"/>
<constraint firstAttribute="bottom" secondItem="Huk-pR-ayq" secondAttribute="bottom" constant="4" id="3Px-xo-dAv"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="trailing" secondItem="mpK-AK-Otf" secondAttribute="trailing" id="5i2-xa-qrD"/>
<constraint firstItem="Alc-jx-Z3v" firstAttribute="baseline" secondItem="eh8-gl-WoS" secondAttribute="baseline" id="8uY-Ir-nmM"/>
<constraint firstAttribute="trailing" secondItem="XHK-NM-ZAP" secondAttribute="trailing" id="9gd-HE-7uf"/>
<constraint firstItem="Huk-pR-ayq" firstAttribute="leading" secondItem="eh8-gl-WoS" secondAttribute="trailing" constant="5" id="Aav-lf-aM8"/>
<constraint firstItem="eh8-gl-WoS" firstAttribute="baseline" secondItem="mpK-AK-Otf" secondAttribute="baseline" id="Inf-xH-Xiu"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="leading" secondItem="Alc-jx-Z3v" secondAttribute="leading" id="Qwp-2y-pUU"/>
<constraint firstItem="Huk-pR-ayq" firstAttribute="top" secondItem="XHK-NM-ZAP" secondAttribute="bottom" constant="2" id="S29-sA-pR1"/>
<constraint firstItem="mpK-AK-Otf" firstAttribute="centerY" secondItem="Huk-pR-ayq" secondAttribute="centerY" id="Y1b-wA-j5b"/>
<constraint firstItem="Alc-jx-Z3v" firstAttribute="centerY" secondItem="eh8-gl-WoS" secondAttribute="centerY" id="YXF-DS-Qzu"/>
<constraint firstItem="mpK-AK-Otf" firstAttribute="leading" secondItem="Alc-jx-Z3v" secondAttribute="trailing" constant="29" id="bF7-N0-Fff"/>
<constraint firstItem="eh8-gl-WoS" firstAttribute="leading" secondItem="GKx-9K-n29" secondAttribute="leading" constant="29" id="flM-s6-dSI"/>
<constraint firstAttribute="bottom" secondItem="Alc-jx-Z3v" secondAttribute="bottom" id="iKi-2E-TFe"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="leading" secondItem="GKx-9K-n29" secondAttribute="leading" id="lRg-3u-LsT"/>
<constraint firstItem="Alc-jx-Z3v" firstAttribute="firstBaseline" secondItem="mpK-AK-Otf" secondAttribute="firstBaseline" id="pp9-Zc-noQ"/>
<constraint firstItem="Huk-pR-ayq" firstAttribute="centerX" secondItem="mpK-AK-Otf" secondAttribute="centerX" id="xqj-LS-MnT"/>
<constraint firstItem="Alc-jx-Z3v" firstAttribute="centerY" secondItem="eh8-gl-WoS" secondAttribute="centerY" id="0mR-AS-Iw9"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="top" secondItem="GKx-9K-n29" secondAttribute="top" id="2Gv-Q0-8sj"/>
<constraint firstItem="eh8-gl-WoS" firstAttribute="leading" secondItem="GKx-9K-n29" secondAttribute="leading" constant="29" id="5Hp-Mp-Huw"/>
<constraint firstItem="mpK-AK-Otf" firstAttribute="centerY" secondItem="Huk-pR-ayq" secondAttribute="centerY" id="92l-eR-8e5"/>
<constraint firstItem="eh8-gl-WoS" firstAttribute="baseline" secondItem="mpK-AK-Otf" secondAttribute="baseline" id="EDq-BU-boS"/>
<constraint firstAttribute="trailing" secondItem="XHK-NM-ZAP" secondAttribute="trailing" id="H11-09-cl1"/>
<constraint firstItem="Huk-pR-ayq" firstAttribute="leading" secondItem="eh8-gl-WoS" secondAttribute="trailing" constant="5" id="KCn-oT-fwW"/>
<constraint firstItem="mpK-AK-Otf" firstAttribute="leading" secondItem="Alc-jx-Z3v" secondAttribute="trailing" constant="28" id="Qse-Ec-Pqp"/>
<constraint firstItem="Alc-jx-Z3v" firstAttribute="firstBaseline" secondItem="mpK-AK-Otf" secondAttribute="firstBaseline" id="Trd-67-sID"/>
<constraint firstAttribute="bottom" secondItem="Alc-jx-Z3v" secondAttribute="bottom" id="UD1-C6-vXP"/>
<constraint firstAttribute="trailing" secondItem="Huk-pR-ayq" secondAttribute="trailing" constant="5" id="jeG-bJ-zDw"/>
<constraint firstItem="Alc-jx-Z3v" firstAttribute="baseline" secondItem="eh8-gl-WoS" secondAttribute="baseline" id="jo2-gd-6U0"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="leading" secondItem="GKx-9K-n29" secondAttribute="leading" id="lHj-7d-9KY"/>
<constraint firstItem="Huk-pR-ayq" firstAttribute="top" secondItem="XHK-NM-ZAP" secondAttribute="bottom" constant="2" id="lbt-SK-129"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="trailing" secondItem="mpK-AK-Otf" secondAttribute="trailing" id="q3f-gS-tLA"/>
<constraint firstAttribute="bottom" secondItem="Huk-pR-ayq" secondAttribute="bottom" constant="4" id="rW0-CH-0JZ"/>
<constraint firstItem="XHK-NM-ZAP" firstAttribute="leading" secondItem="Alc-jx-Z3v" secondAttribute="leading" id="wUx-3P-eJu"/>
</constraints>
</view>
</tabViewItem>
@ -715,10 +669,10 @@
</tabView>
</subviews>
<constraints>
<constraint firstItem="Kht-FW-Kf6" firstAttribute="leading" secondItem="9Rk-3e-xVS" secondAttribute="leading" id="EaK-L0-wht"/>
<constraint firstAttribute="trailing" secondItem="Kht-FW-Kf6" secondAttribute="trailing" id="JMc-UC-ORE"/>
<constraint firstItem="Kht-FW-Kf6" firstAttribute="top" secondItem="9Rk-3e-xVS" secondAttribute="top" id="joC-pf-f1v"/>
<constraint firstAttribute="bottom" secondItem="Kht-FW-Kf6" secondAttribute="bottom" id="yTz-NI-FWd"/>
<constraint firstAttribute="trailing" secondItem="Kht-FW-Kf6" secondAttribute="trailing" id="QKQ-cu-CcX"/>
<constraint firstAttribute="bottom" secondItem="Kht-FW-Kf6" secondAttribute="bottom" id="aJq-Lv-Drp"/>
<constraint firstItem="Kht-FW-Kf6" firstAttribute="top" secondItem="9Rk-3e-xVS" secondAttribute="top" id="cHb-PJ-LRW"/>
<constraint firstItem="Kht-FW-Kf6" firstAttribute="leading" secondItem="9Rk-3e-xVS" secondAttribute="leading" id="qWs-qF-70Y"/>
</constraints>
</view>
<toolbar key="toolbar" implicitIdentifier="B4A5636B-DFED-420B-B2FF-540D729FD569" autosavesConfiguration="NO" allowsUserCustomization="NO" displayMode="iconAndLabel" sizeMode="regular" id="r4I-P0-82j">

View File

@ -3,6 +3,7 @@
#import <CoreAudioKit/AUViewController.h>
#import "AudioUnitViewController.hpp"
#import "AudioGroupFilePresenter.hpp"
#include <amuse/amuse.hpp>
@class DataOutlineController;
@class SamplesTableController;
@ -37,16 +38,17 @@
{
IBOutlet NSWindow* mainWindow;
IBOutlet NSOutlineView* dataOutline;
IBOutlet NSSearchField* dataSearchField;
IBOutlet NSTableView* sfxTable;
IBOutlet NSTableView* samplesTable;
IBOutlet NSTextView* creditsView;
AudioGroupFilePresenter* groupFilePresenter;
DataOutlineController* dataController;
SamplesTableController* samplesController;
SFXTableController* sfxController;
}
- (BOOL)importURL:(NSURL*)url;
@end
@interface MainTabView : NSTabView
@ -98,17 +100,6 @@
@end
@interface DataOutlineController : NSObject <NSOutlineViewDataSource, NSOutlineViewDelegate>
{
}
@end
@implementation DataOutlineController
@end
@interface SamplesTableController : NSObject <NSTableViewDataSource, NSTableViewDelegate>
{
@ -158,9 +149,8 @@
groupFilePresenter = [AudioGroupFilePresenter new];
dataController = [DataOutlineController new];
dataOutline.dataSource = dataController;
dataOutline.delegate = dataController;
dataOutline.dataSource = groupFilePresenter;
dataOutline.delegate = groupFilePresenter;
[dataOutline reloadItem:nil reloadChildren:YES];
samplesController = [SamplesTableController new];
@ -179,9 +169,34 @@
return YES;
}
- (IBAction)quitApp:(id)sender
- (BOOL)importURL:(NSURL*)url
{
[NSApp terminate:sender];
amuse::ContainerRegistry::Type containerType;
std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>> data =
amuse::ContainerRegistry::LoadContainer(url.path.UTF8String, containerType);
if (data.empty())
{
NSString* err = [NSString stringWithFormat:@"Unable to load Audio Groups from %s", url.path.UTF8String];
NSAlert* alert = [[NSAlert alloc] init];
alert.informativeText = err;
alert.messageText = @"Invalid Data File";
[alert runModal];
return false;
}
std::string name(amuse::ContainerRegistry::TypeToName(containerType));
return [groupFilePresenter addCollectionName:std::move(name) items:std::move(data)];
}
- (IBAction)importFile:(id)sender
{
__block NSOpenPanel* panel = [NSOpenPanel openPanel];
[panel beginSheetModalForWindow:mainWindow completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton)
{
[self importURL:panel.URL];
}
}];
}
@end

View File

@ -5,20 +5,44 @@
#import <AppKit/AppKit.h>
#include <map>
#include <string>
#include "optional.hpp"
#include <amuse/amuse.hpp>
#include <athena/FileReader.hpp>
@class AudioGroupFilePresenter;
@class AudioGroupDataToken;
@class AudioGroupCollectionToken;
struct AudioGroupDataCollection
{
std::string m_name;
NSURL* m_proj;
NSURL* m_pool;
NSURL* m_sdir;
NSURL* m_samp;
NSURL* m_meta;
AudioGroupDataToken* m_token;
std::unique_ptr<uint8_t[]> m_projData;
std::unique_ptr<uint8_t[]> m_poolData;
std::unique_ptr<uint8_t[]> m_sdirData;
std::unique_ptr<uint8_t[]> m_sampData;
std::vector<uint8_t> m_projData;
std::vector<uint8_t> m_poolData;
std::vector<uint8_t> m_sdirData;
std::vector<uint8_t> m_sampData;
struct MetaData
{
amuse::DataFormat fmt;
uint32_t absOffs;
uint32_t active;
MetaData(amuse::DataFormat fmtIn, uint32_t absOffsIn, uint32_t activeIn)
: fmt(fmtIn), absOffs(absOffsIn), active(activeIn) {}
MetaData(athena::io::FileReader& r)
: fmt(amuse::DataFormat(r.readUint32Big())), absOffs(r.readUint32Big()), active(r.readUint32Big()) {}
};
std::experimental::optional<MetaData> m_metaData;
std::experimental::optional<amuse::AudioGroupData> m_loadedData;
std::experimental::optional<amuse::AudioGroupProject> m_loadedProj;
void moveURL(NSURL* oldUrl, NSURL* newUrl);
@ -26,24 +50,82 @@ struct AudioGroupDataCollection
bool loadPool(AudioGroupFilePresenter* presenter);
bool loadSdir(AudioGroupFilePresenter* presenter);
bool loadSamp(AudioGroupFilePresenter* presenter);
bool loadMeta(AudioGroupFilePresenter* presenter);
AudioGroupDataCollection(NSURL* proj, NSURL* pool, NSURL* sdir, NSURL* samp)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp) {}
bool isDataComplete () const {return m_projData && m_poolData && m_sdirData && m_sampData;}
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);
};
@interface AudioGroupFilePresenter : NSObject <NSFilePresenter, NSOutlineViewDataSource>
template <class T>
class IteratorTracker
{
typename std::map<std::string, T>::const_iterator m_audioGroupOutlineBegin;
typename std::map<std::string, T>::const_iterator m_audioGroupOutlineEnd;
typename std::map<std::string, T>::const_iterator m_audioGroupOutlineIt;
size_t m_audioGroupOutlineIdx = 0;
public:
IteratorTracker(typename std::map<std::string, T>::const_iterator begin,
typename std::map<std::string, T>::const_iterator end)
: m_audioGroupOutlineBegin(begin), m_audioGroupOutlineEnd(end), m_audioGroupOutlineIt(begin) {}
typename std::map<std::string, T>::const_iterator seekToIndex(size_t idx)
{
if (idx == m_audioGroupOutlineIdx)
return m_audioGroupOutlineIt;
if (idx < m_audioGroupOutlineIdx)
{
for (; idx < m_audioGroupOutlineIdx && m_audioGroupOutlineIt != m_audioGroupOutlineBegin ;
--m_audioGroupOutlineIdx, --m_audioGroupOutlineIt) {}
return m_audioGroupOutlineIt;
}
for (; idx > m_audioGroupOutlineIdx && m_audioGroupOutlineIt != m_audioGroupOutlineEnd ;
++m_audioGroupOutlineIdx, ++m_audioGroupOutlineIt) {}
return m_audioGroupOutlineIt;
}
};
struct AudioGroupCollection
{
NSURL* m_url;
AudioGroupCollectionToken* m_token;
std::map<std::string, AudioGroupDataCollection> m_groups;
std::experimental::optional<IteratorTracker<AudioGroupDataCollection>> m_iteratorTracker;
AudioGroupCollection(NSURL* url);
void addCollection(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&& collection);
void update(AudioGroupFilePresenter* presenter);
};
@interface AudioGroupDataToken : NSObject
{
@public
AudioGroupDataCollection* m_collection;
}
- (id)initWithDataCollection:(AudioGroupDataCollection*)collection;
@end
@interface AudioGroupCollectionToken : NSObject
{
@public
AudioGroupCollection* m_collection;
}
- (id)initWithCollection:(AudioGroupCollection*)collection;
@end
@interface AudioGroupFilePresenter : NSObject <NSFilePresenter, NSOutlineViewDataSource, NSOutlineViewDelegate>
{
NSURL* m_groupURL;
NSOperationQueue* m_dataQueue;
std::map<std::string, AudioGroupDataCollection> m_audioGroupCollections;
std::map<std::string, AudioGroupCollection> m_audioGroupCollections;
NSOutlineView* lastOutlineView;
std::map<std::string, AudioGroupDataCollection>::const_iterator m_audioGroupOutlineIt;
size_t m_audioGroupOutlineIdx;
std::experimental::optional<IteratorTracker<AudioGroupCollection>> m_iteratorTracker;
}
- (BOOL)addCollectionName:(std::string&&)name items:(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&&)collection;
- (void)update;
- (void)resetIterators;
@end
#endif // __AMUSE_AUDIOUNIT_AUDIOGROUPFILEPRESENTER_HPP__

View File

@ -1,7 +1,30 @@
#include "AudioGroupFilePresenter.hpp"
#include <athena/FileReader.hpp>
#include <amuse/AudioGroupProject.hpp>
#import <AppKit/AppKit.h>
@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
- (NSURL*)presentedItemURL
@ -14,6 +37,138 @@
return m_dataQueue;
}
AudioGroupCollection::AudioGroupCollection(NSURL* url)
: m_url(url), m_token([[AudioGroupCollectionToken alloc] initWithCollection:this]) {}
void AudioGroupCollection::addCollection(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&& collection)
{
for (std::pair<std::string, amuse::IntrusiveAudioGroupData>& pair : collection)
{
NSURL* collectionUrl = [m_url URLByAppendingPathComponent:@(pair.first.c_str())];
amuse::IntrusiveAudioGroupData& dataIn = pair.second;
auto search = m_groups.find(pair.first);
if (search == m_groups.end())
{
search = m_groups.emplace(pair.first,
AudioGroupDataCollection{pair.first,
[collectionUrl URLByAppendingPathComponent:@"proj"],
[collectionUrl URLByAppendingPathComponent:@"pool"],
[collectionUrl URLByAppendingPathComponent:@"sdir"],
[collectionUrl URLByAppendingPathComponent:@"samp"],
[collectionUrl URLByAppendingPathComponent:@"meta"]}).first;
}
AudioGroupDataCollection& dataCollection = search->second;
dataCollection.m_projData.resize(dataIn.getProjSize());
memmove(dataCollection.m_projData.data(), dataIn.getProj(), dataIn.getProjSize());
dataCollection.m_poolData.resize(dataIn.getPoolSize());
memmove(dataCollection.m_poolData.data(), dataIn.getPool(), dataIn.getPoolSize());
dataCollection.m_sdirData.resize(dataIn.getSdirSize());
memmove(dataCollection.m_sdirData.data(), dataIn.getSdir(), dataIn.getSdirSize());
dataCollection.m_sampData.resize(dataIn.getSampSize());
memmove(dataCollection.m_sampData.data(), dataIn.getSamp(), dataIn.getSampSize());
dataCollection.m_metaData.emplace(dataIn.getDataFormat(), dataIn.getAbsoluteProjOffsets(), true);
}
}
void AudioGroupCollection::update(AudioGroupFilePresenter* presenter)
{
NSFileManager* fman = [NSFileManager defaultManager];
NSArray<NSURL*>* contents =
[fman contentsOfDirectoryAtURL:m_url
includingPropertiesForKeys:@[NSURLIsDirectoryKey]
options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
if (!contents)
return;
for (NSURL* path in contents)
{
NSNumber* isDir;
[path getResourceValue:&isDir forKey:NSURLIsDirectoryKey error:nil];
if (isDir.boolValue)
{
auto search = m_groups.find(path.lastPathComponent.UTF8String);
if (search == m_groups.end())
{
std::string nameStr = path.lastPathComponent.UTF8String;
search =
m_groups.emplace(nameStr,
AudioGroupDataCollection{nameStr,
[path URLByAppendingPathComponent:@"proj"],
[path URLByAppendingPathComponent:@"pool"],
[path URLByAppendingPathComponent:@"sdir"],
[path URLByAppendingPathComponent:@"samp"],
[path URLByAppendingPathComponent:@"meta"]}).first;
search->second._attemptLoad(presenter);
}
}
}
}
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),
m_token([[AudioGroupDataToken alloc] initWithDataCollection:this]) {}
bool AudioGroupDataCollection::_attemptLoad(AudioGroupFilePresenter* presenter)
{
if (!isDataComplete())
return false;
if (m_metaData && m_loadedProj)
return true;
if (!loadProj(presenter))
return false;
if (!loadPool(presenter))
return false;
if (!loadSdir(presenter))
return false;
if (!loadSamp(presenter))
return false;
if (!loadMeta(presenter))
return false;
switch (m_metaData->fmt)
{
case amuse::DataFormat::GCN:
default:
m_loadedData.emplace(m_projData.data(), m_projData.size(),
m_poolData.data(), m_poolData.size(),
m_sdirData.data(), m_sdirData.size(),
m_sampData.data(), m_sampData.size(),
amuse::GCNDataTag{});
break;
case amuse::DataFormat::N64:
m_loadedData.emplace(m_projData.data(), m_projData.size(),
m_poolData.data(), m_poolData.size(),
m_sdirData.data(), m_sdirData.size(),
m_sampData.data(), m_sampData.size(),
m_metaData->absOffs, amuse::N64DataTag{});
break;
case amuse::DataFormat::PC:
m_loadedData.emplace(m_projData.data(), m_projData.size(),
m_poolData.data(), m_poolData.size(),
m_sdirData.data(), m_sdirData.size(),
m_sampData.data(), m_sampData.size(),
m_metaData->absOffs, amuse::PCDataTag{});
break;
}
if (m_metaData && m_loadedProj)
{
m_loadedProj.emplace(amuse::AudioGroupProject::CreateAudioGroupProject(*m_loadedData));
return true;
}
return false;
}
void AudioGroupDataCollection::moveURL(NSURL* oldUrl, NSURL* newUrl)
{
if (m_proj)
@ -46,7 +201,7 @@ bool AudioGroupDataCollection::loadProj(AudioGroupFilePresenter* presenter)
if (!coord)
return false;
NSError* err;
__block std::unique_ptr<uint8_t[]>& ret = m_projData;
__block std::vector<uint8_t>& ret = m_projData;
[coord coordinateReadingItemAtURL:m_proj
options:NSFileCoordinatorReadingResolvesSymbolicLink error:&err
byAccessor:^(NSURL* newUrl)
@ -54,9 +209,11 @@ bool AudioGroupDataCollection::loadProj(AudioGroupFilePresenter* presenter)
athena::io::FileReader r([[newUrl path] UTF8String], 1024 * 32, false);
if (r.hasError())
return;
ret = r.readUBytes(r.length());
size_t len = r.length();
ret.resize(len);
r.readUBytesToBuf(ret.data(), len);
}];
return m_projData.operator bool();
return ret.size();
}
bool AudioGroupDataCollection::loadPool(AudioGroupFilePresenter* presenter)
@ -67,7 +224,7 @@ bool AudioGroupDataCollection::loadPool(AudioGroupFilePresenter* presenter)
if (!coord)
return false;
NSError* err;
__block std::unique_ptr<uint8_t[]>& ret = m_poolData;
__block std::vector<uint8_t>& ret = m_poolData;
[coord coordinateReadingItemAtURL:m_pool
options:NSFileCoordinatorReadingResolvesSymbolicLink error:&err
byAccessor:^(NSURL* newUrl)
@ -75,9 +232,11 @@ bool AudioGroupDataCollection::loadPool(AudioGroupFilePresenter* presenter)
athena::io::FileReader r([[newUrl path] UTF8String], 1024 * 32, false);
if (r.hasError())
return;
ret = r.readUBytes(r.length());
size_t len = r.length();
ret.resize(len);
r.readUBytesToBuf(ret.data(), len);
}];
return m_poolData.operator bool();
return ret.size();
}
bool AudioGroupDataCollection::loadSdir(AudioGroupFilePresenter* presenter)
@ -88,7 +247,7 @@ bool AudioGroupDataCollection::loadSdir(AudioGroupFilePresenter* presenter)
if (!coord)
return false;
NSError* err;
__block std::unique_ptr<uint8_t[]>& ret = m_sdirData;
__block std::vector<uint8_t>& ret = m_sdirData;
[coord coordinateReadingItemAtURL:m_sdir
options:NSFileCoordinatorReadingResolvesSymbolicLink error:&err
byAccessor:^(NSURL* newUrl)
@ -96,9 +255,11 @@ bool AudioGroupDataCollection::loadSdir(AudioGroupFilePresenter* presenter)
athena::io::FileReader r([[newUrl path] UTF8String], 1024 * 32, false);
if (r.hasError())
return;
ret = r.readUBytes(r.length());
size_t len = r.length();
ret.resize(len);
r.readUBytesToBuf(ret.data(), len);
}];
return m_sdirData.operator bool();
return ret.size();
}
bool AudioGroupDataCollection::loadSamp(AudioGroupFilePresenter* presenter)
@ -109,7 +270,7 @@ bool AudioGroupDataCollection::loadSamp(AudioGroupFilePresenter* presenter)
if (!coord)
return false;
NSError* err;
__block std::unique_ptr<uint8_t[]>& ret = m_sampData;
__block std::vector<uint8_t>& ret = m_sampData;
[coord coordinateReadingItemAtURL:m_samp
options:NSFileCoordinatorReadingResolvesSymbolicLink error:&err
byAccessor:^(NSURL* newUrl)
@ -117,63 +278,189 @@ bool AudioGroupDataCollection::loadSamp(AudioGroupFilePresenter* presenter)
athena::io::FileReader r([[newUrl path] UTF8String], 1024 * 32, false);
if (r.hasError())
return;
ret = r.readUBytes(r.length());
size_t len = r.length();
ret.resize(len);
r.readUBytesToBuf(ret.data(), len);
}];
return m_sampData.operator bool();
return ret.size();
}
bool AudioGroupDataCollection::loadMeta(AudioGroupFilePresenter* presenter)
{
if (!m_meta)
return false;
NSFileCoordinator* coord = [[NSFileCoordinator alloc] initWithFilePresenter:presenter];
if (!coord)
return false;
NSError* err;
__block std::experimental::optional<MetaData>& ret = m_metaData;
[coord coordinateReadingItemAtURL:m_meta
options:NSFileCoordinatorReadingResolvesSymbolicLink error:&err
byAccessor:^(NSURL* newUrl)
{
athena::io::FileReader r([[newUrl path] UTF8String], 1024 * 32, false);
if (r.hasError())
return;
ret.emplace(r);
}];
return ret.operator bool();
}
- (void)presentedSubitemDidAppearAtURL:(NSURL*)url
{
NSURL* dir = nil;
if ([url.lastPathComponent isEqualToString:@"proj"] ||
[url.lastPathComponent isEqualToString:@"pool"] ||
[url.lastPathComponent isEqualToString:@"sdir"] ||
[url.lastPathComponent isEqualToString:@"samp"])
dir = url.baseURL;
auto search = m_audioGroupCollections.find(dir.lastPathComponent.UTF8String);
if (search == m_audioGroupCollections.end())
{
search =
m_audioGroupCollections.emplace(dir.lastPathComponent.UTF8String,
AudioGroupDataCollection{
[dir URLByAppendingPathComponent:@"proj"],
[dir URLByAppendingPathComponent:@"pool"],
[dir URLByAppendingPathComponent:@"sdir"],
[dir URLByAppendingPathComponent:@"samp"]}).first;
}
[self update];
}
- (void)presentedSubitemAtURL:(NSURL*)oldUrl didMoveToURL:(NSURL*)newUrl
{
for (auto it = m_audioGroupCollections.begin() ; it != m_audioGroupCollections.end() ; ++it)
for (auto& pair : m_audioGroupCollections)
{
std::pair<const std::string, AudioGroupDataCollection>& pair = *it;
pair.second.moveURL(oldUrl, newUrl);
for (auto& pair2 : pair.second.m_groups)
{
pair2.second.moveURL(oldUrl, newUrl);
}
}
}
- (NSInteger)outlineView:(NSOutlineView*)outlineView numberOfChildrenOfItem:(nullable id)item
{
lastOutlineView = outlineView;
if (!item)
return m_audioGroupCollections.size();
return 0;
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
return collection.m_groups.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())
return nil;
return search->second.m_token;
}
return nil;
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
auto search = collection.m_iteratorTracker->seekToIndex(index);
if (search == collection.m_groups.end())
return nil;
return search->second.m_token;
}
- (BOOL)outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item
{
if ([item isKindOfClass:[AudioGroupCollectionToken class]])
return YES;
return NO;
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
if ([item isKindOfClass:[AudioGroupCollectionToken class]])
{
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
return [NSNumber numberWithBool:true];
else if ([tableColumn.identifier isEqualToString:@"DetailsColumn"])
return [NSString stringWithFormat:@"%" PRISize " groups", collection.m_groups.size()];
}
else if ([item isKindOfClass:[AudioGroupDataToken class]])
{
AudioGroupDataCollection& data = *((AudioGroupDataToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
return [NSNumber numberWithBool:data.m_metaData->active];
else if ([tableColumn.identifier isEqualToString:@"DetailsColumn"])
{
if (!data.m_loadedProj)
return @"";
return [NSString stringWithFormat:@"%zu SongGroups, %zu SFXGroups",
data.m_loadedProj->songGroups().size(), data.m_loadedProj->sfxGroups().size()];
}
}
return nil;
}
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(nonnull id)cell forTableColumn:(nullable NSTableColumn *)tableColumn item:(nonnull id)item
{
if ([item isKindOfClass:[AudioGroupCollectionToken class]])
{
AudioGroupCollection& collection = *((AudioGroupCollectionToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
((NSButtonCell*)cell).title = collection.m_url.lastPathComponent;
}
else if ([item isKindOfClass:[AudioGroupDataToken class]])
{
AudioGroupDataCollection& data = *((AudioGroupDataToken*)item)->m_collection;
if ([tableColumn.identifier isEqualToString:@"CollectionColumn"])
((NSButtonCell*)cell).title = @(data.m_name.c_str());
}
}
- (BOOL)addCollectionName:(std::string&&)name items:(std::vector<std::pair<std::string, amuse::IntrusiveAudioGroupData>>&&)collection
{
NSFileCoordinator* coord = [[NSFileCoordinator alloc] initWithFilePresenter:self];
if (!coord)
return false;
NSURL* dir = [m_groupURL URLByAppendingPathComponent:@(name.c_str())];
__block AudioGroupCollection& insert = m_audioGroupCollections.emplace(name, 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)
{
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");
if (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");
if (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");
if (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");
if (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");
if (fp)
{
fwrite(&*pair.second.m_metaData, 1, sizeof(*pair.second.m_metaData), fp);
fclose(fp);
}
}
}];
return true;
}
- (void)update
{
NSFileCoordinator* coord = [[NSFileCoordinator alloc] initWithFilePresenter:self];
@ -181,41 +468,47 @@ bool AudioGroupDataCollection::loadSamp(AudioGroupFilePresenter* presenter)
return;
NSError* coordErr;
__block NSError* managerErr;
__block std::map<std::string, AudioGroupDataCollection>& theMap = m_audioGroupCollections;
__block std::map<std::string, AudioGroupCollection>& theMap = m_audioGroupCollections;
__block AudioGroupFilePresenter* presenter = self;
[coord coordinateReadingItemAtURL:m_groupURL options:NSFileCoordinatorReadingResolvesSymbolicLink error:&coordErr
byAccessor:^(NSURL* newUrl)
{
NSFileManager* fman = [NSFileManager defaultManager];
NSArray<NSURL*>* contents =
[fman contentsOfDirectoryAtURL:newUrl
includingPropertiesForKeys:@[NSURLIsDirectoryKey]
options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
NSDirectoryEnumerationSkipsHiddenFiles
error:&managerErr];
if (!contents)
return;
{
NSFileManager* fman = [NSFileManager defaultManager];
NSArray<NSURL*>* contents =
[fman contentsOfDirectoryAtURL:newUrl
includingPropertiesForKeys:@[NSURLIsDirectoryKey]
options:NSDirectoryEnumerationSkipsSubdirectoryDescendants |
NSDirectoryEnumerationSkipsHiddenFiles
error:&managerErr];
if (!contents)
return;
for (NSURL* path in contents)
{
NSNumber* isDir;
[path getResourceValue:&isDir forKey:NSURLIsDirectoryKey error:nil];
if (isDir.boolValue)
{
auto search = theMap.find(path.lastPathComponent.UTF8String);
if (search == theMap.end())
{
search =
theMap.emplace(path.lastPathComponent.UTF8String,
AudioGroupDataCollection{
[path URLByAppendingPathComponent:@"proj"],
[path URLByAppendingPathComponent:@"pool"],
[path URLByAppendingPathComponent:@"sdir"],
[path URLByAppendingPathComponent:@"samp"]}).first;
}
}
}
}];
for (NSURL* path in contents)
{
NSNumber* isDir;
[path getResourceValue:&isDir forKey:NSURLIsDirectoryKey error:nil];
if (isDir.boolValue)
{
auto search = theMap.find(path.lastPathComponent.UTF8String);
if (search == theMap.end())
{
search = theMap.emplace(path.lastPathComponent.UTF8String, path).first;
search->second.update(presenter);
}
}
}
}];
[self resetIterators];
}
- (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());
[lastOutlineView reloadItem:nil reloadChildren:YES];
}
- (id)init

View File

@ -57,7 +57,7 @@ if (APPLE AND (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VE
AmuseContainingApp.mm AudioGroupFilePresenter.mm
PROPERTIES COMPILE_FLAGS -fobjc-arc)
target_link_libraries(amuse-au-container amuse boo soxr ${AUDIOUNIT_LIBRARY} ${COREAUDIOKIT_LIBRARY}
${AVFOUNDATION_LIBRARY} ${BOO_SYS_LIBS} logvisor athena-core)
${AVFOUNDATION_LIBRARY} ${ZLIB_LIBRARIES} ${BOO_SYS_LIBS} logvisor athena-core)
set(APPLE_BUNDLE_ID "io.github.axiodl.Amuse")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/AmuseContainer.entitlements.in

View File

@ -12,35 +12,70 @@ class AudioGroupData
friend class Engine;
protected:
unsigned char* m_proj;
size_t m_projSz;
unsigned char* m_pool;
size_t m_poolSz;
unsigned char* m_sdir;
size_t m_sdirSz;
unsigned char* m_samp;
size_t m_sampSz;
DataFormat m_fmt;
bool m_absOffs;
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp,
AudioGroupData(unsigned char* proj, size_t projSz,
unsigned char* pool, size_t poolSz,
unsigned char* sdir, size_t sdirSz,
unsigned char* samp, size_t sampSz,
DataFormat fmt, bool absOffs)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp),
: m_proj(proj), m_projSz(projSz),
m_pool(pool), m_poolSz(poolSz),
m_sdir(sdir), m_sdirSz(sdirSz),
m_samp(samp), m_sampSz(sampSz),
m_fmt(fmt), m_absOffs(absOffs) {}
public:
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp, GCNDataTag)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp),
AudioGroupData(unsigned char* proj, size_t projSz,
unsigned char* pool, size_t poolSz,
unsigned char* sdir, size_t sdirSz,
unsigned char* samp, size_t sampSz, GCNDataTag)
: m_proj(proj), m_projSz(projSz),
m_pool(pool), m_poolSz(poolSz),
m_sdir(sdir), m_sdirSz(sdirSz),
m_samp(samp), m_sampSz(sampSz),
m_fmt(DataFormat::GCN), m_absOffs(true) {}
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp, bool absOffs, N64DataTag)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp),
AudioGroupData(unsigned char* proj, size_t projSz,
unsigned char* pool, size_t poolSz,
unsigned char* sdir, size_t sdirSz,
unsigned char* samp, size_t sampSz, bool absOffs, N64DataTag)
: m_proj(proj), m_projSz(projSz),
m_pool(pool), m_poolSz(poolSz),
m_sdir(sdir), m_sdirSz(sdirSz),
m_samp(samp), m_sampSz(sampSz),
m_fmt(DataFormat::N64), m_absOffs(absOffs) {}
AudioGroupData(unsigned char* proj, unsigned char* pool,
unsigned char* sdir, unsigned char* samp, bool absOffs, PCDataTag)
: m_proj(proj), m_pool(pool), m_sdir(sdir), m_samp(samp),
AudioGroupData(unsigned char* proj, size_t projSz,
unsigned char* pool, size_t poolSz,
unsigned char* sdir, size_t sdirSz,
unsigned char* samp, size_t sampSz, bool absOffs, PCDataTag)
: m_proj(proj), m_projSz(projSz),
m_pool(pool), m_poolSz(poolSz),
m_sdir(sdir), m_sdirSz(sdirSz),
m_samp(samp), m_sampSz(sampSz),
m_fmt(DataFormat::PC), m_absOffs(absOffs) {}
const unsigned char* getProj() const {return m_proj;}
const unsigned char* getPool() const {return m_pool;}
const unsigned char* getSdir() const {return m_sdir;}
const unsigned char* getSamp() const {return m_samp;}
unsigned char* getProj() {return m_proj;}
unsigned char* getPool() {return m_pool;}
unsigned char* getSdir() {return m_sdir;}
unsigned char* getSamp() {return m_samp;}
size_t getProjSize() const {return m_projSz;}
size_t getPoolSize() const {return m_poolSz;}
size_t getSdirSize() const {return m_sdirSz;}
size_t getSampSize() const {return m_sampSz;}
operator bool() const
{
@ -64,6 +99,8 @@ public:
IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other);
IntrusiveAudioGroupData& operator=(IntrusiveAudioGroupData&& other);
void dangleOwnership() {m_owns = false;}
};
}

View File

@ -37,6 +37,7 @@ public:
static const char* TypeToName(Type tp);
static Type DetectContainerType(const char* path);
static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadContainer(const char* path);
static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadContainer(const char* path, Type& typeOut);
static std::vector<std::pair<std::string, SongData>> LoadSongs(const char* path);
};

View File

@ -15,7 +15,9 @@ IntrusiveAudioGroupData::~IntrusiveAudioGroupData()
}
IntrusiveAudioGroupData::IntrusiveAudioGroupData(IntrusiveAudioGroupData&& other)
: AudioGroupData(other.m_proj, other.m_pool, other.m_sdir, other.m_samp, other.m_fmt, other.m_absOffs)
: AudioGroupData(other.m_proj, other.m_projSz, other.m_pool, other.m_poolSz,
other.m_sdir, other.m_sdirSz, other.m_samp, other.m_sampSz,
other.m_fmt, other.m_absOffs)
{
m_owns = other.m_owns;
other.m_owns = false;

View File

@ -119,7 +119,8 @@ static bool IsSongExtension(const char* path, const char*& dotOut)
static bool ValidateMP1(FILE* fp)
{
FileLength(fp);
if (FileLength(fp) > 40 * 1024 * 1024)
return false;
uint32_t magic;
fread(&magic, 1, 4, fp);
@ -228,29 +229,34 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadMP1(FILE
ReadString(fp);
std::string name = ReadString(fp);
uint32_t len;
fread(&len, 1, 4, fp);
len = SBig(len);
std::unique_ptr<uint8_t[]> pool(new uint8_t[len]);
fread(pool.get(), 1, len, fp);
uint32_t poolLen;
fread(&poolLen, 1, 4, fp);
poolLen = SBig(poolLen);
std::unique_ptr<uint8_t[]> pool(new uint8_t[poolLen]);
fread(pool.get(), 1, poolLen, fp);
fread(&len, 1, 4, fp);
len = SBig(len);
std::unique_ptr<uint8_t[]> proj(new uint8_t[len]);
fread(proj.get(), 1, len, fp);
uint32_t projLen;
fread(&projLen, 1, 4, fp);
projLen = SBig(projLen);
std::unique_ptr<uint8_t[]> proj(new uint8_t[projLen]);
fread(proj.get(), 1, projLen, fp);
fread(&len, 1, 4, fp);
len = SBig(len);
std::unique_ptr<uint8_t[]> samp(new uint8_t[len]);
fread(samp.get(), 1, len, fp);
uint32_t sampLen;
fread(&sampLen, 1, 4, fp);
sampLen = SBig(sampLen);
std::unique_ptr<uint8_t[]> samp(new uint8_t[sampLen]);
fread(samp.get(), 1, sampLen, fp);
fread(&len, 1, 4, fp);
len = SBig(len);
std::unique_ptr<uint8_t[]> sdir(new uint8_t[len]);
fread(sdir.get(), 1, len, fp);
uint32_t sdirLen;
fread(&sdirLen, 1, 4, fp);
sdirLen = SBig(sdirLen);
std::unique_ptr<uint8_t[]> sdir(new uint8_t[sdirLen]);
fread(sdir.get(), 1, sdirLen, fp);
ret.emplace_back(std::move(name), IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(), GCNDataTag{}});
ret.emplace_back(std::move(name), IntrusiveAudioGroupData{proj.release(), projLen,
pool.release(), poolLen,
sdir.release(), sdirLen,
samp.release(), sampLen, GCNDataTag{}});
}
}
FSeek(fp, origPos, SEEK_SET);
@ -263,7 +269,8 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadMP1(FILE
static bool ValidateMP1Songs(FILE* fp)
{
FileLength(fp);
if (FileLength(fp) > 40 * 1024 * 1024)
return false;
uint32_t magic;
fread(&magic, 1, 4, fp);
@ -404,7 +411,8 @@ static std::vector<std::pair<std::string, ContainerRegistry::SongData>> LoadMP1S
static bool ValidateMP2(FILE* fp)
{
FileLength(fp);
if (FileLength(fp) > 40 * 1024 * 1024)
return false;
uint32_t magic;
fread(&magic, 1, 4, fp);
@ -541,8 +549,10 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadMP2(FILE
std::unique_ptr<uint8_t[]> samp(new uint8_t[sampSz]);
fread(samp.get(), 1, sampSz, fp);
ret.emplace_back(std::move(name), IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(), GCNDataTag{}});
ret.emplace_back(std::move(name), IntrusiveAudioGroupData{proj.release(), projSz,
pool.release(), poolSz,
sdir.release(), sdirSz,
samp.release(), sampSz, GCNDataTag{}});
}
}
FSeek(fp, origPos, SEEK_SET);
@ -589,6 +599,8 @@ static void SwapN64Rom32(void* data, size_t size)
static bool ValidateRS1PC(FILE* fp)
{
size_t endPos = FileLength(fp);
if (endPos > 100 * 1024 * 1024)
return false;
uint32_t fstOff;
uint32_t fstSz;
@ -640,41 +652,49 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1PC(FI
fread(entries.get(), fstSz, 1, fp);
std::unique_ptr<uint8_t[]> proj;
size_t projSz = 0;
std::unique_ptr<uint8_t[]> pool;
size_t poolSz = 0;
std::unique_ptr<uint8_t[]> sdir;
size_t sdirSz = 0;
std::unique_ptr<uint8_t[]> samp;
size_t sampSz = 0;
for (uint32_t i=0 ; i<elemCount ; ++i)
{
RS1FSTEntry& entry = entries[i];
if (!strncmp("proj_SND", entry.name, 16))
{
projSz = entry.decompSz;
proj.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(proj.get(), 1, entry.decompSz, fp);
}
else if (!strncmp("pool_SND", entry.name, 16))
{
poolSz = entry.decompSz;
pool.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(pool.get(), 1, entry.decompSz, fp);
}
else if (!strncmp("sdir_SND", entry.name, 16))
{
sdirSz = entry.decompSz;
sdir.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(sdir.get(), 1, entry.decompSz, fp);
}
else if (!strncmp("samp_SND", entry.name, 16))
{
sampSz = entry.decompSz;
samp.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(samp.get(), 1, entry.decompSz, fp);
}
}
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz,
sdir.release(), sdirSz, samp.release(), sampSz,
false, PCDataTag{}});
}
}
@ -764,9 +784,13 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1N64(F
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
std::unique_ptr<uint8_t[]> proj;
size_t projSz = 0;
std::unique_ptr<uint8_t[]> pool;
size_t poolSz = 0;
std::unique_ptr<uint8_t[]> sdir;
size_t sdirSz = 0;
std::unique_ptr<uint8_t[]> samp;
size_t sampSz = 0;
for (; entry != lastEnt ; ++entry)
{
@ -786,6 +810,7 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1N64(F
uLongf outSz = ent.decompSz;
uncompress(proj.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
projSz = ent.decompSz;
}
else if (!strncmp("pool_SND", ent.name, 16))
{
@ -800,6 +825,7 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1N64(F
uLongf outSz = ent.decompSz;
uncompress(pool.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
poolSz = ent.decompSz;
}
else if (!strncmp("sdir_SND", ent.name, 16))
{
@ -814,6 +840,7 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1N64(F
uLongf outSz = ent.decompSz;
uncompress(sdir.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
sdirSz = ent.decompSz;
}
else if (!strncmp("samp_SND", ent.name, 16))
{
@ -828,11 +855,12 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1N64(F
uLongf outSz = ent.decompSz;
uncompress(samp.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
sampSz = ent.decompSz;
}
}
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz,
sdir.release(), sdirSz, samp.release(), sampSz,
false, N64DataTag{}});
}
@ -842,7 +870,9 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS1N64(F
static bool ValidateBFNPC(FILE* fp)
{
size_t endPos = FileLength(fp);
if (endPos > 100 * 1024 * 1024)
return false;
uint32_t fstOff;
uint32_t fstSz;
if (fread(&fstOff, 1, 4, fp) == 4 && fread(&fstSz, 1, 4, fp) == 4)
@ -893,9 +923,13 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNPC(FI
fread(entries.get(), fstSz, 1, fp);
std::unique_ptr<uint8_t[]> proj;
size_t projSz = 0;
std::unique_ptr<uint8_t[]> pool;
size_t poolSz = 0;
std::unique_ptr<uint8_t[]> sdir;
size_t sdirSz = 0;
std::unique_ptr<uint8_t[]> samp;
size_t sampSz = 0;
for (uint32_t i=0 ; i<elemCount ; ++i)
{
@ -905,29 +939,33 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNPC(FI
proj.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(proj.get(), 1, entry.decompSz, fp);
projSz = entry.decompSz;
}
else if (!strncmp("pool", entry.name, 16))
{
pool.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(pool.get(), 1, entry.decompSz, fp);
poolSz = entry.decompSz;
}
else if (!strncmp("sdir", entry.name, 16))
{
sdir.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(sdir.get(), 1, entry.decompSz, fp);
sdirSz = entry.decompSz;
}
else if (!strncmp("samp", entry.name, 16))
{
samp.reset(new uint8_t[entry.decompSz]);
FSeek(fp, entry.offset, SEEK_SET);
fread(samp.get(), 1, entry.decompSz, fp);
sampSz = entry.decompSz;
}
}
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz,
sdir.release(), sdirSz, samp.release(), sampSz,
true, PCDataTag{}});
}
}
@ -1017,9 +1055,13 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNN64(F
const RS1FSTEntry* lastEnt = reinterpret_cast<const RS1FSTEntry*>(dataSeg + fstEnd);
std::unique_ptr<uint8_t[]> proj;
size_t projSz = 0;
std::unique_ptr<uint8_t[]> pool;
size_t poolSz = 0;
std::unique_ptr<uint8_t[]> sdir;
size_t sdirSz = 0;
std::unique_ptr<uint8_t[]> samp;
size_t sampSz = 0;
for (; entry != lastEnt ; ++entry)
{
@ -1039,6 +1081,7 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNN64(F
uLongf outSz = ent.decompSz;
uncompress(proj.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
projSz = ent.decompSz;
}
else if (!strncmp("pool", ent.name, 16))
{
@ -1053,6 +1096,7 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNN64(F
uLongf outSz = ent.decompSz;
uncompress(pool.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
poolSz = ent.decompSz;
}
else if (!strncmp("sdir", ent.name, 16))
{
@ -1067,6 +1111,7 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNN64(F
uLongf outSz = ent.decompSz;
uncompress(sdir.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
sdirSz = ent.decompSz;
}
else if (!strncmp("samp", ent.name, 16))
{
@ -1081,11 +1126,12 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadBFNN64(F
uLongf outSz = ent.decompSz;
uncompress(samp.get(), &outSz, dataSeg + ent.offset, ent.compSz);
}
sampSz = ent.decompSz;
}
}
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projSz, pool.release(), poolSz,
sdir.release(), sdirSz, samp.release(), sampSz,
true, N64DataTag{}});
}
@ -1164,7 +1210,9 @@ struct RS23SONHead
static bool ValidateRS2(FILE* fp)
{
size_t endPos = FileLength(fp);
if (endPos > 600 * 1024 * 1024)
return false;
uint64_t fstOff;
fread(&fstOff, 1, 8, fp);
fstOff = SBig(fstOff);
@ -1241,8 +1289,8 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS2(FILE
char name[128];
snprintf(name, 128, "GroupFile%u", j);
ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(), GCNDataTag{}});
ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(), head.poolLen,
sdir.release(), head.sdirLen, samp.release(), head.sampLen, GCNDataTag{}});
}
break;
@ -1334,7 +1382,9 @@ struct RS3FSTEntry
static bool ValidateRS3(FILE* fp)
{
size_t endPos = FileLength(fp);
if (endPos > 600 * 1024 * 1024)
return false;
uint64_t fstOff;
fread(&fstOff, 1, 8, fp);
fstOff = SBig(fstOff);
@ -1409,8 +1459,8 @@ static std::vector<std::pair<std::string, IntrusiveAudioGroupData>> LoadRS3(FILE
char name[128];
snprintf(name, 128, "GroupFile%u", j);
ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(), GCNDataTag{}});
ret.emplace_back(name, IntrusiveAudioGroupData{proj.release(), head.projLen, pool.release(), head.poolLen,
sdir.release(), head.sdirLen, samp.release(), head.sampLen, GCNDataTag{}});
}
break;
@ -1538,11 +1588,19 @@ ContainerRegistry::Type ContainerRegistry::DetectContainerType(const char* path)
return Type::Invalid;
}
std::vector<std::pair<std::string, IntrusiveAudioGroupData>>
ContainerRegistry::LoadContainer(const char* path)
{
Type typeOut;
return LoadContainer(path, typeOut);
};
std::vector<std::pair<std::string, IntrusiveAudioGroupData>>
ContainerRegistry::LoadContainer(const char* path, Type& typeOut)
{
FILE* fp;
typeOut = Type::Invalid;
/* See if provided file is one of four raw chunks */
const char* dot = nullptr;
@ -1603,49 +1661,50 @@ ContainerRegistry::LoadContainer(const char* path)
fclose(fp);
fp = fopen(projPath, "rb");
size_t fLen = FileLength(fp);
if (!fLen)
size_t projLen = FileLength(fp);
if (!projLen)
return ret;
std::unique_ptr<uint8_t[]> proj(new uint8_t[fLen]);
fread(proj.get(), 1, fLen, fp);
std::unique_ptr<uint8_t[]> proj(new uint8_t[projLen]);
fread(proj.get(), 1, projLen, fp);
fp = fopen(poolPath, "rb");
fLen = FileLength(fp);
if (!fLen)
size_t poolLen = FileLength(fp);
if (!poolLen)
return ret;
std::unique_ptr<uint8_t[]> pool(new uint8_t[fLen]);
fread(pool.get(), 1, fLen, fp);
std::unique_ptr<uint8_t[]> pool(new uint8_t[poolLen]);
fread(pool.get(), 1, poolLen, fp);
fp = fopen(sdirPath, "rb");
fLen = FileLength(fp);
if (!fLen)
size_t sdirLen = FileLength(fp);
if (!sdirLen)
return ret;
std::unique_ptr<uint8_t[]> sdir(new uint8_t[fLen]);
fread(sdir.get(), 1, fLen, fp);
std::unique_ptr<uint8_t[]> sdir(new uint8_t[sdirLen]);
fread(sdir.get(), 1, sdirLen, fp);
fp = fopen(sampPath, "rb");
fLen = FileLength(fp);
if (!fLen)
size_t sampLen = FileLength(fp);
if (!sampPath)
return ret;
std::unique_ptr<uint8_t[]> samp(new uint8_t[fLen]);
fread(samp.get(), 1, fLen, fp);
std::unique_ptr<uint8_t[]> samp(new uint8_t[sampLen]);
fread(samp.get(), 1, sampLen, fp);
fclose(fp);
/* SDIR-based format detection */
if (*reinterpret_cast<uint32_t*>(sdir.get() + 8) == 0x0)
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen,
sdir.release(), sdirLen, samp.release(), sampLen,
GCNDataTag{}});
else if (sdir[9] == 0x0)
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen,
sdir.release(), sdirLen, samp.release(), sampLen,
false, N64DataTag{}});
else
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), pool.release(),
sdir.release(), samp.release(),
ret.emplace_back("Group", IntrusiveAudioGroupData{proj.release(), projLen, pool.release(), poolLen,
sdir.release(), sdirLen, samp.release(), sampLen,
false, PCDataTag{}});
typeOut = Type::Raw4;
return ret;
}
@ -1657,6 +1716,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadMP1(fp);
fclose(fp);
typeOut = Type::MetroidPrime;
return ret;
}
@ -1664,6 +1724,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadMP2(fp);
fclose(fp);
typeOut = Type::MetroidPrime2;
return ret;
}
@ -1671,6 +1732,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadRS1PC(fp);
fclose(fp);
typeOut = Type::RogueSquadronPC;
return ret;
}
@ -1678,6 +1740,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadRS1N64(fp);
fclose(fp);
typeOut = Type::RogueSquadronN64;
return ret;
}
@ -1685,6 +1748,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadBFNPC(fp);
fclose(fp);
typeOut = Type::BattleForNabooPC;
return ret;
}
@ -1692,6 +1756,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadBFNN64(fp);
fclose(fp);
typeOut = Type::BattleForNabooN64;
return ret;
}
@ -1699,6 +1764,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadRS2(fp);
fclose(fp);
typeOut = Type::RogueSquadron2;
return ret;
}
@ -1706,6 +1772,7 @@ ContainerRegistry::LoadContainer(const char* path)
{
auto ret = LoadRS3(fp);
fclose(fp);
typeOut = Type::RogueSquadron3;
return ret;
}