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