]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/bookmarks.m
macosx: do not allow playlist item deletion for sd modules
[vlc] / modules / gui / macosx / bookmarks.m
index 6f656293961d8714d8640a08b8da28662e5633dc..a322cdda2cc9a3066161b9cb55cb56f67d7555bd 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * bookmarks.m: MacOS X Bookmarks window
  *****************************************************************************
- * Copyright (C) 2005 the VideoLAN team
+ * Copyright (C) 2005 - 2012 VLC authors and VideoLAN
  * $Id$
  *
- * Authors: Felix K\9fhne <fkuehne@users.sf.net>
+ * Authors: Felix Paul Kühne <fkuehne at videolan dot org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 
 /*****************************************************************************
- * Note: 
- * the code used to bind with VLC's modules is heavily based upon 
- * ../wxwidgets/bookmarks.cpp, written by Gildas Bazin. 
- * (he is a member of the VideoLAN team) 
+ * Note:
+ * the code used to bind with VLC's modules is heavily based upon
+ * ../wxwidgets/bookmarks.cpp, written by Gildas Bazin.
+ * (he is a member of the VideoLAN team)
  *****************************************************************************/
 
 
  *****************************************************************************/
 
 #import "bookmarks.h"
-#import "intf.h"
 #import "wizard.h"
-#import <vlc/intf.h>
+#import "CompatibilityFixes.h"
 
-/*****************************************************************************
- * VLCExtended implementation
- *
- * implements the GUI functions for the window, the data source and the
- * delegate for o_tbl_dataTable
- *****************************************************************************/
+@interface VLCBookmarks (Internal)
+- (void)initStrings;
+@end
 
 @implementation VLCBookmarks
 
@@ -57,11 +53,10 @@ static VLCBookmarks *_o_sharedInstance = nil;
 
 - (id)init
 {
-    if (_o_sharedInstance) {
+    if (_o_sharedInstance)
         [self dealloc];
-    } else {
+    else
         _o_sharedInstance = [super init];
-    }
 
     return _o_sharedInstance;
 }
@@ -72,22 +67,31 @@ static VLCBookmarks *_o_sharedInstance = nil;
 
 - (void)awakeFromNib
 {
+    if (!OSX_SNOW_LEOPARD)
+        [o_bookmarks_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
+
     [self initStrings];
+
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(inputChangedEvent:)
+                                                 name:VLCInputChangedNotification
+                                               object:nil];
 }
 
 - (void)dealloc
 {
-    if(p_old_input)
-    {
-        free(p_old_input);
-    }
+    if (p_old_input)
+        vlc_object_release(p_old_input);
+
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+
     [super dealloc];
 }
 
 - (void)initStrings
 {
     /* localise the items */
-    
+
     /* main window */
     [o_bookmarks_window setTitle: _NS("Bookmarks")];
     [o_btn_add setTitle: _NS("Add")];
@@ -95,69 +99,72 @@ static VLCBookmarks *_o_sharedInstance = nil;
     [o_btn_edit setTitle: _NS("Edit")];
     [o_btn_extract setTitle: _NS("Extract")];
     [o_btn_rm setTitle: _NS("Remove")];
-    [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell] \
+    [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell]
         setStringValue: _NS("Description")];
-    [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell] \
-        setStringValue: _NS("Size offset")];
-    [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell] \
-        setStringValue: _NS("Time offset")];
-        
+    [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell]
+        setStringValue: _NS("Position")];
+    [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell]
+        setStringValue: _NS("Time")];
+
     /* edit window */
     [o_edit_btn_ok setTitle: _NS("OK")];
     [o_edit_btn_cancel setTitle: _NS("Cancel")];
     [o_edit_lbl_name setStringValue: _NS("Name")];
     [o_edit_lbl_time setStringValue: _NS("Time")];
-    [o_edit_lbl_bytes setStringValue: _NS("Bytes")];
+    [o_edit_lbl_bytes setStringValue: _NS("Position")];
+}
+
+- (void)updateCocoaWindowLevel:(NSInteger)i_level
+{
+    if (o_bookmarks_window && [o_bookmarks_window isVisible] && [o_bookmarks_window level] != i_level)
+        [o_bookmarks_window setLevel: i_level];
 }
 
 - (void)showBookmarks
 {
     /* show the window, called from intf.m */
     [o_bookmarks_window displayIfNeeded];
+    [o_bookmarks_window setLevel: [[[VLCMain sharedInstance] voutController] currentStatusWindowLevel]];
     [o_bookmarks_window makeKeyAndOrderFront:nil];
 }
 
+-(void)inputChangedEvent:(NSNotification *)o_notification
+{
+    [o_tbl_dataTable reloadData];
+}
+
 - (IBAction)add:(id)sender
 {
     /* add item to list */
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf, \
-        VLC_OBJECT_INPUT, FIND_ANYWHERE );
-    if( !p_input )
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
+
+    if (!p_input)
         return;
-    
+
     seekpoint_t bookmark;
-    vlc_value_t pos;
-    bookmark.psz_name = NULL;
-    bookmark.i_byte_offset = 0;
-    bookmark.i_time_offset = 0;
-    
-    var_Get(p_intf, "position", &pos);
-    bookmark.psz_name = _("Untitled");
-    input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
-    var_Get( p_input, "time", &pos );
-    bookmark.i_time_offset = pos.i_time;
-    input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
-    
-    vlc_object_release( p_input );
-    
+
+    if (!input_Control(p_input, INPUT_GET_BOOKMARK, &bookmark)) {
+        bookmark.psz_name = _("Untitled");
+        input_Control(p_input, INPUT_ADD_BOOKMARK, &bookmark);
+    }
+
+    vlc_object_release(p_input);
+
     [o_tbl_dataTable reloadData];
 }
 
 - (IBAction)clear:(id)sender
 {
     /* clear table */
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf, \
-        VLC_OBJECT_INPUT, FIND_ANYWHERE );
-    
-    if( !p_input )
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
+
+    if (!p_input)
         return;
 
-    input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
+    input_Control(p_input, INPUT_CLEAR_BOOKMARKS);
+
+    vlc_object_release(p_input);
 
-    vlc_object_release( p_input );
-    
     [o_tbl_dataTable reloadData];
 }
 
@@ -166,49 +173,45 @@ static VLCBookmarks *_o_sharedInstance = nil;
     /* put values to the sheet's fields and show sheet */
     /* we take the values from the core and not the table, because we cannot
      * really trust it */
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf, \
-        VLC_OBJECT_INPUT, FIND_ANYWHERE );
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
     seekpoint_t **pp_bookmarks;
     int i_bookmarks;
-    char * toBeReturned;
-    toBeReturned = "";
-    int i_toBeReturned;
-    i_toBeReturned = 0;
     int row;
     row = [o_tbl_dataTable selectedRow];
-    
-    if( !p_input )
-    {
+
+    if (!p_input)
         return;
-    } 
-    else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, \
-        &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
+
+    if (row < 0) {
+        vlc_object_release(p_input);
         return;
-    } 
-    else if(row < 0)
-    {
-        vlc_object_release( p_input );
+    }
+
+    if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
+        vlc_object_release(p_input);
         return;
-    } else {
-        [o_edit_fld_name setStringValue: [NSString stringWithUTF8String: \
-            pp_bookmarks[row]->psz_name]];
-        [o_edit_fld_time setStringValue: [[NSNumber numberWithInt: \
-            (pp_bookmarks[row]->i_time_offset / 1000000)] stringValue]];
-        [o_edit_fld_bytes setStringValue: [[NSNumber numberWithInt: \
-            pp_bookmarks[row]->i_byte_offset] stringValue]];
     }
-    
+
+    [o_edit_fld_name setStringValue: toNSStr(pp_bookmarks[row]->psz_name)];
+    int total = pp_bookmarks[row]->i_time_offset/ 1000000;
+    int hour = total / (60*60);
+    int min = (total - hour*60*60) / 60;
+    int sec = total - hour*60*60 - min*60;
+    [o_edit_fld_time setStringValue: [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min, sec]];
+    [o_edit_fld_bytes setStringValue: [NSString stringWithFormat:@"%lli", pp_bookmarks[row]->i_byte_offset]];
+
+    /* Just keep the pointer value to check if it
+     * changes. Note, we don't need to keep a reference to the object.
+     * so release it now. */
     p_old_input = p_input;
-    vlc_object_release( p_input );
+    vlc_object_release(p_input);
+
+    [NSApp beginSheet: o_edit_window modalForWindow: o_bookmarks_window modalDelegate: o_edit_window didEndSelector: nil contextInfo: nil];
 
-    [NSApp beginSheet: o_edit_window
-        modalForWindow: o_bookmarks_window
-        modalDelegate: o_edit_window
-        didEndSelector: nil
-        contextInfo: nil];
+    // Clear the bookmark list
+    for (int i = 0; i < i_bookmarks; i++)
+        vlc_seekpoint_Delete(pp_bookmarks[i]);
+    free(pp_bookmarks);
 }
 
 - (IBAction)edit_cancel:(id)sender
@@ -221,265 +224,200 @@ static VLCBookmarks *_o_sharedInstance = nil;
 - (IBAction)edit_ok:(id)sender
 {
     /* save field contents and close sheet */
-    
-    intf_thread_t * p_intf = VLCIntf;
-    seekpoint_t **pp_bookmarks;
+     seekpoint_t **pp_bookmarks;
     int i_bookmarks, i;
-    input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf, \
-        VLC_OBJECT_INPUT, FIND_ANYWHERE );
-    
-    if( !p_input )
-    {
-        NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"), \
-                @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("No " \
-                "input found. The stream must be playing or paused for " \
-                "bookmarks to work."));
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
+
+    if (!p_input) {
+        NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("No input found. A stream must be playing or paused for bookmarks to work."));
         return;
     }
-    if( p_old_input != p_input )
-    {
-        NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"), \
-                @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("Input " \
-                "has changed, unable to save bookmark. Use \"pause\" while " \
-                "editing bookmarks to keep the same input."));
-        vlc_object_release( p_input );
+    if (p_old_input != p_input) {
+        NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("Input has changed, unable to save bookmark. Suspending playback with \"Pause\" while editing bookmarks to ensure to keep the same input."));
+        vlc_object_release(p_input);
         return;
     }
-    
-    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, \
-        &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
+
+    if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
+        vlc_object_release(p_input);
         return;
-    } 
+    }
 
     i = [o_tbl_dataTable selectedRow];
-    
-    if( pp_bookmarks[i]->psz_name ) 
-    {
-        free( pp_bookmarks[i]->psz_name );
-    }
 
-    pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]); 
+    free(pp_bookmarks[i]->psz_name);
+
+    pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]);
     pp_bookmarks[i]->i_byte_offset = [[o_edit_fld_bytes stringValue] intValue];
-    pp_bookmarks[i]->i_time_offset = ([[o_edit_fld_time stringValue] intValue]  * 1000000);
-    
-    if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i ) \
-        != VLC_SUCCESS )
-    {
-        msg_Warn( p_intf, "VLCBookmarks: changing bookmark failed");
-        vlc_object_release( p_input );
-        return;
+
+    NSArray * components = [[o_edit_fld_time stringValue] componentsSeparatedByString:@":"];
+    NSUInteger componentCount = [components count];
+    if (componentCount == 1)
+        pp_bookmarks[i]->i_time_offset = 1000000 * ([[components objectAtIndex:0] intValue]);
+    else if (componentCount == 2)
+        pp_bookmarks[i]->i_time_offset = 1000000 * ([[components objectAtIndex:0] intValue] * 60 + [[components objectAtIndex:1] intValue]);
+    else if (componentCount == 3)
+        pp_bookmarks[i]->i_time_offset = 1000000 * ([[components objectAtIndex:0] intValue] * 3600 + [[components objectAtIndex:1] intValue] * 60 + [[components objectAtIndex:2] intValue]);
+    else {
+        msg_Err(VLCIntf, "Invalid string format for time");
+        goto clear;
+    }
+
+    if (input_Control(p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i) != VLC_SUCCESS) {
+        msg_Warn(VLCIntf, "Unable to change the bookmark");
+        goto clear;
     }
-    
+
     [o_tbl_dataTable reloadData];
-    vlc_object_release( p_input );
-     
-    
+    vlc_object_release(p_input);
+
     [NSApp endSheet: o_edit_window];
     [o_edit_window close];
+
+clear:
+    // Clear the bookmark list
+    for (int i = 0; i < i_bookmarks; i++)
+        vlc_seekpoint_Delete(pp_bookmarks[i]);
+    free(pp_bookmarks);
 }
 
 - (IBAction)extract:(id)sender
 {
-    /* extract */
-    
-    intf_thread_t * p_intf = VLCIntf;
-    
-    if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
-    {
-        NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"), \
-                @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("" \
-                "You must select two bookmarks"));
+    if ([o_tbl_dataTable numberOfSelectedRows] < 2) {
+        NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("Two bookmarks have to be selected."));
         return;
     }
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input )
-    {
-        NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"), \
-                @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("" \
-                "The stream must be playing or paused for bookmarks to work"));
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
+    if (!p_input) {
+        NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("The stream must be playing or paused for bookmarks to work."));
         return;
     }
-    
+
     seekpoint_t **pp_bookmarks;
     int i_bookmarks ;
     int i_first = -1;
     int i_second = -1;
-    int x = 0;
     int c = 0;
-    while (c != 2)
-    {
-        if([o_tbl_dataTable isRowSelected:x])
-        {
-            if (i_first == -1)
-            {
+    for (NSUInteger x = 0; c != 2; x++) {
+        if ([o_tbl_dataTable isRowSelected:x]) {
+            if (i_first == -1) {
                 i_first = x;
                 c = 1;
-            } 
-            else if (i_second == -1)
-            {
+            } else if (i_second == -1) {
                 i_second = x;
                 c = 2;
             }
         }
-        x = (x + 1);
     }
-    
-    msg_Dbg(p_intf, "got the bookmark-indexes");
-    
-    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, \
-        &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
-        msg_Err(p_intf, "bookmarks couldn't be retrieved from core");
+
+    if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
+        vlc_object_release(p_input);
+        msg_Err(VLCIntf, "already defined bookmarks couldn't be retrieved");
         return;
     }
-    msg_Dbg(p_intf, "calling wizard");
-
-    [[[VLCMain sharedInstance] getWizard] initWithExtractValuesFrom: \
-            [[NSNumber numberWithInt: \
-            (pp_bookmarks[i_first]->i_time_offset/1000000)] stringValue] \
-            to: [[NSNumber numberWithInt: \
-            (pp_bookmarks[i_second]->i_time_offset/1000000)] stringValue] \
-            ofItem: [NSString stringWithUTF8String: \
-            p_input->input.p_item->psz_uri]];
-    vlc_object_release( p_input );
-    msg_Dbg(p_intf, "released input");
+
+    char *psz_uri = input_item_GetURI(input_GetItem(p_input));
+    [[[VLCMain sharedInstance] wizard] initWithExtractValuesFrom: [NSString stringWithFormat:@"%lli", pp_bookmarks[i_first]->i_time_offset/1000000] to: [NSString stringWithFormat:@"%lli", pp_bookmarks[i_second]->i_time_offset/1000000] ofItem: toNSStr(psz_uri)];
+    free(psz_uri);
+    vlc_object_release(p_input);
+
+    // Clear the bookmark list
+    for (int i = 0; i < i_bookmarks; i++)
+        vlc_seekpoint_Delete(pp_bookmarks[i]);
+    free(pp_bookmarks);
 }
 
 - (IBAction)goToBookmark:(id)sender
 {
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t *p_input =
-    (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
-    
-    if( !p_input ) 
-    {
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
+
+    if (!p_input)
         return;
-    }
 
-    input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
+    input_Control(p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow]);
 
-    vlc_object_release( p_input );
+    vlc_object_release(p_input);
 }
 
 - (IBAction)remove:(id)sender
 {
-    /* remove selected item */
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t *p_input =
-    (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
-    
-    if( !p_input ) return;
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
+
+    if (!p_input)
+        return;
 
     int i_focused = [o_tbl_dataTable selectedRow];
-    if( i_focused >= 0 )
-    {
-        input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
-    }
 
-    vlc_object_release( p_input );
-    
-    [o_tbl_dataTable reloadData];
-}
+    if (i_focused >= 0)
+        input_Control(p_input, INPUT_DEL_BOOKMARK, i_focused);
 
-/*****************************************************************************
- * callback stuff
- *****************************************************************************/
+    vlc_object_release(p_input);
 
--(id)getDataTable
-{
-    return o_tbl_dataTable;
+    [o_tbl_dataTable reloadData];
 }
 
 /*****************************************************************************
  * data source methods
  *****************************************************************************/
 
-- (int)numberOfRowsInTableView:(NSTableView *)theDataTable
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)theDataTable
 {
     /* return the number of bookmarks */
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf, \
-        VLC_OBJECT_INPUT, FIND_ANYWHERE );
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
     seekpoint_t **pp_bookmarks;
     int i_bookmarks;
-    
-    if( !p_input )
-    {
+
+    if (!p_input)
         return 0;
-    }
-    else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, \
-                       &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
+
+    int returnValue = input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks);
+    vlc_object_release(p_input);
+
+    if (returnValue != VLC_SUCCESS)
         return 0;
-    }
-    else {
-        vlc_object_release( p_input );
-        return i_bookmarks;
-    }
+
+    for (int i = 0; i < i_bookmarks; i++)
+        vlc_seekpoint_Delete(pp_bookmarks[i]);
+    free(pp_bookmarks);
+
+    return i_bookmarks;
 }
 
-- (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn: \
-    (NSTableColumn *)theTableColumn row: (int)row
+- (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn: (NSTableColumn *)theTableColumn row: (NSInteger)row
 {
     /* return the corresponding data as NSString */
-    intf_thread_t * p_intf = VLCIntf;
-    input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf, \
-        VLC_OBJECT_INPUT, FIND_ANYWHERE );
+    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
     seekpoint_t **pp_bookmarks;
     int i_bookmarks;
-    char * toBeReturned;
-    toBeReturned = "";
-    int i_toBeReturned;
-    i_toBeReturned = 0;
-    
-    if( !p_input )
-    {
-        return @"";
-    } 
-    else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, \
-                       &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
+    id ret = @"";
+
+    if (!p_input)
         return @"";
-    }
-    else
-    {
-        if ([[theTableColumn identifier] isEqualToString: @"description"])
-        {
-            toBeReturned = pp_bookmarks[row]->psz_name;
-            vlc_object_release( p_input );
-            return [NSString stringWithUTF8String: toBeReturned];
-        } 
-        else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
-        {
-            i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
-            vlc_object_release( p_input );
-            return [[NSNumber numberWithInt: i_toBeReturned] stringValue];
-        }
-        else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
-        {
-            i_toBeReturned = pp_bookmarks[row]->i_time_offset;
-            vlc_object_release( p_input );
-            return [[NSNumber numberWithInt: (i_toBeReturned / 1000000)] \
-                stringValue];
-        }
-        else
-        {
-            /* may not happen, but just in case */
-            vlc_object_release( p_input );
-            msg_Err(p_intf, "VLCBookmarks: unknown table column identifier " \
-                "(%s) while updating table", [[theTableColumn identifier] \
-                UTF8String] );
-            return @"unknown identifier";
+    else if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS)
+        ret = @"";
+    else if (row >= i_bookmarks)
+        ret = @"";
+    else {
+        NSString * identifier = [theTableColumn identifier];
+        if ([identifier isEqualToString: @"description"])
+            ret = toNSStr(pp_bookmarks[row]->psz_name);
+        else if ([identifier isEqualToString: @"size_offset"])
+            ret = [NSString stringWithFormat:@"%lli", pp_bookmarks[row]->i_byte_offset];
+        else if ([identifier isEqualToString: @"time_offset"]) {
+            int total = pp_bookmarks[row]->i_time_offset/ 1000000;
+            int hour = total / (60*60);
+            int min = (total - hour*60*60) / 60;
+            int sec = total - hour*60*60 - min*60;
+            ret = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min, sec];
         }
-    }
 
+        // Clear the bookmark list
+        for (int i = 0; i < i_bookmarks; i++)
+            vlc_seekpoint_Delete(pp_bookmarks[i]);
+        free(pp_bookmarks);
+    }
+    vlc_object_release(p_input);
+    return ret;
 }
 
 /*****************************************************************************
@@ -489,22 +427,17 @@ static VLCBookmarks *_o_sharedInstance = nil;
 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
 {
     /* check whether a row is selected and en-/disable the edit/remove buttons */
-    if ([o_tbl_dataTable selectedRow] == -1)
-    {
+    if ([o_tbl_dataTable selectedRow] == -1) {
         /* no row is selected */
         [o_btn_edit setEnabled: NO];
         [o_btn_rm setEnabled: NO];
         [o_btn_extract setEnabled: NO];
-    }
-    else
-    {
+    } else {
         /* a row is selected */
         [o_btn_edit setEnabled: YES];
         [o_btn_rm setEnabled: YES];
         if ([o_tbl_dataTable numberOfSelectedRows] == 2)
-        {
             [o_btn_extract setEnabled: YES];
-        }
     }
 }