markup.push({

    // MARK: RTMP
    
    RTMPBlock:
    {
        "+": "OutputTemplate",
        geNodeClass: "GERTMPNode",
		geOutputRank: 5,	// outputs have an order of importance for status display
		geOutputVerb: "Streaming",
        h4PresetsId: "LiveStreamPresets",
        gxTitle: "Live Stream",
        gxLibraryDescription: "Stream audio to an RTMP server",
        gxLibraryIcon: "library.broadcast",
        gxPopoverInfo: "RTMPPopover", 
        gxChildViews:
        {
            status: {
                "+": "LabelView.top.foreColorTheme1.mediumWeight.size14",
                gxFrameRect: "12,42,96,22",
                gxValueKey: "node.displayState",
                axTitle: "streaming status",
                axIsIgnored: false,
            },
            streamTime: {
                "+": "LabelView.blockReadout.top",
                gxFrameRect: "12,62,96,22",
                gxFormatter: { nsClass:"PTTrackTimeFormatter" },
                gxValueKey: "node.streamTime",
                gxAnimateOnKey: "running",
                gxHideOnNilValue: true,
                axTitle: "streaming duration",
                axIsIgnored: false,
            },
			details: {
				"+": "LabelView.top.blockReadout",
				gxFrameRect: "12,84,96,16",
				gxValueKey: "node.metaTitle",
                gxAnimateOnKey: "running",
                axTitle: "current track title",
                axIsIgnored: false,
			},
        }
    },
    
	// MARK: popover
	
    RTMPPopover:
    {
        "+": "PopoverTemplate",
        gxTitle: "Live Stream",
        gxLayout: [
            "H:|-12-[self]-12-|",	// preview (RTMPBroadcastView) view is determining popover width
            "V:|-12-[self]-12-|",
            "V:|-41-[group]-6-[presetsGroup]",
        ],
        gxChildViews:
        {
            title: "PopoverTitle",
            onOff: "PopoverOnOffSwitch",
			presetsGroup: presetsGroup(),
			group:
			{
				"+": "GroupView",
				gxLayout: [
					"H:|[self]|",
					"V:|-35-[previewBtn]-0-[previewGroup]-0-[videoBtn]-0-[videoSetup]-0-[serverBtn]-0-[serverSetup]-0-|",
					
					"V:|-10-[state]",
					"H:|-13-[stateLabel]-6-[state(80)]-102-[durationLabel]-6-[duration(80)]-(>=0)-[dataLabel]-6-[data(70)]-13-|&alignBaseline",
				],
				gxChildViews :
				{
					stateLabel: labelView("Status:"),
					state:
					{
						"+": "LabelView.left.colorThemeLive2.size13",
						gxDefaultValue: "Offline",
						gxValueKey: "node.displayState",
						axTitle: "Status",
						axIsIgnored: false,
					},
					durationLabel: labelView("Duration:"),
					duration:
					{
						"+": "LabelView.left.colorThemeLive2.size13",
						gxValueKey: "node.streamTime",
						gxFormatter: { nsClass:"PTTrackTimeFormatter" },
						axTitle: "Duration",
						axIsIgnored: false,
					},
					dataLabel: labelView("Upload:"),
					data:
					{
						"+": "LabelView.left.colorThemeLive2.size13",
						gxValueKey: "node.dataRate",
						gxAnimateOnKey: "uiState.popoverState.isShown",
						axTitle: "Upload Size",
						axIsIgnored: false,
					},
					previewBtn:
					{
						"+": "AdvancedGroupButton",
						gxTitle: "<disclosure/> Preview",
						gxValueKey: "uiState.previewCollapsed",
						axFormatter: disclosureAxFormatter("Preview"),
					},
					previewGroup:	// MARK: preview
					{
						"+": "ExpandingGroupView.noTopStroke",
						gxValueKey: "uiState.previewCollapsed",
						gxCollapsedSize: 1,
						gxExtraSize: 10,
						axTitle: "Video Preview",
						axHelp: "This contains a preview of video to be streamed. The video may feature text, stylized audio meters and provided artwork.",
						gxLayout:
						[
							"H:|[self]|",
						 	"V:|-2-[preview]",
							"H:|[preview]|",
						],
						gxChildViews:
						{
							preview: { "+" : "RTMPBroadcastView" },
						}
					},
					videoBtn:
					{
						"+": "AdvancedGroupButton.noTopStroke",
						gxTitle: "<disclosure/> Video Layout",
						gxValueKey: "uiState.videoLayoutCollapsed",
						axFormatter: disclosureAxFormatter("Video Layout"),
					},
					videoSetup:		// MARK: video setup
					{
						"+": "ExpandingGroupView.noTopStroke",
						gxValueKey: "uiState.videoLayoutCollapsed",
						gxCollapsedSize: 1,
						gxExtraSize: 10,
						//axTitle: "Video Layout Group",
						gxLayout:
						[
							"H:|[self]|",
							"V:|-4-[mainTitleField]",
						 	"V:[mainTitleField]-12-[subTitleField]-12-[titles]-12-[source]-12-[showAlbumArtwork]&alignLeft",
						 
							"H:|-110-[mainTitleField]-60-[logo(123)]-12-|&alignTop",
						 
							"H:[mainTitleFieldLabel]-8-[mainTitleField]-(>=0)-[logoLabel(35)]&alignBaseline",
							"H:[subTitleFieldLabel]-8-[subTitleField(==mainTitleField)]&alignBaseline",
						 	"H:[titlesLabel]-8-[titles(==mainTitleField)]&alignBaseline",
						 	"H:[sourceLabel]-8-[source(==mainTitleField)]&alignBaseline",

							"H:[logoLabel(35)]-8-[logo]",
						 	"H:[mainTitleField]-(>=0)-[logoLabel(35)]&alignBaseline",
						 
							"V:[logo(123)]-(>=0)-[visualizerType]&alignLeft",

							"H:[showAlbumArtwork(160)]-(>=0)-[visualizerTypeLabel]-8-[visualizerType(123)]-12-|&alignBaseline",
						],
						gxChildViews:
						{
							logoLabel: labelView("Logo:"),
							logo:
							{
								"+": "ArtView",
								gxValueKey: "node.logo",
								axTitle: "Logo Art",
								axHelp: "Paste an image to display in the streamed video",
							},
							visualizerType: {
								"+" : "PopupMenuTemplate",
								gxLabelTemplate: "LabelView.right.size13",
								gxLabelText: "Visualizer:",
								gxMenuItems: [{	gxTitle: "None",		gxValue: 0 },
											  { gxTitle: "Oscilloscope",gxValue: 1 },
											  {	gxTitle: "Spectrum",	gxValue: 2 }],
								gxValueKey: "node.visualizer",
							},
							showAlbumArtwork: {
								"+": "CheckboxTemplate",
								gxTitle: "<checkbox/> Use Album Artwork",
								gxValueKey: "node.showAlbumArtwork",
							},
							mainTitleFieldLabel: labelView("Main Title:"),
							mainTitleField: {
								"+": "DarkTextField",
								gxValueKey: "node.mainTitle",
								axTitle: "Main Title",
							},
							subTitleFieldLabel: labelView("Subtitle:"),
							subTitleField: {
								"+": "DarkTextField",
								gxValueKey: "node.subTitle",
								axTitle: "Subtitle",
							},
							titlesLabel: labelView("Track Format:"),
							titles:
							{
								"+": "TrackTitleTokenField",
								gxValueKey: "node.trackTitlesFormat",
								gxBaselineOffset: 6,
								axTitle: "Track Titles Format",
								axHelp: "Tokens can be added to this field from the context menu",
							},
							sourceLabel: labelView("Track Source:"),
							source: {
								nsClass: "GETitleSourceAppPopupView",
								gxValueKey: "node.sourceAppPath",
								defaultAppIcon: "app.icon.generic.small",
								gxIntrinsicHeight: 25,
								gxBackPainter: "ControlBack",
								gxTitlePainter: {
									"+": "ControlFore.left.useMarkup",
									gxEdgeInsets: "28,0,0,0",
								},
								gxArrowPainter: "PopupArrows",
								gxIconPainter: {
									"+": "ImagePainter.left",
									gxEdgeInsets: "5, 4, 0, 3",
								},
								axTitle: "Track Titles Source Application",
								axHelp: "A source application that can provide track data as it plays.",
							},
						},
					},
					serverBtn: {
						"+": "AdvancedGroupButton.noTopStroke",
						gxTitle: "<disclosure/> Setup",
						gxValueKey: "uiState.setupPanelCollapsed",
						axFormatter: disclosureAxFormatter("Setup"),
					},
					serverSetup:	// MARK: server setup
					{
						"+": "ExpandingGroupView.noTopStroke",
						gxValueKey: "uiState.setupPanelCollapsed",
						gxCollapsedSize: 1,
						gxExtraSize: 10,
						//axTitle: "Setup Group",
						gxLayout: [
							"H:|[self]|",
							"V:|-4-[url]",
								   
						   "V:[url]-12-[key]-12-[quality]&alignRight",
						   "H:|-12-[urlLabel(90)]-8-[url]-12-[urlHelp]-12-|&alignBaseline",
						   "H:|-12-[keyLabel(90)]-8-[key]&alignBaseline",
						   "H:|-12-[qualityLabel(90)]-8-[quality]&alignBaseline",
						],
						gxChildViews: {
							urlHelp :{
								"+" : "ButtonView",
								gxValueKey: "node.showHelpPage",
								gxDefaultDisplayValue: "?",
								gxIntrinsicHeight: 21,
								gxIntrinsicWidth: 21,
								gxBaselineOffset: 4,
								axTitle: "Server Setup Help",
								axHelp: "Opens help for server configuration in your web browser",
								gxBackPainter: {
									"+": "ControlBack",
									gxCornerRadius: 10,
								},
							},
							urlLabel: labelView("Server URL:"),
							url:
							{
								"+": "DarkTextField",
								gxValueKey: "node.rtmpURL",
								axTitle: "Server URL",
								gxDisableOnKey: "running"
							},
							keyLabel: labelView("Key:"),
							key:
							{
								"+": "DarkTextField",
								nsClass: "GXPasswordField",
								gxValueKey: "node.rtmpKey",
								axTitle: "Server Key",
								gxDisableOnKey: "running"
							},
							qualityLabel: labelView("Quality:"),
							quality:
							{
								"+": "PopupMenuView",
								gxMenuItems:
								[
									{ gxTitle: "Good Quality (1-2 Mbps)",	gxValue: 0 },
									{ gxTitle: "Higher Quality (3-4 Mbps)", 	gxValue: 1 },
									{ gxTitle: "Best Quality (6-7 Mbps)",	gxValue: 2 }
								],
								gxValueKey: "node.qualityPreset",
								axTitle: "Stream Quality",
								gxDisableOnKey: "running"
							},
						},
					}, 
				},
            },
        }
    },
	
	"BroadcastTitleFore" :
	{
		"+" : "LabelFore",
		gxFontKerning: -0.6,
		gxFontWeight: 0.4
	},
	
	"BroadcastSubtitleFore" :
	{
		"+" : "LabelFore",
		gxFontKerning: 1.1,
		gxFontWeight: -0.5,
	},
	
	
	// MARK: video view
	
	RTMPBroadcastView :  // This name is references in code
	{
		nsClass: "GXRTMPPreview",
		gxWantsLayer: true,
		gxBackPainter: {
			nsClass: "GXPainter",
			gxFillColor: "BlackColor",
		},
		gxLayoutKeyPath: "node.viewLayout",
		standardLayout :
		[
			"V:[self(324)]",
			"H:[self(576)]",
			"H:[self]-(<=0)-[backgroundImage(700)]&alignCenterY",
			"V:[self]-(<=0)-[backgroundImage(700)]&alignCenterX",
			"V:|-80-[mainTitle(36)]-10-[subTitle(25)]-0-[metaTitle(60)]",
            "V:[albumArt]-10-[oscope]-10-|",
			"V:[albumArt]-10-[spectrum]-0-|",
            "H:|-30-[albumArt(150)]",
			"V:|-50-[albumArt(150)]",
			"V:[logo(90)]-20-|",
			"H:[logo(90)]-20-|",
			"H:|-30-[oscope]",
			"H:|-30-[spectrum]",
		],
		layoutLogo : [
			"H:[oscope]-20-[logo]",
			"H:[spectrum]-20-[logo]",
		],
		layoutNoLogo : [
			"H:[oscope]-30-|",
			"H:[spectrum]-30-|",
		],
		layoutArt : [
			"H:[albumArt]-20-[mainTitle]-30-|",
			"H:[albumArt]-20-[subTitle]-30-|",
			"H:[albumArt]-20-[metaTitle]-30-|",
		],
		layoutNoArt : [
			"H:|-20-[mainTitle]-20-|",
			"H:|-20-[subTitle]-20-|",
			"H:|-20-[metaTitle]-20-|",
		],
		gxChildViews: {
			"backgroundImage" :
			{
				nsClass: "GXDrawView",
				gxWantsLayer: true,
				gxForePainter: "ImagePainter",
				gxBackPainter: "",
				gxValueKey: "node.backgroundImage",
				gxAddViewBelow: true,
			},
			"mainTitle" : {
				"+": "LabelView",
				gxWantsLayer: true,
				gxForePainter: "BroadcastTitleFore.useMarkup.center.colorTheme1.size28",
				gxIntrinsicWidth: -1,
				gxDisableOnNil: false,
				gxIntrinsicHeight: null,
				gxValueKey: "node.mainTitleColored",
			},
			"subTitle" : {
				"+": "LabelView",
				gxWantsLayer: true,
				gxForePainter: { "+" : "BroadcastSubtitleFore.useMarkup.colorTheme2.size21" },
				gxIntrinsicWidth: -1,
				gxIntrinsicHeight: null,
				gxDisableOnNil: false,
				gxValueKey: "node.subTitleColored",
			},
			"metaTitle": {
				"+": "LabelView",
				gxWantsLayer: true,
				gxForePainter:
				{
					"+" : "BroadcastSubtitleFore.useMarkup.centerX.top.colorTheme2.size19.wrap.truncates",
				},
				gxIntrinsicWidth: -1,
				gxIntrinsicHeight: null,
				gxDisableOnNil: false,
				gxValueKey: "node.metaTitleColored",
				gxShowOnKey: "node.showTrackTitles",
			},
			"albumArt" : {
				nsClass: "GXDrawView",
				gxWantsLayer: true,
				gxForePainter:  "ImagePainter",
				gxValueKey: "node.broadcastArtwork",
				gxHideOnNilValue: true,
				gxAddViewBelow: true,
			},
			"spectrum" : {
				nsClass: "GXBezierPathView",
				gxWantsLayer: true,
				gxShowOnKey: "node.showSpectrum",
				gxValueKey: "node.spectrumPath",
				gxHackedAnimateOnKey: "uiState.popoverState.isShown",
				gxFillColorKeyPath: "node.broadcastColors.secondary",
				gxForePainter : {
					nsClass: "GXPainter",
					gxFillColor	: "ColorTheme2",
				}, 
			},
			"oscope" : {
				nsClass: "GXBezierPathView",
				gxWantsLayer: true,
				gxShowOnKey: "node.showOscope",
				gxValueKey: "node.oscopePath",
				gxHackedAnimateOnKey: "uiState.popoverState.isShown",
				gxFillColorKeyPath: "node.broadcastColors.secondary",
				gxForePainter : {
					nsClass: "GXPainter",
					gxFillColor	: "ColorTheme2",
				},
			},
			"logo" : {
				nsClass: "GXDrawView",
				gxWantsLayer: true,
				gxForePainter: "ImagePainter",
				gxLayerZPosition: 2,
				gxShowOnKey: "node.showAlbumArtwork",
				gxHideOnNilValue: true,
				gxValueKey: "node.logo",
			},
		},
	},
    

})
