[vlc-commits] macosx: Rework log message storage and fix filtering

Marvin Scholz git at videolan.org
Thu Sep 7 03:02:21 CEST 2017


vlc | branch: master | Marvin Scholz <epirat07 at gmail.com> | Thu Sep  7 03:00:15 2017 +0200| [660257430f41f106ecb1834af7ccaf2a37a281de] | committer: Marvin Scholz

macosx: Rework log message storage and fix filtering

This is a quite large change to how the log message window data storage
works. It completely removes the message buffer that was used.
Instead, the messages are added to the backing array of the array
controller directly. The array controller will not pick up these changes,
so adding a lot of messages at once is not a concern.
The timer is now used to sync the array controller with its backing
array by calling NSArrayControllers `rearrangeObjects`.

The array controller is changed to not clear the predicate on adding
new items, which was the initial reason why the other changes became
necessary, as the array controller would not allow adding objects
that did not match the filter predicate. Adding them to the backing
array and syncing with the array controller by calling rearrangeObjects
seems to be no problem though.

This means filtering is now possible while new messages arrive and
while the filter is set, it will only show new messages matching
the filter, until the filter is unset, at which point it will show
all messages again, as expected.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=660257430f41f106ecb1834af7ccaf2a37a281de
---

 modules/gui/macosx/UI/LogMessageWindow.xib  |  2 +-
 modules/gui/macosx/VLCLogWindowController.m | 86 ++++++++++++++---------------
 2 files changed, 41 insertions(+), 47 deletions(-)

diff --git a/modules/gui/macosx/UI/LogMessageWindow.xib b/modules/gui/macosx/UI/LogMessageWindow.xib
index 79d1c01763..e8f3b4422c 100644
--- a/modules/gui/macosx/UI/LogMessageWindow.xib
+++ b/modules/gui/macosx/UI/LogMessageWindow.xib
@@ -442,7 +442,7 @@ IA
             </toolbar>
             <point key="canvasLocation" x="139" y="192"/>
         </window>
-        <arrayController editable="NO" selectsInsertedObjects="NO" id="0Or-bh-QJU">
+        <arrayController editable="NO" selectsInsertedObjects="NO" clearsFilterPredicateOnInsertion="NO" id="0Or-bh-QJU">
             <declaredKeys>
                 <string>component</string>
                 <string>message</string>
diff --git a/modules/gui/macosx/VLCLogWindowController.m b/modules/gui/macosx/VLCLogWindowController.m
index 22d5c54162..a09839031d 100644
--- a/modules/gui/macosx/VLCLogWindowController.m
+++ b/modules/gui/macosx/VLCLogWindowController.m
@@ -32,16 +32,19 @@
 /* This array stores messages that are managed by the arrayController */
 @property (retain) NSMutableArray *messagesArray;
 
-/* This array stores messages before they are added to the messagesArray on refresh */
- at property (retain) NSMutableArray *messageBuffer;
-
 /* We do not want to refresh the table for every message, as that would be very frequent when
- * there are a lot of messages, therefore we use a timer to refresh the table with new data
- * from the messageBuffer every now and then, which is much more efficient and still fast
- * enough for a good user experience
+ * there are a lot of messages, therefore we use a timer to refresh the table every now and
+ * then, which is much more efficient and still fast enough for a good user experience.
  */
 @property (retain) NSTimer        *refreshTimer;
 
+/*
+ * Indicates if an update is needed, which is the case when new messages were added
+ * after the last firing of the update timer. It is used to prevent unnecessary
+ * rearranging of the NSArrayController content.
+ */
+ at property (atomic) BOOL           needsUpdate;
+
 - (void)addMessage:(NSDictionary *)message;
 
 @end
@@ -87,8 +90,7 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
 {
     self = [super initWithWindowNibName:@"LogMessageWindow"];
     if (self) {
-        _messagesArray = [[NSMutableArray alloc] initWithCapacity:500];
-        _messageBuffer = [[NSMutableArray alloc] initWithCapacity:100];
+        _messagesArray = [[NSMutableArray alloc] initWithCapacity:1000];
     }
     return self;
 }
@@ -140,7 +142,7 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
     vlc_LogSet(getIntf()->obj.libvlc, MsgCallback, (__bridge void*)self);
     _refreshTimer = [NSTimer scheduledTimerWithTimeInterval:0.3
                                                      target:self
-                                                   selector:@selector(appendMessageBuffer)
+                                                   selector:@selector(updateArrayController:)
                                                    userInfo:nil
                                                     repeats:YES];
     return [super showWindow:sender];
@@ -152,14 +154,24 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
     vlc_LogSet( getIntf()->obj.libvlc, NULL, NULL );
 
     // Remove all messages
-    [self clearMessageBuffer];
-    [self clearMessageTable];
+    [self removeAllMessages];
 
     // Invalidate timer
     [_refreshTimer invalidate];
     _refreshTimer = nil;
 }
 
+/**
+ Called by the timer to re-sync the array controller with the backing array
+ */
+- (void)updateArrayController:(NSTimer *)timer
+{
+    if (_needsUpdate)
+        [_arrayController rearrangeObjects];
+
+    _needsUpdate = NO;
+}
+
 #pragma mark -
 #pragma mark Delegate methods
 
@@ -236,8 +248,7 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
     vlc_LogSet(getIntf()->obj.libvlc, NULL, NULL);
 
     // Remove all messages
-    [self clearMessageBuffer];
-    [self clearMessageTable];
+    [self removeAllMessages];
 
     // Reregister handler, to write new header to log
     vlc_LogSet(getIntf()->obj.libvlc, MsgCallback, (__bridge void*)self);
@@ -247,7 +258,7 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
  */
 - (IBAction)refreshLog:(id)sender
 {
-    [self appendMessageBuffer];
+    [_arrayController rearrangeObjects];
     [_messageTable scrollToEndOfDocument:self];
 }
 
@@ -264,7 +275,7 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
 
 /* Called when the user hits CMD + C or copy is clicked in the edit menu
  */
-- (void) copy:(id)sender {
+- (void)copy:(id)sender {
     NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
     [pasteBoard clearContents];
     for (NSDictionary *line in [_arrayController selectedObjects]) {
@@ -301,47 +312,30 @@ static void MsgCallback(void *data, int type, const vlc_log_t *item, const char
 #pragma mark Data handling
 
 /** 
- Adds a message to the messageBuffer, it does not has to be called from the main thread, as
- items are only added to the messageArray on refresh.
+ Adds a message, it is only added visibly to the table on the next firing
+ of the update timer.
  */
 - (void)addMessage:(NSDictionary *)messageDict
 {
-    @synchronized (_messageBuffer) {
-        [_messageBuffer addObject:messageDict];
-    }
-}
+    @synchronized (_messagesArray) {
+        if ([_messagesArray count] > 1000000) {
+            [_messagesArray removeObjectsInRange:NSMakeRange(0, 2)];
+        }
+        [_messagesArray addObject:messageDict];
 
-/**
- Clears the message buffer
- */
-- (void)clearMessageBuffer
-{
-    @synchronized (_messageBuffer) {
-        [_messageBuffer removeAllObjects];
+        _needsUpdate = YES;
     }
+    
 }
 
 /**
- Clears all messages in the message table by removing all items from the arrayController
+ Clears all messages in the message table by removing all items from the array and
+ calling `rearrangeObjects` on the array controller.
  */
-- (void)clearMessageTable
+- (void)removeAllMessages
 {
-    NSRange range = NSMakeRange(0, [[_arrayController arrangedObjects] count]);
-    [_arrayController removeObjectsAtArrangedObjectIndexes:[NSIndexSet indexSetWithIndexesInRange:range]];
-}
-
-/**
- Appends all messages from the buffer to the arrayController and clears the buffer
- */
-- (void)appendMessageBuffer
-{
-    if ([_messagesArray count] > 1000000) {
-        [_messagesArray removeObjectsInRange:NSMakeRange(0, 2)];
-    }
-    @synchronized (_messageBuffer) {
-        [_arrayController addObjects:_messageBuffer];
-        [_messageBuffer removeAllObjects];
-    }
+    [_messagesArray removeAllObjects];
+    [_arrayController rearrangeObjects];
 }
 
 @end



More information about the vlc-commits mailing list