]> git.sesse.net Git - vlc/blob - modules/gui/macosx/bookmarks.m
macosx/CAS: simplify stream-out summary to something useful
[vlc] / modules / gui / macosx / bookmarks.m
1 /*****************************************************************************
2  * bookmarks.m: MacOS X Bookmarks window
3  *****************************************************************************
4  * Copyright (C) 2005 - 2012 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Felix Paul 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 @interface VLCBookmarks (Internal)
43 - (void)initStrings;
44 @end
45
46 @implementation VLCBookmarks
47
48 static VLCBookmarks *_o_sharedInstance = nil;
49
50 + (VLCBookmarks *)sharedInstance
51 {
52     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
53 }
54
55 - (id)init
56 {
57     if (_o_sharedInstance)
58         [self dealloc];
59     else
60         _o_sharedInstance = [super init];
61
62     return _o_sharedInstance;
63 }
64
65 /*****************************************************************************
66  * GUI methods
67  *****************************************************************************/
68
69 - (void)awakeFromNib
70 {
71     if (!OSX_SNOW_LEOPARD)
72         [o_bookmarks_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
73
74     [self initStrings];
75 }
76
77 - (void)dealloc
78 {
79     if (p_old_input)
80         vlc_object_release(p_old_input);
81
82     [super dealloc];
83 }
84
85 - (void)initStrings
86 {
87     /* localise the items */
88
89     /* main window */
90     [o_bookmarks_window setTitle: _NS("Bookmarks")];
91     [o_btn_add setTitle: _NS("Add")];
92     [o_btn_clear setTitle: _NS("Clear")];
93     [o_btn_edit setTitle: _NS("Edit")];
94     [o_btn_extract setTitle: _NS("Extract")];
95     [o_btn_rm setTitle: _NS("Remove")];
96     [[[o_tbl_dataTable tableColumnWithIdentifier:@"description"] headerCell]
97         setStringValue: _NS("Description")];
98     [[[o_tbl_dataTable tableColumnWithIdentifier:@"size_offset"] headerCell]
99         setStringValue: _NS("Position")];
100     [[[o_tbl_dataTable tableColumnWithIdentifier:@"time_offset"] headerCell]
101         setStringValue: _NS("Time")];
102
103     /* edit window */
104     [o_edit_btn_ok setTitle: _NS("OK")];
105     [o_edit_btn_cancel setTitle: _NS("Cancel")];
106     [o_edit_lbl_name setStringValue: _NS("Name")];
107     [o_edit_lbl_time setStringValue: _NS("Time")];
108     [o_edit_lbl_bytes setStringValue: _NS("Position")];
109 }
110
111 - (void)showBookmarks
112 {
113     /* show the window, called from intf.m */
114     [o_bookmarks_window displayIfNeeded];
115     [o_bookmarks_window makeKeyAndOrderFront:nil];
116 }
117
118 - (IBAction)add:(id)sender
119 {
120     /* add item to list */
121     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
122
123     if (!p_input)
124         return;
125
126     seekpoint_t bookmark;
127
128     if (!input_Control(p_input, INPUT_GET_BOOKMARK, &bookmark)) {
129         bookmark.psz_name = _("Untitled");
130         input_Control(p_input, INPUT_ADD_BOOKMARK, &bookmark);
131     }
132
133     vlc_object_release(p_input);
134
135     [o_tbl_dataTable reloadData];
136 }
137
138 - (IBAction)clear:(id)sender
139 {
140     /* clear table */
141     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
142
143     if (!p_input)
144         return;
145
146     input_Control(p_input, INPUT_CLEAR_BOOKMARKS);
147
148     vlc_object_release(p_input);
149
150     [o_tbl_dataTable reloadData];
151 }
152
153 - (IBAction)edit:(id)sender
154 {
155     /* put values to the sheet's fields and show sheet */
156     /* we take the values from the core and not the table, because we cannot
157      * really trust it */
158     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
159     seekpoint_t **pp_bookmarks;
160     int i_bookmarks;
161     int row;
162     row = [o_tbl_dataTable selectedRow];
163
164     if (!p_input)
165         return;
166
167     if (row < 0) {
168         vlc_object_release(p_input);
169         return;
170     }
171
172     if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
173         vlc_object_release(p_input);
174         return;
175     }
176
177     [o_edit_fld_name setStringValue: [NSString stringWithFormat:@"%s", pp_bookmarks[row]->psz_name]];
178     int total = pp_bookmarks[row]->i_time_offset/ 1000000;
179     int hour = total / (60*60);
180     int min = (total - hour*60*60) / 60;
181     int sec = total - hour*60*60 - min*60;
182     [o_edit_fld_time setStringValue: [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min, sec]];
183     [o_edit_fld_bytes setStringValue: [NSString stringWithFormat:@"%lli", pp_bookmarks[row]->i_byte_offset]];
184
185     /* Just keep the pointer value to check if it
186      * changes. Note, we don't need to keep a reference to the object.
187      * so release it now. */
188     p_old_input = p_input;
189     vlc_object_release(p_input);
190
191     [NSApp beginSheet: o_edit_window modalForWindow: o_bookmarks_window modalDelegate: o_edit_window didEndSelector: nil contextInfo: nil];
192
193     // Clear the bookmark list
194     for (int i = 0; i < i_bookmarks; i++)
195         vlc_seekpoint_Delete(pp_bookmarks[i]);
196     free(pp_bookmarks);
197 }
198
199 - (IBAction)edit_cancel:(id)sender
200 {
201     /* close sheet */
202     [NSApp endSheet:o_edit_window];
203     [o_edit_window close];
204 }
205
206 - (IBAction)edit_ok:(id)sender
207 {
208     /* save field contents and close sheet */
209      seekpoint_t **pp_bookmarks;
210     int i_bookmarks, i;
211     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
212
213     if (!p_input) {
214         NSBeginCriticalAlertSheet(_NS("No input"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("No input found. A stream must be playing or paused for bookmarks to work."));
215         return;
216     }
217     if (p_old_input != p_input) {
218         NSBeginCriticalAlertSheet(_NS("Input has changed"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("Input has changed, unable to save bookmark. Suspending playback with \"Pause\" while editing bookmarks to ensure to keep the same input."));
219         vlc_object_release(p_input);
220         return;
221     }
222
223     if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
224         vlc_object_release(p_input);
225         return;
226     }
227
228     i = [o_tbl_dataTable selectedRow];
229
230     free(pp_bookmarks[i]->psz_name);
231
232     pp_bookmarks[i]->psz_name = strdup([[o_edit_fld_name stringValue] UTF8String]);
233     pp_bookmarks[i]->i_byte_offset = [[o_edit_fld_bytes stringValue] intValue];
234
235     NSArray * components = [[o_edit_fld_time stringValue] componentsSeparatedByString:@":"];
236     NSUInteger componentCount = [components count];
237     if (componentCount == 1)
238         pp_bookmarks[i]->i_time_offset = 1000000 * ([[components objectAtIndex:0] intValue]);
239     else if (componentCount == 2)
240         pp_bookmarks[i]->i_time_offset = 1000000 * ([[components objectAtIndex:0] intValue] * 60 + [[components objectAtIndex:1] intValue]);
241     else if (componentCount == 3)
242         pp_bookmarks[i]->i_time_offset = 1000000 * ([[components objectAtIndex:0] intValue] * 3600 + [[components objectAtIndex:1] intValue] * 60 + [[components objectAtIndex:2] intValue]);
243     else {
244         msg_Err(VLCIntf, "Invalid string format for time");
245         goto clear;
246     }
247
248     if (input_Control(p_input, INPUT_CHANGE_BOOKMARK, pp_bookmarks[i], i) != VLC_SUCCESS) {
249         msg_Warn(VLCIntf, "Unable to change the bookmark");
250         goto clear;
251     }
252
253     [o_tbl_dataTable reloadData];
254     vlc_object_release(p_input);
255
256     [NSApp endSheet: o_edit_window];
257     [o_edit_window close];
258
259 clear:
260     // Clear the bookmark list
261     for (int i = 0; i < i_bookmarks; i++)
262         vlc_seekpoint_Delete(pp_bookmarks[i]);
263     free(pp_bookmarks);
264 }
265
266 - (IBAction)extract:(id)sender
267 {
268     if ([o_tbl_dataTable numberOfSelectedRows] < 2) {
269         NSBeginAlertSheet(_NS("Invalid selection"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("Two bookmarks have to be selected."));
270         return;
271     }
272     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
273     if (!p_input) {
274         NSBeginCriticalAlertSheet(_NS("No input found"), _NS("OK"), @"", @"", o_bookmarks_window, nil, nil, nil, nil, @"%@",_NS("The stream must be playing or paused for bookmarks to work."));
275         return;
276     }
277
278     seekpoint_t **pp_bookmarks;
279     int i_bookmarks ;
280     int i_first = -1;
281     int i_second = -1;
282     int c = 0;
283     for (NSUInteger x = 0; c != 2; x++) {
284         if ([o_tbl_dataTable isRowSelected:x]) {
285             if (i_first == -1) {
286                 i_first = x;
287                 c = 1;
288             } else if (i_second == -1) {
289                 i_second = x;
290                 c = 2;
291             }
292         }
293     }
294
295     if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
296         vlc_object_release(p_input);
297         msg_Err(VLCIntf, "already defined bookmarks couldn't be retrieved");
298         return;
299     }
300
301     char *psz_uri = input_item_GetURI(input_GetItem(p_input));
302     [[[VLCMain sharedInstance] wizard] initWithExtractValuesFrom: [NSString stringWithFormat:@"%lli", pp_bookmarks[i_first]->i_time_offset/1000000] to: [NSString stringWithFormat:@"%lli", pp_bookmarks[i_second]->i_time_offset/1000000] ofItem: [NSString stringWithFormat:@"%s", psz_uri]];
303     free(psz_uri);
304     vlc_object_release(p_input);
305
306     // Clear the bookmark list
307     for (int i = 0; i < i_bookmarks; i++)
308         vlc_seekpoint_Delete(pp_bookmarks[i]);
309     free(pp_bookmarks);
310 }
311
312 - (IBAction)goToBookmark:(id)sender
313 {
314     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
315
316     if (!p_input)
317         return;
318
319     input_Control(p_input, INPUT_SET_BOOKMARK, [o_tbl_dataTable selectedRow]);
320
321     vlc_object_release(p_input);
322 }
323
324 - (IBAction)remove:(id)sender
325 {
326     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
327
328     if (!p_input)
329         return;
330
331     int i_focused = [o_tbl_dataTable selectedRow];
332
333     if (i_focused >= 0)
334         input_Control(p_input, INPUT_DEL_BOOKMARK, i_focused);
335
336     vlc_object_release(p_input);
337
338     [o_tbl_dataTable reloadData];
339 }
340
341 /*****************************************************************************
342  * callback stuff
343  *****************************************************************************/
344
345 -(id)dataTable
346 {
347     return o_tbl_dataTable;
348 }
349
350 /*****************************************************************************
351  * data source methods
352  *****************************************************************************/
353
354 - (NSInteger)numberOfRowsInTableView:(NSTableView *)theDataTable
355 {
356     /* return the number of bookmarks */
357     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
358     seekpoint_t **pp_bookmarks;
359     int i_bookmarks;
360
361     if (!p_input)
362         return 0;
363     else if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS) {
364         vlc_object_release(p_input);
365         return 0;
366     } else {
367         vlc_object_release(p_input);
368         // Clear the bookmark list
369         for (int i = 0; i < i_bookmarks; i++)
370             vlc_seekpoint_Delete(pp_bookmarks[i]);
371         free(pp_bookmarks);
372         return i_bookmarks;
373     }
374 }
375
376 - (id)tableView:(NSTableView *)theDataTable objectValueForTableColumn: (NSTableColumn *)theTableColumn row: (NSInteger)row
377 {
378     /* return the corresponding data as NSString */
379     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
380     seekpoint_t **pp_bookmarks;
381     int i_bookmarks;
382     id ret;
383
384     if (!p_input)
385         return @"";
386     else if (input_Control(p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks, &i_bookmarks) != VLC_SUCCESS)
387         ret = @"";
388     else {
389         NSString * identifier = [theTableColumn identifier];
390         if ([identifier isEqualToString: @"description"])
391             ret = [NSString stringWithFormat:@"%s", pp_bookmarks[row]->psz_name];
392         else if ([identifier isEqualToString: @"size_offset"])
393             ret = [NSString stringWithFormat:@"%lli", pp_bookmarks[row]->i_byte_offset];
394         else if ([identifier isEqualToString: @"time_offset"]) {
395             int total = pp_bookmarks[row]->i_time_offset/ 1000000;
396             int hour = total / (60*60);
397             int min = (total - hour*60*60) / 60;
398             int sec = total - hour*60*60 - min*60;
399             ret = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min, sec];
400         }
401
402         // Clear the bookmark list
403         for (int i = 0; i < i_bookmarks; i++)
404             vlc_seekpoint_Delete(pp_bookmarks[i]);
405         free(pp_bookmarks);
406     }
407     vlc_object_release(p_input);
408     return ret;
409 }
410
411 /*****************************************************************************
412  * delegate methods
413  *****************************************************************************/
414
415 - (void)tableViewSelectionDidChange:(NSNotification *)aNotification
416 {
417     /* check whether a row is selected and en-/disable the edit/remove buttons */
418     if ([o_tbl_dataTable selectedRow] == -1) {
419         /* no row is selected */
420         [o_btn_edit setEnabled: NO];
421         [o_btn_rm setEnabled: NO];
422         [o_btn_extract setEnabled: NO];
423     } else {
424         /* a row is selected */
425         [o_btn_edit setEnabled: YES];
426         [o_btn_rm setEnabled: YES];
427         if ([o_tbl_dataTable numberOfSelectedRows] == 2)
428             [o_btn_extract setEnabled: YES];
429     }
430 }
431
432 @end