1 /*****************************************************************************
2 * bookmarks.m: MacOS X Bookmarks window
3 *****************************************************************************
4 * Copyright (C) 2005 - 2007 the VideoLAN team
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>
41 /*****************************************************************************
42 * VLCExtended implementation
44 * implements the GUI functions for the window, the data source and the
45 * delegate for o_tbl_dataTable
46 *****************************************************************************/
48 @implementation VLCBookmarks
50 static VLCBookmarks *_o_sharedInstance = nil;
52 + (VLCBookmarks *)sharedInstance
54 return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
59 if (_o_sharedInstance) {
62 _o_sharedInstance = [super init];
65 return _o_sharedInstance;
68 /*****************************************************************************
70 *****************************************************************************/
84 /* localise the items */
87 [o_bookmarks_window setTitle: _NS("Bookmarks")];
88 [o_btn_add setTitle: _NS("Add")];
89 [o_btn_clear setTitle: _NS("Clear")];
90 [o_btn_edit setTitle: _NS("Edit")];
91 [o_btn_extract setTitle: _NS("Extract")];
92 [o_btn_rm setTitle: _NS("Remove")];
93 [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell]
94 setStringValue: _NS("Description")];
95 [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell]
96 setStringValue: _NS("Position")];
97 [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell]
98 setStringValue: _NS("Time")];
101 [o_edit_btn_ok setTitle: _NS("OK")];
102 [o_edit_btn_cancel setTitle: _NS("Cancel")];
103 [o_edit_lbl_name setStringValue: _NS("Name")];
104 [o_edit_lbl_time setStringValue: _NS("Time")];
105 [o_edit_lbl_bytes setStringValue: _NS("Position")];
108 - (void)showBookmarks
110 /* show the window, called from intf.m */
111 [o_bookmarks_window displayIfNeeded];
112 [o_bookmarks_window makeKeyAndOrderFront:nil];
115 - (IBAction)add:(id)sender
117 /* add item to list */
118 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
120 if( !p_input ) return;
122 seekpoint_t bookmark;
124 if( !input_Control( p_input, INPUT_GET_BOOKMARK, &bookmark ) )
126 bookmark.psz_name = _("Untitled");
127 input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
130 vlc_object_release( p_input );
132 [o_tbl_dataTable reloadData];
135 - (IBAction)clear:(id)sender
138 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
143 input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
145 vlc_object_release( p_input );
147 [o_tbl_dataTable reloadData];
150 - (IBAction)edit:(id)sender
152 /* put values to the sheet's fields and show sheet */
153 /* we take the values from the core and not the table, because we cannot
155 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
156 seekpoint_t **pp_bookmarks;
159 row = [o_tbl_dataTable selectedRow];
161 if( !p_input && row < 0 )
164 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
165 &i_bookmarks ) != VLC_SUCCESS )
167 vlc_object_release( p_input );
171 [o_edit_fld_name setStringValue: [NSString stringWithUTF8String:
172 pp_bookmarks[row]->psz_name]];
173 [o_edit_fld_time setStringValue: [[NSNumber numberWithInt:
174 (pp_bookmarks[row]->i_time_offset / 1000000)] stringValue]];
175 [o_edit_fld_bytes setStringValue: [[NSNumber numberWithInt:
176 pp_bookmarks[row]->i_byte_offset] stringValue]];
178 /* Just keep the pointer value to check if it
179 * changes. Note, we don't need to keep a reference to the object.
180 * so release it now. */
181 p_old_input = p_input;
182 vlc_object_release( p_input );
184 [NSApp beginSheet: o_edit_window
185 modalForWindow: o_bookmarks_window
186 modalDelegate: o_edit_window
190 // Clear the bookmark list
191 for( int i = 0; i < i_bookmarks; i++)
192 vlc_seekpoint_Delete( pp_bookmarks[i] );
193 free( pp_bookmarks );
197 - (IBAction)edit_cancel:(id)sender
200 [NSApp endSheet:o_edit_window];
201 [o_edit_window close];
204 - (IBAction)edit_ok:(id)sender
206 /* save field contents and close sheet */
207 seekpoint_t **pp_bookmarks;
209 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
213 NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"),
214 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("No "
215 "input found. A stream must be playing or paused for "
216 "bookmarks to work."));
219 if( p_old_input != p_input )
221 NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"),
222 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("Input "
223 "has changed, unable to save bookmark. Suspending playback with "
224 "\"Pause\" while editing bookmarks to ensure to keep the same "
226 vlc_object_release( p_input );
230 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
231 &i_bookmarks ) != VLC_SUCCESS )
233 vlc_object_release( p_input );
237 i = [o_tbl_dataTable selectedRow];
239 free( pp_bookmarks[i]->psz_name );
241 pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]);
242 pp_bookmarks[i]->i_byte_offset = [[o_edit_fld_bytes stringValue] intValue];
243 pp_bookmarks[i]->i_time_offset = ([[o_edit_fld_time stringValue] intValue] * 1000000);
245 if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i )
248 msg_Warn( VLCIntf, "Unable to change the bookmark");
252 [o_tbl_dataTable reloadData];
253 vlc_object_release( p_input );
256 [NSApp endSheet: o_edit_window];
257 [o_edit_window close];
260 // Clear the bookmark list
261 for( int i = 0; i < i_bookmarks; i++)
262 vlc_seekpoint_Delete( pp_bookmarks[i] );
263 free( pp_bookmarks );
266 - (IBAction)extract:(id)sender
269 if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
271 NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"),
272 @"", @"", o_bookmarks_window, nil, nil, nil, nil,
273 _NS("Two bookmarks have to be selected."));
276 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
279 NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"),
280 @"", @"", o_bookmarks_window, nil, nil, nil, nil,
281 _NS("The stream must be playing or paused for bookmarks to work."));
285 seekpoint_t **pp_bookmarks;
293 if([o_tbl_dataTable isRowSelected:x])
300 else if (i_second == -1)
309 msg_Dbg( VLCIntf, "got the bookmark-indexes");
311 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
312 &i_bookmarks ) != VLC_SUCCESS )
314 vlc_object_release( p_input );
315 msg_Err( VLCIntf, "already defined bookmarks couldn't be retrieved");
318 msg_Dbg( VLCIntf, "calling wizard");
320 char *psz_uri = input_item_GetURI( input_GetItem( p_input ) );
321 [[[VLCMain sharedInstance] wizard] initWithExtractValuesFrom:
322 [[NSNumber numberWithInt:
323 (pp_bookmarks[i_first]->i_time_offset/1000000)] stringValue]
324 to: [[NSNumber numberWithInt:
325 (pp_bookmarks[i_second]->i_time_offset/1000000)] stringValue]
326 ofItem: [NSString stringWithUTF8String: psz_uri]];
328 vlc_object_release( p_input );
329 msg_Dbg( VLCIntf, "released input");
331 // Clear the bookmark list
332 for( int i = 0; i < i_bookmarks; i++)
333 vlc_seekpoint_Delete( pp_bookmarks[i] );
334 free( pp_bookmarks );
337 - (IBAction)goToBookmark:(id)sender
339 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
341 if( !p_input ) return;
343 input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
345 vlc_object_release( p_input );
348 - (IBAction)remove:(id)sender
350 /* remove selected item */
351 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
353 if( !p_input ) return;
355 int i_focused = [o_tbl_dataTable selectedRow];
358 input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
360 vlc_object_release( p_input );
362 [o_tbl_dataTable reloadData];
365 /*****************************************************************************
367 *****************************************************************************/
371 return o_tbl_dataTable;
374 /*****************************************************************************
375 * data source methods
376 *****************************************************************************/
378 - (NSInteger)numberOfRowsInTableView:(NSTableView *)theDataTable
380 /* return the number of bookmarks */
381 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
382 seekpoint_t **pp_bookmarks;
385 if( !p_input ) return 0;
386 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
387 &i_bookmarks ) != VLC_SUCCESS )
389 vlc_object_release( p_input );
393 vlc_object_release( p_input );
394 // Clear the bookmark list
395 for( int i = 0; i < i_bookmarks; i++)
396 vlc_seekpoint_Delete( pp_bookmarks[i] );
397 free( pp_bookmarks );
402 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
403 (NSTableColumn *)theTableColumn row: (NSInteger)row
405 /* return the corresponding data as NSString */
406 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
407 seekpoint_t **pp_bookmarks;
410 int i_toBeReturned = 0;
413 if( !p_input ) return @"";
414 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
415 &i_bookmarks ) != VLC_SUCCESS )
421 if ([[theTableColumn identifier] isEqualToString: @"description"])
423 toBeReturned = pp_bookmarks[row]->psz_name;
424 ret = [NSString stringWithUTF8String: toBeReturned];
426 else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
428 i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
429 ret = [[NSNumber numberWithInt: i_toBeReturned] stringValue];
431 else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
433 i_toBeReturned = pp_bookmarks[row]->i_time_offset;
434 ret = [[NSNumber numberWithInt: (i_toBeReturned / 1000000)]
439 /* may not happen, just in case */
440 msg_Err( VLCIntf, "unknown table column identifier (%s) while "
441 "updating the bookmark table", [[theTableColumn identifier]
443 ret = @"unknown identifier";
446 // Clear the bookmark list
447 for( int i = 0; i < i_bookmarks; i++)
448 vlc_seekpoint_Delete( pp_bookmarks[i] );
449 free( pp_bookmarks );
451 vlc_object_release( p_input );
455 /*****************************************************************************
457 *****************************************************************************/
459 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
461 /* check whether a row is selected and en-/disable the edit/remove buttons */
462 if ([o_tbl_dataTable selectedRow] == -1)
464 /* no row is selected */
465 [o_btn_edit setEnabled: NO];
466 [o_btn_rm setEnabled: NO];
467 [o_btn_extract setEnabled: NO];
471 /* a row is selected */
472 [o_btn_edit setEnabled: YES];
473 [o_btn_rm setEnabled: YES];
474 if ([o_tbl_dataTable numberOfSelectedRows] == 2)
476 [o_btn_extract setEnabled: YES];