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