]> git.sesse.net Git - vlc/blob - modules/gui/macosx/bookmarks.m
qt4 - Main_Interface: show the cone when back from playlist for the --qt-always-video...
[vlc] / modules / gui / macosx / bookmarks.m
1 /*****************************************************************************
2  * bookmarks.m: MacOS X Bookmarks window
3  *****************************************************************************
4  * Copyright (C) 2005 - 2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Felix Kühne <fkuehne@users.sf.net>
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 "intf.h"
39 #import "wizard.h"
40 #import <vlc_interface.h>
41
42 /*****************************************************************************
43  * VLCExtended implementation
44  *
45  * implements the GUI functions for the window, the data source and the
46  * delegate for o_tbl_dataTable
47  *****************************************************************************/
48
49 @implementation VLCBookmarks
50
51 static VLCBookmarks *_o_sharedInstance = nil;
52
53 + (VLCBookmarks *)sharedInstance
54 {
55     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
56 }
57
58 - (id)init
59 {
60     if (_o_sharedInstance) {
61         [self dealloc];
62     } else {
63         _o_sharedInstance = [super init];
64     }
65
66     return _o_sharedInstance;
67 }
68
69 /*****************************************************************************
70  * GUI methods
71  *****************************************************************************/
72
73 - (void)awakeFromNib
74 {
75     [self initStrings];
76 }
77
78 - (void)dealloc
79 {
80     if( p_old_input )
81         vlc_object_release( p_old_input );
82     [super dealloc];
83 }
84
85 #if GC_ENABLED
86 - (void)finalize
87 {
88     /* release old input even if GC is enabled on 10.5 */
89     if( p_old_input )   
90         vlc_object_release( p_old_input );
91     [super finalize];
92 }
93 #endif
94
95 - (void)initStrings
96 {
97     /* localise the items */
98     
99     /* main window */
100     [o_bookmarks_window setTitle: _NS("Bookmarks")];
101     [o_btn_add setTitle: _NS("Add")];
102     [o_btn_clear setTitle: _NS("Clear")];
103     [o_btn_edit setTitle: _NS("Edit")];
104     [o_btn_extract setTitle: _NS("Extract")];
105     [o_btn_rm setTitle: _NS("Remove")];
106     [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell]
107         setStringValue: _NS("Description")];
108     [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell]
109         setStringValue: _NS("Position")];
110     [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell]
111         setStringValue: _NS("Time")];
112         
113     /* edit window */
114     [o_edit_btn_ok setTitle: _NS("OK")];
115     [o_edit_btn_cancel setTitle: _NS("Cancel")];
116     [o_edit_lbl_name setStringValue: _NS("Name")];
117     [o_edit_lbl_time setStringValue: _NS("Time")];
118     [o_edit_lbl_bytes setStringValue: _NS("Position")];
119 }
120
121 - (void)showBookmarks
122 {
123     /* show the window, called from intf.m */
124     [o_bookmarks_window displayIfNeeded];
125     [o_bookmarks_window makeKeyAndOrderFront:nil];
126 }
127
128 - (IBAction)add:(id)sender
129 {
130     /* add item to list */
131     intf_thread_t * p_intf = VLCIntf;
132     input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
133         VLC_OBJECT_INPUT, FIND_ANYWHERE );
134     if( !p_input )
135         return;
136     
137     seekpoint_t bookmark;
138     vlc_value_t pos;
139     bookmark.psz_name = NULL;
140     bookmark.i_byte_offset = 0;
141     bookmark.i_time_offset = 0;
142     
143     var_Get(p_intf, "position", &pos);
144     bookmark.psz_name = _("Untitled");
145     input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
146     var_Get( p_input, "time", &pos );
147     bookmark.i_time_offset = pos.i_time;
148     input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
149     
150     vlc_object_release( p_input );
151     
152     [o_tbl_dataTable reloadData];
153 }
154
155 - (IBAction)clear:(id)sender
156 {
157     /* clear table */
158     intf_thread_t * p_intf = VLCIntf;
159     input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
160         VLC_OBJECT_INPUT, FIND_ANYWHERE );
161     
162     if( !p_input )
163         return;
164
165     input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
166
167     vlc_object_release( p_input );
168     
169     [o_tbl_dataTable reloadData];
170 }
171
172 - (IBAction)edit:(id)sender
173 {
174     /* put values to the sheet's fields and show sheet */
175     /* we take the values from the core and not the table, because we cannot
176      * really trust it */
177     intf_thread_t * p_intf = VLCIntf;
178     input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
179         VLC_OBJECT_INPUT, FIND_ANYWHERE );
180     seekpoint_t **pp_bookmarks;
181     int i_bookmarks;
182     int row;
183     row = [o_tbl_dataTable selectedRow];
184     
185     if( !p_input )
186     {
187         return;
188     } 
189     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
190         &i_bookmarks ) != VLC_SUCCESS )
191     {
192         vlc_object_release( p_input );
193         return;
194     } 
195     else if(row < 0)
196     {
197         vlc_object_release( p_input );
198         return;
199     } else {
200         [o_edit_fld_name setStringValue: [NSString stringWithUTF8String:
201             pp_bookmarks[row]->psz_name]];
202         [o_edit_fld_time setStringValue: [[NSNumber numberWithInt:
203             (pp_bookmarks[row]->i_time_offset / 1000000)] stringValue]];
204         [o_edit_fld_bytes setStringValue: [[NSNumber numberWithInt:
205             pp_bookmarks[row]->i_byte_offset] stringValue]];
206     }
207     
208     p_old_input = p_input;
209     vlc_object_release( p_input );
210
211     [NSApp beginSheet: o_edit_window
212         modalForWindow: o_bookmarks_window
213         modalDelegate: o_edit_window
214         didEndSelector: nil
215         contextInfo: nil];
216 }
217
218 - (IBAction)edit_cancel:(id)sender
219 {
220     /* close sheet */
221     [NSApp endSheet:o_edit_window];
222     [o_edit_window close];
223 }
224
225 - (IBAction)edit_ok:(id)sender
226 {
227     /* save field contents and close sheet */
228     
229     intf_thread_t * p_intf = VLCIntf;
230     seekpoint_t **pp_bookmarks;
231     int i_bookmarks, i;
232     input_thread_t *p_input = (input_thread_t *)vlc_object_find( p_intf,
233         VLC_OBJECT_INPUT, FIND_ANYWHERE );
234     
235     if( !p_input )
236     {
237         NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"),
238                 @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("No "
239                 "input found. A stream must be playing or paused for "
240                 "bookmarks to work."));
241         return;
242     }
243     if( p_old_input != p_input )
244     {
245         NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"),
246             @"", @"", o_bookmarks_window, nil, nil, nil, nil, _NS("Input "
247             "has changed, unable to save bookmark. Suspending playback with "
248             "\"Pause\" while editing bookmarks to ensure to keep the same "
249             "input."));
250         vlc_object_release( p_input );
251         return;
252     }
253     
254     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
255         &i_bookmarks ) != VLC_SUCCESS )
256     {
257         vlc_object_release( p_input );
258         return;
259     } 
260
261     i = [o_tbl_dataTable selectedRow];
262     
263     if( pp_bookmarks[i]->psz_name ) 
264         free( pp_bookmarks[i]->psz_name );
265
266     pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]); 
267     pp_bookmarks[i]->i_byte_offset = [[o_edit_fld_bytes stringValue] intValue];
268     pp_bookmarks[i]->i_time_offset = ([[o_edit_fld_time stringValue] intValue]  * 1000000);
269     
270     if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i )
271         != VLC_SUCCESS )
272     {
273         msg_Warn( p_intf, "Unable to change the bookmark");
274         vlc_object_release( p_input );
275         return;
276     }
277     
278     [o_tbl_dataTable reloadData];
279     vlc_object_release( p_input );
280      
281     
282     [NSApp endSheet: o_edit_window];
283     [o_edit_window close];
284 }
285
286 - (IBAction)extract:(id)sender
287 {
288     /* extract */
289     
290     intf_thread_t * p_intf = VLCIntf;
291     
292     if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
293     {
294         NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"),
295             @"", @"", o_bookmarks_window, nil, nil, nil, nil, 
296             _NS("Two bookmarks have to be selected."));
297         return;
298     }
299     input_thread_t *p_input =
300         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
301                                            FIND_ANYWHERE );
302     if( !p_input )
303     {
304         NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"),
305             @"", @"", o_bookmarks_window, nil, nil, nil, nil, 
306             _NS("The stream must be playing or paused for bookmarks to work."));
307         return;
308     }
309     
310     seekpoint_t **pp_bookmarks;
311     int i_bookmarks ;
312     int i_first = -1;
313     int i_second = -1;
314     int x = 0;
315     int c = 0;
316     while (c != 2)
317     {
318         if([o_tbl_dataTable isRowSelected:x])
319         {
320             if (i_first == -1)
321             {
322                 i_first = x;
323                 c = 1;
324             } 
325             else if (i_second == -1)
326             {
327                 i_second = x;
328                 c = 2;
329             }
330         }
331         x = (x + 1);
332     }
333     
334     msg_Dbg(p_intf, "got the bookmark-indexes");
335     
336     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
337         &i_bookmarks ) != VLC_SUCCESS )
338     {
339         vlc_object_release( p_input );
340         msg_Err(p_intf, "already defined bookmarks couldn't be retrieved");
341         return;
342     }
343     msg_Dbg(p_intf, "calling wizard");
344
345     [[[VLCMain sharedInstance] getWizard] initWithExtractValuesFrom:
346             [[NSNumber numberWithInt:
347             (pp_bookmarks[i_first]->i_time_offset/1000000)] stringValue]
348             to: [[NSNumber numberWithInt:
349             (pp_bookmarks[i_second]->i_time_offset/1000000)] stringValue]
350             ofItem: [NSString stringWithUTF8String:
351             input_GetItem(p_input)->psz_uri]];
352     vlc_object_release( p_input );
353     msg_Dbg(p_intf, "released input");
354 }
355
356 - (IBAction)goToBookmark:(id)sender
357 {
358     intf_thread_t * p_intf = VLCIntf;
359     input_thread_t *p_input =
360     (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT, 
361         FIND_ANYWHERE );
362     
363     if( !p_input ) return;
364
365     input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
366
367     vlc_object_release( p_input );
368 }
369
370 - (IBAction)remove:(id)sender
371 {
372     /* remove selected item */
373     intf_thread_t * p_intf = VLCIntf;
374     input_thread_t *p_input =
375     (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT, 
376         FIND_ANYWHERE );
377     
378     if( !p_input ) return;
379
380     int i_focused = [o_tbl_dataTable selectedRow];
381
382     if( i_focused >= 0 )
383         input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
384
385     vlc_object_release( p_input );
386     
387     [o_tbl_dataTable reloadData];
388 }
389
390 /*****************************************************************************
391  * callback stuff
392  *****************************************************************************/
393
394 -(id)getDataTable
395 {
396     return o_tbl_dataTable;
397 }
398
399 /*****************************************************************************
400  * data source methods
401  *****************************************************************************/
402
403 - (int)numberOfRowsInTableView:(NSTableView *)theDataTable
404 {
405     /* return the number of bookmarks */
406     intf_thread_t * p_intf = VLCIntf;
407     input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
408         VLC_OBJECT_INPUT, FIND_ANYWHERE );
409     seekpoint_t **pp_bookmarks;
410     int i_bookmarks;
411     
412     if( !p_input ) return 0;
413     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
414                        &i_bookmarks ) != VLC_SUCCESS )
415     {
416         vlc_object_release( p_input );
417         return 0;
418     }
419     else {
420         vlc_object_release( p_input );
421         return i_bookmarks;
422     }
423 }
424
425 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
426     (NSTableColumn *)theTableColumn row: (int)row
427 {
428     /* return the corresponding data as NSString */
429     intf_thread_t * p_intf = VLCIntf;
430     input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf,
431         VLC_OBJECT_INPUT, FIND_ANYWHERE );
432     seekpoint_t **pp_bookmarks;
433     int i_bookmarks;
434     char *toBeReturned;
435     int i_toBeReturned = 0;
436     
437     if( !p_input ) return @"";
438     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
439                        &i_bookmarks ) != VLC_SUCCESS )
440     {
441         vlc_object_release( p_input );
442         return @"";
443     }
444     else
445     {
446         if ([[theTableColumn identifier] isEqualToString: @"description"])
447         {
448             toBeReturned = pp_bookmarks[row]->psz_name;
449             vlc_object_release( p_input );
450             return [NSString stringWithUTF8String: toBeReturned];
451         } 
452         else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
453         {
454             i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
455             vlc_object_release( p_input );
456             return [[NSNumber numberWithInt: i_toBeReturned] stringValue];
457         }
458         else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
459         {
460             i_toBeReturned = pp_bookmarks[row]->i_time_offset;
461             vlc_object_release( p_input );
462             return [[NSNumber numberWithInt: (i_toBeReturned / 1000000)]
463                 stringValue];
464         }
465         else
466         {
467             /* may not happen, just in case */
468             vlc_object_release( p_input );
469             msg_Err(p_intf, "unknown table column identifier (%s) while "
470                 "updating the bookmark table", [[theTableColumn identifier]
471                 UTF8String] );
472             return @"unknown identifier";
473         }
474     }
475
476 }
477
478 /*****************************************************************************
479  * delegate methods
480  *****************************************************************************/
481
482 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
483 {
484     /* check whether a row is selected and en-/disable the edit/remove buttons */
485     if ([o_tbl_dataTable selectedRow] == -1)
486     {
487         /* no row is selected */
488         [o_btn_edit setEnabled: NO];
489         [o_btn_rm setEnabled: NO];
490         [o_btn_extract setEnabled: NO];
491     }
492     else
493     {
494         /* a row is selected */
495         [o_btn_edit setEnabled: YES];
496         [o_btn_rm setEnabled: YES];
497         if ([o_tbl_dataTable numberOfSelectedRows] == 2)
498         {
499             [o_btn_extract setEnabled: YES];
500         }
501     }
502 }
503
504 @end