1 /*****************************************************************************
2 * bookmarks.m: MacOS X Bookmarks window
3 *****************************************************************************
4 * Copyright (C) 2005 - 2007 VLC authors and VideoLAN
7 * Authors: Felix Kühne <fkuehne at videolan dot org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
25 /*****************************************************************************
27 * the code used to bind with VLC's modules is heavily based upon
28 * ../wxwidgets/bookmarks.cpp, written by Gildas Bazin.
29 * (he is a member of the VideoLAN team)
30 *****************************************************************************/
33 /*****************************************************************************
35 *****************************************************************************/
39 #import <vlc_interface.h>
40 #import "CompatibilityFixes.h"
42 @implementation VLCBookmarks
44 static VLCBookmarks *_o_sharedInstance = nil;
46 + (VLCBookmarks *)sharedInstance
48 return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
53 if (_o_sharedInstance) {
56 _o_sharedInstance = [super init];
59 return _o_sharedInstance;
62 /*****************************************************************************
64 *****************************************************************************/
69 [o_bookmarks_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
81 /* localise the items */
84 [o_bookmarks_window setTitle: _NS("Bookmarks")];
85 [o_btn_add setTitle: _NS("Add")];
86 [o_btn_clear setTitle: _NS("Clear")];
87 [o_btn_edit setTitle: _NS("Edit")];
88 [o_btn_extract setTitle: _NS("Extract")];
89 [o_btn_rm setTitle: _NS("Remove")];
90 [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell]
91 setStringValue: _NS("Description")];
92 [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell]
93 setStringValue: _NS("Position")];
94 [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell]
95 setStringValue: _NS("Time")];
98 [o_edit_btn_ok setTitle: _NS("OK")];
99 [o_edit_btn_cancel setTitle: _NS("Cancel")];
100 [o_edit_lbl_name setStringValue: _NS("Name")];
101 [o_edit_lbl_time setStringValue: _NS("Time")];
102 [o_edit_lbl_bytes setStringValue: _NS("Position")];
105 - (void)showBookmarks
107 /* show the window, called from intf.m */
108 [o_bookmarks_window displayIfNeeded];
109 [o_bookmarks_window makeKeyAndOrderFront:nil];
112 - (IBAction)add:(id)sender
114 /* add item to list */
115 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
117 if( !p_input ) return;
119 seekpoint_t bookmark;
121 if( !input_Control( p_input, INPUT_GET_BOOKMARK, &bookmark ) )
123 bookmark.psz_name = _("Untitled");
124 input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
127 vlc_object_release( p_input );
129 [o_tbl_dataTable reloadData];
132 - (IBAction)clear:(id)sender
135 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
140 input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
142 vlc_object_release( p_input );
144 [o_tbl_dataTable reloadData];
147 - (IBAction)edit:(id)sender
149 /* put values to the sheet's fields and show sheet */
150 /* we take the values from the core and not the table, because we cannot
152 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
153 seekpoint_t **pp_bookmarks;
156 row = [o_tbl_dataTable selectedRow];
158 if( !p_input && row < 0 )
161 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
162 &i_bookmarks ) != VLC_SUCCESS )
164 vlc_object_release( p_input );
168 [o_edit_fld_name setStringValue: [NSString stringWithUTF8String:
169 pp_bookmarks[row]->psz_name]];
170 [o_edit_fld_time setStringValue: [[NSNumber numberWithInt:
171 (pp_bookmarks[row]->i_time_offset / 1000000)] stringValue]];
172 [o_edit_fld_bytes setStringValue: [[NSNumber numberWithInt:
173 pp_bookmarks[row]->i_byte_offset] stringValue]];
175 /* Just keep the pointer value to check if it
176 * changes. Note, we don't need to keep a reference to the object.
177 * so release it now. */
178 p_old_input = p_input;
179 vlc_object_release( p_input );
181 [NSApp beginSheet: o_edit_window
182 modalForWindow: o_bookmarks_window
183 modalDelegate: o_edit_window
187 // Clear the bookmark list
188 for( int i = 0; i < i_bookmarks; i++)
189 vlc_seekpoint_Delete( pp_bookmarks[i] );
190 free( pp_bookmarks );
194 - (IBAction)edit_cancel:(id)sender
197 [NSApp endSheet:o_edit_window];
198 [o_edit_window close];
201 - (IBAction)edit_ok:(id)sender
203 /* save field contents and close sheet */
204 seekpoint_t **pp_bookmarks;
206 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
210 NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"),
211 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("No "
212 "input found. A stream must be playing or paused for "
213 "bookmarks to work."));
216 if( p_old_input != p_input )
218 NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"),
219 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("Input "
220 "has changed, unable to save bookmark. Suspending playback with "
221 "\"Pause\" while editing bookmarks to ensure to keep the same "
223 vlc_object_release( p_input );
227 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
228 &i_bookmarks ) != VLC_SUCCESS )
230 vlc_object_release( p_input );
234 i = [o_tbl_dataTable selectedRow];
236 free( pp_bookmarks[i]->psz_name );
238 pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]);
239 pp_bookmarks[i]->i_byte_offset = [[o_edit_fld_bytes stringValue] intValue];
240 pp_bookmarks[i]->i_time_offset = ([[o_edit_fld_time stringValue] intValue] * 1000000);
242 if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i )
245 msg_Warn( VLCIntf, "Unable to change the bookmark");
249 [o_tbl_dataTable reloadData];
250 vlc_object_release( p_input );
253 [NSApp endSheet: o_edit_window];
254 [o_edit_window close];
257 // Clear the bookmark list
258 for( int i = 0; i < i_bookmarks; i++)
259 vlc_seekpoint_Delete( pp_bookmarks[i] );
260 free( pp_bookmarks );
263 - (IBAction)extract:(id)sender
266 if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
268 NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"),
269 @"", @"", o_bookmarks_window, nil, nil, nil, nil,
270 _NS("Two bookmarks have to be selected."));
273 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
276 NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"),
277 @"", @"", o_bookmarks_window, nil, nil, nil, nil,
278 _NS("The stream must be playing or paused for bookmarks to work."));
282 seekpoint_t **pp_bookmarks;
290 if([o_tbl_dataTable isRowSelected:x])
297 else if (i_second == -1)
306 msg_Dbg( VLCIntf, "got the bookmark-indexes");
308 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
309 &i_bookmarks ) != VLC_SUCCESS )
311 vlc_object_release( p_input );
312 msg_Err( VLCIntf, "already defined bookmarks couldn't be retrieved");
315 msg_Dbg( VLCIntf, "calling wizard");
317 char *psz_uri = input_item_GetURI( input_GetItem( p_input ) );
318 [[[VLCMain sharedInstance] wizard] initWithExtractValuesFrom:
319 [[NSNumber numberWithInt:
320 (pp_bookmarks[i_first]->i_time_offset/1000000)] stringValue]
321 to: [[NSNumber numberWithInt:
322 (pp_bookmarks[i_second]->i_time_offset/1000000)] stringValue]
323 ofItem: [NSString stringWithUTF8String: psz_uri]];
325 vlc_object_release( p_input );
326 msg_Dbg( VLCIntf, "released input");
328 // Clear the bookmark list
329 for( int i = 0; i < i_bookmarks; i++)
330 vlc_seekpoint_Delete( pp_bookmarks[i] );
331 free( pp_bookmarks );
334 - (IBAction)goToBookmark:(id)sender
336 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
338 if( !p_input ) return;
340 input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
342 vlc_object_release( p_input );
345 - (IBAction)remove:(id)sender
347 /* remove selected item */
348 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
350 if( !p_input ) return;
352 int i_focused = [o_tbl_dataTable selectedRow];
355 input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
357 vlc_object_release( p_input );
359 [o_tbl_dataTable reloadData];
362 /*****************************************************************************
364 *****************************************************************************/
368 return o_tbl_dataTable;
371 /*****************************************************************************
372 * data source methods
373 *****************************************************************************/
375 - (NSInteger)numberOfRowsInTableView:(NSTableView *)theDataTable
377 /* return the number of bookmarks */
378 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
379 seekpoint_t **pp_bookmarks;
382 if( !p_input ) return 0;
383 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
384 &i_bookmarks ) != VLC_SUCCESS )
386 vlc_object_release( p_input );
390 vlc_object_release( p_input );
391 // Clear the bookmark list
392 for( int i = 0; i < i_bookmarks; i++)
393 vlc_seekpoint_Delete( pp_bookmarks[i] );
394 free( pp_bookmarks );
399 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
400 (NSTableColumn *)theTableColumn row: (NSInteger)row
402 /* return the corresponding data as NSString */
403 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
404 seekpoint_t **pp_bookmarks;
407 int i_toBeReturned = 0;
410 if( !p_input ) return @"";
411 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
412 &i_bookmarks ) != VLC_SUCCESS )
418 if ([[theTableColumn identifier] isEqualToString: @"description"])
420 toBeReturned = pp_bookmarks[row]->psz_name;
421 ret = [NSString stringWithUTF8String: toBeReturned];
423 else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
425 i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
426 ret = [[NSNumber numberWithInt: i_toBeReturned] stringValue];
428 else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
430 i_toBeReturned = pp_bookmarks[row]->i_time_offset;
431 ret = [[NSNumber numberWithInt: (i_toBeReturned / 1000000)]
436 /* may not happen, just in case */
437 msg_Err( VLCIntf, "unknown table column identifier (%s) while "
438 "updating the bookmark table", [[theTableColumn identifier]
440 ret = @"unknown identifier";
443 // Clear the bookmark list
444 for( int i = 0; i < i_bookmarks; i++)
445 vlc_seekpoint_Delete( pp_bookmarks[i] );
446 free( pp_bookmarks );
448 vlc_object_release( p_input );
452 /*****************************************************************************
454 *****************************************************************************/
456 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
458 /* check whether a row is selected and en-/disable the edit/remove buttons */
459 if ([o_tbl_dataTable selectedRow] == -1)
461 /* no row is selected */
462 [o_btn_edit setEnabled: NO];
463 [o_btn_rm setEnabled: NO];
464 [o_btn_extract setEnabled: NO];
468 /* a row is selected */
469 [o_btn_edit setEnabled: YES];
470 [o_btn_rm setEnabled: YES];
471 if ([o_tbl_dataTable numberOfSelectedRows] == 2)
473 [o_btn_extract setEnabled: YES];