Convert source item outline view to use a data source instead of bound NSTreeController (was causing weird memory leaks..????)

Actually bounce the NDIReceiver audio delegate call through the requested queue
Fixed drag and drop reorder bug with source lists that was preventing a source from being placed at the bottom
This commit is contained in:
Zakk 2018-01-23 01:02:31 -05:00
parent 46362e71ce
commit dfa4e76244
10 changed files with 161 additions and 57 deletions

View file

@ -471,7 +471,6 @@
-(void)registerPCMOutput:(CMItemCount)frameCount audioFormat:(const AudioStreamBasicDescription *)audioFormat -(void)registerPCMOutput:(CMItemCount)frameCount audioFormat:(const AudioStreamBasicDescription *)audioFormat
{ {
if (self.pcmPlayer) if (self.pcmPlayer)
{ {
//looks like we already have one? //looks like we already have one?

View file

@ -158,9 +158,11 @@
return; return;
} }
//dispatch_async(dispatch_get_main_queue(), ^{
_pcmPlayer = [self createPCMInput:self.captureName withFormat:audioFormat];
_pcmPlayer.name = self.captureName;
_pcmPlayer = [self createPCMInput:self.captureName withFormat:audioFormat]; // });
_pcmPlayer.name = self.captureName;
} }
@ -181,8 +183,6 @@
-(void)NDIAudioOutput:(CAMultiAudioPCM *)pcmData fromReceiver:(CSNDIReceiver *)fromReceiver -(void)NDIAudioOutput:(CAMultiAudioPCM *)pcmData fromReceiver:(CSNDIReceiver *)fromReceiver
{ {
if (!_pcmPlayer && self.isLive) if (!_pcmPlayer && self.isLive)
{ {
AudioStreamBasicDescription useFormat = pcmData.pcmFormat; AudioStreamBasicDescription useFormat = pcmData.pcmFormat;
@ -311,5 +311,16 @@
return [bundle imageForResource:@"ndi_logo"]; return [bundle imageForResource:@"ndi_logo"];
} }
-(void)willDelete
{
NSLog(@"WILL DELEGTE");
[self deregisterPCMOutput];
}
-(void)dealloc
{
NSLog(@"DEALLOC NDI");
}
@end @end

View file

@ -19,8 +19,8 @@
CSNDISource *_ndi_source; CSNDISource *_ndi_source;
CVPixelBufferPoolRef _cvpool; CVPixelBufferPoolRef _cvpool;
NSSize _currentSize; NSSize _currentSize;
dispatch_queue_t _video_output_queue; __weak dispatch_queue_t _video_output_queue;
dispatch_queue_t _audio_output_queue; __weak dispatch_queue_t _audio_output_queue;
bool _stop_audio; bool _stop_audio;
bool _stop_video; bool _stop_video;
bool _audio_running; bool _audio_running;

View file

@ -243,7 +243,9 @@
{ {
memcpy(dBuf, audio_frame.p_data, 4*audio_frame.no_samples*audio_frame.no_channels); memcpy(dBuf, audio_frame.p_data, 4*audio_frame.no_samples*audio_frame.no_channels);
} }
[_audioDelegate NDIAudioOutput:retPCM fromReceiver:self]; dispatch_async(_audio_output_queue, ^{
[_audioDelegate NDIAudioOutput:retPCM fromReceiver:self];
});
} }
dispatch->NDIlib_recv_free_audio(_receiver_instance, &audio_frame); dispatch->NDIlib_recv_free_audio(_receiver_instance, &audio_frame);

View file

@ -423,7 +423,6 @@
useEngine = layerSrc.sourceLayout.recorder.audioEngine; useEngine = layerSrc.sourceLayout.recorder.audioEngine;
} }
} }
if (!useEngine) if (!useEngine)
{ {
useEngine = [CaptureController sharedCaptureController].multiAudioEngine; useEngine = [CaptureController sharedCaptureController].multiAudioEngine;

View file

@ -3,7 +3,6 @@
// CocoaSplit // CocoaSplit
// //
// Created by Zakk on 7/4/14. // Created by Zakk on 7/4/14.
// Copyright (c) 2014 Zakk. All rights reserved.
// //
#import "CompressorBase.h" #import "CompressorBase.h"

View file

@ -2502,6 +2502,9 @@ static NSArray *_sourceTypes = nil;
self.name = _editedName; self.name = _editedName;
} }
-(void) setSelectedVideoType:(NSString *)selectedVideoType -(void) setSelectedVideoType:(NSString *)selectedVideoType
{ {
NSMutableDictionary *pluginMap = [[CSPluginLoader sharedPluginLoader] sourcePlugins]; NSMutableDictionary *pluginMap = [[CSPluginLoader sharedPluginLoader] sourcePlugins];

View file

@ -50,19 +50,73 @@
-(void)outlineViewDoubleClick:(NSOutlineView *)sender -(void)outlineViewDoubleClick:(NSOutlineView *)sender
{ {
NSTreeNode *node = [sender itemAtRow:sender.clickedRow]; NSObject<CSInputSourceProtocol>*src = [sender itemAtRow:sender.clickedRow];
if (node) if (src)
{ {
NSObject<CSInputSourceProtocol>*src = node.representedObject;
[self openInputConfigWindows:@[src]]; [self openInputConfigWindows:@[src]];
} }
} }
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
if (!item)
{
SourceLayout *layout = self.sourceLayoutController.content;
return [layout.topLevelSourceList objectAtIndex:index];
}
NSObject<CSInputSourceProtocol> *useItem = item;
if (useItem.isVideo)
{
InputSource *vItem = (InputSource *)useItem;
return [vItem.attachedInputs objectAtIndex:index];
}
return nil;
}
-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
if (!item)
{
return YES;
}
NSObject<CSInputSourceProtocol> *useItem = item;
if (!useItem.isVideo)
{
return NO;
}
InputSource *vSrc = item;
return vSrc.attachedInputs.count > 0;
}
-(NSInteger) outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
if (!item)
{
SourceLayout *layout = self.sourceLayoutController.content;
return layout.topLevelSourceList.count;
}
NSObject<CSInputSourceProtocol> *useItem = item;
if (useItem.isVideo)
{
InputSource *vItem = item;
return vItem.attachedInputs.count;
}
return 0;
}
-(void)outlineView:(NSOutlineView *)outlineView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row -(void)outlineView:(NSOutlineView *)outlineView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row
{ {
NSTreeNode *node = [outlineView itemAtRow:row]; NSObject<CSInputSourceProtocol> *src = [outlineView itemAtRow:row];
NSObject<CSInputSourceProtocol> *src = node.representedObject;
if (!src.isVideo || !((InputSource *)src).parentInput) if (!src.isVideo || !((InputSource *)src).parentInput)
{ {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@ -72,15 +126,23 @@
} }
-(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSTableCellView *ret = [outlineView makeViewWithIdentifier:@"defaultView" owner:self];
ret.objectValue = item;
return ret;
}
-(BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard -(BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard
{ {
NSPasteboardItem *pItem = [[NSPasteboardItem alloc] init]; NSPasteboardItem *pItem = [[NSPasteboardItem alloc] init];
NSMutableArray *sourceIDS = [NSMutableArray array]; NSMutableArray *sourceIDS = [NSMutableArray array];
for (NSTreeNode *node in items) for (NSObject<CSInputSourceProtocol>*iSrc in items)
{ {
NSObject<CSInputSourceProtocol> *iSrc = node.representedObject;
NSString *iUUID = iSrc.uuid; NSString *iUUID = iSrc.uuid;
[sourceIDS addObject:iUUID]; [sourceIDS addObject:iUUID];
@ -93,12 +155,7 @@
-(NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id<NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index -(NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id<NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
{ {
NSTreeNode *nodeItem = (NSTreeNode *)item; InputSource *nodeInput = item;
InputSource *nodeInput = nil;
if (nodeItem)
{
nodeInput = nodeItem.representedObject;
}
@ -306,8 +363,7 @@
NSArray *draggedUUIDS = [pb propertyListForType:@"cocoasplit.input.item"]; NSArray *draggedUUIDS = [pb propertyListForType:@"cocoasplit.input.item"];
NSTreeNode *parentNode = (NSTreeNode *)item; InputSource *parentSource = item;
InputSource *parentSource = nil;
NSMutableDictionary *currentDepths = [NSMutableDictionary dictionary]; NSMutableDictionary *currentDepths = [NSMutableDictionary dictionary];
@ -317,32 +373,26 @@
} }
NSIndexPath *droppedIdxPath = nil;
if (parentNode)
{
parentSource = parentNode.representedObject;
droppedIdxPath = [[parentNode indexPath] indexPathByAddingIndex:index];
} else {
droppedIdxPath = [NSIndexPath indexPathWithIndex:index];
}
NSTreeNode *idxNode = nil;
NSObject <CSInputSourceProtocol> *iSrc = nil;
float newDepth = 1; float newDepth = 1;
if (index == -1) if (index == -1)
{ {
newDepth = -FLT_MAX; newDepth = -FLT_MAX;
} else { } else {
idxNode = [self.sourceTreeController.arrangedObjects descendantNodeAtIndexPath:droppedIdxPath]; if (index < [outlineView numberOfChildrenOfItem:item])
{
iSrc = [outlineView child:index ofItem:item];
}
} }
if (idxNode) if (iSrc)
{ {
NSObject<CSInputSourceProtocol> *iSrc = idxNode.representedObject;
if (iSrc.isVideo) if (iSrc.isVideo)
{ {
InputSource *dSrc = (InputSource *)iSrc; InputSource *dSrc = (InputSource *)iSrc;
@ -382,6 +432,7 @@
[parentSource attachInput:iSrc]; [parentSource attachInput:iSrc];
[[undoManager prepareWithInvocationTarget:self] detachSourcesByUUID:@[iSrc.uuid]]; [[undoManager prepareWithInvocationTarget:self] detachSourcesByUUID:@[iSrc.uuid]];
} }
iSrc.depth = newDepth++; iSrc.depth = newDepth++;
} }
@ -533,10 +584,29 @@
_activeConfigWindows = [NSMutableDictionary dictionary]; _activeConfigWindows = [NSMutableDictionary dictionary];
_activeConfigControllers = [NSMutableDictionary dictionary]; _activeConfigControllers = [NSMutableDictionary dictionary];
}
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"content.topLevelSourceList"])
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.sourceOutlineView reloadData];
});
} }
} }
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
if (self.sourceLayoutController)
{
[self.sourceLayoutController addObserver:self forKeyPath:@"content.topLevelSourceList" options:NSKeyValueObservingOptionNew context:NULL];
}
// Do view setup here. // Do view setup here.
} }
@ -607,11 +677,26 @@
-(NSArray *)getSelectedItems
{
NSIndexSet *selectedRows = [self.sourceOutlineView selectedRowIndexes];
NSMutableArray *selectedItems = [NSMutableArray array];
[selectedRows enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
id item = [self.sourceOutlineView itemAtRow:idx];
if (item)
{
[selectedItems addObject:item];
}
}];
return selectedItems;
}
-(IBAction)sourceDeleteClicked:(NSButton *)sender -(IBAction)sourceDeleteClicked:(NSButton *)sender
{ {
NSArray *selectedSources = self.sourceTreeController.selectedObjects; NSArray *selectedSources = [self getSelectedItems];
NSUndoManager *undoManager = self.view.window.undoManager; NSUndoManager *undoManager = self.view.window.undoManager;
@ -640,6 +725,8 @@
[undoMap addObject:undoEntry]; [undoMap addObject:undoEntry];
} }
self.selectedObjects = @[];
NSData *undoData = [NSKeyedArchiver archivedDataWithRootObject:undoMap]; NSData *undoData = [NSKeyedArchiver archivedDataWithRootObject:undoMap];
[[undoManager prepareWithInvocationTarget:self] undoDeleteSources:undoData]; [[undoManager prepareWithInvocationTarget:self] undoDeleteSources:undoData];
} }
@ -647,7 +734,7 @@
-(IBAction)sourceConfigClicked:(NSButton *)sender -(IBAction)sourceConfigClicked:(NSButton *)sender
{ {
NSArray *selectedSources = self.sourceTreeController.selectedObjects; NSArray *selectedSources = [self getSelectedItems];
[self openInputConfigWindows:selectedSources]; [self openInputConfigWindows:selectedSources];
} }
@ -661,20 +748,23 @@
-(void)highlightSources:(NSArray *)sources -(void)highlightSources:(NSArray *)sources
{ {
[self.sourceTreeController setSelectionIndexPaths:@[]]; NSMutableIndexSet *selectedRows = [[NSMutableIndexSet alloc] init];
for (NSObject *src in sources) for (NSObject *src in sources)
{ {
NSIndexPath *srcPath = [self.sourceTreeController indexPathOfObject:src]; NSInteger idx = [self.sourceOutlineView rowForItem:src];
if (srcPath)
{ [selectedRows addIndex:idx];
[self.sourceTreeController addSelectionIndexPaths:@[srcPath]];
}
} }
[self.sourceOutlineView selectRowIndexes:selectedRows byExtendingSelection:NO];
} }
-(void)outlineViewSelectionDidChange:(NSNotification *)notification -(void)outlineViewSelectionDidChange:(NSNotification *)notification
{ {
self.selectedObjects = self.sourceTreeController.selectedObjects;
self.selectedObjects = [self getSelectedItems];
} }
-(void)menuEndedTracking:(NSNotification *)notification -(void)menuEndedTracking:(NSNotification *)notification
@ -941,5 +1031,12 @@
} }
} }
-(void)dealloc
{
if (self.sourceLayoutController)
{
[self.sourceLayoutController removeObserver:self forKeyPath:@"content.topLevelSourceList"];
}
}
@end @end

View file

@ -45,7 +45,7 @@
</textFieldCell> </textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews> <prototypeCellViews>
<tableCellView id="K7P-gj-44p"> <tableCellView identifier="defaultView" id="K7P-gj-44p">
<rect key="frame" x="1" y="1" width="415" height="17"/> <rect key="frame" x="1" y="1" width="415" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
@ -106,8 +106,6 @@
</tableColumns> </tableColumns>
<connections> <connections>
<action trigger="doubleAction" selector="outlineViewDoubleClick:" target="-2" id="SnR-fY-bsU"/> <action trigger="doubleAction" selector="outlineViewDoubleClick:" target="-2" id="SnR-fY-bsU"/>
<binding destination="d5r-1v-wmD" name="content" keyPath="arrangedObjects" id="REu-8i-kkD"/>
<binding destination="d5r-1v-wmD" name="selectionIndexPaths" keyPath="selectionIndexPaths" previousBinding="REu-8i-kkD" id="Ccb-Xm-9EN"/>
<outlet property="dataSource" destination="-2" id="J0b-9p-2zz"/> <outlet property="dataSource" destination="-2" id="J0b-9p-2zz"/>
<outlet property="delegate" destination="-2" id="sxE-KE-Fjx"/> <outlet property="delegate" destination="-2" id="sxE-KE-Fjx"/>
</connections> </connections>
@ -192,11 +190,7 @@ CA
</constraints> </constraints>
<point key="canvasLocation" x="-90" y="137.5"/> <point key="canvasLocation" x="-90" y="137.5"/>
</customView> </customView>
<treeController childrenKeyPath="attachedInputs" id="d5r-1v-wmD" userLabel="sourceTreeController"> <treeController childrenKeyPath="attachedInputs" id="d5r-1v-wmD" userLabel="sourceTreeController"/>
<connections>
<binding destination="-2" name="contentArray" keyPath="self.sourceLayoutController.selection.topLevelSourceList" id="jp4-cZ-FTe"/>
</connections>
</treeController>
</objects> </objects>
<resources> <resources>
<image name="NSActionTemplate" width="14" height="14"/> <image name="NSActionTemplate" width="14" height="14"/>

View file

@ -497,7 +497,7 @@ JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx);
NSMutableArray *tmpArray = [NSMutableArray array]; NSMutableArray *tmpArray = [NSMutableArray array];
NSMutableArray *noLayer = [NSMutableArray array]; NSMutableArray *noLayer = [NSMutableArray array];
float currentDepth = 0.0f; float currentDepth = 100.0f;
[self willChangeValueForKey:@"topLevelSourceList"]; [self willChangeValueForKey:@"topLevelSourceList"];