]> git.sesse.net Git - vlc/blob - modules/gui/macosx/bookmarks.m
Added a new INPUT_GET_BOOKMARK to allow future safe bookmark.
[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 "wizard.h"
39 #import <vlc_interface.h>
40
41 /*****************************************************************************
42  * VLCExtended implementation
43  *
44  * implements the GUI functions for the window, the data source and the
45  * delegate for o_tbl_dataTable
46  *****************************************************************************/
47
48 @implementation VLCBookmarks
49
50 static VLCBookmarks *_o_sharedInstance = nil;
51
52 + (VLCBookmarks *)sharedInstance
53 {
54     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
55 }
56
57 - (id)init
58 {
59     if (_o_sharedInstance) {
60         [self dealloc];
61     } else {
62         _o_sharedInstance = [super init];
63     }
64
65     return _o_sharedInstance;
66 }
67
68 /*****************************************************************************
69  * GUI methods
70  *****************************************************************************/
71
72 - (void)awakeFromNib
73 {
74     [self initStrings];
75 }
76
77 - (void)dealloc
78 {
79     [super dealloc];
80 }
81
82 - (void)initStrings
83 {
84     /* localise the items */
85  
86     /* main window */
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")];
99  
100     /* edit window */
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")];
106 }
107
108 - (void)showBookmarks
109 {
110     /* show the window, called from intf.m */
111     [o_bookmarks_window displayIfNeeded];
112     [o_bookmarks_window makeKeyAndOrderFront:nil];
113 }
114
115 - (IBAction)add:(id)sender
116 {
117     /* add item to list */
118     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
119
120     if( !p_input ) return;
121  
122     seekpoint_t bookmark;
123
124     if( !input_Control( p_input, INPUT_GET_BOOKMARK, &bookmark ) )
125         {
126                 bookmark.psz_name = _("Untitled");
127                 input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
128         }
129  
130     vlc_object_release( p_input );
131  
132     [o_tbl_dataTable reloadData];
133 }
134
135 - (IBAction)clear:(id)sender
136 {
137     /* clear table */
138     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
139  
140     if( !p_input )
141         return;
142
143     input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
144
145     vlc_object_release( p_input );
146  
147     [o_tbl_dataTable reloadData];
148 }
149
150 - (IBAction)edit:(id)sender
151 {
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
154      * really trust it */
155     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
156     seekpoint_t **pp_bookmarks;
157     int i_bookmarks;
158     int row;
159     row = [o_tbl_dataTable selectedRow];
160  
161     if( !p_input )
162     {
163         return;
164     }
165     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
166         &i_bookmarks ) != VLC_SUCCESS )
167     {
168         vlc_object_release( p_input );
169         return;
170     }
171     else if(row < 0)
172     {
173         vlc_object_release( p_input );
174         return;
175     } else {
176         [o_edit_fld_name setStringValue: [NSString stringWithUTF8String:
177             pp_bookmarks[row]->psz_name]];
178         [o_edit_fld_time setStringValue: [[NSNumber numberWithInt:
179             (pp_bookmarks[row]->i_time_offset / 1000000)] stringValue]];
180         [o_edit_fld_bytes setStringValue: [[NSNumber numberWithInt:
181             pp_bookmarks[row]->i_byte_offset] stringValue]];
182     }
183  
184     /* Just keep the pointer value to check if it
185      * changes. Note, we don't need to keep a reference to the object.
186      * so release it now. */
187     p_old_input = p_input;
188     vlc_object_release( p_input );
189
190     [NSApp beginSheet: o_edit_window
191         modalForWindow: o_bookmarks_window
192         modalDelegate: o_edit_window
193         didEndSelector: nil
194         contextInfo: nil];
195 }
196
197 - (IBAction)edit_cancel:(id)sender
198 {
199     /* close sheet */
200     [NSApp endSheet:o_edit_window];
201     [o_edit_window close];
202 }
203
204 - (IBAction)edit_ok:(id)sender
205 {
206     /* save field contents and close sheet */
207      seekpoint_t **pp_bookmarks;
208     int i_bookmarks, i;
209     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
210  
211     if( !p_input )
212     {
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."));
217         return;
218     }
219     if( p_old_input != p_input )
220     {
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 "
225             "input."));
226         vlc_object_release( p_input );
227         return;
228     }
229  
230     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
231         &i_bookmarks ) != VLC_SUCCESS )
232     {
233         vlc_object_release( p_input );
234         return;
235     }
236
237     i = [o_tbl_dataTable selectedRow];
238  
239     free( pp_bookmarks[i]->psz_name );
240
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);
244  
245     if( input_Control( p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i )
246         != VLC_SUCCESS )
247     {
248         msg_Warn( VLCIntf, "Unable to change the bookmark");
249         vlc_object_release( p_input );
250         return;
251     }
252  
253     [o_tbl_dataTable reloadData];
254     vlc_object_release( p_input );
255  
256  
257     [NSApp endSheet: o_edit_window];
258     [o_edit_window close];
259 }
260
261 - (IBAction)extract:(id)sender
262 {
263     /* extract */
264     if( [o_tbl_dataTable numberOfSelectedRows] < 2 )
265     {
266         NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"),
267             @"", @"", o_bookmarks_window, nil, nil, nil, nil,
268             _NS("Two bookmarks have to be selected."));
269         return;
270     }
271     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
272     if( !p_input )
273     {
274         NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"),
275             @"", @"", o_bookmarks_window, nil, nil, nil, nil,
276             _NS("The stream must be playing or paused for bookmarks to work."));
277         return;
278     }
279  
280     seekpoint_t **pp_bookmarks;
281     int i_bookmarks ;
282     int i_first = -1;
283     int i_second = -1;
284     int x = 0;
285     int c = 0;
286     while (c != 2)
287     {
288         if([o_tbl_dataTable isRowSelected:x])
289         {
290             if (i_first == -1)
291             {
292                 i_first = x;
293                 c = 1;
294             }
295             else if (i_second == -1)
296             {
297                 i_second = x;
298                 c = 2;
299             }
300         }
301         x = (x + 1);
302     }
303  
304     msg_Dbg( VLCIntf, "got the bookmark-indexes");
305  
306     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
307         &i_bookmarks ) != VLC_SUCCESS )
308     {
309         vlc_object_release( p_input );
310         msg_Err( VLCIntf, "already defined bookmarks couldn't be retrieved");
311         return;
312     }
313     msg_Dbg( VLCIntf, "calling wizard");
314
315     char *psz_uri = input_item_GetURI( input_GetItem( p_input ) );
316     [[[VLCMain sharedInstance] getWizard] initWithExtractValuesFrom:
317             [[NSNumber numberWithInt:
318             (pp_bookmarks[i_first]->i_time_offset/1000000)] stringValue]
319             to: [[NSNumber numberWithInt:
320             (pp_bookmarks[i_second]->i_time_offset/1000000)] stringValue]
321             ofItem: [NSString stringWithUTF8String: psz_uri]];
322     free( psz_uri );
323     vlc_object_release( p_input );
324     msg_Dbg( VLCIntf, "released input");
325 }
326
327 - (IBAction)goToBookmark:(id)sender
328 {
329     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
330  
331     if( !p_input ) return;
332
333     input_Control( p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow] );
334
335     vlc_object_release( p_input );
336 }
337
338 - (IBAction)remove:(id)sender
339 {
340     /* remove selected item */
341     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
342  
343     if( !p_input ) return;
344
345     int i_focused = [o_tbl_dataTable selectedRow];
346
347     if( i_focused >= 0 )
348         input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
349
350     vlc_object_release( p_input );
351  
352     [o_tbl_dataTable reloadData];
353 }
354
355 /*****************************************************************************
356  * callback stuff
357  *****************************************************************************/
358
359 -(id)getDataTable
360 {
361     return o_tbl_dataTable;
362 }
363
364 /*****************************************************************************
365  * data source methods
366  *****************************************************************************/
367
368 - (int)numberOfRowsInTableView:(NSTableView *)theDataTable
369 {
370     /* return the number of bookmarks */
371     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
372     seekpoint_t **pp_bookmarks;
373     int i_bookmarks;
374  
375     if( !p_input ) return 0;
376     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
377                        &i_bookmarks ) != VLC_SUCCESS )
378     {
379         vlc_object_release( p_input );
380         return 0;
381     }
382     else {
383         vlc_object_release( p_input );
384         return i_bookmarks;
385     }
386 }
387
388 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn:
389     (NSTableColumn *)theTableColumn row: (int)row
390 {
391     /* return the corresponding data as NSString */
392     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
393     seekpoint_t **pp_bookmarks;
394     int i_bookmarks;
395     char *toBeReturned;
396     int i_toBeReturned = 0;
397     id ret;
398
399     if( !p_input ) return @"";
400     else if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
401                        &i_bookmarks ) != VLC_SUCCESS )
402     {
403         ret = @"";
404     }
405     else
406     {
407         if ([[theTableColumn identifier] isEqualToString: @"description"])
408         {
409             toBeReturned = pp_bookmarks[row]->psz_name;
410             ret = [NSString stringWithUTF8String: toBeReturned];
411         }
412         else if ([[theTableColumn identifier] isEqualToString: @"size_offset"])
413         {
414             i_toBeReturned = pp_bookmarks[row]->i_byte_offset;
415             ret = [[NSNumber numberWithInt: i_toBeReturned] stringValue];
416         }
417         else if ([[theTableColumn identifier] isEqualToString: @"time_offset"])
418         {
419             i_toBeReturned = pp_bookmarks[row]->i_time_offset;
420             ret = [[NSNumber numberWithInt: (i_toBeReturned / 1000000)]
421                 stringValue];
422         }
423         else
424         {
425             /* may not happen, just in case */
426             msg_Err( VLCIntf, "unknown table column identifier (%s) while "
427                 "updating the bookmark table", [[theTableColumn identifier]
428                 UTF8String] );
429             ret = @"unknown identifier";
430         }
431     }
432     vlc_object_release( p_input );
433     return ret;
434 }
435
436 /*****************************************************************************
437  * delegate methods
438  *****************************************************************************/
439
440 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
441 {
442     /* check whether a row is selected and en-/disable the edit/remove buttons */
443     if ([o_tbl_dataTable selectedRow] == -1)
444     {
445         /* no row is selected */
446         [o_btn_edit setEnabled: NO];
447         [o_btn_rm setEnabled: NO];
448         [o_btn_extract setEnabled: NO];
449     }
450     else
451     {
452         /* a row is selected */
453         [o_btn_edit setEnabled: YES];
454         [o_btn_rm setEnabled: YES];
455         if ([o_tbl_dataTable numberOfSelectedRows] == 2)
456         {
457             [o_btn_extract setEnabled: YES];
458         }
459     }
460 }
461
462 @end