]> git.sesse.net Git - vlc/blob - modules/gui/macosx/bookmarks.m
macosx: copyright fixes
[vlc] / modules / gui / macosx / bookmarks.m
1 /*****************************************************************************
2  * bookmarks.m: MacOS X Bookmarks window
3  *****************************************************************************
4  * Copyright (C) 2005 - 2007 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Felix Kühne <fkuehne at videolan dot org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24
25 /*****************************************************************************
26  * Note:
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  *****************************************************************************/
31
32
33 /*****************************************************************************
34  * Preamble
35  *****************************************************************************/
36
37 #import "bookmarks.h"
38 #import "wizard.h"
39 #import <vlc_interface.h>
40 #import "CompatibilityFixes.h"
41
42 @implementation VLCBookmarks
43
44 static VLCBookmarks *_o_sharedInstance = nil;
45
46 + (VLCBookmarks *)sharedInstance
47 {
48     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
49 }
50
51 - (id)init
52 {
53     if (_o_sharedInstance) {
54         [self dealloc];
55     } else {
56         _o_sharedInstance = [super init];
57     }
58
59     return _o_sharedInstance;
60 }
61
62 /*****************************************************************************
63  * GUI methods
64  *****************************************************************************/
65
66 - (void)awakeFromNib
67 {
68     if (OSX_LION)
69         [o_bookmarks_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
70
71     [self initStrings];
72 }
73
74 - (void)dealloc
75 {
76     [super dealloc];
77 }
78
79 - (void)initStrings
80 {
81     /* localise the items */
82  
83     /* main window */
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")];
96  
97     /* edit window */
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")];
103 }
104
105 - (void)showBookmarks
106 {
107     /* show the window, called from intf.m */
108     [o_bookmarks_window displayIfNeeded];
109     [o_bookmarks_window makeKeyAndOrderFront:nil];
110 }
111
112 - (IBAction)add:(id)sender
113 {
114     /* add item to list */
115     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
116
117     if( !p_input ) return;
118  
119     seekpoint_t bookmark;
120
121     if( !input_Control( p_input, INPUT_GET_BOOKMARK, &bookmark ) )
122         {
123                 bookmark.psz_name = _("Untitled");
124                 input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
125         }
126  
127     vlc_object_release( p_input );
128  
129     [o_tbl_dataTable reloadData];
130 }
131
132 - (IBAction)clear:(id)sender
133 {
134     /* clear table */
135     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
136  
137     if( !p_input )
138         return;
139
140     input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
141
142     vlc_object_release( p_input );
143  
144     [o_tbl_dataTable reloadData];
145 }
146
147 - (IBAction)edit:(id)sender
148 {
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
151      * really trust it */
152     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
153     seekpoint_t **pp_bookmarks;
154     int i_bookmarks;
155     int row;
156     row = [o_tbl_dataTable selectedRow];
157  
158     if( !p_input && row < 0 )
159         return;
160
161     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
162         &i_bookmarks ) != VLC_SUCCESS )
163     {
164         vlc_object_release( p_input );
165         return;
166     }
167
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]];
174  
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 );
180
181     [NSApp beginSheet: o_edit_window
182         modalForWindow: o_bookmarks_window
183         modalDelegate: o_edit_window
184         didEndSelector: nil
185         contextInfo: nil];
186
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 );
191
192 }
193
194 - (IBAction)edit_cancel:(id)sender
195 {
196     /* close sheet */
197     [NSApp endSheet:o_edit_window];
198     [o_edit_window close];
199 }
200
201 - (IBAction)edit_ok:(id)sender
202 {
203     /* save field contents and close sheet */
204      seekpoint_t **pp_bookmarks;
205     int i_bookmarks, i;
206     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
207  
208     if( !p_input )
209     {
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."));
214         return;
215     }
216     if( p_old_input != p_input )
217     {
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 "
222             "input."));
223         vlc_object_release( p_input );
224         return;
225     }
226  
227     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
228         &i_bookmarks ) != VLC_SUCCESS )
229     {
230         vlc_object_release( p_input );
231         return;
232     }
233
234     i = [o_tbl_dataTable selectedRow];
235  
236     free( pp_bookmarks[i]->psz_name );
237
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);
241  
242     if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i )
243         != VLC_SUCCESS )
244     {
245         msg_Warn( VLCIntf, "Unable to change the bookmark");
246         goto clear;
247     }
248  
249     [o_tbl_dataTable reloadData];
250     vlc_object_release( p_input );
251  
252  
253     [NSApp endSheet: o_edit_window];
254     [o_edit_window close];
255
256 clear:
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 );
261 }
262
263 - (IBAction)extract:(id)sender
264 {
265     /* extract */
266     if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
267     {
268         NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"),
269             @"", @"", o_bookmarks_window, nil, nil, nil, nil,
270             _NS("Two bookmarks have to be selected."));
271         return;
272     }
273     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
274     if( !p_input )
275     {
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."));
279         return;
280     }
281  
282     seekpoint_t **pp_bookmarks;
283     int i_bookmarks ;
284     int i_first = -1;
285     int i_second = -1;
286     int x = 0;
287     int c = 0;
288     while (c != 2)
289     {
290         if([o_tbl_dataTable isRowSelected:x])
291         {
292             if (i_first == -1)
293             {
294                 i_first = x;
295                 c = 1;
296             }
297             else if (i_second == -1)
298             {
299                 i_second = x;
300                 c = 2;
301             }
302         }
303         x = (x + 1);
304     }
305  
306     msg_Dbg( VLCIntf, "got the bookmark-indexes");
307  
308     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
309         &i_bookmarks ) != VLC_SUCCESS )
310     {
311         vlc_object_release( p_input );
312         msg_Err( VLCIntf, "already defined bookmarks couldn't be retrieved");
313         return;
314     }
315     msg_Dbg( VLCIntf, "calling wizard");
316
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]];
324     free( psz_uri );
325     vlc_object_release( p_input );
326     msg_Dbg( VLCIntf, "released input");
327
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 );
332 }
333
334 - (IBAction)goToBookmark:(id)sender
335 {
336     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
337  
338     if( !p_input ) return;
339
340     input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
341
342     vlc_object_release( p_input );
343 }
344
345 - (IBAction)remove:(id)sender
346 {
347     /* remove selected item */
348     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
349  
350     if( !p_input ) return;
351
352     int i_focused = [o_tbl_dataTable selectedRow];
353
354     if( i_focused >= 0 )
355         input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
356
357     vlc_object_release( p_input );
358  
359     [o_tbl_dataTable reloadData];
360 }
361
362 /*****************************************************************************
363  * callback stuff
364  *****************************************************************************/
365
366 -(id)dataTable
367 {
368     return o_tbl_dataTable;
369 }
370
371 /*****************************************************************************
372  * data source methods
373  *****************************************************************************/
374
375 - (NSInteger)numberOfRowsInTableView:(NSTableView *)theDataTable
376 {
377     /* return the number of bookmarks */
378     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
379     seekpoint_t **pp_bookmarks;
380     int i_bookmarks;
381  
382     if( !p_input ) return 0;
383     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
384                        &i_bookmarks ) != VLC_SUCCESS )
385     {
386         vlc_object_release( p_input );
387         return 0;
388     }
389     else {
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 );
395         return i_bookmarks;
396     }
397 }
398
399 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
400     (NSTableColumn *)theTableColumn row: (NSInteger)row
401 {
402     /* return the corresponding data as NSString */
403     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
404     seekpoint_t **pp_bookmarks;
405     int i_bookmarks;
406     char *toBeReturned;
407     int i_toBeReturned = 0;
408     id ret;
409
410     if( !p_input ) return @"";
411     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
412                        &i_bookmarks ) != VLC_SUCCESS )
413     {
414         ret = @"";
415     }
416     else
417     {
418         if ([[theTableColumn identifier] isEqualToString: @"description"])
419         {
420             toBeReturned = pp_bookmarks[row]->psz_name;
421             ret = [NSString stringWithUTF8String: toBeReturned];
422         }
423         else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
424         {
425             i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
426             ret = [[NSNumber numberWithInt: i_toBeReturned] stringValue];
427         }
428         else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
429         {
430             i_toBeReturned = pp_bookmarks[row]->i_time_offset;
431             ret = [[NSNumber numberWithInt: (i_toBeReturned / 1000000)]
432                 stringValue];
433         }
434         else
435         {
436             /* may not happen, just in case */
437             msg_Err( VLCIntf, "unknown table column identifier (%s) while "
438                 "updating the bookmark table", [[theTableColumn identifier]
439                 UTF8String] );
440             ret = @"unknown identifier";
441         }
442
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 );
447     }
448     vlc_object_release( p_input );
449     return ret;
450 }
451
452 /*****************************************************************************
453  * delegate methods
454  *****************************************************************************/
455
456 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
457 {
458     /* check whether a row is selected and en-/disable the edit/remove buttons */
459     if ([o_tbl_dataTable selectedRow] == -1)
460     {
461         /* no row is selected */
462         [o_btn_edit setEnabled: NO];
463         [o_btn_rm setEnabled: NO];
464         [o_btn_extract setEnabled: NO];
465     }
466     else
467     {
468         /* a row is selected */
469         [o_btn_edit setEnabled: YES];
470         [o_btn_rm setEnabled: YES];
471         if ([o_tbl_dataTable numberOfSelectedRows] == 2)
472         {
473             [o_btn_extract setEnabled: YES];
474         }
475     }
476 }
477
478 @end