1 /*****************************************************************************
2 * bookmarks.m: MacOS X Bookmarks window
3 *****************************************************************************
4 * Copyright (C) 2005 - 2007 the VideoLAN team
7 * Authors: Felix Kühne <fkuehne@users.sf.net>
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 *****************************************************************************/
80 vlc_object_release( p_old_input );
86 /* localise the items */
89 [o_bookmarks_window setTitle: _NS("Bookmarks")];
90 [o_btn_add setTitle: _NS("Add")];
91 [o_btn_clear setTitle: _NS("Clear")];
92 [o_btn_edit setTitle: _NS("Edit")];
93 [o_btn_extract setTitle: _NS("Extract")];
94 [o_btn_rm setTitle: _NS("Remove")];
95 [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell]
96 setStringValue: _NS("Description")];
97 [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell]
98 setStringValue: _NS("Position")];
99 [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell]
100 setStringValue: _NS("Time")];
103 [o_edit_btn_ok setTitle: _NS("OK")];
104 [o_edit_btn_cancel setTitle: _NS("Cancel")];
105 [o_edit_lbl_name setStringValue: _NS("Name")];
106 [o_edit_lbl_time setStringValue: _NS("Time")];
107 [o_edit_lbl_bytes setStringValue: _NS("Position")];
110 - (void)showBookmarks
112 /* show the window, called from intf.m */
113 [o_bookmarks_window displayIfNeeded];
114 [o_bookmarks_window makeKeyAndOrderFront:nil];
117 - (IBAction)add:(id)sender
119 /* add item to list */
120 intf_thread_t * p_intf = VLCIntf;
121 input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
122 VLC_OBJECT_INPUT, FIND_ANYWHERE );
126 seekpoint_t bookmark;
128 bookmark.psz_name = NULL;
129 bookmark.i_byte_offset = 0;
130 bookmark.i_time_offset = 0;
132 var_Get(p_intf, "position", &pos);
133 bookmark.psz_name = _("Untitled");
134 input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
135 var_Get( p_input, "time", &pos );
136 bookmark.i_time_offset = pos.i_time;
137 input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
139 vlc_object_release( p_input );
141 [o_tbl_dataTable reloadData];
144 - (IBAction)clear:(id)sender
147 intf_thread_t * p_intf = VLCIntf;
148 input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
149 VLC_OBJECT_INPUT, FIND_ANYWHERE );
154 input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
156 vlc_object_release( p_input );
158 [o_tbl_dataTable reloadData];
161 - (IBAction)edit:(id)sender
163 /* put values to the sheet's fields and show sheet */
164 /* we take the values from the core and not the table, because we cannot
166 intf_thread_t * p_intf = VLCIntf;
167 input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
168 VLC_OBJECT_INPUT, FIND_ANYWHERE );
169 seekpoint_t **pp_bookmarks;
172 row = [o_tbl_dataTable selectedRow];
178 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
179 &i_bookmarks ) != VLC_SUCCESS )
181 vlc_object_release( p_input );
186 vlc_object_release( p_input );
189 [o_edit_fld_name setStringValue: [NSString stringWithUTF8String:
190 pp_bookmarks[row]->psz_name]];
191 [o_edit_fld_time setStringValue: [[NSNumber numberWithInt:
192 (pp_bookmarks[row]->i_time_offset / 1000000)] stringValue]];
193 [o_edit_fld_bytes setStringValue: [[NSNumber numberWithInt:
194 pp_bookmarks[row]->i_byte_offset] stringValue]];
197 p_old_input = p_input;
198 vlc_object_release( p_input );
200 [NSApp beginSheet: o_edit_window
201 modalForWindow: o_bookmarks_window
202 modalDelegate: o_edit_window
207 - (IBAction)edit_cancel:(id)sender
210 [NSApp endSheet:o_edit_window];
211 [o_edit_window close];
214 - (IBAction)edit_ok:(id)sender
216 /* save field contents and close sheet */
218 intf_thread_t * p_intf = VLCIntf;
219 seekpoint_t **pp_bookmarks;
221 input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
222 VLC_OBJECT_INPUT, FIND_ANYWHERE );
226 NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"),
227 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("No "
228 "input found. A stream must be playing or paused for "
229 "bookmarks to work."));
232 if( p_old_input != p_input )
234 NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"),
235 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("Input "
236 "has changed, unable to save bookmark. Suspending playback with "
237 "\"Pause\" while editing bookmarks to ensure to keep the same "
239 vlc_object_release( p_input );
243 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
244 &i_bookmarks ) != VLC_SUCCESS )
246 vlc_object_release( p_input );
250 i = [o_tbl_dataTable selectedRow];
252 if( pp_bookmarks[i]->psz_name )
253 free( pp_bookmarks[i]->psz_name );
255 pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]);
256 pp_bookmarks[i]->i_byte_offset = [[o_edit_fld_bytes stringValue] intValue];
257 pp_bookmarks[i]->i_time_offset = ([[o_edit_fld_time stringValue] intValue] * 1000000);
259 if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i )
262 msg_Warn( p_intf, "Unable to change the bookmark");
263 vlc_object_release( p_input );
267 [o_tbl_dataTable reloadData];
268 vlc_object_release( p_input );
271 [NSApp endSheet: o_edit_window];
272 [o_edit_window close];
275 - (IBAction)extract:(id)sender
279 intf_thread_t * p_intf = VLCIntf;
281 if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
283 NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"),
284 @"", @"", o_bookmarks_window, nil, nil, nil, nil,
285 _NS("Two bookmarks have to be selected."));
288 input_thread_t *p_input =
289 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
293 NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"),
294 @"", @"", o_bookmarks_window, nil, nil, nil, nil,
295 _NS("The stream must be playing or paused for bookmarks to work."));
299 seekpoint_t **pp_bookmarks;
307 if([o_tbl_dataTable isRowSelected:x])
314 else if (i_second == -1)
323 msg_Dbg(p_intf, "got the bookmark-indexes");
325 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
326 &i_bookmarks ) != VLC_SUCCESS )
328 vlc_object_release( p_input );
329 msg_Err(p_intf, "already defined bookmarks couldn't be retrieved");
332 msg_Dbg(p_intf, "calling wizard");
334 char *psz_uri = input_item_GetURI( input_GetItem( p_input ) );
335 [[[VLCMain sharedInstance] getWizard] initWithExtractValuesFrom:
336 [[NSNumber numberWithInt:
337 (pp_bookmarks[i_first]->i_time_offset/1000000)] stringValue]
338 to: [[NSNumber numberWithInt:
339 (pp_bookmarks[i_second]->i_time_offset/1000000)] stringValue]
340 ofItem: [NSString stringWithUTF8String: psz_uri]];
342 vlc_object_release( p_input );
343 msg_Dbg(p_intf, "released input");
346 - (IBAction)goToBookmark:(id)sender
348 intf_thread_t * p_intf = VLCIntf;
349 input_thread_t *p_input =
350 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
353 if( !p_input ) return;
355 input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
357 vlc_object_release( p_input );
360 - (IBAction)remove:(id)sender
362 /* remove selected item */
363 intf_thread_t * p_intf = VLCIntf;
364 input_thread_t *p_input =
365 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
368 if( !p_input ) return;
370 int i_focused = [o_tbl_dataTable selectedRow];
373 input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
375 vlc_object_release( p_input );
377 [o_tbl_dataTable reloadData];
380 /*****************************************************************************
382 *****************************************************************************/
386 return o_tbl_dataTable;
389 /*****************************************************************************
390 * data source methods
391 *****************************************************************************/
393 - (int)numberOfRowsInTableView:(NSTableView *)theDataTable
395 /* return the number of bookmarks */
396 intf_thread_t * p_intf = VLCIntf;
397 input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
398 VLC_OBJECT_INPUT, FIND_ANYWHERE );
399 seekpoint_t **pp_bookmarks;
402 if( !p_input ) return 0;
403 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
404 &i_bookmarks ) != VLC_SUCCESS )
406 vlc_object_release( p_input );
410 vlc_object_release( p_input );
415 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
416 (NSTableColumn *)theTableColumn row: (int)row
418 /* return the corresponding data as NSString */
419 intf_thread_t * p_intf = VLCIntf;
420 input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
421 VLC_OBJECT_INPUT, FIND_ANYWHERE );
422 seekpoint_t **pp_bookmarks;
425 int i_toBeReturned = 0;
427 if( !p_input ) return @"";
428 else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
429 &i_bookmarks ) != VLC_SUCCESS )
431 vlc_object_release( p_input );
436 if ([[theTableColumn identifier] isEqualToString: @"description"])
438 toBeReturned = pp_bookmarks[row]->psz_name;
439 vlc_object_release( p_input );
440 return [NSString stringWithUTF8String: toBeReturned];
442 else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
444 i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
445 vlc_object_release( p_input );
446 return [[NSNumber numberWithInt: i_toBeReturned] stringValue];
448 else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
450 i_toBeReturned = pp_bookmarks[row]->i_time_offset;
451 vlc_object_release( p_input );
452 return [[NSNumber numberWithInt: (i_toBeReturned / 1000000)]
457 /* may not happen, just in case */
458 vlc_object_release( p_input );
459 msg_Err(p_intf, "unknown table column identifier (%s) while "
460 "updating the bookmark table", [[theTableColumn identifier]
462 return @"unknown identifier";
468 /*****************************************************************************
470 *****************************************************************************/
472 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
474 /* check whether a row is selected and en-/disable the edit/remove buttons */
475 if ([o_tbl_dataTable selectedRow] == -1)
477 /* no row is selected */
478 [o_btn_edit setEnabled: NO];
479 [o_btn_rm setEnabled: NO];
480 [o_btn_extract setEnabled: NO];
484 /* a row is selected */
485 [o_btn_edit setEnabled: YES];
486 [o_btn_rm setEnabled: YES];
487 if ([o_tbl_dataTable numberOfSelectedRows] == 2)
489 [o_btn_extract setEnabled: YES];