1/***************************************************************************** 2 *MainMenu.m: MacOS X interface module 3 ***************************************************************************** 4 *Copyright (C) 2011-2018 Felix Paul Kühne 5 *$Id: 736dd27b492cc7dc5f11bb393a2f8c5445a7d4c7 $ 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#import "VLCMainMenu.h" 25#import "VLCMain.h" 26 27#import <vlc_common.h> 28#import <vlc_playlist.h> 29#import <vlc_input.h> 30 31#import "VLCAboutWindowController.h" 32#import "VLCOpenWindowController.h" 33#import "VLCAudioEffectsWindowController.h" 34#import "VLCErrorWindowController.h" 35#import "VLCTrackSynchronizationWindowController.h" 36#import "VLCHelpWindowController.h" 37#import "VLCVideoEffectsWindowController.h" 38#import "VLCBookmarksWindowController.h" 39#import "VLCSimplePrefsController.h" 40#import "VLCPlaylist.h" 41#import "VLCPlaylistInfo.h" 42#import "VLCVoutView.h" 43#import "VLCCoreDialogProvider.h" 44#import "VLCCoreInteraction.h" 45#import "VLCMainWindow.h" 46#import "VLCMainWindowControlsBar.h" 47#import "VLCExtensionsManager.h" 48#import "VLCConvertAndSaveWindowController.h" 49#import "VLCLogWindowController.h" 50#import "VLCAddonsWindowController.h" 51#import "VLCTimeSelectionPanelController.h" 52#import "NSScreen+VLCAdditions.h" 53#import "VLCRendererMenuController.h" 54 55#ifdef HAVE_SPARKLE 56#import <Sparkle/Sparkle.h> 57#endif 58 59@interface VLCMainMenu() <NSMenuDelegate> 60{ 61 VLCAboutWindowController *_aboutWindowController; 62 VLCHelpWindowController *_helpWindowController; 63 VLCAddonsWindowController *_addonsController; 64 VLCRendererMenuController *_rendererMenuController; 65 NSTimer *_cancelRendererDiscoveryTimer; 66 67 NSMenu *_playlistTableColumnsContextMenu; 68 69 __strong VLCTimeSelectionPanelController *_timeSelectionPanel; 70} 71@end 72 73@implementation VLCMainMenu 74 75#pragma mark - Initialization 76 77- (void)dealloc 78{ 79 msg_Dbg(getIntf(), "Deinitializing main menu"); 80 [[NSNotificationCenter defaultCenter] removeObserver: self]; 81 82 [self releaseRepresentedObjects:[NSApp mainMenu]]; 83} 84 85- (void)awakeFromNib 86{ 87 _timeSelectionPanel = [[VLCTimeSelectionPanelController alloc] init]; 88 89 /* check whether the user runs OSX with a RTL language */ 90 NSArray* languages = [NSLocale preferredLanguages]; 91 NSString* preferredLanguage = [languages firstObject]; 92 93 if ([NSLocale characterDirectionForLanguage:preferredLanguage] == NSLocaleLanguageDirectionRightToLeft) { 94 msg_Dbg(getIntf(), "adapting interface since '%s' is a RTL language", [preferredLanguage UTF8String]); 95 [_rateTextField setAlignment: NSLeftTextAlignment]; 96 } 97 98 [self setRateControlsEnabled:NO]; 99 100#ifdef HAVE_SPARKLE 101 [_checkForUpdate setAction:@selector(checkForUpdates:)]; 102 [_checkForUpdate setTarget:[SUUpdater sharedUpdater]]; 103#else 104 [_checkForUpdate setEnabled:NO]; 105#endif 106 107 NSString* keyString; 108 vlc_value_t val; 109 VLCStringUtility *stringUtility = [VLCStringUtility sharedInstance]; 110 char *key; 111 112 /* Get ExtensionsManager */ 113 intf_thread_t *p_intf = getIntf(); 114 115 [self initStrings]; 116 117 key = config_GetPsz(p_intf, "key-quit"); 118 keyString = [NSString stringWithFormat:@"%s", key]; 119 [_quit setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 120 [_quit setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 121 FREENULL(key); 122 123 // do not assign play/pause key 124 125 key = config_GetPsz(p_intf, "key-stop"); 126 keyString = [NSString stringWithFormat:@"%s", key]; 127 [_stop setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 128 [_stop setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 129 FREENULL(key); 130 131 key = config_GetPsz(p_intf, "key-prev"); 132 keyString = [NSString stringWithFormat:@"%s", key]; 133 [_previous setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 134 [_previous setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 135 FREENULL(key); 136 137 key = config_GetPsz(p_intf, "key-next"); 138 keyString = [NSString stringWithFormat:@"%s", key]; 139 [_next setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 140 [_next setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 141 FREENULL(key); 142 143 key = config_GetPsz(p_intf, "key-jump+short"); 144 keyString = [NSString stringWithFormat:@"%s", key]; 145 [_fwd setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 146 [_fwd setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 147 FREENULL(key); 148 149 key = config_GetPsz(p_intf, "key-jump-short"); 150 keyString = [NSString stringWithFormat:@"%s", key]; 151 [_bwd setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 152 [_bwd setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 153 FREENULL(key); 154 155 key = config_GetPsz(p_intf, "key-vol-up"); 156 keyString = [NSString stringWithFormat:@"%s", key]; 157 [_vol_up setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 158 [_vol_up setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 159 FREENULL(key); 160 161 key = config_GetPsz(p_intf, "key-vol-down"); 162 keyString = [NSString stringWithFormat:@"%s", key]; 163 [_vol_down setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 164 [_vol_down setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 165 FREENULL(key); 166 167 key = config_GetPsz(p_intf, "key-vol-mute"); 168 keyString = [NSString stringWithFormat:@"%s", key]; 169 [_mute setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 170 [_mute setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 171 FREENULL(key); 172 173 key = config_GetPsz(p_intf, "key-toggle-fullscreen"); 174 keyString = [NSString stringWithFormat:@"%s", key]; 175 [_fullscreenItem setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 176 [_fullscreenItem setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 177 FREENULL(key); 178 179 key = config_GetPsz(p_intf, "key-snapshot"); 180 keyString = [NSString stringWithFormat:@"%s", key]; 181 [_snapshot setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 182 [_snapshot setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 183 FREENULL(key); 184 185 key = config_GetPsz(p_intf, "key-random"); 186 keyString = [NSString stringWithFormat:@"%s", key]; 187 [_random setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 188 [_random setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 189 FREENULL(key); 190 191 key = config_GetPsz(p_intf, "key-zoom-half"); 192 keyString = [NSString stringWithFormat:@"%s", key]; 193 [_half_window setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 194 [_half_window setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 195 FREENULL(key); 196 197 key = config_GetPsz(p_intf, "key-zoom-original"); 198 keyString = [NSString stringWithFormat:@"%s", key]; 199 [_normal_window setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 200 [_normal_window setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 201 FREENULL(key); 202 203 key = config_GetPsz(p_intf, "key-zoom-double"); 204 keyString = [NSString stringWithFormat:@"%s", key]; 205 [_double_window setKeyEquivalent: [stringUtility VLCKeyToString: keyString]]; 206 [_double_window setKeyEquivalentModifierMask: [stringUtility VLCModifiersToCocoa:keyString]]; 207 FREENULL(key); 208 209 [self setSubmenusEnabled: FALSE]; 210 211 /* configure playback / controls menu */ 212 self.controlsMenu.delegate = self; 213 [_rendererNoneItem setState:NSOnState]; 214 _rendererMenuController = [[VLCRendererMenuController alloc] init]; 215 _rendererMenuController.rendererNoneItem = _rendererNoneItem; 216 _rendererMenuController.rendererMenu = _rendererMenu; 217 218 [[NSNotificationCenter defaultCenter] addObserver: self 219 selector: @selector(refreshVoutDeviceMenu:) 220 name: NSApplicationDidChangeScreenParametersNotification 221 object: nil]; 222 223 [self setupVarMenuItem:_add_intf target: (vlc_object_t *)p_intf 224 var:"intf-add" selector: @selector(toggleVar:)]; 225 226 /* setup extensions menu */ 227 /* Let the ExtensionsManager itself build the menu */ 228 VLCExtensionsManager *extMgr = [[VLCMain sharedInstance] extensionsManager]; 229 [extMgr buildMenu:_extensionsMenu]; 230 [_extensions setEnabled: ([_extensionsMenu numberOfItems] > 0)]; 231 232 // FIXME: Implement preference for autoloading extensions on mac 233 if (![extMgr isLoaded] && ![extMgr cannotLoad]) 234 [extMgr loadExtensions]; 235 236 /* setup post-proc menu */ 237 NSUInteger count = (NSUInteger) [_postprocessingMenu numberOfItems]; 238 if (count > 0) 239 [_postprocessingMenu removeAllItems]; 240 241 NSMenuItem *mitem; 242 [_postprocessingMenu setAutoenablesItems: YES]; 243 [_postprocessingMenu addItemWithTitle: _NS("Disable") action:@selector(togglePostProcessing:) keyEquivalent:@""]; 244 mitem = [_postprocessingMenu itemAtIndex: 0]; 245 [mitem setTag: -1]; 246 [mitem setEnabled: YES]; 247 [mitem setTarget: self]; 248 for (NSUInteger x = 1; x < 7; x++) { 249 [_postprocessingMenu addItemWithTitle:[NSString stringWithFormat:_NS("Level %i"), x] 250 action:@selector(togglePostProcessing:) 251 keyEquivalent:@""]; 252 mitem = [_postprocessingMenu itemAtIndex:x]; 253 [mitem setEnabled:YES]; 254 [mitem setTag:x]; 255 [mitem setTarget:self]; 256 } 257 char *psz_config = config_GetPsz(p_intf, "video-filter"); 258 if (psz_config) { 259 if (!strstr(psz_config, "postproc")) 260 [[_postprocessingMenu itemAtIndex:0] setState:NSOnState]; 261 else 262 [[_postprocessingMenu itemWithTag:config_GetInt(p_intf, "postproc-q")] setState:NSOnState]; 263 free(psz_config); 264 } else 265 [[_postprocessingMenu itemAtIndex:0] setState:NSOnState]; 266 [_postprocessing setEnabled: NO]; 267 268 [self refreshAudioDeviceList]; 269 270 /* setup subtitles menu */ 271 // Persist those variables on the playlist 272 playlist_t *p_playlist = pl_Get(getIntf()); 273 var_Create(p_playlist, "freetype-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); 274 var_Create(p_playlist, "freetype-background-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); 275 var_Create(p_playlist, "freetype-background-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); 276 var_Create(p_playlist, "freetype-outline-thickness", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); 277 278 [self setupMenu: _subtitle_textcolorMenu withIntList:"freetype-color" andSelector:@selector(switchSubtitleOption:)]; 279 [_subtitle_bgopacity_sld setIntValue: config_GetInt(VLC_OBJECT(p_intf), "freetype-background-opacity")]; 280 [self setupMenu: _subtitle_bgcolorMenu withIntList:"freetype-background-color" andSelector:@selector(switchSubtitleOption:)]; 281 [self setupMenu: _subtitle_outlinethicknessMenu withIntList:"freetype-outline-thickness" andSelector:@selector(switchSubtitleOption:)]; 282 283 /* Build size menu based on different scale factors */ 284 struct { 285 const char *const name; 286 int scaleValue; 287 } scaleValues[] = { 288 { N_("Smaller"), 50}, 289 { N_("Small"), 75}, 290 { N_("Normal"), 100}, 291 { N_("Large"), 125}, 292 { N_("Larger"), 150}, 293 { NULL, 0 } 294 }; 295 296 for(int i = 0; scaleValues[i].name; i++) { 297 NSMenuItem *menuItem = [_subtitle_sizeMenu addItemWithTitle: _NS(scaleValues[i].name) action:@selector(switchSubtitleSize:) keyEquivalent:@""]; 298 [menuItem setTag:scaleValues[i].scaleValue]; 299 [menuItem setTarget: self]; 300 } 301} 302 303- (void)setupMenu: (NSMenu*)menu withIntList: (char *)psz_name andSelector:(SEL)selector 304{ 305 module_config_t *p_item; 306 307 [menu removeAllItems]; 308 p_item = config_FindConfig(psz_name); 309 310 if (!p_item) { 311 msg_Err(getIntf(), "couldn't create menu int list for item '%s' as it does not exist", psz_name); 312 return; 313 } 314 315 for (int i = 0; i < p_item->list_count; i++) { 316 NSMenuItem *mi; 317 if (p_item->list_text != NULL) 318 mi = [[NSMenuItem alloc] initWithTitle: _NS(p_item->list_text[i]) action:NULL keyEquivalent: @""]; 319 else if (p_item->list.i[i]) 320 mi = [[NSMenuItem alloc] initWithTitle: [NSString stringWithFormat: @"%d", p_item->list.i[i]] action:NULL keyEquivalent: @""]; 321 else { 322 msg_Err(getIntf(), "item %d of pref %s failed to be created", i, psz_name); 323 continue; 324 } 325 326 [mi setTarget:self]; 327 [mi setAction:selector]; 328 [mi setTag:p_item->list.i[i]]; 329 [mi setRepresentedObject:toNSStr(psz_name)]; 330 [menu addItem:mi]; 331 if (p_item->value.i == p_item->list.i[i]) 332 [mi setState:NSOnState]; 333 } 334} 335 336- (void)initStrings 337{ 338 /* main menu */ 339 [_about setTitle: [_NS("About VLC media player") \ 340 stringByAppendingString: @"..."]]; 341 [_checkForUpdate setTitle: _NS("Check for Update...")]; 342 [_prefs setTitle: _NS("Preferences...")]; 343 [_extensions setTitle: _NS("Extensions")]; 344 [_extensionsMenu setTitle: _NS("Extensions")]; 345 [_addonManager setTitle: _NS("Addons Manager")]; 346 [_add_intf setTitle: _NS("Add Interface")]; 347 [_add_intfMenu setTitle: _NS("Add Interface")]; 348 [_services setTitle: _NS("Services")]; 349 [_hide setTitle: _NS("Hide VLC")]; 350 [_hide_others setTitle: _NS("Hide Others")]; 351 [_show_all setTitle: _NS("Show All")]; 352 [_quit setTitle: _NS("Quit VLC")]; 353 354 [_fileMenu setTitle: _ANS("1:File")]; 355 [_open_generic setTitle: _NS("Advanced Open File...")]; 356 [_open_file setTitle: _NS("Open File...")]; 357 [_open_disc setTitle: _NS("Open Disc...")]; 358 [_open_net setTitle: _NS("Open Network...")]; 359 [_open_capture setTitle: _NS("Open Capture Device...")]; 360 [_open_recent setTitle: _NS("Open Recent")]; 361 [_close_window setTitle: _NS("Close Window")]; 362 [_convertandsave setTitle: _NS("Convert / Stream...")]; 363 [_save_playlist setTitle: _NS("Save Playlist...")]; 364 [_revealInFinder setTitle: _NS("Reveal in Finder")]; 365 366 [_editMenu setTitle: _NS("Edit")]; 367 [_cutItem setTitle: _NS("Cut")]; 368 [_mcopyItem setTitle: _NS("Copy")]; 369 [_pasteItem setTitle: _NS("Paste")]; 370 [_clearItem setTitle: _NS("Delete")]; 371 [_select_all setTitle: _NS("Select All")]; 372 [_findItem setTitle: _NS("Find")]; 373 374 [_viewMenu setTitle: _NS("View")]; 375 [_toggleJumpButtons setTitle: _NS("Show Previous & Next Buttons")]; 376 [_toggleJumpButtons setState: var_InheritBool(getIntf(), "macosx-show-playback-buttons")]; 377 [_togglePlaymodeButtons setTitle: _NS("Show Shuffle & Repeat Buttons")]; 378 [_togglePlaymodeButtons setState: var_InheritBool(getIntf(), "macosx-show-playmode-buttons")]; 379 [_toggleEffectsButton setTitle: _NS("Show Audio Effects Button")]; 380 [_toggleEffectsButton setState: var_InheritBool(getIntf(), "macosx-show-effects-button")]; 381 [_toggleSidebar setTitle: _NS("Show Sidebar")]; 382 [_playlistTableColumns setTitle: _NS("Playlist Table Columns")]; 383 384 [_controlsMenu setTitle: _NS("Playback")]; 385 [_play setTitle: _NS("Play")]; 386 [_stop setTitle: _NS("Stop")]; 387 [_record setTitle: _NS("Record")]; 388 [_rate_view setAutoresizingMask:NSViewWidthSizable]; 389 [_rate setView: _rate_view]; 390 [_rateLabel setStringValue: _NS("Playback Speed")]; 391 [_rate_slowerLabel setStringValue: _NS("Slower")]; 392 [_rate_normalLabel setStringValue: _NS("Normal")]; 393 [_rate_fasterLabel setStringValue: _NS("Faster")]; 394 [_trackSynchronization setTitle: _NS("Track Synchronization")]; 395 [_previous setTitle: _NS("Previous")]; 396 [_next setTitle: _NS("Next")]; 397 [_random setTitle: _NS("Random")]; 398 [_repeat setTitle: _NS("Repeat One")]; 399 [_loop setTitle: _NS("Repeat All")]; 400 [_AtoBloop setTitle: _NS("A→B Loop")]; 401 [_quitAfterPB setTitle: _NS("Quit after Playback")]; 402 [_fwd setTitle: _NS("Step Forward")]; 403 [_bwd setTitle: _NS("Step Backward")]; 404 [_jumpToTime setTitle: _NS("Jump to Time")]; 405 [_rendererMenuItem setTitle:_NS("Renderer")]; 406 [_rendererNoneItem setTitle:_NS("No renderer")]; 407 [_program setTitle: _NS("Program")]; 408 [_programMenu setTitle: _NS("Program")]; 409 [_title setTitle: _NS("Title")]; 410 [_titleMenu setTitle: _NS("Title")]; 411 [_chapter setTitle: _NS("Chapter")]; 412 [_chapterMenu setTitle: _NS("Chapter")]; 413 414 [_audioMenu setTitle: _NS("Audio")]; 415 [_vol_up setTitle: _NS("Increase Volume")]; 416 [_vol_down setTitle: _NS("Decrease Volume")]; 417 [_mute setTitle: _NS("Mute")]; 418 [_audiotrack setTitle: _NS("Audio Track")]; 419 [_audiotrackMenu setTitle: _NS("Audio Track")]; 420 [_channels setTitle: _NS("Stereo audio mode")]; 421 [_channelsMenu setTitle: _NS("Stereo audio mode")]; 422 [_audioDevice setTitle: _NS("Audio Device")]; 423 [_audioDeviceMenu setTitle: _NS("Audio Device")]; 424 [_visual setTitle: _NS("Visualizations")]; 425 [_visualMenu setTitle: _NS("Visualizations")]; 426 427 [_videoMenu setTitle: _NS("Video")]; 428 [_half_window setTitle: _NS("Half Size")]; 429 [_normal_window setTitle: _NS("Normal Size")]; 430 [_double_window setTitle: _NS("Double Size")]; 431 [_fittoscreen setTitle: _NS("Fit to Screen")]; 432 [_fullscreenItem setTitle: _NS("Fullscreen")]; 433 [_floatontop setTitle: _NS("Float on Top")]; 434 [_snapshot setTitle: _NS("Snapshot")]; 435 [_videotrack setTitle: _NS("Video Track")]; 436 [_videotrackMenu setTitle: _NS("Video Track")]; 437 [_aspect_ratio setTitle: _NS("Aspect ratio")]; 438 [_aspect_ratioMenu setTitle: _NS("Aspect ratio")]; 439 [_crop setTitle: _NS("Crop")]; 440 [_cropMenu setTitle: _NS("Crop")]; 441 [_screen setTitle: _NS("Fullscreen Video Device")]; 442 [_screenMenu setTitle: _NS("Fullscreen Video Device")]; 443 [_deinterlace setTitle: _NS("Deinterlace")]; 444 [_deinterlaceMenu setTitle: _NS("Deinterlace")]; 445 [_deinterlace_mode setTitle: _NS("Deinterlace mode")]; 446 [_deinterlace_modeMenu setTitle: _NS("Deinterlace mode")]; 447 [_postprocessing setTitle: _NS("Post processing")]; 448 [_postprocessingMenu setTitle: _NS("Post processing")]; 449 450 [_subtitlesMenu setTitle:_NS("Subtitles")]; 451 [_openSubtitleFile setTitle: _NS("Add Subtitle File...")]; 452 [_subtitle_track setTitle: _NS("Subtitles Track")]; 453 [_subtitle_tracksMenu setTitle: _NS("Subtitles Track")]; 454 [_subtitle_size setTitle: _NS("Text Size")]; 455 [_subtitle_textcolor setTitle: _NS("Text Color")]; 456 [_subtitle_outlinethickness setTitle: _NS("Outline Thickness")]; 457 458 // Autoresizing with constraints does not work on 10.7, 459 // translate autoresizing mask to constriaints for now 460 [_subtitle_bgopacity_view setAutoresizingMask:NSViewWidthSizable]; 461 [_subtitle_bgopacity setView: _subtitle_bgopacity_view]; 462 [_subtitle_bgopacityLabel setStringValue: _NS("Background Opacity")]; 463 [_subtitle_bgopacityLabel_gray setStringValue: _NS("Background Opacity")]; 464 [_subtitle_bgcolor setTitle: _NS("Background Color")]; 465 [_teletext setTitle: _NS("Teletext")]; 466 [_teletext_transparent setTitle: _NS("Transparent")]; 467 [_teletext_index setTitle: _NS("Index")]; 468 [_teletext_red setTitle: _NS("Red")]; 469 [_teletext_green setTitle: _NS("Green")]; 470 [_teletext_yellow setTitle: _NS("Yellow")]; 471 [_teletext_blue setTitle: _NS("Blue")]; 472 473 [_windowMenu setTitle: _NS("Window")]; 474 [_minimize setTitle: _NS("Minimize")]; 475 [_zoom_window setTitle: _NS("Zoom")]; 476 [_player setTitle: _NS("Player...")]; 477 [_controller setTitle: _NS("Main Window...")]; 478 [_audioeffects setTitle: _NS("Audio Effects...")]; 479 [_videoeffects setTitle: _NS("Video Effects...")]; 480 [_bookmarks setTitle: _NS("Bookmarks...")]; 481 [_playlist setTitle: _NS("Playlist...")]; 482 [_info setTitle: _NS("Media Information...")]; 483 [_messages setTitle: _NS("Messages...")]; 484 [_errorsAndWarnings setTitle: _NS("Errors and Warnings...")]; 485 486 [_bring_atf setTitle: _NS("Bring All to Front")]; 487 488 [_helpMenu setTitle: _NS("Help")]; 489 [_help setTitle: _NS("VLC media player Help...")]; 490 [_license setTitle: _NS("License")]; 491 [_documentation setTitle: _NS("Online Documentation...")]; 492 [_website setTitle: _NS("VideoLAN Website...")]; 493 [_donation setTitle: _NS("Make a donation...")]; 494 [_forum setTitle: _NS("Online Forum...")]; 495 496 /* dock menu */ 497 [_dockMenuplay setTitle: _NS("Play")]; 498 [_dockMenustop setTitle: _NS("Stop")]; 499 [_dockMenunext setTitle: _NS("Next")]; 500 [_dockMenuprevious setTitle: _NS("Previous")]; 501 [_dockMenumute setTitle: _NS("Mute")]; 502 503 /* vout menu */ 504 [_voutMenuplay setTitle: _NS("Play")]; 505 [_voutMenustop setTitle: _NS("Stop")]; 506 [_voutMenuprev setTitle: _NS("Previous")]; 507 [_voutMenunext setTitle: _NS("Next")]; 508 [_voutMenuvolup setTitle: _NS("Volume Up")]; 509 [_voutMenuvoldown setTitle: _NS("Volume Down")]; 510 [_voutMenumute setTitle: _NS("Mute")]; 511 [_voutMenufullscreen setTitle: _NS("Fullscreen")]; 512 [_voutMenusnapshot setTitle: _NS("Snapshot")]; 513} 514 515#pragma mark - Termination 516 517- (void)releaseRepresentedObjects:(NSMenu *)the_menu 518{ 519 NSArray *menuitems_array = [the_menu itemArray]; 520 NSUInteger menuItemCount = [menuitems_array count]; 521 for (NSUInteger i=0; i < menuItemCount; i++) { 522 NSMenuItem *one_item = [menuitems_array objectAtIndex:i]; 523 if ([one_item hasSubmenu]) 524 [self releaseRepresentedObjects: [one_item submenu]]; 525 526 [one_item setRepresentedObject:NULL]; 527 } 528} 529 530#pragma mark - Interface update 531 532- (void)setupMenus 533{ 534 playlist_t *p_playlist = pl_Get(getIntf()); 535 input_thread_t *p_input = playlist_CurrentInput(p_playlist); 536 if (p_input != NULL) { 537 [self setupVarMenuItem:_program target: (vlc_object_t *)p_input 538 var:"program" selector: @selector(toggleVar:)]; 539 540 [self setupVarMenuItem:_title target: (vlc_object_t *)p_input 541 var:"title" selector: @selector(toggleVar:)]; 542 543 [self setupVarMenuItem:_chapter target: (vlc_object_t *)p_input 544 var:"chapter" selector: @selector(toggleVar:)]; 545 546 [self setupVarMenuItem:_audiotrack target: (vlc_object_t *)p_input 547 var:"audio-es" selector: @selector(toggleVar:)]; 548 549 [self setupVarMenuItem:_videotrack target: (vlc_object_t *)p_input 550 var:"video-es" selector: @selector(toggleVar:)]; 551 552 [self setupVarMenuItem:_subtitle_track target: (vlc_object_t *)p_input 553 var:"spu-es" selector: @selector(toggleVar:)]; 554 555 audio_output_t *p_aout = playlist_GetAout(p_playlist); 556 if (p_aout != NULL) { 557 [self setupVarMenuItem:_channels target: (vlc_object_t *)p_aout 558 var:"stereo-mode" selector: @selector(toggleVar:)]; 559 560 [self setupVarMenuItem:_visual target: (vlc_object_t *)p_aout 561 var:"visual" selector: @selector(toggleVar:)]; 562 vlc_object_release(p_aout); 563 } 564 565 vout_thread_t *p_vout = getVoutForActiveWindow(); 566 567 if (p_vout != NULL) { 568 [self setupVarMenuItem:_aspect_ratio target: (vlc_object_t *)p_vout 569 var:"aspect-ratio" selector: @selector(toggleVar:)]; 570 571 [self setupVarMenuItem:_crop target: (vlc_object_t *) p_vout 572 var:"crop" selector: @selector(toggleVar:)]; 573 574 [self setupVarMenuItem:_deinterlace target: (vlc_object_t *)p_vout 575 var:"deinterlace" selector: @selector(toggleVar:)]; 576 577 [self setupVarMenuItem:_deinterlace_mode target: (vlc_object_t *)p_vout 578 var:"deinterlace-mode" selector: @selector(toggleVar:)]; 579 580 vlc_object_release(p_vout); 581 582 [self refreshVoutDeviceMenu:nil]; 583 } 584 [_postprocessing setEnabled:YES]; 585 vlc_object_release(p_input); 586 } else { 587 [_postprocessing setEnabled:NO]; 588 } 589} 590 591- (void)refreshVoutDeviceMenu:(NSNotification *)notification 592{ 593 NSUInteger count = (NSUInteger) [_screenMenu numberOfItems]; 594 NSMenu *submenu = _screenMenu; 595 if (count > 0) 596 [submenu removeAllItems]; 597 598 NSArray *screens = [NSScreen screens]; 599 NSMenuItem *mitem; 600 count = [screens count]; 601 [_screen setEnabled: YES]; 602 [submenu addItemWithTitle: _NS("Default") action:@selector(toggleFullscreenDevice:) keyEquivalent:@""]; 603 mitem = [submenu itemAtIndex: 0]; 604 [mitem setTag: 0]; 605 [mitem setEnabled: YES]; 606 [mitem setTarget: self]; 607 NSRect s_rect; 608 for (NSUInteger i = 0; i < count; i++) { 609 s_rect = [[screens objectAtIndex:i] frame]; 610 [submenu addItemWithTitle: [NSString stringWithFormat: @"%@ %li (%ix%i)", _NS("Screen"), i+1, 611 (int)s_rect.size.width, (int)s_rect.size.height] action:@selector(toggleFullscreenDevice:) keyEquivalent:@""]; 612 mitem = [submenu itemAtIndex:i+1]; 613 [mitem setTag: (int)[[screens objectAtIndex:i] displayID]]; 614 [mitem setEnabled: YES]; 615 [mitem setTarget: self]; 616 } 617 [[submenu itemWithTag: var_InheritInteger(getIntf(), "macosx-vdev")] setState: NSOnState]; 618} 619 620- (void)setSubmenusEnabled:(BOOL)b_enabled 621{ 622 [_program setEnabled: b_enabled]; 623 [_title setEnabled: b_enabled]; 624 [_chapter setEnabled: b_enabled]; 625 [_audiotrack setEnabled: b_enabled]; 626 [_visual setEnabled: b_enabled]; 627 [_videotrack setEnabled: b_enabled]; 628 [_subtitle_track setEnabled: b_enabled]; 629 [_channels setEnabled: b_enabled]; 630 [_deinterlace setEnabled: b_enabled]; 631 [_deinterlace_mode setEnabled: b_enabled]; 632 [_screen setEnabled: b_enabled]; 633 [_aspect_ratio setEnabled: b_enabled]; 634 [_crop setEnabled: b_enabled]; 635} 636 637- (void)setSubtitleMenuEnabled:(BOOL)b_enabled 638{ 639 [_openSubtitleFile setEnabled: b_enabled]; 640 if (b_enabled) { 641 [_subtitle_bgopacityLabel_gray setHidden: YES]; 642 [_subtitle_bgopacityLabel setHidden: NO]; 643 } else { 644 [_subtitle_bgopacityLabel_gray setHidden: NO]; 645 [_subtitle_bgopacityLabel setHidden: YES]; 646 } 647 [_subtitle_bgopacity_sld setEnabled: b_enabled]; 648 [_teletext setEnabled: b_enabled]; 649} 650 651- (void)setRateControlsEnabled:(BOOL)b_enabled 652{ 653 [_rate_sld setEnabled: b_enabled]; 654 [_rate_sld setIntValue: [[VLCCoreInteraction sharedInstance] playbackRate]]; 655 int i = [[VLCCoreInteraction sharedInstance] playbackRate]; 656 double speed = pow(2, (double)i / 17); 657 [_rateTextField setStringValue: [NSString stringWithFormat:@"%.2fx", speed]]; 658 659 NSColor *color = b_enabled ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]; 660 661 [_rateLabel setTextColor:color]; 662 [_rate_slowerLabel setTextColor:color]; 663 [_rate_normalLabel setTextColor:color]; 664 [_rate_fasterLabel setTextColor:color]; 665 [_rateTextField setTextColor:color]; 666 667 [self setSubtitleMenuEnabled: b_enabled]; 668} 669 670#pragma mark - View 671 672- (IBAction)toggleEffectsButton:(id)sender 673{ 674 BOOL b_value = !var_InheritBool(getIntf(), "macosx-show-effects-button"); 675 config_PutInt(getIntf(), "macosx-show-effects-button", b_value); 676 [(VLCMainWindowControlsBar *)[[[VLCMain sharedInstance] mainWindow] controlsBar] setupEffectsButton:YES]; 677 [_toggleEffectsButton setState: b_value]; 678} 679 680- (IBAction)toggleJumpButtons:(id)sender 681{ 682 BOOL b_value = !var_InheritBool(getIntf(), "macosx-show-playback-buttons"); 683 config_PutInt(getIntf(), "macosx-show-playback-buttons", b_value); 684 685 [(VLCMainWindowControlsBar *)[[[VLCMain sharedInstance] mainWindow] controlsBar] setupJumpButtons:YES]; 686 [[[VLCMain sharedInstance] voutController] updateWindowsUsingBlock:^(VLCVideoWindowCommon *window) { 687 [[window controlsBar] toggleForwardBackwardMode: b_value]; 688 }]; 689 690 [_toggleJumpButtons setState: b_value]; 691} 692 693- (IBAction)togglePlaymodeButtons:(id)sender 694{ 695 BOOL b_value = !var_InheritBool(getIntf(), "macosx-show-playmode-buttons"); 696 config_PutInt(getIntf(), "macosx-show-playmode-buttons", b_value); 697 [(VLCMainWindowControlsBar *)[[[VLCMain sharedInstance] mainWindow] controlsBar] setupPlaymodeButtons:YES]; 698 [_togglePlaymodeButtons setState: b_value]; 699} 700 701- (IBAction)toggleSidebar:(id)sender 702{ 703 [[[VLCMain sharedInstance] mainWindow] toggleLeftSubSplitView]; 704} 705 706- (void)updateSidebarMenuItem:(BOOL)show; 707{ 708 [_toggleSidebar setState:show]; 709} 710 711#pragma mark - Playback 712 713- (IBAction)play:(id)sender 714{ 715 [[VLCCoreInteraction sharedInstance] playOrPause]; 716} 717 718- (IBAction)stop:(id)sender 719{ 720 [[VLCCoreInteraction sharedInstance] stop]; 721} 722 723- (IBAction)prev:(id)sender 724{ 725 [[VLCCoreInteraction sharedInstance] previous]; 726} 727 728- (IBAction)next:(id)sender 729{ 730 [[VLCCoreInteraction sharedInstance] next]; 731} 732 733- (IBAction)random:(id)sender 734{ 735 [[VLCCoreInteraction sharedInstance] shuffle]; 736} 737 738- (IBAction)repeat:(id)sender 739{ 740 vlc_value_t val; 741 intf_thread_t *p_intf = getIntf(); 742 playlist_t *p_playlist = pl_Get(p_intf); 743 744 var_Get(p_playlist, "repeat", &val); 745 if (! val.b_bool) 746 [[VLCCoreInteraction sharedInstance] repeatOne]; 747 else 748 [[VLCCoreInteraction sharedInstance] repeatOff]; 749} 750 751- (IBAction)loop:(id)sender 752{ 753 vlc_value_t val; 754 intf_thread_t *p_intf = getIntf(); 755 playlist_t *p_playlist = pl_Get(p_intf); 756 757 var_Get(p_playlist, "loop", &val); 758 if (! val.b_bool) 759 [[VLCCoreInteraction sharedInstance] repeatAll]; 760 else 761 [[VLCCoreInteraction sharedInstance] repeatOff]; 762} 763 764- (IBAction)forward:(id)sender 765{ 766 [[VLCCoreInteraction sharedInstance] forward]; 767} 768 769- (IBAction)backward:(id)sender 770{ 771 [[VLCCoreInteraction sharedInstance] backward]; 772} 773 774- (IBAction)volumeUp:(id)sender 775{ 776 [[VLCCoreInteraction sharedInstance] volumeUp]; 777} 778 779- (IBAction)volumeDown:(id)sender 780{ 781 [[VLCCoreInteraction sharedInstance] volumeDown]; 782} 783 784- (IBAction)mute:(id)sender 785{ 786 [[VLCCoreInteraction sharedInstance] toggleMute]; 787} 788 789- (void)lockVideosAspectRatio:(id)sender 790{ 791 [[VLCCoreInteraction sharedInstance] setAspectRatioIsLocked: ![sender state]]; 792 [sender setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]]; 793} 794 795- (IBAction)quitAfterPlayback:(id)sender 796{ 797 playlist_t *p_playlist = pl_Get(getIntf()); 798 bool b_value = !var_CreateGetBool(p_playlist, "play-and-exit"); 799 var_SetBool(p_playlist, "play-and-exit", b_value); 800 config_PutInt(getIntf(), "play-and-exit", b_value); 801} 802 803- (IBAction)toggleRecord:(id)sender 804{ 805 [[VLCCoreInteraction sharedInstance] toggleRecord]; 806} 807 808- (void)updateRecordState:(BOOL)b_value 809{ 810 [_record setState:b_value]; 811} 812 813- (IBAction)setPlaybackRate:(id)sender 814{ 815 [[VLCCoreInteraction sharedInstance] setPlaybackRate: [_rate_sld intValue]]; 816 int i = [[VLCCoreInteraction sharedInstance] playbackRate]; 817 double speed = pow(2, (double)i / 17); 818 [_rateTextField setStringValue: [NSString stringWithFormat:@"%.2fx", speed]]; 819} 820 821- (void)updatePlaybackRate 822{ 823 int i = [[VLCCoreInteraction sharedInstance] playbackRate]; 824 double speed = pow(2, (double)i / 17); 825 [_rateTextField setStringValue: [NSString stringWithFormat:@"%.2fx", speed]]; 826 [_rate_sld setIntValue: i]; 827} 828 829- (IBAction)toggleAtoBloop:(id)sender 830{ 831 [[VLCCoreInteraction sharedInstance] setAtoB]; 832} 833 834- (IBAction)goToSpecificTime:(id)sender 835{ 836 input_thread_t *p_input = pl_CurrentInput(getIntf()); 837 if (p_input) { 838 /* we can obviously only do that if an input is available */ 839 int64_t length = var_GetInteger(p_input, "length"); 840 [_timeSelectionPanel setMaxValue:(length / CLOCK_FREQ)]; 841 int64_t pos = var_GetInteger(p_input, "time"); 842 [_timeSelectionPanel setJumpTimeValue: (pos / CLOCK_FREQ)]; 843 [_timeSelectionPanel runModalForWindow:[NSApp mainWindow] 844 completionHandler:^(NSInteger returnCode, int64_t returnTime) { 845 846 if (returnCode != NSOKButton) 847 return; 848 849 input_thread_t *p_input = pl_CurrentInput(getIntf()); 850 if (p_input) { 851 input_Control(p_input, INPUT_SET_TIME, (int64_t)(returnTime *1000000)); 852 vlc_object_release(p_input); 853 } 854 }]; 855 856 vlc_object_release(p_input); 857 } 858} 859 860- (IBAction)selectRenderer:(id)sender 861{ 862 [_rendererMenuController selectRenderer:sender]; 863} 864 865#pragma mark - audio menu 866 867- (void)refreshAudioDeviceList 868{ 869 char **ids, **names; 870 char *currentDevice; 871 872 [_audioDeviceMenu removeAllItems]; 873 874 audio_output_t *p_aout = getAout(); 875 if (!p_aout) 876 return; 877 878 int n = aout_DevicesList(p_aout, &ids, &names); 879 if (n == -1) { 880 vlc_object_release(p_aout); 881 return; 882 } 883 884 currentDevice = aout_DeviceGet(p_aout); 885 NSMenuItem *_tmp; 886 887 for (NSUInteger x = 0; x < n; x++) { 888 _tmp = [_audioDeviceMenu addItemWithTitle:toNSStr(names[x]) action:@selector(toggleAudioDevice:) keyEquivalent:@""]; 889 [_tmp setTarget:self]; 890 [_tmp setTag:[[NSString stringWithFormat:@"%s", ids[x]] intValue]]; 891 } 892 vlc_object_release(p_aout); 893 894 [[_audioDeviceMenu itemWithTag:[[NSString stringWithFormat:@"%s", currentDevice] intValue]] setState:NSOnState]; 895 896 free(currentDevice); 897 898 for (NSUInteger x = 0; x < n; x++) { 899 free(ids[x]); 900 free(names[x]); 901 } 902 free(ids); 903 free(names); 904 905 [_audioDeviceMenu setAutoenablesItems:YES]; 906 [_audioDevice setEnabled:YES]; 907} 908 909- (void)toggleAudioDevice:(id)sender 910{ 911 audio_output_t *p_aout = getAout(); 912 if (!p_aout) 913 return; 914 915 int returnValue = 0; 916 917 if ([sender tag] > 0) 918 returnValue = aout_DeviceSet(p_aout, [[NSString stringWithFormat:@"%li", [sender tag]] UTF8String]); 919 else 920 returnValue = aout_DeviceSet(p_aout, NULL); 921 922 if (returnValue != 0) 923 msg_Warn(getIntf(), "failed to set audio device %li", [sender tag]); 924 925 vlc_object_release(p_aout); 926 [self refreshAudioDeviceList]; 927} 928 929#pragma mark - video menu 930 931- (IBAction)toggleFullscreen:(id)sender 932{ 933 [[VLCCoreInteraction sharedInstance] toggleFullscreen]; 934} 935 936- (IBAction)resizeVideoWindow:(id)sender 937{ 938 input_thread_t *p_input = pl_CurrentInput(getIntf()); 939 if (p_input) { 940 vout_thread_t *p_vout = getVoutForActiveWindow(); 941 if (p_vout) { 942 if (sender == _half_window) 943 var_SetFloat(p_vout, "zoom", 0.5); 944 else if (sender == _normal_window) 945 var_SetFloat(p_vout, "zoom", 1.0); 946 else if (sender == _double_window) 947 var_SetFloat(p_vout, "zoom", 2.0); 948 else 949 { 950 [[NSApp keyWindow] performZoom:sender]; 951 } 952 vlc_object_release(p_vout); 953 } 954 vlc_object_release(p_input); 955 } 956} 957 958- (IBAction)floatOnTop:(id)sender 959{ 960 input_thread_t *p_input = pl_CurrentInput(getIntf()); 961 if (p_input) { 962 vout_thread_t *p_vout = getVoutForActiveWindow(); 963 if (p_vout) { 964 BOOL b_fs = var_ToggleBool(p_vout, "video-on-top"); 965 var_SetBool(pl_Get(getIntf()), "video-on-top", b_fs); 966 967 vlc_object_release(p_vout); 968 } 969 vlc_object_release(p_input); 970 } 971} 972 973- (IBAction)createVideoSnapshot:(id)sender 974{ 975 input_thread_t *p_input = pl_CurrentInput(getIntf()); 976 if (p_input) { 977 vout_thread_t *p_vout = getVoutForActiveWindow(); 978 if (p_vout) { 979 var_TriggerCallback(p_vout, "video-snapshot"); 980 vlc_object_release(p_vout); 981 } 982 vlc_object_release(p_input); 983 } 984} 985 986- (void)_disablePostProcessing 987{ 988 [[VLCCoreInteraction sharedInstance] setVideoFilter:"postproc" on:false]; 989} 990 991- (void)_enablePostProcessing 992{ 993 [[VLCCoreInteraction sharedInstance] setVideoFilter:"postproc" on:true]; 994} 995 996- (void)togglePostProcessing:(id)sender 997{ 998 char *psz_name = "postproc"; 999 NSInteger count = [_postprocessingMenu numberOfItems]; 1000 for (NSUInteger x = 0; x < count; x++) 1001 [[_postprocessingMenu itemAtIndex:x] setState:NSOffState]; 1002 1003 if ([sender tag] == -1) { 1004 [self _disablePostProcessing]; 1005 [sender setState:NSOnState]; 1006 } else { 1007 [self _enablePostProcessing]; 1008 [sender setState:NSOnState]; 1009 1010 [[VLCCoreInteraction sharedInstance] setVideoFilterProperty:"postproc-q" forFilter:"postproc" withValue:(vlc_value_t){ .i_int = [sender tag] }]; 1011 } 1012} 1013 1014- (void)toggleFullscreenDevice:(id)sender 1015{ 1016 config_PutInt(getIntf(), "macosx-vdev", [sender tag]); 1017 [self refreshVoutDeviceMenu: nil]; 1018} 1019 1020#pragma mark - Subtitles Menu 1021 1022- (IBAction)addSubtitleFile:(id)sender 1023{ 1024 NSInteger i_returnValue = 0; 1025 input_thread_t *p_input = pl_CurrentInput(getIntf()); 1026 if (!p_input) 1027 return; 1028 1029 input_item_t *p_item = input_GetItem(p_input); 1030 if (!p_item) { 1031 vlc_object_release(p_input); 1032 return; 1033 } 1034 1035 char *path = input_item_GetURI(p_item); 1036 1037 if (!path) 1038 path = strdup(""); 1039 1040 NSOpenPanel *openPanel = [NSOpenPanel openPanel]; 1041 [openPanel setCanChooseFiles: YES]; 1042 [openPanel setCanChooseDirectories: NO]; 1043 [openPanel setAllowsMultipleSelection: YES]; 1044 1045 [openPanel setAllowedFileTypes: [NSArray arrayWithObjects:@"cdg",@"idx",@"srt",@"sub",@"utf",@"ass",@"ssa",@"aqt",@"jss",@"psb",@"rt",@"smi",@"txt",@"smil",@"stl",@"usf",@"dks",@"pjs",@"mpl2",@"mks",@"vtt",@"ttml",@"dfxp",nil]]; 1046 1047 NSURL *url = [NSURL URLWithString:[toNSStr(path) stringByExpandingTildeInPath]]; 1048 url = [url URLByDeletingLastPathComponent]; 1049 [openPanel setDirectoryURL: url]; 1050 free(path); 1051 vlc_object_release(p_input); 1052 1053 i_returnValue = [openPanel runModal]; 1054 1055 if (i_returnValue == NSOKButton) 1056 [[VLCCoreInteraction sharedInstance] addSubtitlesToCurrentInput:[openPanel URLs]]; 1057} 1058 1059- (void)switchSubtitleSize:(id)sender 1060{ 1061 int intValue = [sender tag]; 1062 var_SetInteger(pl_Get(getIntf()), "sub-text-scale", intValue); 1063} 1064 1065 1066- (void)switchSubtitleOption:(id)sender 1067{ 1068 int intValue = [sender tag]; 1069 NSString *representedObject = [sender representedObject]; 1070 1071 var_SetInteger(pl_Get(getIntf()), [representedObject UTF8String], intValue); 1072 1073 NSMenu *menu = [sender menu]; 1074 NSUInteger count = (NSUInteger) [menu numberOfItems]; 1075 for (NSUInteger x = 0; x < count; x++) 1076 [[menu itemAtIndex:x] setState:NSOffState]; 1077 [[menu itemWithTag:intValue] setState:NSOnState]; 1078} 1079 1080- (IBAction)switchSubtitleBackgroundOpacity:(id)sender 1081{ 1082 var_SetInteger(pl_Get(getIntf()), "freetype-background-opacity", [sender intValue]); 1083} 1084 1085- (IBAction)telxTransparent:(id)sender 1086{ 1087 vlc_object_t *p_vbi; 1088 p_vbi = (vlc_object_t *) vlc_object_find_name(pl_Get(getIntf()), "zvbi"); 1089 if (p_vbi) { 1090 var_SetBool(p_vbi, "vbi-opaque", [sender state]); 1091 [sender setState: ![sender state]]; 1092 vlc_object_release(p_vbi); 1093 } 1094} 1095 1096- (IBAction)telxNavLink:(id)sender 1097{ 1098 vlc_object_t *p_vbi; 1099 int i_page = 0; 1100 1101 if ([[sender title] isEqualToString: _NS("Index")]) 1102 i_page = 'i' << 16; 1103 else if ([[sender title] isEqualToString: _NS("Red")]) 1104 i_page = 'r' << 16; 1105 else if ([[sender title] isEqualToString: _NS("Green")]) 1106 i_page = 'g' << 16; 1107 else if ([[sender title] isEqualToString: _NS("Yellow")]) 1108 i_page = 'y' << 16; 1109 else if ([[sender title] isEqualToString: _NS("Blue")]) 1110 i_page = 'b' << 16; 1111 if (i_page == 0) return; 1112 1113 p_vbi = (vlc_object_t *) vlc_object_find_name(pl_Get(getIntf()), "zvbi"); 1114 if (p_vbi) { 1115 var_SetInteger(p_vbi, "vbi-page", i_page); 1116 vlc_object_release(p_vbi); 1117 } 1118} 1119 1120#pragma mark - Panels 1121 1122- (IBAction)intfOpenFile:(id)sender 1123{ 1124 [[[VLCMain sharedInstance] open] openFileWithAction:^(NSArray *files) { 1125 [[[VLCMain sharedInstance] playlist] addPlaylistItems:files]; 1126 }]; 1127} 1128 1129- (IBAction)intfOpenFileGeneric:(id)sender 1130{ 1131 [[[VLCMain sharedInstance] open] openFileGeneric]; 1132} 1133 1134- (IBAction)intfOpenDisc:(id)sender 1135{ 1136 [[[VLCMain sharedInstance] open] openDisc]; 1137} 1138 1139- (IBAction)intfOpenNet:(id)sender 1140{ 1141 [[[VLCMain sharedInstance] open] openNet]; 1142} 1143 1144- (IBAction)intfOpenCapture:(id)sender 1145{ 1146 [[[VLCMain sharedInstance] open] openCapture]; 1147} 1148 1149- (IBAction)savePlaylist:(id)sender 1150{ 1151 playlist_t *p_playlist = pl_Get(getIntf()); 1152 1153 NSSavePanel *savePanel = [NSSavePanel savePanel]; 1154 NSString * name = [NSString stringWithFormat: @"%@", _NS("Untitled")]; 1155 1156 [NSBundle loadNibNamed:@"PlaylistAccessoryView" owner:self]; 1157 1158 [_playlistSaveAccessoryText setStringValue: _NS("File Format:")]; 1159 [[_playlistSaveAccessoryPopup itemAtIndex:0] setTitle: _NS("Extended M3U")]; 1160 [[_playlistSaveAccessoryPopup itemAtIndex:1] setTitle: _NS("XML Shareable Playlist Format (XSPF)")]; 1161 [[_playlistSaveAccessoryPopup itemAtIndex:2] setTitle: _NS("HTML playlist")]; 1162 1163 [savePanel setTitle: _NS("Save Playlist")]; 1164 [savePanel setPrompt: _NS("Save")]; 1165 [savePanel setAccessoryView: _playlistSaveAccessoryView]; 1166 [savePanel setNameFieldStringValue: name]; 1167 1168 if ([savePanel runModal] == NSFileHandlingPanelOKButton) { 1169 NSString *filename = [[savePanel URL] path]; 1170 1171 if ([_playlistSaveAccessoryPopup indexOfSelectedItem] == 0) { 1172 NSString *actualFilename; 1173 NSRange range; 1174 range.location = [filename length] - [@".m3u" length]; 1175 range.length = [@".m3u" length]; 1176 1177 if ([filename compare:@".m3u" options: NSCaseInsensitiveSearch range: range] != NSOrderedSame) 1178 actualFilename = [NSString stringWithFormat: @"%@.m3u", filename]; 1179 else 1180 actualFilename = filename; 1181 1182 playlist_Export(p_playlist, 1183 [actualFilename fileSystemRepresentation], 1184 true, "export-m3u"); 1185 } else if ([_playlistSaveAccessoryPopup indexOfSelectedItem] == 1) { 1186 NSString *actualFilename; 1187 NSRange range; 1188 range.location = [filename length] - [@".xspf" length]; 1189 range.length = [@".xspf" length]; 1190 1191 if ([filename compare:@".xspf" options: NSCaseInsensitiveSearch range: range] != NSOrderedSame) 1192 actualFilename = [NSString stringWithFormat: @"%@.xspf", filename]; 1193 else 1194 actualFilename = filename; 1195 1196 playlist_Export(p_playlist, 1197 [actualFilename fileSystemRepresentation], 1198 true, "export-xspf"); 1199 } else { 1200 NSString *actualFilename; 1201 NSRange range; 1202 range.location = [filename length] - [@".html" length]; 1203 range.length = [@".html" length]; 1204 1205 if ([filename compare:@".html" options: NSCaseInsensitiveSearch range: range] != NSOrderedSame) 1206 actualFilename = [NSString stringWithFormat: @"%@.html", filename]; 1207 else 1208 actualFilename = filename; 1209 1210 playlist_Export(p_playlist, 1211 [actualFilename fileSystemRepresentation], 1212 true, "export-html"); 1213 } 1214 } 1215} 1216 1217- (IBAction)showConvertAndSave:(id)sender 1218{ 1219 [[[VLCMain sharedInstance] convertAndSaveWindow] showWindow:self]; 1220} 1221 1222- (IBAction)showVideoEffects:(id)sender 1223{ 1224 [[[VLCMain sharedInstance] videoEffectsPanel] toggleWindow:sender]; 1225} 1226 1227- (IBAction)showTrackSynchronization:(id)sender 1228{ 1229 [[[VLCMain sharedInstance] trackSyncPanel] toggleWindow:sender]; 1230} 1231 1232- (IBAction)showAudioEffects:(id)sender 1233{ 1234 [[[VLCMain sharedInstance] audioEffectsPanel] toggleWindow:sender]; 1235} 1236 1237- (IBAction)showBookmarks:(id)sender 1238{ 1239 [[[VLCMain sharedInstance] bookmarks] toggleWindow:sender]; 1240} 1241 1242- (IBAction)showPreferences:(id)sender 1243{ 1244 NSInteger i_level = [[[VLCMain sharedInstance] voutController] currentStatusWindowLevel]; 1245 [[[VLCMain sharedInstance] simplePreferences] showSimplePrefsWithLevel:i_level]; 1246} 1247 1248- (IBAction)openAddonManager:(id)sender 1249{ 1250 if (!_addonsController) 1251 _addonsController = [[VLCAddonsWindowController alloc] init]; 1252 1253 [_addonsController showWindow:self]; 1254} 1255 1256- (IBAction)showErrorsAndWarnings:(id)sender 1257{ 1258 [[[[VLCMain sharedInstance] coreDialogProvider] errorPanel] showWindow:self]; 1259} 1260 1261- (IBAction)showMessagesPanel:(id)showMessagesPanel 1262{ 1263 [[[VLCMain sharedInstance] debugMsgPanel] showWindow:self]; 1264} 1265 1266- (IBAction)showMainWindow:(id)sender 1267{ 1268 [[[VLCMain sharedInstance] mainWindow] makeKeyAndOrderFront:sender]; 1269} 1270 1271- (IBAction)showPlaylist:(id)sender 1272{ 1273 [[[VLCMain sharedInstance] mainWindow] changePlaylistState: psUserMenuEvent]; 1274} 1275 1276#pragma mark - Help and Docs 1277 1278- (IBAction)showAbout:(id)sender 1279{ 1280 if (!_aboutWindowController) 1281 _aboutWindowController = [[VLCAboutWindowController alloc] init]; 1282 1283 [_aboutWindowController showAbout]; 1284} 1285 1286- (IBAction)showLicense:(id)sender 1287{ 1288 if (!_aboutWindowController) 1289 _aboutWindowController = [[VLCAboutWindowController alloc] init]; 1290 1291 [_aboutWindowController showGPL]; 1292} 1293 1294- (IBAction)showHelp:(id)sender 1295{ 1296 if (!_helpWindowController) 1297 _helpWindowController = [[VLCHelpWindowController alloc] init]; 1298 1299 [_helpWindowController showHelp]; 1300} 1301 1302- (IBAction)openDocumentation:(id)sender 1303{ 1304 NSURL *url = [NSURL URLWithString: @"https://www.videolan.org/doc/"]; 1305 1306 [[NSWorkspace sharedWorkspace] openURL: url]; 1307} 1308 1309- (IBAction)openWebsite:(id)sender 1310{ 1311 NSURL *url = [NSURL URLWithString: @"https://www.videolan.org/"]; 1312 1313 [[NSWorkspace sharedWorkspace] openURL: url]; 1314} 1315 1316- (IBAction)openForum:(id)sender 1317{ 1318 NSURL *url = [NSURL URLWithString: @"https://forum.videolan.org/"]; 1319 1320 [[NSWorkspace sharedWorkspace] openURL: url]; 1321} 1322 1323- (IBAction)openDonate:(id)sender 1324{ 1325 NSURL *url = [NSURL URLWithString: @"https://www.videolan.org/contribute.html#paypal"]; 1326 1327 [[NSWorkspace sharedWorkspace] openURL: url]; 1328} 1329 1330- (IBAction)showInformationPanel:(id)sender 1331{ 1332 [[[VLCMain sharedInstance] currentMediaInfoPanel] toggleWindow:sender]; 1333} 1334 1335#pragma mark - convinience stuff for other objects 1336 1337- (void)setPlay 1338{ 1339 [_play setTitle: _NS("Play")]; 1340 [_dockMenuplay setTitle: _NS("Play")]; 1341 [_voutMenuplay setTitle: _NS("Play")]; 1342} 1343 1344- (void)setPause 1345{ 1346 [_play setTitle: _NS("Pause")]; 1347 [_dockMenuplay setTitle: _NS("Pause")]; 1348 [_voutMenuplay setTitle: _NS("Pause")]; 1349} 1350 1351- (void)setRepeatOne 1352{ 1353 [_repeat setState: NSOnState]; 1354 [_loop setState: NSOffState]; 1355} 1356 1357- (void)setRepeatAll 1358{ 1359 [_repeat setState: NSOffState]; 1360 [_loop setState: NSOnState]; 1361} 1362 1363- (void)setRepeatOff 1364{ 1365 [_repeat setState: NSOffState]; 1366 [_loop setState: NSOffState]; 1367} 1368 1369- (void)setShuffle 1370{ 1371 bool b_value; 1372 playlist_t *p_playlist = pl_Get(getIntf()); 1373 b_value = var_GetBool(p_playlist, "random"); 1374 1375 [_random setState: b_value]; 1376} 1377 1378#pragma mark - Dynamic menu creation and validation 1379 1380- (void)setupVarMenuItem:(NSMenuItem *)mi 1381 target:(vlc_object_t *)p_object 1382 var:(const char *)psz_variable 1383 selector:(SEL)pf_callback 1384{ 1385 vlc_value_t val, text; 1386 int i_type = var_Type(p_object, psz_variable); 1387 1388 switch(i_type & VLC_VAR_TYPE) { 1389 case VLC_VAR_VOID: 1390 case VLC_VAR_BOOL: 1391 case VLC_VAR_STRING: 1392 case VLC_VAR_INTEGER: 1393 break; 1394 default: 1395 /* Variable doesn't exist or isn't handled */ 1396 msg_Warn(p_object, "variable %s doesn't exist or isn't handled", psz_variable); 1397 return; 1398 } 1399 1400 /* Get the descriptive name of the variable */ 1401 var_Change(p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL); 1402 [mi setTitle: _NS(text.psz_string ? text.psz_string : psz_variable)]; 1403 1404 if (i_type & VLC_VAR_HASCHOICE) { 1405 NSMenu *menu = [mi submenu]; 1406 1407 [self setupVarMenu:menu forMenuItem:mi target:p_object 1408 var:psz_variable selector:pf_callback]; 1409 1410 free(text.psz_string); 1411 return; 1412 } 1413 1414 if (var_Get(p_object, psz_variable, &val) < 0) 1415 return; 1416 1417 VLCAutoGeneratedMenuContent *data; 1418 switch(i_type & VLC_VAR_TYPE) { 1419 case VLC_VAR_VOID: 1420 data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object 1421 andValue: val ofType: i_type]; 1422 [mi setRepresentedObject:data]; 1423 break; 1424 1425 case VLC_VAR_BOOL: 1426 data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object 1427 andValue: val ofType: i_type]; 1428 [mi setRepresentedObject:data]; 1429 if (!(i_type & VLC_VAR_ISCOMMAND)) 1430 [mi setState: val.b_bool ? TRUE : FALSE ]; 1431 break; 1432 1433 default: 1434 break; 1435 } 1436 1437 if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string); 1438 free(text.psz_string); 1439} 1440 1441 1442- (void)setupVarMenu:(NSMenu *)menu 1443 forMenuItem: (NSMenuItem *)parent 1444 target:(vlc_object_t *)p_object 1445 var:(const char *)psz_variable 1446 selector:(SEL)pf_callback 1447{ 1448 vlc_value_t val, val_list, text_list; 1449 int i_type, i; 1450 1451 /* remove previous items */ 1452 [menu removeAllItems]; 1453 1454 /* we disable everything here, and enable it again when needed, below */ 1455 [parent setEnabled:NO]; 1456 1457 /* Aspect Ratio */ 1458 if ([[parent title] isEqualToString: _NS("Aspect ratio")] == YES) { 1459 NSMenuItem *lmi_tmp2; 1460 lmi_tmp2 = [menu addItemWithTitle: _NS("Lock Aspect Ratio") action: @selector(lockVideosAspectRatio:) keyEquivalent: @""]; 1461 [lmi_tmp2 setTarget: self]; 1462 [lmi_tmp2 setEnabled: YES]; 1463 [lmi_tmp2 setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]]; 1464 [parent setEnabled: YES]; 1465 [menu addItem: [NSMenuItem separatorItem]]; 1466 } 1467 1468 /* Check the type of the object variable */ 1469 i_type = var_Type(p_object, psz_variable); 1470 1471 /* Make sure we want to display the variable */ 1472 if (i_type & VLC_VAR_HASCHOICE) { 1473 var_Change(p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL); 1474 if (val.i_int == 0 || val.i_int == 1) 1475 return; 1476 } 1477 else 1478 return; 1479 1480 switch(i_type & VLC_VAR_TYPE) { 1481 case VLC_VAR_VOID: 1482 case VLC_VAR_BOOL: 1483 case VLC_VAR_STRING: 1484 case VLC_VAR_INTEGER: 1485 break; 1486 default: 1487 /* Variable doesn't exist or isn't handled */ 1488 return; 1489 } 1490 1491 if (var_Get(p_object, psz_variable, &val) < 0) { 1492 return; 1493 } 1494 1495 if (var_Change(p_object, psz_variable, VLC_VAR_GETCHOICES, 1496 &val_list, &text_list) < 0) { 1497 if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string); 1498 return; 1499 } 1500 1501 /* make (un)sensitive */ 1502 [parent setEnabled: (val_list.p_list->i_count > 1)]; 1503 1504 for (i = 0; i < val_list.p_list->i_count; i++) { 1505 NSMenuItem *lmi; 1506 NSString *title = @""; 1507 VLCAutoGeneratedMenuContent *data; 1508 1509 switch(i_type & VLC_VAR_TYPE) { 1510 case VLC_VAR_STRING: 1511 1512 title = _NS(text_list.p_list->p_values[i].psz_string ? text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string); 1513 1514 lmi = [menu addItemWithTitle: title action: pf_callback keyEquivalent: @""]; 1515 data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object 1516 andValue: val_list.p_list->p_values[i] ofType: i_type]; 1517 [lmi setRepresentedObject:data]; 1518 [lmi setTarget: self]; 1519 1520 if (!strcmp(val.psz_string, val_list.p_list->p_values[i].psz_string) && !(i_type & VLC_VAR_ISCOMMAND)) 1521 [lmi setState: TRUE ]; 1522 1523 break; 1524 1525 case VLC_VAR_INTEGER: 1526 1527 title = text_list.p_list->p_values[i].psz_string ? 1528 _NS(text_list.p_list->p_values[i].psz_string) : [NSString stringWithFormat: @"%"PRId64, val_list.p_list->p_values[i].i_int]; 1529 1530 lmi = [menu addItemWithTitle: title action: pf_callback keyEquivalent: @""]; 1531 data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object 1532 andValue: val_list.p_list->p_values[i] ofType: i_type]; 1533 [lmi setRepresentedObject:data]; 1534 [lmi setTarget: self]; 1535 1536 if (val_list.p_list->p_values[i].i_int == val.i_int && !(i_type & VLC_VAR_ISCOMMAND)) 1537 [lmi setState: TRUE ]; 1538 break; 1539 1540 default: 1541 break; 1542 } 1543 } 1544 1545 /* clean up everything */ 1546 if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string); 1547 var_FreeList(&val_list, &text_list); 1548} 1549 1550- (void)toggleVar:(id)sender 1551{ 1552 NSMenuItem *mi = (NSMenuItem *)sender; 1553 VLCAutoGeneratedMenuContent *data = [mi representedObject]; 1554 [NSThread detachNewThreadSelector: @selector(toggleVarThread:) 1555 toTarget: self withObject: data]; 1556 1557 return; 1558} 1559 1560- (int)toggleVarThread: (id)data 1561{ 1562 @autoreleasepool { 1563 vlc_object_t *p_object; 1564 1565 assert([data isKindOfClass:[VLCAutoGeneratedMenuContent class]]); 1566 VLCAutoGeneratedMenuContent *menuContent = (VLCAutoGeneratedMenuContent *)data; 1567 1568 p_object = [menuContent vlcObject]; 1569 1570 if (p_object != NULL) { 1571 var_Set(p_object, [menuContent name], [menuContent value]); 1572 vlc_object_release(p_object); 1573 return true; 1574 } 1575 return VLC_EGENERIC; 1576 } 1577} 1578 1579#pragma mark - menu delegation 1580 1581- (void)menuWillOpen:(NSMenu *)menu 1582{ 1583 [_cancelRendererDiscoveryTimer invalidate]; 1584 [_rendererMenuController startRendererDiscoveries]; 1585} 1586 1587- (void)menuDidClose:(NSMenu *)menu 1588{ 1589 _cancelRendererDiscoveryTimer = [NSTimer scheduledTimerWithTimeInterval:20. 1590 target:self 1591 selector:@selector(cancelRendererDiscovery) 1592 userInfo:nil 1593 repeats:NO]; 1594} 1595 1596- (void)cancelRendererDiscovery 1597{ 1598 [_rendererMenuController stopRendererDiscoveries]; 1599} 1600 1601@end 1602 1603@implementation VLCMainMenu (NSMenuValidation) 1604 1605- (BOOL)validateMenuItem:(NSMenuItem *)mi 1606{ 1607 NSString *title = [mi title]; 1608 BOOL enabled = YES; 1609 vlc_value_t val; 1610 playlist_t *p_playlist = pl_Get(getIntf()); 1611 input_thread_t *p_input = playlist_CurrentInput(p_playlist); 1612 1613 if (mi == _stop || mi == _voutMenustop || mi == _dockMenustop) { 1614 if (!p_input) 1615 enabled = NO; 1616 [self setupMenus]; /* Make sure input menu is up to date */ 1617 } else if (mi == _previous || 1618 mi == _voutMenuprev || 1619 mi == _dockMenuprevious || 1620 mi == _next || 1621 mi == _voutMenunext || 1622 mi == _dockMenunext 1623 ) { 1624 PL_LOCK; 1625 enabled = playlist_CurrentSize(p_playlist) > 1; 1626 PL_UNLOCK; 1627 } else if (mi == _record) { 1628 enabled = NO; 1629 if (p_input) 1630 enabled = var_GetBool(p_input, "can-record"); 1631 } else if (mi == _random) { 1632 int i_state; 1633 var_Get(p_playlist, "random", &val); 1634 i_state = val.b_bool ? NSOnState : NSOffState; 1635 [mi setState: i_state]; 1636 } else if (mi == _repeat) { 1637 int i_state; 1638 var_Get(p_playlist, "repeat", &val); 1639 i_state = val.b_bool ? NSOnState : NSOffState; 1640 [mi setState: i_state]; 1641 } else if (mi == _loop) { 1642 int i_state; 1643 var_Get(p_playlist, "loop", &val); 1644 i_state = val.b_bool ? NSOnState : NSOffState; 1645 [mi setState: i_state]; 1646 } else if (mi == _quitAfterPB) { 1647 int i_state; 1648 bool b_value = var_InheritBool(p_playlist, "play-and-exit"); 1649 i_state = b_value ? NSOnState : NSOffState; 1650 [mi setState: i_state]; 1651 } else if (mi == _fwd || mi == _bwd || mi == _jumpToTime) { 1652 if (p_input != NULL) { 1653 var_Get(p_input, "can-seek", &val); 1654 enabled = val.b_bool; 1655 } else { 1656 enabled = NO; 1657 } 1658 } else if (mi == _mute || mi == _dockMenumute || mi == _voutMenumute) { 1659 [mi setState: [[VLCCoreInteraction sharedInstance] mute] ? NSOnState : NSOffState]; 1660 [self setupMenus]; /* Make sure audio menu is up to date */ 1661 [self refreshAudioDeviceList]; 1662 } else if (mi == _half_window || 1663 mi == _normal_window || 1664 mi == _double_window || 1665 mi == _fittoscreen || 1666 mi == _snapshot || 1667 mi == _voutMenusnapshot || 1668 mi == _fullscreenItem || 1669 mi == _voutMenufullscreen || 1670 mi == _floatontop 1671 ) { 1672 enabled = NO; 1673 1674 if (p_input != NULL) { 1675 vout_thread_t *p_vout = getVoutForActiveWindow(); 1676 if (p_vout != NULL) { 1677 if (mi == _floatontop) 1678 [mi setState: var_GetBool(p_vout, "video-on-top")]; 1679 1680 if (mi == _fullscreenItem || mi == _voutMenufullscreen) 1681 [mi setState: var_GetBool(p_vout, "fullscreen")]; 1682 1683 enabled = YES; 1684 vlc_object_release(p_vout); 1685 } 1686 } 1687 1688 [self setupMenus]; /* Make sure video menu is up to date */ 1689 1690 } else if (mi == _openSubtitleFile) { 1691 enabled = [mi isEnabled]; 1692 [self setupMenus]; /* Make sure subtitles menu is up to date */ 1693 } else { 1694 NSMenuItem *_parent = [mi parentItem]; 1695 if (_parent == _subtitle_size || mi == _subtitle_size || 1696 _parent == _subtitle_textcolor || mi == _subtitle_textcolor || 1697 _parent == _subtitle_bgcolor || mi == _subtitle_bgcolor || 1698 _parent == _subtitle_bgopacity || mi == _subtitle_bgopacity || 1699 _parent == _subtitle_outlinethickness || mi == _subtitle_outlinethickness || 1700 _parent == _teletext || mi == _teletext 1701 ) { 1702 enabled = _openSubtitleFile.isEnabled; 1703 } 1704 } 1705 1706 if (p_input) 1707 vlc_object_release(p_input); 1708 1709 return enabled; 1710} 1711 1712@end 1713 1714 1715/***************************************************************************** 1716 *VLCAutoGeneratedMenuContent implementation 1717 ***************************************************************************** 1718 *Object connected to a playlistitem which remembers the data belonging to 1719 *the variable of the autogenerated menu 1720 *****************************************************************************/ 1721 1722@interface VLCAutoGeneratedMenuContent () 1723{ 1724 char *psz_name; 1725 vlc_object_t *vlc_object; 1726 vlc_value_t value; 1727 int i_type; 1728} 1729@end 1730@implementation VLCAutoGeneratedMenuContent 1731 1732-(id) initWithVariableName:(const char *)name ofObject:(vlc_object_t *)object 1733 andValue:(vlc_value_t)val ofType:(int)type 1734{ 1735 self = [super init]; 1736 1737 if (self != nil) { 1738 vlc_object = vlc_object_hold(object); 1739 psz_name = strdup(name); 1740 i_type = type; 1741 value = val; 1742 if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) 1743 value.psz_string = strdup(val.psz_string); 1744 } 1745 1746 return(self); 1747} 1748 1749- (void)dealloc 1750{ 1751 if (vlc_object) 1752 vlc_object_release(vlc_object); 1753 if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) 1754 free(value.psz_string); 1755 free(psz_name); 1756} 1757 1758- (const char *)name 1759{ 1760 return psz_name; 1761} 1762 1763- (vlc_value_t)value 1764{ 1765 return value; 1766} 1767 1768- (vlc_object_t *)vlcObject 1769{ 1770 return vlc_object_hold(vlc_object); 1771} 1772 1773- (int)type 1774{ 1775 return i_type; 1776} 1777 1778@end 1779