From 054d3dac41fa4a409e1cdf190ab7e459681712cc Mon Sep 17 00:00:00 2001 From: Lord-Grey Date: Sun, 14 Feb 2021 11:39:03 +0100 Subject: [PATCH] Discovery VideoSources and Dynamically Update Editor --- assets/webconfig/i18n/en.json | 1911 +++++++++-------- assets/webconfig/js/content_grabber.js | 667 +++--- assets/webconfig/js/hyperion.js | 382 ++-- assets/webconfig/js/ui_utils.js | 1558 +++++++------- include/api/JsonAPI.h | 6 + .../JSONRPC_schema/schema-inputsource.json | 28 + libsrc/api/JSONRPC_schema/schema.json | 2 +- libsrc/api/JSONRPC_schemas.qrc | 3 +- libsrc/api/JsonAPI.cpp | 182 +- libsrc/hyperion/SettingsManager.cpp | 13 + .../hyperion/schema/schema-grabberV4L2.json | 545 ++--- 11 files changed, 2782 insertions(+), 2515 deletions(-) create mode 100644 libsrc/api/JSONRPC_schema/schema-inputsource.json diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index f2568a31..ac9a5c26 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -1,957 +1,958 @@ { - "InfoDialog_access_text": "Depending on settings level you could adjust more options or get access to more features. Recommended is the \"Default\" level.", - "InfoDialog_access_title": "Settings level", - "InfoDialog_changePassword_success": "Password successfully saved!", - "InfoDialog_changePassword_title": "Change Password", - "InfoDialog_iswitch_text": "If you run Hyperion more than once in your local network, you could switch between the web configurations. Select the Hyperion instance below and switch!", - "InfoDialog_iswitch_title": "Hyperion switcher", - "InfoDialog_lang_text": "If you don't like the result of the automatic language detection you could overwrite it here.", - "InfoDialog_lang_title": "Language setting", - "InfoDialog_nowrite_foottext": "The WebUI will be unlocked automatically after you solved the problem!", - "InfoDialog_nowrite_text": "Hyperion can't write to your current loaded configuration file. Please repair the file permissions to proceed.", - "InfoDialog_nowrite_title": "write permission error!", - "about_3rd_party_licenses": "3rd party licenses", - "about_3rd_party_licenses_error": "We had trouble collecting 3rd party licenses information from web.
Please follow this link to the GitHub Resource.", - "about_build": "Build", - "about_builddate": "Build date", - "about_contribute": "Develop Hyperion further with us!", - "about_credits": "Credits to all these developers!", - "about_resources": "$1 libraries", - "about_translations": "Translations", - "about_version": "Version", - "conf_colors_blackborder_intro": "Skip black bars wherever they are. Each mode use another detection algorithm which is tuned for special situations. Higher the threshold if it doesn't work for you.", - "conf_colors_color_intro": "Create one or more calibration profiles, adjust each color, brightness, linearization and more.", - "conf_colors_smoothing_intro": "Smoothing flattens color/brightness changes to reduce annoying distraction.", - "conf_effect_bgeff_intro": "Define a background effect/color, which is shown during Hyperion \"idle\". Starts always with priority channel 255.", - "conf_effect_fgeff_intro": "Define a boot-effect or color, which is shown during Hyperion startup for the defined duration.", - "conf_effect_path_intro": "Load effects from the defined paths. Additional you can disable single effects by name to hide them from all effect lists.", - "conf_general_createInst_btn": "Create Instance", - "conf_general_impexp_expbtn": "Export", - "conf_general_impexp_impbtn": "Import", - "conf_general_impexp_l1": "Import a configuration by selecting a configuration file below and click on \"Import\".", - "conf_general_impexp_l2": "Export a configuration by clicking on \"Export\". Your browser starts a download.", - "conf_general_impexp_title": "Import/Export Configuration", - "conf_general_inst_actionhead": "Action", - "conf_general_inst_delreq_h": "Delete LED Hardware instance", - "conf_general_inst_delreq_t": "Are you sure that you want to delete instance \"$1\"? All settings will be deleted too.", - "conf_general_inst_desc": "Use different LED hardware at the same time. Each instance runs independent of each other which allows different LED layouts and calibration settings. Running instances are available at the top icon bar", - "conf_general_inst_name_title": "New Instance name", - "conf_general_inst_namehead": "Instance name", - "conf_general_inst_renreq_t": "Enter a new name for your instance in the field below.", - "conf_general_inst_title": "LED Hardware Instance Management", - "conf_general_intro": "Basic settings around Hyperion and WebUI that don't fit into another category.", - "conf_general_label_title": "General settings", - "conf_grabber_fg_intro": "Platform capture is your local system capture as input source, Hyperion is installed on.", - "conf_grabber_v4l_intro": "USB capture is a (capture)device connected via USB which is used to input source pictures for processing.", - "conf_helptable_expl": "Explanation", - "conf_helptable_option": "Option", - "conf_leds_contr_label_contrtype": "Controller type:", - "conf_leds_device_intro": "Hyperion supports a lot of controllers to transmit data to your target device. Select a LED controller out of the sorted list and configure it. We have chosen the best default settings for each device.", - "conf_leds_layout_advanced": "Advanced Settings", - "conf_leds_layout_btn_checklist": "Show checklist", - "conf_leds_layout_button_savelay": "Save Layout", - "conf_leds_layout_button_updsim": "Update Preview", - "conf_leds_layout_checkp1": "The black led is your first led, the first led is the point where you input your data signal.", - "conf_leds_layout_checkp2": "The layout is always the front view of your TV, never the back view.", - "conf_leds_layout_checkp3": "Make sure the direction is right. The grey LEDs indicate LED number 2 and 3 to visualise the data direction.", - "conf_leds_layout_checkp4": "Case Gap: To create a gap, ignore it first when you define Top/Bottom/Left/Right and set afterwards your gap length to remove a amount of leds. Modify the gap position until it matches.", - "conf_leds_layout_cl_bottom": "Bottom", - "conf_leds_layout_cl_bottomleft": "Bottom Left (Corner)", - "conf_leds_layout_cl_bottomright": "Bottom Right (Corner)", - "conf_leds_layout_cl_cornergap": "Corner Gap", - "conf_leds_layout_cl_edgegap": "Edge Gap", - "conf_leds_layout_cl_gaglength": "Gap length", - "conf_leds_layout_cl_gappos": "gap position", - "conf_leds_layout_cl_hleddepth": "Horizontal LED depth", - "conf_leds_layout_cl_inppos": "Input position", - "conf_leds_layout_cl_left": "Left", - "conf_leds_layout_cl_leftbottom": "Left 50% - 100% Bottom", - "conf_leds_layout_cl_leftmiddle": "Left 25% - 75% Middle", - "conf_leds_layout_cl_lefttop": "Left 0% - 50% Top", - "conf_leds_layout_cl_overlap": "Overlap", - "conf_leds_layout_cl_reversdir": "Reverse direction", - "conf_leds_layout_cl_right": "Right", - "conf_leds_layout_cl_rightbottom": "Right 50% - 100% Bottom", - "conf_leds_layout_cl_rightmiddle": "Right 25% - 75% Middle", - "conf_leds_layout_cl_righttop": "Right 0% - 50% Top", - "conf_leds_layout_cl_top": "Top", - "conf_leds_layout_cl_topleft": "Top Left (Corner)", - "conf_leds_layout_cl_topright": "Top Right (Corner)", - "conf_leds_layout_cl_vleddepth": "Vertical LED depth", - "conf_leds_layout_frame": "Classic Layout (LED Frame)", - "conf_leds_layout_generatedconf": "Generated/Current LED Configuration", - "conf_leds_layout_intro": "You need also a led layout, which reflects your led positions. The classic layout is the usual used tv frame, but we also support led matrix (led walls) creation. The view on this layout is ALWAYS of the FRONT of your TV.", - "conf_leds_layout_ma_cabling": "Cabling", - "conf_leds_layout_ma_horiz": "Horizontal", - "conf_leds_layout_ma_optbottomleft": "Bottom left", - "conf_leds_layout_ma_optbottomright": "Bottom right", - "conf_leds_layout_ma_opthoriz": "Horizontal", - "conf_leds_layout_ma_optparallel": "Parallel", - "conf_leds_layout_ma_optsnake": "Snake", - "conf_leds_layout_ma_opttopleft": "Top Left", - "conf_leds_layout_ma_opttopright": "Top right", - "conf_leds_layout_ma_optvert": "Vertical", - "conf_leds_layout_ma_order": "Order", - "conf_leds_layout_ma_position": "Input", - "conf_leds_layout_ma_vert": "Vertical", - "conf_leds_layout_matrix": "Matrix Layout (LED Wall)", - "conf_leds_layout_pbl": "Point Bottom Left", - "conf_leds_layout_pbr": "Point Bottom Right", - "conf_leds_layout_peview": "LED Layout Preview", - "conf_leds_layout_preview_l1": "This is your first led (input position)", - "conf_leds_layout_preview_l2": "This visualizes the data direction (second/third led)", - "conf_leds_layout_preview_ledpower": "Max. power consumption: $1 A", - "conf_leds_layout_preview_originCL": "Created from: Classic Layout (LED Frame)", - "conf_leds_layout_preview_originMA": "Created from: Matrix Layout(LED wall)", - "conf_leds_layout_preview_originTEXT": "Created from: Textfield", - "conf_leds_layout_preview_totalleds": "Total LEDs: $1", - "conf_leds_layout_ptl": "Point Top Left", - "conf_leds_layout_ptlh": "Horizontal", - "conf_leds_layout_ptln": "Tripplepoints", - "conf_leds_layout_ptlv": "Vertical", - "conf_leds_layout_ptr": "Point Top Right", - "conf_leds_layout_textf1": "This text field shows by default your current loaded layout and will be overwritten if you generate a new one with the options above. Optional you could perform further edits.", - "conf_leds_nav_label_ledcontroller": "LED Controller", - "conf_leds_nav_label_ledlayout": "LED Layout", - "conf_leds_optgroup_RPiGPIO": "RPi GPIO", - "conf_leds_optgroup_RPiPWM": "RPi PWM", - "conf_leds_optgroup_RPiSPI": "RPi SPI", - "conf_leds_optgroup_debug": "Debug", - "conf_leds_optgroup_network": "Network", - "conf_leds_optgroup_usb": "USB/Serial", - "conf_logging_btn_autoscroll": "Auto scrolling", - "conf_logging_btn_pbupload": "Upload a report for support requests", - "conf_logging_contpolicy": "Report Privacy Policy", - "conf_logging_label_intro": "Area to check log messages, you will see more or less information depending on the logging level set.", - "conf_logging_lastreports": "Previous reports", - "conf_logging_nomessage": "No log messages available.", - "conf_logging_report": "Report", - "conf_logging_uplfailed": "Upload failed! Please check your internet connection!", - "conf_logging_uploading": "Prepare data...", - "conf_logging_uplpolicy": "By clicking this button you accept the", - "conf_logging_yourlink": "Link to your report", - "conf_network_bobl_intro": "Receiver for Boblight", - "conf_network_createToken_btn": "Create Token", - "conf_network_fbs_intro": "Google Flatbuffers Receiver. Used for fast image transmission.", - "conf_network_forw_intro": "Forward all input to a second Hyperion instance which could be driven with another led controller", - "conf_network_json_intro": "The JSON-RPC-Port of all Hyperion instances, used for remote control.", - "conf_network_net_intro": "Network related settings which are applied to all network services.", - "conf_network_proto_intro": "The PROTO-Port of all Hyperion instances, used for picture streams (HyperionScreenCap, Kodi Addon, Android Hyperion Grabber, ...)", - "conf_network_tok_cidhead": "Description", - "conf_network_tok_comment_title": "Token description", - "conf_network_tok_desc": "Tokens grant other applications access to the Hyperion API, an application can request a token where you need to accept it or you create them on your own below. These tokens are just required when \"API Authorization\" is enabled in network settings.", - "conf_network_tok_diaMsg": "Here is your new token which can be used to grant an application access to the Hyperion API. For security reasons you can't view it again so use/note it down.", - "conf_network_tok_diaTitle": "New Token created!", - "conf_network_tok_grantMsg": "An App requested a token to get access to the Hyperion API. Do you want to grant access? Please verify the provided information!", - "conf_network_tok_grantT": "App Requests Token", - "conf_network_tok_intro": "Here you can create and delete tokens for API authentication. Created tokens will only be displayed once.", - "conf_network_tok_lastuse": "Last use", - "conf_network_tok_title": "Token Management", - "conf_webconfig_label_intro": "Webconfiguration settings. Edit wisely.", - "dashboard_active_instance": "Selected instance", - "dashboard_alert_message_confedit": "Your Hyperion configuration has been modified. To apply it, restart Hyperion.", - "dashboard_alert_message_confedit_t": "Configuration modified", - "dashboard_alert_message_confsave_success": "Your Hyperion configuration has been saved successfully. Your changes are now active.", - "dashboard_alert_message_confsave_success_t": "Configuration saved", - "dashboard_alert_message_disabled": "This instance is currently disabled! To use it again, enable it at the dashboard.", - "dashboard_alert_message_disabled_t": "LED hardware instance disabled", - "dashboard_componentbox_label_comp": "Component", - "dashboard_componentbox_label_status": "Status", - "dashboard_componentbox_label_title": "Components status", - "dashboard_infobox_label_currenthyp": "Your Hyperion version:", - "dashboard_infobox_label_disableh": "Disable Instance: $1", - "dashboard_infobox_label_enableh": "Enable Instance: $1", - "dashboard_infobox_label_instance": "Instance:", - "dashboard_infobox_label_latesthyp": "Latest Hyperion version:", - "dashboard_infobox_label_platform": "Platform:", - "dashboard_infobox_label_ports": "Ports (flat|proto):", - "dashboard_infobox_label_smartacc": "Smart Access", - "dashboard_infobox_label_statush": "Hyperion status:", - "dashboard_infobox_label_title": "Information", - "dashboard_infobox_label_watchedversionbranch": "Watched version branch:", - "dashboard_infobox_message_updatesuccess": "You run the latest version of Hyperion.", - "dashboard_infobox_message_updatewarning": "A newer version of Hyperion is available! ($1)", - "dashboard_label_intro": "The dashboard give you a quick overview about the status of Hyperion and show you the latest news of the Hyperion Blog.", - "dashboard_message_default_password": "The default password for the WebUi is set. We strongly recommend to change this.", - "dashboard_message_default_password_t": "WebUI default password is set", - "dashboard_message_do_not_show_again": "Do not show this message again", - "dashboard_message_global_setting": "The settings on this page are not depending on a specific instance. Changes will be stored globally for all instances.", - "dashboard_message_global_setting_t": "Instance independent setting", - "dashboard_newsbox_label_title": "Hyperion-Blog", - "dashboard_newsbox_noconn": "Can't connect to Hyperion Server to retrieve latest posts, does your internet connection work?", - "dashboard_newsbox_readmore": "Read more", - "dashboard_newsbox_visitblog": "Visit Hyperion-Blog", - "edt_append_degree": "°", - "edt_append_hz": "Hz", - "edt_append_leds": "LEDs", - "edt_append_ms": "ms", - "edt_append_ns": "ns", - "edt_append_percent": "%", - "edt_append_percent_h": "% hori", - "edt_append_percent_v": "% vert", - "edt_append_pixel": "Pixel", - "edt_append_s": "s", - "edt_append_sdegree": "s/degree", - "edt_conf_bb_blurRemoveCnt_expl": "Number of pixels that get removed from the detected border to cut away blur.", - "edt_conf_bb_blurRemoveCnt_title": "Blur pixel", - "edt_conf_bb_borderFrameCnt_expl": "Number of frames before a consistent detected border is set.", - "edt_conf_bb_borderFrameCnt_title": "Border frames", - "edt_conf_bb_heading_title": "Blackbar detector", - "edt_conf_bb_maxInconsistentCnt_expl": "Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency.", - "edt_conf_bb_maxInconsistentCnt_title": "Inconsistent frames", - "edt_conf_bb_mode_expl": "Algorithm for processing. (see Wiki)", - "edt_conf_bb_mode_title": "Mode", - "edt_conf_bb_threshold_expl": "If the detection doesn't work, higher the threshold to adjust on 'greyish' black", - "edt_conf_bb_threshold_title": "Threshold", - "edt_conf_bb_unknownFrameCnt_expl": "Number of frames without any detection before the border is set to 0.", - "edt_conf_bb_unknownFrameCnt_title": "Unknown frames", - "edt_conf_bge_heading_title": "Background Effect/Color", - "edt_conf_bobls_heading_title": "Boblight Server", - "edt_conf_color_backlightColored_expl": "Add some color to your backlight.", - "edt_conf_color_backlightColored_title": "Colored backlight", - "edt_conf_color_backlightThreshold_expl": "The minimum amount of brightness (backlight). Disabled during effects, colors and in status \"Off\"", - "edt_conf_color_backlightThreshold_title": "Backlight threshold", - "edt_conf_color_black_expl": "The calibrated black value.", - "edt_conf_color_black_title": "Black", - "edt_conf_color_blue_expl": "The calibrated blue value.", - "edt_conf_color_blue_title": "Blue", - "edt_conf_color_brightnessComp_expl": "Compensates brightness differences between red green blue, cyan magenta yellow and white. 100 means full compensation, 0 no compensation", - "edt_conf_color_brightnessComp_title": "Brightness compensation", - "edt_conf_color_brightness_expl": "set overall brightness of LEDs", - "edt_conf_color_brightness_title": "Brightness", - "edt_conf_color_channelAdjustment_header_expl": "Create color profiles that could be assigned to a specific component. Adjust color, gamma, brightness, compensation and more.", - "edt_conf_color_channelAdjustment_header_itemtitle": "Profile", - "edt_conf_color_channelAdjustment_header_title": "Color channel adjustments", - "edt_conf_color_cyan_expl": "The calibrated cyan value.", - "edt_conf_color_cyan_title": "Cyan", - "edt_conf_color_gammaBlue_expl": "The gamma of blue. 1.0 is neutral. Over 1.0 it reduces blue, lower than 1.0 it adds blue.", - "edt_conf_color_gammaBlue_title": "Gamma blue", - "edt_conf_color_gammaGreen_expl": "The gamma of green. 1.0 is neutral. Over 1.0 it reduces green, lower than 1.0 it adds green.", - "edt_conf_color_gammaGreen_title": "Gamma green", - "edt_conf_color_gammaRed_expl": "The gamma of red. 1.0 is neutral. Over 1.0 it reduces red, lower than 1.0 it adds red.", - "edt_conf_color_gammaRed_title": "Gamma red", - "edt_conf_color_green_expl": "The calibrated green value.", - "edt_conf_color_green_title": "Green", - "edt_conf_color_heading_title": "Color Calibration", - "edt_conf_color_id_expl": "User given name", - "edt_conf_color_id_title": "ID", - "edt_conf_color_imageToLedMappingType_expl": "Overwrites the led area assignment of your led layout if it's not \"multicolor\"", - "edt_conf_color_imageToLedMappingType_title": "Led area assignment", - "edt_conf_color_leds_expl": "Assign this adjustment to all LEDs (*) or just some (0-24).", - "edt_conf_color_leds_title": "LED index", - "edt_conf_color_magenta_expl": "The calibrated magenta value.", - "edt_conf_color_magenta_title": "Magenta", - "edt_conf_color_red_expl": "The calibrated red value.", - "edt_conf_color_red_title": "Red", - "edt_conf_color_white_expl": "The calibrated white value.", - "edt_conf_color_white_title": "White", - "edt_conf_color_yellow_expl": "The calibrated yellow value.", - "edt_conf_color_yellow_title": "Yellow", - "edt_conf_effp_disable_expl": "Add effect names here to disable/hide them from all effect lists.", - "edt_conf_effp_disable_itemtitle": "Effect", - "edt_conf_effp_disable_title": "Disabled Effects", - "edt_conf_effp_heading_title": "Effect Paths", - "edt_conf_effp_paths_expl": "You could define more folders that contain effects. The effect configurator will always save inside the first folder.", - "edt_conf_effp_paths_itemtitle": "Path", - "edt_conf_effp_paths_title": "Effect Path(s)", - "edt_conf_enum_NO_CHANGE": "Automatic", - "edt_conf_enum_NTSC": "NTSC", - "edt_conf_enum_PAL": "PAL", - "edt_conf_enum_SECAM": "SECAM", - "edt_conf_enum_HORIZONTAL": "Horizontal", - "edt_conf_enum_VERTICAL": "Vertical", - "edt_conf_enum_BOTH": "Horizontal & Vertical", - "edt_conf_enum_automatic": "Automatic", - "edt_conf_enum_bbclassic": "Classic", - "edt_conf_enum_bbdefault": "Default", - "edt_conf_enum_bbletterbox": "Letterbox", - "edt_conf_enum_bbosd": "OSD", - "edt_conf_enum_bgr": "BGR", - "edt_conf_enum_bottom_up": "Bottom up", - "edt_conf_enum_brg": "BRG", - "edt_conf_enum_color": "Color", - "edt_conf_enum_custom": "Custom", - "edt_conf_enum_decay": "Decay", - "edt_conf_enum_dl_error": "Error", - "edt_conf_enum_dl_informational": "Informational", - "edt_conf_enum_dl_nodebug": "No Debug output", - "edt_conf_enum_dl_statechange": "State Change", - "edt_conf_enum_dl_verbose": "Verbose", - "edt_conf_enum_dl_verbose1": "Verbosity level 1", - "edt_conf_enum_dl_verbose2": "Verbosity level 2", - "edt_conf_enum_dl_verbose3": "Verbosity level 3", - "edt_conf_enum_effect": "Effect", - "edt_conf_enum_gbr": "GBR", - "edt_conf_enum_grb": "GRB", - "edt_conf_enum_hsv": "HSV", - "edt_conf_enum_left_right": "Left to right", - "edt_conf_enum_linear": "Linear", - "edt_conf_enum_logdebug": "Debug", - "edt_conf_enum_logsilent": "Silent", - "edt_conf_enum_logverbose": "Verbose", - "edt_conf_enum_logwarn": "Warning", - "edt_conf_enum_multicolor_mean": "Multicolor", - "edt_conf_enum_rbg": "RBG", - "edt_conf_enum_rgb": "RGB", - "edt_conf_enum_right_left": "Right to left", - "edt_conf_enum_top_down": "Top down", - "edt_conf_enum_transeffect_smooth": "Smooth", - "edt_conf_enum_transeffect_sudden": "Sudden", - "edt_conf_enum_unicolor_mean": "Unicolor", - "edt_conf_fbs_heading_title": "Flatbuffers Server", - "edt_conf_fbs_timeout_expl": "If no data are received for the given period, the component will be (soft) disabled.", - "edt_conf_fbs_timeout_title": "Timeout", - "edt_conf_fg_display_expl": "Select which desktop should be captured (multi monitor setup)", - "edt_conf_fg_display_title": "Display", - "edt_conf_fg_frequency_Hz_expl": "How fast new pictures are captured", - "edt_conf_fg_frequency_Hz_title": "Capture frequency", - "edt_conf_fg_heading_title": "Platform Capture", - "edt_conf_fg_height_expl": "Shrink picture to this height, as raw picture needs a lot of CPU time.", - "edt_conf_fg_height_title": "Height", - "edt_conf_fg_pixelDecimation_expl": "Reduce picture size (factor) based on original size. A factor of 1 means no change", - "edt_conf_fg_pixelDecimation_title": "Picture decimation", - "edt_conf_fg_type_expl": "Type of platform capture, default is 'auto'", - "edt_conf_fg_type_title": "Type", - "edt_conf_fg_width_expl": "Shrink picture to this width, as raw picture needs a lot of cpu time.", - "edt_conf_fg_width_title": "Width", - "edt_conf_fge_color_expl": "If type is \"Color\", set a color of your choice here.", - "edt_conf_fge_color_title": "Color", - "edt_conf_fge_duration_ms_expl": "Duration of Effect/Color during Hyperion start-up.", - "edt_conf_fge_duration_ms_title": "Duration", - "edt_conf_fge_effect_expl": "If type is \"Effect\", select an effect of your choice (Also self created effects).", - "edt_conf_fge_effect_title": "Effect", - "edt_conf_fge_heading_title": "Boot Effect/Color", - "edt_conf_fge_type_expl": "Choose between a color or effect.", - "edt_conf_fge_type_title": "Type", - "edt_conf_fw_flat_expl": "One flatbuffer target per line. Contains IP:PORT (Example: 127.0.0.1:19401)", - "edt_conf_fw_flat_itemtitle": "flatbuffer target", - "edt_conf_fw_flat_title": "List of flatbuffer clients", - "edt_conf_fw_heading_title": "Forwarder", - "edt_conf_fw_json_expl": "One json target per line. Contains IP:PORT (Example: 127.0.0.1:19446)", - "edt_conf_fw_json_itemtitle": "Json target", - "edt_conf_fw_json_title": "List of json clients", - "edt_conf_gen_heading_title": "General Settings", - "edt_conf_gen_name_expl": "A user defined name which is used to detect Hyperion. (Helpful with more than one Hyperion instance)", - "edt_conf_gen_name_title": "Configuration name", - "edt_conf_gen_showOptHelp_expl": "Show all available explanations in each section. Highly recommended for beginners!", - "edt_conf_gen_showOptHelp_title": "Show explanations", - "edt_conf_gen_watchedVersionBranch_expl": "Selects which version branch should be used for searching new Hyperion versions.", - "edt_conf_gen_watchedVersionBranch_title": "Watched version branch", - "edt_conf_general_enable_expl": "If checked, the component is enabled.", - "edt_conf_general_enable_title": "Activate", - "edt_conf_general_port_expl": "The port that is used.", - "edt_conf_general_port_title": "Port", - "edt_conf_general_priority_expl": "The priority of this component", - "edt_conf_general_priority_title": "Priority channel", - "edt_conf_instC_systemEnable_expl": "Enables the platform capture for this led hardware instance", - "edt_conf_instC_systemEnable_title": "Enable platform capture", - "edt_conf_instC_v4lEnable_expl": "Enables the USB capture for this led hardware instance", - "edt_conf_instC_v4lEnable_title": "Enable USB capture", - "edt_conf_instCapture_heading_title": "Instance Capture", - "edt_conf_js_heading_title": "JSON Server", - "edt_conf_log_heading_title": "Logging", - "edt_conf_log_level_expl": "Depending on loglevel you see less or more messages in your log.", - "edt_conf_log_level_title": "Log-Level", - "edt_conf_net_apiAuth_expl": "Enforce all applications that use the Hyperion API to authenticate themself against Hyperion (Exception see \"Local API Authentication\"). Higher security, as you control the access and revoke it at any time.", - "edt_conf_net_apiAuth_title": "API Authentication", - "edt_conf_net_heading_title": "Network", - "edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Webinterface from the internet, disable for higher security.", - "edt_conf_net_internetAccessAPI_title": "Internet API Access", - "edt_conf_net_ipWhitelist_expl": "You can whitelist IP addresses instead allowing all connections from internet to connect to the Hyperion API/Webinterface.", - "edt_conf_net_ipWhitelist_title": "Whitelisted IP's", - "edt_conf_net_ip_itemtitle": "IP", - "edt_conf_net_localAdminAuth_expl": "When enabled, administration access from your local network needs a password.", - "edt_conf_net_localAdminAuth_title": "Local Admin API Authentication", - "edt_conf_net_localApiAuth_expl": "When enabled, connections from your home network needs to authenticate themself against Hyperion with a token.", - "edt_conf_net_localApiAuth_title": "Local API Authentication", - "edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict the access to the API through the internet to certain IP's.", - "edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP's", - "edt_conf_pbs_heading_title": "Protocol Buffers Server", - "edt_conf_pbs_timeout_expl": "If no data are received for the given period, the component will be (soft) disabled.", - "edt_conf_pbs_timeout_title": "Timeout", - "edt_conf_smooth_continuousOutput_expl": "Update the LEDs even there is no changed picture.", - "edt_conf_smooth_continuousOutput_title": "Continuous output", - "edt_conf_smooth_decay_expl": "The speed of decay. 1 is linear, greater values are have stronger effect.", - "edt_conf_smooth_decay_title": "Decay-Power", - "edt_conf_smooth_dithering_expl": "Improve color accuracy at high output speeds by alternating between adjacent colors.", - "edt_conf_smooth_dithering_title": "Dithering", - "edt_conf_smooth_heading_title": "Smoothing", - "edt_conf_smooth_interpolationRate_expl": "Speed of the calculation of smooth intermediate frames.", - "edt_conf_smooth_interpolationRate_title": "Interpolation Rate", - "edt_conf_smooth_outputRate_expl": "The output speed to your led controller.", - "edt_conf_smooth_outputRate_title": "Output Rate", - "edt_conf_smooth_time_ms_expl": "How long should the smoothing gather pictures?", - "edt_conf_smooth_time_ms_title": "Time", - "edt_conf_smooth_type_expl": "Type of smoothing.", - "edt_conf_smooth_type_title": "Type", - "edt_conf_smooth_updateDelay_expl": "Delay the output in case your ambient light is faster than your TV.", - "edt_conf_smooth_updateDelay_title": "Update delay", - "edt_conf_smooth_updateFrequency_expl": "The output speed to your led controller.", - "edt_conf_smooth_updateFrequency_title": "Update frequency", - "edt_conf_v4l2_blueSignalThreshold_expl": "Darkens low blue values (recognized as black)", - "edt_conf_v4l2_blueSignalThreshold_title": "Blue signal threshold", - "edt_conf_v4l2_cecDetection_expl": "If enabled, USB capture will be temporarily disabled when CEC standby event received from HDMI bus.", - "edt_conf_v4l2_cecDetection_title": "CEC detection", - "edt_conf_v4l2_cropBottom_expl": "Count of pixels on the bottom side that are removed from the picture.", - "edt_conf_v4l2_cropBottom_title": "Crop bottom", - "edt_conf_v4l2_cropLeft_expl": "Count of pixels on the left side that are removed from the picture.", - "edt_conf_v4l2_cropLeft_title": "Crop left", - "edt_conf_v4l2_cropRight_expl": "Count of pixels on the right side that are removed from the picture.", - "edt_conf_v4l2_cropRight_title": "Crop right", - "edt_conf_v4l2_cropTop_expl": "Count of pixels on the top side that are removed from the picture.", - "edt_conf_v4l2_cropTop_title": "Crop top", - "edt_conf_v4l2_device_expl": "The path to the USB capture interface. Set to 'Automatic' for automatic detection. Example: '/dev/video0'", - "edt_conf_v4l2_device_title": "Device", - "edt_conf_v4l2_framerate_expl": "The supported frames per second of the active device", - "edt_conf_v4l2_framerate_title": "Frames per second", - "edt_conf_v4l2_greenSignalThreshold_expl": "Darkens low green values (recognized as black)", - "edt_conf_v4l2_greenSignalThreshold_title": "Green signal threshold", - "edt_conf_v4l2_heading_title": "USB Capture", - "edt_conf_v4l2_input_expl": "Select the video input of your device. 'Automatic' keeps the value chosen by the v4l2 interface.", - "edt_conf_v4l2_input_title": "Input", - "edt_conf_v4l2_redSignalThreshold_expl": "Darkens low red values (recognized as black)", - "edt_conf_v4l2_redSignalThreshold_title": "Red signal threshold", - "edt_conf_v4l2_resolution_expl": "A list of supported resolutions of the active device", - "edt_conf_v4l2_resolution_title": "Device Resolution", - "edt_conf_v4l2_sDHOffsetMax_expl": "Signal detection area horizontal maximum (0.0-1.0)", - "edt_conf_v4l2_sDHOffsetMax_title": "Signal Detection HMax", - "edt_conf_v4l2_sDHOffsetMin_expl": "Signal detection area horizontal minimum (0.0-1.0)", - "edt_conf_v4l2_sDHOffsetMin_title": "Signal Detection HMin", - "edt_conf_v4l2_sDVOffsetMax_expl": "Signal detection area vertical maximum (0.0-1.0)", - "edt_conf_v4l2_sDVOffsetMax_title": "Signal Detection VMax", - "edt_conf_v4l2_sDVOffsetMin_expl": "Signal detection area vertical minimum (0.0-1.0)", - "edt_conf_v4l2_sDVOffsetMin_title": "Signal Detection VMin", - "edt_conf_v4l2_signalDetection_expl": "If enabled, usb capture will be temporarily disabled when no signal was found. This will happen when the picture fall below the threshold value for a period of 4 seconds.", - "edt_conf_v4l2_signalDetection_title": "Signal detection", - "edt_conf_v4l2_sizeDecimation_expl": "The factor of size decimation. 1 means no decimation (keep original size)", - "edt_conf_v4l2_sizeDecimation_title": "Size decimation", - "edt_conf_v4l2_standard_expl": "Select the video standard for your region. 'Automatic' keeps the value chosen by the v4l2 interface.", - "edt_conf_v4l2_standard_title": "Video standard", - "edt_conf_v4l2_flip_expl": "This allows you to flip the image horizontally, vertically, or both.", - "edt_conf_v4l2_flip_title": "Image flip", - "edt_conf_v4l2_fpsSoftwareDecimation_title" : "Software frame skipping", - "edt_conf_v4l2_fpsSoftwareDecimation_expl" : "To save resources every n'th frame will be processed only. For ex. if grabber is set to 30FPS with this option set to 5 the final result will be around 6FPS (1 - disabled)", - "edt_conf_v4l2_encoding_title" : "Encoding format", - "edt_conf_v4l2_encoding_expl" : "Force video encoding for multiformat capable grabbers", - "edt_conf_v4l2_hardware_brightness_title" : "Hardware brightness control", - "edt_conf_v4l2_hardware_brightness_expl" : "Set hardware brightness if device supports it, check logs (0=disabled)", - "edt_conf_v4l2_hardware_contrast_title" : "Hardware contrast control", - "edt_conf_v4l2_hardware_contrast_expl" : "Set hardware contrast if device supports it, check logs (0=disabled)", - "edt_conf_v4l2_noSignalCounterThreshold_title" : "Signal Counter Threshold", - "edt_conf_v4l2_noSignalCounterThreshold_expl" : "Count of frames (check that with grabber's current FPS mode) after which the no signal is triggered", - "edt_conf_v4l2_hardware_saturation_title" : "Hardware saturation control", - "edt_conf_v4l2_hardware_saturation_expl" : "Set hardware saturation if device supports it, check logs (0=disabled)", - "edt_conf_v4l2_hardware_hue_title" : "Hardware hue control", - "edt_conf_v4l2_hardware_hue_expl" : "Set hardware hue if device supports it, check logs (0=disabled)", - "edt_conf_webc_crtPath_expl": "Path to the certification file (format should be PEM)", - "edt_conf_webc_crtPath_title": "Certificate path", - "edt_conf_webc_docroot_expl": "Local webinterface root path (just for webui developer)", - "edt_conf_webc_docroot_title": "Document Root", - "edt_conf_webc_heading_title": "Web Configuration", - "edt_conf_webc_keyPassPhrase_expl": "Optional: The key might be protected with a password", - "edt_conf_webc_keyPassPhrase_title": "Key password", - "edt_conf_webc_keyPath_expl": "Path to the key file (format PEM, encrypted with RSA)", - "edt_conf_webc_keyPath_title": "Private key path", - "edt_conf_webc_sslport_expl": "Port oft the HTTPS-Webserver", - "edt_conf_webc_sslport_title": "HTTPS Port", - "edt_dev_auth_key_title": "Authentication Token", - "edt_dev_enum_sub_min_cool_adjust": "Subtract cool white", - "edt_dev_enum_sub_min_warm_adjust": "Subtract warm white", - "edt_dev_enum_subtract_minimum": "Subtract minimum", - "edt_dev_enum_white_off": "White off", - "edt_dev_general_colorOrder_title": "RGB byte order", - "edt_dev_general_hardwareLedCount_title": "Hardware LED count", - "edt_dev_general_heading_title": "General Settings", - "edt_dev_general_name_title": "Configuration name", - "edt_dev_general_rewriteTime_title": "Refresh time", - "edt_dev_spec_FCledToOn_title": "Fadecandy LED set to on", - "edt_dev_spec_FCmanualControl_title": "Manual control of fadecandy LED", - "edt_dev_spec_FCsetConfig_title": "Set fadecandy configuration", - "edt_dev_spec_LBap102Mode_title": "LightBerry APA102 Mode", - "edt_dev_spec_PBFiFo_title": "Pi-Blaster FiFo", - "edt_dev_spec_baudrate_title": "Baudrate", - "edt_dev_spec_blackLightsTimeout_title": "Signal detection timeout on black", - "edt_dev_spec_brightnessFactor_title": "Brightness factor", - "edt_dev_spec_brightnessMax_title": "Brightness maximum", - "edt_dev_spec_brightnessMin_title": "Brightness minimum", - "edt_dev_spec_brightnessThreshold_title": "Signal detection brightness minimum", - "edt_dev_spec_chanperfixture_title": "Channels per Fixture", - "edt_dev_spec_cid_title": "CID", - "edt_dev_spec_clientKey_title": "Clientkey", - "edt_dev_spec_colorComponent_title": "Colour component", - "edt_dev_spec_debugLevel_title": "Debug Level", - "edt_dev_spec_debugStreamer_title": "Streamer Debug", - "edt_dev_spec_delayAfterConnect_title": "Delay after connect", - "edt_dev_spec_dithering_title": "Dithering", - "edt_dev_spec_dmaNumber_title": "DMA channel", - "edt_dev_spec_gamma_title": "Gamma", - "edt_dev_spec_globalBrightnessControlMaxLevel_title": "Max Current Level", - "edt_dev_spec_globalBrightnessControlThreshold_title": "Adaptive Current Threshold", - "edt_dev_spec_gpioBcm_title": "GPIO Pin", - "edt_dev_spec_gpioMap_title": "GPIO mapping", - "edt_dev_spec_gpioNumber_title": "GPIO number", - "edt_dev_spec_groupId_title": "Group ID", - "edt_dev_spec_header_title": "Specific Settings", - "edt_dev_spec_interpolation_title": "Interpolation", - "edt_dev_spec_intervall_title": "Interval", - "edt_dev_spec_invert_title": "Invert signal", - "edt_dev_spec_latchtime_title": "Latch time", - "edt_dev_spec_ledIndex_title": "LED index", - "edt_dev_spec_ledType_title": "LED Type", - "edt_dev_spec_lightid_itemtitle": "ID", - "edt_dev_spec_lightid_title": "Light ID(s)", - "edt_dev_spec_lights_itemtitle": "Light", - "edt_dev_spec_lights_name": "Name", - "edt_dev_spec_lights_title": "Light(s)", - "edt_dev_spec_maxPacket_title": "Max packet", - "edt_dev_spec_maximumLedCount_title": "Maximum LED count", - "edt_dev_spec_multicastGroup_title": "Multicast group", - "edt_dev_spec_networkDeviceName_title": "Network devicename", - "edt_dev_spec_networkDevicePort_title": "Port", - "edt_dev_spec_numberOfLeds_title": "Number of LEDs", - "edt_dev_spec_orbIds_title": "Orb ID(s)", - "edt_dev_spec_order_left_right_title": "2.", - "edt_dev_spec_order_top_down_title": "1.", - "edt_dev_spec_outputPath_title": "Output path", - "edt_dev_spec_panel_start_position": "Start panel [0-max panels]", - "edt_dev_spec_panelorganisation_title": "Panel numbering sequence", - "edt_dev_spec_pid_title": "PID", - "edt_dev_spec_port_title": "Port", - "edt_dev_spec_printTimeStamp_title": "Add timestamp", - "edt_dev_spec_pwmChannel_title": "PWM channel", - "edt_dev_spec_restoreOriginalState_title": "Restore lights' original state when disabled", - "edt_dev_spec_serial_title": "Serial number", - "edt_dev_spec_spipath_title": "SPI path", - "edt_dev_spec_sslHSTimeoutMax_title": "Streamer handshake timeout maximum", - "edt_dev_spec_sslHSTimeoutMin_title": "Streamer handshake timeout minimum", - "edt_dev_spec_sslReadTimeout_title": "Streamer read timeout", - "edt_dev_spec_switchOffOnBlack_title": "Switch off on black", - "edt_dev_spec_switchOffOnbelowMinBrightness_title": "Switch-off, below minimum", - "edt_dev_spec_targetIpHost_title": "Target IP/Hostname", - "edt_dev_spec_targetIp_title": "Target IP", - "edt_dev_spec_transeffect_title": "Transition effect", - "edt_dev_spec_transistionTimeExtra_title": "Extra time darkness", - "edt_dev_spec_transistionTime_title": "Transition time", - "edt_dev_spec_uid_title": "UID", - "edt_dev_spec_universe_title": "Universe", - "edt_dev_spec_useEntertainmentAPI_title": "Use Hue Entertainment API", - "edt_dev_spec_useOrbSmoothing_title": "Use orb smoothing", - "edt_dev_spec_useRgbwProtocol_title": "Use RGBW protocol", - "edt_dev_spec_username_title": "Username", - "edt_dev_spec_verbose_title": "Log all Hue commands", - "edt_dev_spec_vid_title": "VID", - "edt_dev_spec_whiteLedAlgor_title": "White LED algorithm", - "edt_dev_spec_whitepoint_title": "Whitepoint", - "edt_eff_alarmcolor": "Alarm color", - "edt_eff_backgroundColor": "Background Color", - "edt_eff_basecolorchange": "Base color change", - "edt_eff_basecolorchangerate": "BC change rate", - "edt_eff_basecolorrangeleft": "BC range left", - "edt_eff_basecolorrangeright": "BC range right", - "edt_eff_blobcount": "Blob count", - "edt_eff_brightness": "Brightness", - "edt_eff_candle_header": "Candle", - "edt_eff_candle_header_desc": "Shimmering candles", - "edt_eff_centerx": "Center X-Axis", - "edt_eff_centery": "Center Y-Axis", - "edt_eff_collision_header": "color collision", - "edt_eff_collision_header_desc": "Two color projectiles are sent from random positions and collide with each other", - "edt_eff_color": "Color", - "edt_eff_colorHour": "Color hour", - "edt_eff_colorMarker": "Marker color", - "edt_eff_colorMinute": "Color minute", - "edt_eff_colorSecond": "Color second", - "edt_eff_colorcount": "Color length", - "edt_eff_colorend": "Color end", - "edt_eff_colorendtime": "Time to hold start color", - "edt_eff_colorevel": "Color level", - "edt_eff_colorone": "Color one", - "edt_eff_colorrandom": "Random color", - "edt_eff_colorshift": "Color Shift", - "edt_eff_colorstart": "Color start", - "edt_eff_colorstarttime": "Time to hold end color", - "edt_eff_colortwo": "Color two", - "edt_eff_count": "Count", - "edt_eff_countries": "Countries", - "edt_eff_customColor": "Custom Color", - "edt_eff_enableSecondSwirl": "Second Swirl", - "edt_eff_enableshutdown": "Real shutdown", - "edt_eff_enum_all": "All", - "edt_eff_enum_all-together": "All together", - "edt_eff_enum_list": "LED List", - "edt_eff_explodeRadius": "Detonation Range ", - "edt_eff_fade_header": "Fade", - "edt_eff_fade_header_desc": "Fades between colors", - "edt_eff_fadefactor": "Fade factor", - "edt_eff_fadeintime": "Fade in time", - "edt_eff_fadeouttime": "Fade out time", - "edt_eff_flag_header": "Flags", - "edt_eff_flag_header_desc": "Let your LEDs shine bright in the colours of your country. You can select more than one flag and they will change based on the interval time.", - "edt_eff_fps": "Frames per seconds", - "edt_eff_frequency": "Frequency", - "edt_eff_gif_header": "GIF's", - "edt_eff_gif_header_desc": "This effect plays .gif files, provide a simple video like loop as effect.", - "edt_eff_height": "Height", - "edt_eff_huechange": "Color change", - "edt_eff_image": "Image file", - "edt_eff_interval": "Interval", - "edt_eff_knightrider_header": "Knight Rider", - "edt_eff_knightrider_header_desc": "K.I.T.T is back! The front-scanner of the well known car, this time not just in red.", - "edt_eff_ledlist": "Led List", - "edt_eff_ledtest_header": "Led Test", - "edt_eff_ledtest_header_desc": "Rotating output: Red, Blue, Green, White, Black", - "edt_eff_length": "Length", - "edt_eff_lightclock_header": "Light Clock", - "edt_eff_lightclock_header_desc": "A real clock as light! Adjust the colors of hours, minute, seconds. A optional 3/6/9/12 o'clock marker is also available. In case the clock is wrong, you need to check your system clock.", - "edt_eff_maintain_end_color": "Keep endcolor", - "edt_eff_margin": "Margin", - "edt_eff_markerDepth": "Marker depth", - "edt_eff_markerEnable": "Show Marker", - "edt_eff_markerWidth": "Marker width", - "edt_eff_max_len": "Maximal length", - "edt_eff_min_len": "Minimal length", - "edt_eff_moodblobs_header": "Mood Blobs", - "edt_eff_moodblobs_header_desc": "Relax at the evening with slow moving and color changing blobs.", - "edt_eff_offset": "Offset", - "edt_eff_pacman_header": "Pac-Man", - "edt_eff_pacman_header_desc": "Small hungry and yellow. Who will survive?", - "edt_eff_plasma_header": "Plasma", - "edt_eff_plasma_header_desc": "Color distortion in different directions", - "edt_eff_police_header": "Police", - "edt_eff_police_header_desc": "Lights like a police car in action", - "edt_eff_postcolor": "Post color", - "edt_eff_rainbowmood_header": "Rainbow Mood", - "edt_eff_rainbowmood_header_desc": "All LEDs rainbow mood", - "edt_eff_randomCenter": "Random Center", - "edt_eff_random_header": "Random", - "edt_eff_random_header_desc": "Pixel Dot, dot, dot...", - "edt_eff_repeat": "Repeat", - "edt_eff_repeatcount": "Repeat count", - "edt_eff_reverseRandomTime": "Reverse every", - "edt_eff_reversedirection": "Reverse direction", - "edt_eff_rotationtime": "Rotation time", - "edt_eff_saturation": "Saturation", - "edt_eff_showseconds": "Show seconds", - "edt_eff_sleeptime": "Sleep time", - "edt_eff_smooth_custom": "Enable smoothing", - "edt_eff_smooth_time_ms": "Smoothing time", - "edt_eff_smooth_updateFrequency": "Smoothing update frequency", - "edt_eff_snake_header": "Snake", - "edt_eff_snake_header_desc": "Where is something to eat?", - "edt_eff_sparks_header": "Sparks", - "edt_eff_sparks_header_desc": "Star-Sparking, choose between a static color or random. You could also adjust brightness, saturation and speed.", - "edt_eff_speed": "Speed", - "edt_eff_swirl_header": "Color Swirl", - "edt_eff_swirl_header_desc": "A swirl with custom colors. Colors are even spread to 360°, in between colors shifts will be calculated. Additional you can add a second swirl on top, be aware that you need partly transparency! Hint: A repeat of the same color results in a \"higher\" color area and a reduced color shift area.", - "edt_eff_systemshutdown_header": "System Shutdown", - "edt_eff_systemshutdown_header_desc": "A short animation with probably a real system shutdown", - "edt_eff_traces_header": "Color Traces", - "edt_eff_traces_header_desc": "Requires redesign", - "edt_eff_trails_header": "Falling stars", - "edt_eff_trails_header_desc": "Colored stars that fall from top to bottom", - "edt_eff_waves_header": "Waves", - "edt_eff_waves_header_desc": "Waves of color! Choose your colors, rotation time, direction reverse and more.", - "edt_eff_whichleds": "Which LEDs", - "edt_eff_whitelevel": "White level", - "edt_eff_x-mas_header": "X-Mas", - "edt_eff_x-mas_header_desc": "Touch of Christmas", - "edt_msg_button_add_row_title": "Add $1", - "edt_msg_button_collapse": "Collapse", - "edt_msg_button_delete_all": "All", - "edt_msg_button_delete_all_title": "Delete All", - "edt_msg_button_delete_last": "Last $1", - "edt_msg_button_delete_last_title": "Delete Last $1", - "edt_msg_button_delete_row_title": "Delete $1", - "edt_msg_button_delete_row_title_short": "Delete", - "edt_msg_button_expand": "Expand", - "edt_msg_button_move_down_title": "Move down", - "edt_msg_button_move_up_title": "Move up", - "edt_msg_error_additionalItems": "No additional items allowed in this array", - "edt_msg_error_additional_properties": "No additional properties allowed, but property $1 is set", - "edt_msg_error_anyOf": "Value must validate against at least one of the provided schemas", - "edt_msg_error_dependency": "Must have property $1", - "edt_msg_error_disallow": "Value must not be of type $1", - "edt_msg_error_disallow_union": "Value must not be one of the provided disallowed types", - "edt_msg_error_enum": "Value must be one of the enumerated values", - "edt_msg_error_maxItems": "Value must have at most $1 items", - "edt_msg_error_maxLength": "Value must be at most $1 characters long", - "edt_msg_error_maxProperties": "Object must have at most $1 properties", - "edt_msg_error_maximum_excl": "Value must be less than $1", - "edt_msg_error_maximum_incl": "Value must be at most $1", - "edt_msg_error_minItems": "Value must have at least $1 items", - "edt_msg_error_minLength": "Value must be at least $1 characters long", - "edt_msg_error_minProperties": "Object must have at least $1 properties", - "edt_msg_error_minimum_excl": "Value must be greater than $1", - "edt_msg_error_minimum_incl": "Value must be at least $1", - "edt_msg_error_multipleOf": "Value must be a multiple of $1", - "edt_msg_error_not": "Value must not validate against the provided schema", - "edt_msg_error_notempty": "Value required", - "edt_msg_error_notset": "Property must be set", - "edt_msg_error_oneOf": "Value must validate against exactly one of the provided schemas. It currently validates against $1 of the schemas.", - "edt_msg_error_pattern": "Value must match the pattern", - "edt_msg_error_required": "Object is missing the required property '$1'", - "edt_msg_error_type": "Value must be of type $1", - "edt_msg_error_type_union": "Value must be one of the provided types", - "edt_msg_error_uniqueItems": "Array must have unique items", - "effectsconfigurator_button_conttest": "Continuous test", - "effectsconfigurator_button_deleffect": "Delete Effect", - "effectsconfigurator_button_editeffect": "Load Effect", - "effectsconfigurator_button_saveeffect": "Save Effect", - "effectsconfigurator_button_starttest": "Start test", - "effectsconfigurator_button_stoptest": "Stop test", - "effectsconfigurator_editdeleff": "Delete/Load Effect", - "effectsconfigurator_label_chooseeff": "Choose Template", - "effectsconfigurator_label_effectname": "Effect name", - "effectsconfigurator_label_intro": "Create out of the base effects new effects that are tuned to your liking. Depending on Effect there are options like color, speed, direction and more available.", - "general_access_advanced": "Advanced", - "general_access_default": "Default", - "general_access_expert": "Expert", - "general_btn_back": "Back", - "general_btn_cancel": "Cancel", - "general_btn_continue": "Continue", - "general_btn_delete": "Delete", - "general_btn_denyAccess": "Deny Access", - "general_btn_grantAccess": "Grant Access", - "general_btn_iswitch": "Switch", - "general_btn_next": "Next", - "general_btn_off": "Off", - "general_btn_ok": "OK", - "general_btn_on": "On", - "general_btn_rename": "Rename", - "general_btn_restarthyperion": "Restart Hyperion", - "general_btn_save": "Save", - "general_btn_saveandreload": "Save and reload", - "general_btn_saverestart": "Save and restart", - "general_btn_start": "Start", - "general_btn_stop": "Stop", - "general_btn_yes": "Yes", - "general_button_savesettings": "Save settings", - "general_chars_needed": "more characters needed", - "general_col_blue": "blue", - "general_col_green": "green", - "general_col_red": "red", - "general_comp_BLACKBORDER": "Blackbar Detection", - "general_comp_BOBLIGHTSERVER": "Boblight Server", - "general_comp_FLATBUFSERVER": "Flatbuffers Server", - "general_comp_FORWARDER": "Forwarder", - "general_comp_GRABBER": "Platform Capture", - "general_comp_LEDDEVICE": "LED device", - "general_comp_PROTOSERVER": "Protocol Buffers Server", - "general_comp_SMOOTHING": "Smoothing", - "general_comp_V4L": "USB Capture", - "general_country_cn": "China", - "general_country_de": "Germany", - "general_country_es": "Spain", - "general_country_fr": "France", - "general_country_it": "Italy", - "general_country_nl": "Netherlands", - "general_country_ru": "Russia", - "general_country_uk": "United Kingdom", - "general_country_us": "United States", - "general_speech_cs": "Czech", - "general_speech_de": "German", - "general_speech_en": "English", - "general_speech_es": "Spanish", - "general_speech_fr": "French", - "general_speech_it": "Italian", - "general_speech_nl": "Dutch", - "general_speech_pl": "Polish", - "general_speech_ro": "Romanian", - "general_speech_ru": "Russian", - "general_speech_sv": "Swedish", - "general_speech_tr": "Turkish", - "general_speech_vi": "Vietnamese", - "general_speech_zh-CN": "Chinese (simplified)", - "general_webui_title": "Hyperion - Web Configuration", - "general_wiki_moreto": "More information to \"$1\" at our Wiki", - "infoDialog_checklist_title": "Checklist!", - "infoDialog_effconf_created_text": "The effect \"$1\" has been created successfully!", - "infoDialog_effconf_deleted_text": "The effect \"$1\" has been deleted successfully!", - "infoDialog_general_error_title": "Error", - "infoDialog_general_success_title": "Success", - "infoDialog_general_warning_title": "Warning", - "infoDialog_import_comperror_text": "Sad! Your browser doesn't support a import. Please try again with another browser.", - "infoDialog_import_confirm_text": "Are you sure to import \"$1\"? This process can't be reverted!", - "infoDialog_import_confirm_title": "Confirm import", - "infoDialog_import_hyperror_text": "The selected configuration file \"$1\" can't be imported. It's not compatible with Hyperion 2.0 and higher!", - "infoDialog_import_jsonerror_text": "The selected configuration file \"$1\" is no .json file or it's corrupted. Error message: ($2)", - "infoDialog_wizrgb_text": "Your RGB Byte Order is already well adjusted.", - "infoDialog_writeconf_error_text": "Saving your configuration failed.", - "infoDialog_writeimage_error_text": "The selected file \"$1\" is no image file or it's corrupted! Please select another image file.", - "info_404": "The page you requested is not available!", - "info_conlost_label_autorecon": "We reconnect again after Hyperion is available.", - "info_conlost_label_autorefresh": "This page will be automatically refreshed.", - "info_conlost_label_reason": "Possible reasons:", - "info_conlost_label_reason1": "- Bad WLAN connection", - "info_conlost_label_reason2": "- You perform an update", - "info_conlost_label_reason3": "- Hyperion isn't running", - "info_conlost_label_reload": "Auto reconnect stopped - limit exceeded, please refresh page or click me.", - "info_conlost_label_title": "Lost connection to Hyperion service!", - "info_restart_contus": "If you still hang around here after 20 seconds and you have no clue why please open a new topic at our support forum...", - "info_restart_contusa": "...with your last steps. Thank you!", - "info_restart_rightback": "Hyperion will be right back immediately!", - "info_restart_title": "Restarts currently...", - "main_ledsim_btn_togglelednumber": "LED numbers", - "main_ledsim_btn_toggleleds": "Show LEDs", - "main_ledsim_btn_togglelivevideo": "Live video", - "main_ledsim_text": "Live visualization of led colors and optional the current video stream of your capture device.", - "main_ledsim_title": "LED Visualization", - "main_menu_about_token": "About Hyperion", - "main_menu_colors_conf_token": "Image Processing", - "main_menu_configuration_token": "Configuration", - "main_menu_dashboard_token": "Dashboard", - "main_menu_effect_conf_token": "Effects", - "main_menu_effectsconfigurator_token": "Effects Configurator", - "main_menu_general_conf_token": "General", - "main_menu_grabber_conf_token": "Capturing Hardware", - "main_menu_input_selection_token": "Input Selection", - "main_menu_leds_conf_token": "LED Hardware", - "main_menu_logging_token": "Log", - "main_menu_network_conf_token": "Network Services", - "main_menu_remotecontrol_token": "Remote Control", - "main_menu_support_token": "Support", - "main_menu_system_token": "System", - "main_menu_update_token": "Update", - "main_menu_webconfig_token": "Web configuration", - "remote_adjustment_intro": "Modify color/brightness/compensation during runtime. $1", - "remote_adjustment_label": "Color adjustment", - "remote_color_button_reset": "Reset Color/Effect", - "remote_color_intro": "Set an effect or color. Also your self created effects are listed (if available). $1", - "remote_color_label": "Colors/Effects", - "remote_color_label_color": "Color:", - "remote_components_intro": "Enable and disable components of Hyperion during runtime. $1", - "remote_components_label": "Components control", - "remote_effects_label_effects": "Effect:", - "remote_effects_label_picture": "Picture:", - "remote_input_clearall": "Clear all Effects/Colors", - "remote_input_duration": "Duration:", - "remote_input_intro": "Hyperion uses a priority system to select a source. Everything you set has a priority (Effect/Color/Platform capture/USB capture and network sources). By default, Hyperion select sources depending on priority (lowest number reflects the current active source). Now you have the opportunity to select sources on your own. $1", - "remote_input_ip": "IP:", - "remote_input_label": "Source Selection", - "remote_input_label_autoselect": "Auto Selection", - "remote_input_origin": "Origin", - "remote_input_owner": "Type", - "remote_input_priority": "Priority", - "remote_input_setsource_btn": "Select Source", - "remote_input_sourceactiv_btn": "Source active", - "remote_input_status": "Status/Action", - "remote_losthint": "Note: All changes are lost after a restart.", - "remote_maptype_intro": "Usually the led layout defines which LED covers a specific picture area, you could change it here: $1.", - "remote_maptype_label": "Mapping type", - "remote_maptype_label_multicolor_mean": "Multicolor", - "remote_maptype_label_unicolor_mean": "Unicolor", - "remote_optgroup_syseffets": "Provided Effects", - "remote_optgroup_usreffets": "User Effects", - "remote_videoMode_2D": "2D", - "remote_videoMode_3DSBS": "3DSBS", - "remote_videoMode_3DTAB": "3DTAB", - "remote_videoMode_intro": "Switch between different video modes to enjoy 3D movies! Supported are all capture devices. $1", - "remote_videoMode_label": "Video mode", - "support_label_affinstr1": "Click on the appropriate link of your country", - "support_label_affinstr2": "Everything you buy (doesn't matter what) we get a small fee based on your turnover", - "support_label_affinstr3": "You ALWAYS pay the same price, there is absolutely no difference. Try it out!", - "support_label_btctext": "Address:", - "support_label_donate": "Donate or use our affiliate links", - "support_label_donationpp": "Donation:", - "support_label_fbtext": "Share our Hyperion Facebook page and get a notice when new updates are released", - "support_label_forumtext": "Showcases, discussions, help and more", - "support_label_forumtitle": "Forum", - "support_label_ggtext": "Circle us on Google +!", - "support_label_ghtext": "Visit us on GitHub", - "support_label_igtext": "Visit us on Instagram to watch the latest Hyperion pictures!", - "support_label_intro": "Hyperion is a free non-profit software. A small team is working on it and this is why we need your steady support.", - "support_label_spreadtheword": "Spread the word", - "support_label_title": "Support Hyperion", - "support_label_twtext": "Share and follow on Twitter, be always up to date with latest post about the Hyperion development", - "support_label_webpagetext": "Home of Hyperion", - "support_label_webpagetitle": "Webpage", - "support_label_webrestitle": "Information and help resources", - "support_label_wikitext": "The A to Z source for almost everything Hyperion related", - "support_label_wikititle": "Wiki", - "support_label_yttext": "Bored from pictures? Check out our YouTube channel!", - "update_button_changelog": "Full changelog", - "update_button_install": "Install", - "update_error_getting_versions": "We had trouble determining the latest available Version.", - "update_label_description": "Description:", - "update_label_intro": "Overview about all available Hyperion versions. On top you could update or downgrade your version of Hyperion whenever you want. Sorted from newest to oldest", - "update_label_type": "Type:", - "update_no_updates_for_branch": "No updates for selected version channel.", - "update_versreminder": "Your version: $1", - "wiz_atmoorb_desc2": "Now choose which Orbs should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.", - "wiz_atmoorb_intro1": "This wizards configures Hyperion for AtmoOrbs. Features are the AtmoOrb auto detection, setting each light to a specific position on your picture or disable it and optimise the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", - "wiz_atmoorb_title": "AtmoOrb Wizard", - "wiz_cc_adjustgamma": "Gamma: What you have to do is, adjust gamma levels of each channel until you have the same perceived amount of each channel. Hint: Neutral is 1.0! For example, if your Grey is a bit reddish it means that you have to increase red gamma to reduce the amount of red (the more gamma, the less amount of color).", - "wiz_cc_adjustit": "Adjust your \"$1\", until your are fine with it. Take notice: The more you adjust away from the default value the color spectrum will be limited (Also for all colors in between). Depending on TV/LED color spectrum the results will vary.", - "wiz_cc_backlight": "Additional you could define a backlight to sort out \"bad colors\" on nearly dark areas or if you don't like the switch between color and off during watching. Additional you could define if there should be some color in it or just white. This is disabled during the state \"Off\" ,\"Color\" and \"Effect\".", - "wiz_cc_btn_stop": "Stop video", - "wiz_cc_btn_switchpic": "Switch picture", - "wiz_cc_chooseid": "Define a name for this color profile.", - "wiz_cc_intro1": "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be sent directly to it. Prerequisite: You need to enable \"Allow remote control from applications on other systems\" in Kodi.
Alternatively, you might want downloading these files yourself and display them when the wizard asks you to adjust the setting.", - "wiz_cc_kodicon": "Kodi found, proceed with Kodi support.", - "wiz_cc_kodidiscon": "Kodi not found, proceed without Kodi support.", - "wiz_cc_kodidisconlink": "Download link pictures:", - "wiz_cc_kodimsg_start": "Test success - time to proceed!", - "wiz_cc_kodishould": "Kodi should show the following picture: $1", - "wiz_cc_kwebs": "Kodi webserver (Hostname or IP)", - "wiz_cc_lettvshow": "Let your TV show the following picture: $1", - "wiz_cc_lettvshowm": "Check this with the following pictures: $1", - "wiz_cc_link": "Click me!", - "wiz_cc_morethanone": "You have more than one profile, please choose the profile you want to calibrate.", - "wiz_cc_summary": "A conclusion of your settings. During video playback, you could change or test values again. If you are done, click on save.", - "wiz_cc_testintro": "Time for a real test!", - "wiz_cc_testintrok": "Push on a button below to start a test video.", - "wiz_cc_testintrowok": "Check out the following link to download test videos:", - "wiz_cc_title": "Colour calibration wizard", - "wiz_cololight_desc2": "Now choose which Cololights should be added. To identify single lights, press the button on the right.", - "wiz_cololight_intro1": "This wizards configures Hyperion for the Cololight system. Features are the Cololight auto detection and tune the Hyperion settings automatically! In short: All you need are some clicks and you are done!
Note: In case of Cololight Strip, you might need to manually correct the LED count and layout.", - "wiz_cololight_noprops": "Not able to get device properties - Define Hardware LED count manually", - "wiz_cololight_title": "Cololight Wizard", - "wiz_guideyou": "The $1 will guide you through the settings. Just press the button!", - "wiz_hue_blinkblue": "Let ID $1 light up blue", - "wiz_hue_clientkey": "Clientkey:", - "wiz_hue_create_user": "Create new User", - "wiz_hue_desc1": "It searches automatically for a Hue-Bridge, in case it can't find one you need to provide the IP-address and push the reload button on the right. Now you need a user ID, if you don't have one create a new one.", - "wiz_hue_desc2": "Now choose which lamps should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.", - "wiz_hue_e_clientkey_needed": "A clientkey that matches the username is required to use the entertainment API. Please enter an existing one or use the button below to create a new one.", - "wiz_hue_e_create_user": "Create new User and clientkey", - "wiz_hue_e_desc1": "It searches automatically for a hue bridge, in case it can't find one you need to provide the ip address and push the reload button on the right. Now you need a user id and the clientkey, if you don't have both, create a new one.", - "wiz_hue_e_desc2": "Now choose your entertainment group, which has all your lights inside for use with Hyperion.", - "wiz_hue_e_desc3": "Now you can choose in which position the respective lamp should be \"in the picture\". A preselection of the position was made based on the configured positions of the lights in the entertainment group. This is just a recommendation and can be customized as desired. You can therefore highlight them briefly by clicking on the right button to improve the selection.", - "wiz_hue_e_intro1": "This wizards configures Hyperion for the well known Philips Hue Entertainment system. Features are: Hue Bridge auto detection, user and clientkey creation, entertainment group selection, setting group lights to a specific position on your picture and optimise the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", - "wiz_hue_e_noapisupport": "The Wizard has disabled entertainment API support and will continue in classic mode.", - "wiz_hue_e_noapisupport_hint": "The option \"Use Hue Entertainment API\" was unchecked.", - "wiz_hue_e_noegrpids": "No entertainment groups in this Hue bridge defined.", - "wiz_hue_e_nogrpids": "This Hue bridge has no groups defined, please create at least one before with the Hue Apps.", - "wiz_hue_e_title": "Philips Hue Entertainment Wizard", - "wiz_hue_e_use_group": "Use group", - "wiz_hue_e_use_groupid": "Use group ID $1", - "wiz_hue_failure_connection": "Timeout: Please press the bridge button within the period of 30 seconds", - "wiz_hue_failure_ip": "No Bridge found, please type in a valid IP-Address", - "wiz_hue_failure_user": "User not found, create a new one with the button below or input a valid user id and press the \"reload\" symbol.", - "wiz_hue_intro1": "This wizards configures Hyperion for the well known Philips Hue system. Features are Hue Bridge auto detection, user creation, set each hue light to a specific position on your picture or disable it and tune the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", - "wiz_hue_ip": "Hue Bridge IP:", - "wiz_hue_noids": "This Hue bridge has no bulbs/stripes, please pair them before with the Hue Apps", - "wiz_hue_press_link": "Please press link button on the Hue Bridge.", - "wiz_hue_searchb": "Searching for bridge...", - "wiz_hue_title": "Philips Hue Wizard", - "wiz_hue_username": "User ID:", - "wiz_identify": "Identify", - "wiz_identify_light": "Identify $1", - "wiz_ids_disabled": "Deactivated", - "wiz_ids_entire": "Whole picture", - "wiz_noLights": "No $1 found! Please get the lights connected to the network or configure them manually.", - "wiz_pos": "Position/State", - "wiz_rgb_expl": "The color dot switches every x seconds the color (red, green), at the same time your LEDs switch the color too. Answer the questions at the bottom to check/correct your byte order.", - "wiz_rgb_intro1": "This wizard will guide you through the finding process of the correct color order for your leds. Click on continue to begin.", - "wiz_rgb_intro2": "When do you need this wizard? Example: You set the color red, but you get green or blue. You could also use it for first configuration.", - "wiz_rgb_q": "Which color show your LEDs, when the color dot above shows...", - "wiz_rgb_qgend": "...green?", - "wiz_rgb_qrend": "...red?", - "wiz_rgb_switchevery": "Switch color every...", - "wiz_rgb_title": "RGB Byte Order Wizard", - "wiz_wizavail": "Wizard available", - "wiz_yeelight_desc2": "Now choose which lamps should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.", - "wiz_yeelight_intro1": "This wizards configures Hyperion for the Yeelight system. Features are the Yeelighs' auto detection, setting each light to a specific position on your picture or disable it and tune the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", - "wiz_yeelight_title": "Yeelight Wizard", - "wiz_yeelight_unsupported": "Unsupported" + "InfoDialog_access_text": "Depending on settings level you could adjust more options or get access to more features. Recommended is the \"Default\" level.", + "InfoDialog_access_title": "Settings level", + "InfoDialog_changePassword_success": "Password successfully saved!", + "InfoDialog_changePassword_title": "Change Password", + "InfoDialog_iswitch_text": "If you run Hyperion more than once in your local network, you could switch between the web configurations. Select the Hyperion instance below and switch!", + "InfoDialog_iswitch_title": "Hyperion switcher", + "InfoDialog_lang_text": "If you don't like the result of the automatic language detection you could overwrite it here.", + "InfoDialog_lang_title": "Language setting", + "InfoDialog_nowrite_foottext": "The WebUI will be unlocked automatically after you solved the problem!", + "InfoDialog_nowrite_text": "Hyperion can't write to your current loaded configuration file. Please repair the file permissions to proceed.", + "InfoDialog_nowrite_title": "write permission error!", + "about_3rd_party_licenses": "3rd party licenses", + "about_3rd_party_licenses_error": "We had trouble collecting 3rd party licenses information from web.
Please follow this link to the GitHub Resource.", + "about_build": "Build", + "about_builddate": "Build date", + "about_contribute": "Develop Hyperion further with us!", + "about_credits": "Credits to all these developers!", + "about_resources": "$1 libraries", + "about_translations": "Translations", + "about_version": "Version", + "conf_colors_blackborder_intro": "Skip black bars wherever they are. Each mode use another detection algorithm which is tuned for special situations. Higher the threshold if it doesn't work for you.", + "conf_colors_color_intro": "Create one or more calibration profiles, adjust each color, brightness, linearization and more.", + "conf_colors_smoothing_intro": "Smoothing flattens color/brightness changes to reduce annoying distraction.", + "conf_effect_bgeff_intro": "Define a background effect/color, which is shown during Hyperion \"idle\". Starts always with priority channel 255.", + "conf_effect_fgeff_intro": "Define a boot-effect or color, which is shown during Hyperion startup for the defined duration.", + "conf_effect_path_intro": "Load effects from the defined paths. Additional you can disable single effects by name to hide them from all effect lists.", + "conf_general_createInst_btn": "Create Instance", + "conf_general_impexp_expbtn": "Export", + "conf_general_impexp_impbtn": "Import", + "conf_general_impexp_l1": "Import a configuration by selecting a configuration file below and click on \"Import\".", + "conf_general_impexp_l2": "Export a configuration by clicking on \"Export\". Your browser starts a download.", + "conf_general_impexp_title": "Import/Export Configuration", + "conf_general_inst_actionhead": "Action", + "conf_general_inst_delreq_h": "Delete LED Hardware instance", + "conf_general_inst_delreq_t": "Are you sure that you want to delete instance \"$1\"? All settings will be deleted too.", + "conf_general_inst_desc": "Use different LED hardware at the same time. Each instance runs independent of each other which allows different LED layouts and calibration settings. Running instances are available at the top icon bar", + "conf_general_inst_name_title": "New Instance name", + "conf_general_inst_namehead": "Instance name", + "conf_general_inst_renreq_t": "Enter a new name for your instance in the field below.", + "conf_general_inst_title": "LED Hardware Instance Management", + "conf_general_intro": "Basic settings around Hyperion and WebUI that don't fit into another category.", + "conf_general_label_title": "General settings", + "conf_grabber_fg_intro": "Platform capture is your local system capture as input source, Hyperion is installed on.", + "conf_grabber_v4l_intro": "USB capture is a (capture)device connected via USB which is used to input source pictures for processing.", + "conf_helptable_expl": "Explanation", + "conf_helptable_option": "Option", + "conf_leds_contr_label_contrtype": "Controller type:", + "conf_leds_device_intro": "Hyperion supports a lot of controllers to transmit data to your target device. Select a LED controller out of the sorted list and configure it. We have chosen the best default settings for each device.", + "conf_leds_layout_advanced": "Advanced Settings", + "conf_leds_layout_btn_checklist": "Show checklist", + "conf_leds_layout_button_savelay": "Save Layout", + "conf_leds_layout_button_updsim": "Update Preview", + "conf_leds_layout_checkp1": "The black led is your first led, the first led is the point where you input your data signal.", + "conf_leds_layout_checkp2": "The layout is always the front view of your TV, never the back view.", + "conf_leds_layout_checkp3": "Make sure the direction is right. The grey LEDs indicate LED number 2 and 3 to visualise the data direction.", + "conf_leds_layout_checkp4": "Case Gap: To create a gap, ignore it first when you define Top/Bottom/Left/Right and set afterwards your gap length to remove a amount of leds. Modify the gap position until it matches.", + "conf_leds_layout_cl_bottom": "Bottom", + "conf_leds_layout_cl_bottomleft": "Bottom Left (Corner)", + "conf_leds_layout_cl_bottomright": "Bottom Right (Corner)", + "conf_leds_layout_cl_cornergap": "Corner Gap", + "conf_leds_layout_cl_edgegap": "Edge Gap", + "conf_leds_layout_cl_gaglength": "Gap length", + "conf_leds_layout_cl_gappos": "gap position", + "conf_leds_layout_cl_hleddepth": "Horizontal LED depth", + "conf_leds_layout_cl_inppos": "Input position", + "conf_leds_layout_cl_left": "Left", + "conf_leds_layout_cl_leftbottom": "Left 50% - 100% Bottom", + "conf_leds_layout_cl_leftmiddle": "Left 25% - 75% Middle", + "conf_leds_layout_cl_lefttop": "Left 0% - 50% Top", + "conf_leds_layout_cl_overlap": "Overlap", + "conf_leds_layout_cl_reversdir": "Reverse direction", + "conf_leds_layout_cl_right": "Right", + "conf_leds_layout_cl_rightbottom": "Right 50% - 100% Bottom", + "conf_leds_layout_cl_rightmiddle": "Right 25% - 75% Middle", + "conf_leds_layout_cl_righttop": "Right 0% - 50% Top", + "conf_leds_layout_cl_top": "Top", + "conf_leds_layout_cl_topleft": "Top Left (Corner)", + "conf_leds_layout_cl_topright": "Top Right (Corner)", + "conf_leds_layout_cl_vleddepth": "Vertical LED depth", + "conf_leds_layout_frame": "Classic Layout (LED Frame)", + "conf_leds_layout_generatedconf": "Generated/Current LED Configuration", + "conf_leds_layout_intro": "You need also a led layout, which reflects your led positions. The classic layout is the usual used tv frame, but we also support led matrix (led walls) creation. The view on this layout is ALWAYS of the FRONT of your TV.", + "conf_leds_layout_ma_cabling": "Cabling", + "conf_leds_layout_ma_horiz": "Horizontal", + "conf_leds_layout_ma_optbottomleft": "Bottom left", + "conf_leds_layout_ma_optbottomright": "Bottom right", + "conf_leds_layout_ma_opthoriz": "Horizontal", + "conf_leds_layout_ma_optparallel": "Parallel", + "conf_leds_layout_ma_optsnake": "Snake", + "conf_leds_layout_ma_opttopleft": "Top Left", + "conf_leds_layout_ma_opttopright": "Top right", + "conf_leds_layout_ma_optvert": "Vertical", + "conf_leds_layout_ma_order": "Order", + "conf_leds_layout_ma_position": "Input", + "conf_leds_layout_ma_vert": "Vertical", + "conf_leds_layout_matrix": "Matrix Layout (LED Wall)", + "conf_leds_layout_pbl": "Point Bottom Left", + "conf_leds_layout_pbr": "Point Bottom Right", + "conf_leds_layout_peview": "LED Layout Preview", + "conf_leds_layout_preview_l1": "This is your first led (input position)", + "conf_leds_layout_preview_l2": "This visualizes the data direction (second/third led)", + "conf_leds_layout_preview_ledpower": "Max. power consumption: $1 A", + "conf_leds_layout_preview_originCL": "Created from: Classic Layout (LED Frame)", + "conf_leds_layout_preview_originMA": "Created from: Matrix Layout(LED wall)", + "conf_leds_layout_preview_originTEXT": "Created from: Textfield", + "conf_leds_layout_preview_totalleds": "Total LEDs: $1", + "conf_leds_layout_ptl": "Point Top Left", + "conf_leds_layout_ptlh": "Horizontal", + "conf_leds_layout_ptln": "Tripplepoints", + "conf_leds_layout_ptlv": "Vertical", + "conf_leds_layout_ptr": "Point Top Right", + "conf_leds_layout_textf1": "This text field shows by default your current loaded layout and will be overwritten if you generate a new one with the options above. Optional you could perform further edits.", + "conf_leds_nav_label_ledcontroller": "LED Controller", + "conf_leds_nav_label_ledlayout": "LED Layout", + "conf_leds_optgroup_RPiGPIO": "RPi GPIO", + "conf_leds_optgroup_RPiPWM": "RPi PWM", + "conf_leds_optgroup_RPiSPI": "RPi SPI", + "conf_leds_optgroup_debug": "Debug", + "conf_leds_optgroup_network": "Network", + "conf_leds_optgroup_usb": "USB/Serial", + "conf_logging_btn_autoscroll": "Auto scrolling", + "conf_logging_btn_pbupload": "Upload a report for support requests", + "conf_logging_contpolicy": "Report Privacy Policy", + "conf_logging_label_intro": "Area to check log messages, you will see more or less information depending on the logging level set.", + "conf_logging_lastreports": "Previous reports", + "conf_logging_nomessage": "No log messages available.", + "conf_logging_report": "Report", + "conf_logging_uplfailed": "Upload failed! Please check your internet connection!", + "conf_logging_uploading": "Prepare data...", + "conf_logging_uplpolicy": "By clicking this button you accept the", + "conf_logging_yourlink": "Link to your report", + "conf_network_bobl_intro": "Receiver for Boblight", + "conf_network_createToken_btn": "Create Token", + "conf_network_fbs_intro": "Google Flatbuffers Receiver. Used for fast image transmission.", + "conf_network_forw_intro": "Forward all input to a second Hyperion instance which could be driven with another led controller", + "conf_network_json_intro": "The JSON-RPC-Port of all Hyperion instances, used for remote control.", + "conf_network_net_intro": "Network related settings which are applied to all network services.", + "conf_network_proto_intro": "The PROTO-Port of all Hyperion instances, used for picture streams (HyperionScreenCap, Kodi Addon, Android Hyperion Grabber, ...)", + "conf_network_tok_cidhead": "Description", + "conf_network_tok_comment_title": "Token description", + "conf_network_tok_desc": "Tokens grant other applications access to the Hyperion API, an application can request a token where you need to accept it or you create them on your own below. These tokens are just required when \"API Authorization\" is enabled in network settings.", + "conf_network_tok_diaMsg": "Here is your new token which can be used to grant an application access to the Hyperion API. For security reasons you can't view it again so use/note it down.", + "conf_network_tok_diaTitle": "New Token created!", + "conf_network_tok_grantMsg": "An App requested a token to get access to the Hyperion API. Do you want to grant access? Please verify the provided information!", + "conf_network_tok_grantT": "App Requests Token", + "conf_network_tok_intro": "Here you can create and delete tokens for API authentication. Created tokens will only be displayed once.", + "conf_network_tok_lastuse": "Last use", + "conf_network_tok_title": "Token Management", + "conf_webconfig_label_intro": "Webconfiguration settings. Edit wisely.", + "dashboard_active_instance": "Selected instance", + "dashboard_alert_message_confedit": "Your Hyperion configuration has been modified. To apply it, restart Hyperion.", + "dashboard_alert_message_confedit_t": "Configuration modified", + "dashboard_alert_message_confsave_success": "Your Hyperion configuration has been saved successfully. Your changes are now active.", + "dashboard_alert_message_confsave_success_t": "Configuration saved", + "dashboard_alert_message_disabled": "This instance is currently disabled! To use it again, enable it at the dashboard.", + "dashboard_alert_message_disabled_t": "LED hardware instance disabled", + "dashboard_componentbox_label_comp": "Component", + "dashboard_componentbox_label_status": "Status", + "dashboard_componentbox_label_title": "Components status", + "dashboard_infobox_label_currenthyp": "Your Hyperion version:", + "dashboard_infobox_label_disableh": "Disable Instance: $1", + "dashboard_infobox_label_enableh": "Enable Instance: $1", + "dashboard_infobox_label_instance": "Instance:", + "dashboard_infobox_label_latesthyp": "Latest Hyperion version:", + "dashboard_infobox_label_platform": "Platform:", + "dashboard_infobox_label_ports": "Ports (flat|proto):", + "dashboard_infobox_label_smartacc": "Smart Access", + "dashboard_infobox_label_statush": "Hyperion status:", + "dashboard_infobox_label_title": "Information", + "dashboard_infobox_label_watchedversionbranch": "Watched version branch:", + "dashboard_infobox_message_updatesuccess": "You run the latest version of Hyperion.", + "dashboard_infobox_message_updatewarning": "A newer version of Hyperion is available! ($1)", + "dashboard_label_intro": "The dashboard give you a quick overview about the status of Hyperion and show you the latest news of the Hyperion Blog.", + "dashboard_message_default_password": "The default password for the WebUi is set. We strongly recommend to change this.", + "dashboard_message_default_password_t": "WebUI default password is set", + "dashboard_message_do_not_show_again": "Do not show this message again", + "dashboard_message_global_setting": "The settings on this page are not depending on a specific instance. Changes will be stored globally for all instances.", + "dashboard_message_global_setting_t": "Instance independent setting", + "dashboard_newsbox_label_title": "Hyperion-Blog", + "dashboard_newsbox_noconn": "Can't connect to Hyperion Server to retrieve latest posts, does your internet connection work?", + "dashboard_newsbox_readmore": "Read more", + "dashboard_newsbox_visitblog": "Visit Hyperion-Blog", + "edt_append_degree": "°", + "edt_append_hz": "Hz", + "edt_append_leds": "LEDs", + "edt_append_ms": "ms", + "edt_append_ns": "ns", + "edt_append_percent": "%", + "edt_append_percent_h": "% hori", + "edt_append_percent_v": "% vert", + "edt_append_pixel": "Pixel", + "edt_append_s": "s", + "edt_append_sdegree": "s/degree", + "edt_conf_bb_blurRemoveCnt_expl": "Number of pixels that get removed from the detected border to cut away blur.", + "edt_conf_bb_blurRemoveCnt_title": "Blur pixel", + "edt_conf_bb_borderFrameCnt_expl": "Number of frames before a consistent detected border is set.", + "edt_conf_bb_borderFrameCnt_title": "Border frames", + "edt_conf_bb_heading_title": "Blackbar detector", + "edt_conf_bb_maxInconsistentCnt_expl": "Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency.", + "edt_conf_bb_maxInconsistentCnt_title": "Inconsistent frames", + "edt_conf_bb_mode_expl": "Algorithm for processing. (see Wiki)", + "edt_conf_bb_mode_title": "Mode", + "edt_conf_bb_threshold_expl": "If the detection doesn't work, higher the threshold to adjust on 'greyish' black", + "edt_conf_bb_threshold_title": "Threshold", + "edt_conf_bb_unknownFrameCnt_expl": "Number of frames without any detection before the border is set to 0.", + "edt_conf_bb_unknownFrameCnt_title": "Unknown frames", + "edt_conf_bge_heading_title": "Background Effect/Color", + "edt_conf_bobls_heading_title": "Boblight Server", + "edt_conf_color_backlightColored_expl": "Add some color to your backlight.", + "edt_conf_color_backlightColored_title": "Colored backlight", + "edt_conf_color_backlightThreshold_expl": "The minimum amount of brightness (backlight). Disabled during effects, colors and in status \"Off\"", + "edt_conf_color_backlightThreshold_title": "Backlight threshold", + "edt_conf_color_black_expl": "The calibrated black value.", + "edt_conf_color_black_title": "Black", + "edt_conf_color_blue_expl": "The calibrated blue value.", + "edt_conf_color_blue_title": "Blue", + "edt_conf_color_brightnessComp_expl": "Compensates brightness differences between red green blue, cyan magenta yellow and white. 100 means full compensation, 0 no compensation", + "edt_conf_color_brightnessComp_title": "Brightness compensation", + "edt_conf_color_brightness_expl": "set overall brightness of LEDs", + "edt_conf_color_brightness_title": "Brightness", + "edt_conf_color_channelAdjustment_header_expl": "Create color profiles that could be assigned to a specific component. Adjust color, gamma, brightness, compensation and more.", + "edt_conf_color_channelAdjustment_header_itemtitle": "Profile", + "edt_conf_color_channelAdjustment_header_title": "Color channel adjustments", + "edt_conf_color_cyan_expl": "The calibrated cyan value.", + "edt_conf_color_cyan_title": "Cyan", + "edt_conf_color_gammaBlue_expl": "The gamma of blue. 1.0 is neutral. Over 1.0 it reduces blue, lower than 1.0 it adds blue.", + "edt_conf_color_gammaBlue_title": "Gamma blue", + "edt_conf_color_gammaGreen_expl": "The gamma of green. 1.0 is neutral. Over 1.0 it reduces green, lower than 1.0 it adds green.", + "edt_conf_color_gammaGreen_title": "Gamma green", + "edt_conf_color_gammaRed_expl": "The gamma of red. 1.0 is neutral. Over 1.0 it reduces red, lower than 1.0 it adds red.", + "edt_conf_color_gammaRed_title": "Gamma red", + "edt_conf_color_green_expl": "The calibrated green value.", + "edt_conf_color_green_title": "Green", + "edt_conf_color_heading_title": "Color Calibration", + "edt_conf_color_id_expl": "User given name", + "edt_conf_color_id_title": "ID", + "edt_conf_color_imageToLedMappingType_expl": "Overwrites the led area assignment of your led layout if it's not \"multicolor\"", + "edt_conf_color_imageToLedMappingType_title": "Led area assignment", + "edt_conf_color_leds_expl": "Assign this adjustment to all LEDs (*) or just some (0-24).", + "edt_conf_color_leds_title": "LED index", + "edt_conf_color_magenta_expl": "The calibrated magenta value.", + "edt_conf_color_magenta_title": "Magenta", + "edt_conf_color_red_expl": "The calibrated red value.", + "edt_conf_color_red_title": "Red", + "edt_conf_color_white_expl": "The calibrated white value.", + "edt_conf_color_white_title": "White", + "edt_conf_color_yellow_expl": "The calibrated yellow value.", + "edt_conf_color_yellow_title": "Yellow", + "edt_conf_effp_disable_expl": "Add effect names here to disable/hide them from all effect lists.", + "edt_conf_effp_disable_itemtitle": "Effect", + "edt_conf_effp_disable_title": "Disabled Effects", + "edt_conf_effp_heading_title": "Effect Paths", + "edt_conf_effp_paths_expl": "You could define more folders that contain effects. The effect configurator will always save inside the first folder.", + "edt_conf_effp_paths_itemtitle": "Path", + "edt_conf_effp_paths_title": "Effect Path(s)", + "edt_conf_enum_NO_CHANGE": "Automatic", + "edt_conf_enum_NTSC": "NTSC", + "edt_conf_enum_PAL": "PAL", + "edt_conf_enum_SECAM": "SECAM", + "edt_conf_enum_HORIZONTAL": "Horizontal", + "edt_conf_enum_VERTICAL": "Vertical", + "edt_conf_enum_BOTH": "Horizontal & Vertical", + "edt_conf_enum_automatic": "Automatic", + "edt_conf_enum_bbclassic": "Classic", + "edt_conf_enum_bbdefault": "Default", + "edt_conf_enum_bbletterbox": "Letterbox", + "edt_conf_enum_bbosd": "OSD", + "edt_conf_enum_bgr": "BGR", + "edt_conf_enum_bottom_up": "Bottom up", + "edt_conf_enum_brg": "BRG", + "edt_conf_enum_color": "Color", + "edt_conf_enum_custom": "Custom", + "edt_conf_enum_decay": "Decay", + "edt_conf_enum_dl_error": "Error", + "edt_conf_enum_dl_informational": "Informational", + "edt_conf_enum_dl_nodebug": "No Debug output", + "edt_conf_enum_dl_statechange": "State Change", + "edt_conf_enum_dl_verbose": "Verbose", + "edt_conf_enum_dl_verbose1": "Verbosity level 1", + "edt_conf_enum_dl_verbose2": "Verbosity level 2", + "edt_conf_enum_dl_verbose3": "Verbosity level 3", + "edt_conf_enum_effect": "Effect", + "edt_conf_enum_gbr": "GBR", + "edt_conf_enum_grb": "GRB", + "edt_conf_enum_hsv": "HSV", + "edt_conf_enum_left_right": "Left to right", + "edt_conf_enum_linear": "Linear", + "edt_conf_enum_logdebug": "Debug", + "edt_conf_enum_logsilent": "Silent", + "edt_conf_enum_logverbose": "Verbose", + "edt_conf_enum_logwarn": "Warning", + "edt_conf_enum_multicolor_mean": "Multicolor", + "edt_conf_enum_rbg": "RBG", + "edt_conf_enum_rgb": "RGB", + "edt_conf_enum_right_left": "Right to left", + "edt_conf_enum_top_down": "Top down", + "edt_conf_enum_transeffect_smooth": "Smooth", + "edt_conf_enum_transeffect_sudden": "Sudden", + "edt_conf_enum_unicolor_mean": "Unicolor", + "edt_conf_fbs_heading_title": "Flatbuffers Server", + "edt_conf_fbs_timeout_expl": "If no data are received for the given period, the component will be (soft) disabled.", + "edt_conf_fbs_timeout_title": "Timeout", + "edt_conf_fg_display_expl": "Select which desktop should be captured (multi monitor setup)", + "edt_conf_fg_display_title": "Display", + "edt_conf_fg_frequency_Hz_expl": "How fast new pictures are captured", + "edt_conf_fg_frequency_Hz_title": "Capture frequency", + "edt_conf_fg_heading_title": "Platform Capture", + "edt_conf_fg_height_expl": "Shrink picture to this height, as raw picture needs a lot of CPU time.", + "edt_conf_fg_height_title": "Height", + "edt_conf_fg_pixelDecimation_expl": "Reduce picture size (factor) based on original size. A factor of 1 means no change", + "edt_conf_fg_pixelDecimation_title": "Picture decimation", + "edt_conf_fg_type_expl": "Type of platform capture, default is 'auto'", + "edt_conf_fg_type_title": "Type", + "edt_conf_fg_width_expl": "Shrink picture to this width, as raw picture needs a lot of cpu time.", + "edt_conf_fg_width_title": "Width", + "edt_conf_fge_color_expl": "If type is \"Color\", set a color of your choice here.", + "edt_conf_fge_color_title": "Color", + "edt_conf_fge_duration_ms_expl": "Duration of Effect/Color during Hyperion start-up.", + "edt_conf_fge_duration_ms_title": "Duration", + "edt_conf_fge_effect_expl": "If type is \"Effect\", select an effect of your choice (Also self created effects).", + "edt_conf_fge_effect_title": "Effect", + "edt_conf_fge_heading_title": "Boot Effect/Color", + "edt_conf_fge_type_expl": "Choose between a color or effect.", + "edt_conf_fge_type_title": "Type", + "edt_conf_fw_flat_expl": "One flatbuffer target per line. Contains IP:PORT (Example: 127.0.0.1:19401)", + "edt_conf_fw_flat_itemtitle": "flatbuffer target", + "edt_conf_fw_flat_title": "List of flatbuffer clients", + "edt_conf_fw_heading_title": "Forwarder", + "edt_conf_fw_json_expl": "One json target per line. Contains IP:PORT (Example: 127.0.0.1:19446)", + "edt_conf_fw_json_itemtitle": "Json target", + "edt_conf_fw_json_title": "List of json clients", + "edt_conf_gen_heading_title": "General Settings", + "edt_conf_gen_name_expl": "A user defined name which is used to detect Hyperion. (Helpful with more than one Hyperion instance)", + "edt_conf_gen_name_title": "Configuration name", + "edt_conf_gen_showOptHelp_expl": "Show all available explanations in each section. Highly recommended for beginners!", + "edt_conf_gen_showOptHelp_title": "Show explanations", + "edt_conf_gen_watchedVersionBranch_expl": "Selects which version branch should be used for searching new Hyperion versions.", + "edt_conf_gen_watchedVersionBranch_title": "Watched version branch", + "edt_conf_general_enable_expl": "If checked, the component is enabled.", + "edt_conf_general_enable_title": "Activate", + "edt_conf_general_port_expl": "The port that is used.", + "edt_conf_general_port_title": "Port", + "edt_conf_general_priority_expl": "The priority of this component", + "edt_conf_general_priority_title": "Priority channel", + "edt_conf_grabber_discovered_none": "No Devices Discovered", + "edt_conf_instC_systemEnable_expl": "Enables the platform capture for this led hardware instance", + "edt_conf_instC_systemEnable_title": "Enable platform capture", + "edt_conf_instC_v4lEnable_expl": "Enables the USB capture for this led hardware instance", + "edt_conf_instC_v4lEnable_title": "Enable USB capture", + "edt_conf_instCapture_heading_title": "Instance Capture", + "edt_conf_js_heading_title": "JSON Server", + "edt_conf_log_heading_title": "Logging", + "edt_conf_log_level_expl": "Depending on loglevel you see less or more messages in your log.", + "edt_conf_log_level_title": "Log-Level", + "edt_conf_net_apiAuth_expl": "Enforce all applications that use the Hyperion API to authenticate themself against Hyperion (Exception see \"Local API Authentication\"). Higher security, as you control the access and revoke it at any time.", + "edt_conf_net_apiAuth_title": "API Authentication", + "edt_conf_net_heading_title": "Network", + "edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Webinterface from the internet, disable for higher security.", + "edt_conf_net_internetAccessAPI_title": "Internet API Access", + "edt_conf_net_ipWhitelist_expl": "You can whitelist IP addresses instead allowing all connections from internet to connect to the Hyperion API/Webinterface.", + "edt_conf_net_ipWhitelist_title": "Whitelisted IP's", + "edt_conf_net_ip_itemtitle": "IP", + "edt_conf_net_localAdminAuth_expl": "When enabled, administration access from your local network needs a password.", + "edt_conf_net_localAdminAuth_title": "Local Admin API Authentication", + "edt_conf_net_localApiAuth_expl": "When enabled, connections from your home network needs to authenticate themself against Hyperion with a token.", + "edt_conf_net_localApiAuth_title": "Local API Authentication", + "edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict the access to the API through the internet to certain IP's.", + "edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP's", + "edt_conf_pbs_heading_title": "Protocol Buffers Server", + "edt_conf_pbs_timeout_expl": "If no data are received for the given period, the component will be (soft) disabled.", + "edt_conf_pbs_timeout_title": "Timeout", + "edt_conf_smooth_continuousOutput_expl": "Update the LEDs even there is no changed picture.", + "edt_conf_smooth_continuousOutput_title": "Continuous output", + "edt_conf_smooth_decay_expl": "The speed of decay. 1 is linear, greater values are have stronger effect.", + "edt_conf_smooth_decay_title": "Decay-Power", + "edt_conf_smooth_dithering_expl": "Improve color accuracy at high output speeds by alternating between adjacent colors.", + "edt_conf_smooth_dithering_title": "Dithering", + "edt_conf_smooth_heading_title": "Smoothing", + "edt_conf_smooth_interpolationRate_expl": "Speed of the calculation of smooth intermediate frames.", + "edt_conf_smooth_interpolationRate_title": "Interpolation Rate", + "edt_conf_smooth_outputRate_expl": "The output speed to your led controller.", + "edt_conf_smooth_outputRate_title": "Output Rate", + "edt_conf_smooth_time_ms_expl": "How long should the smoothing gather pictures?", + "edt_conf_smooth_time_ms_title": "Time", + "edt_conf_smooth_type_expl": "Type of smoothing.", + "edt_conf_smooth_type_title": "Type", + "edt_conf_smooth_updateDelay_expl": "Delay the output in case your ambient light is faster than your TV.", + "edt_conf_smooth_updateDelay_title": "Update delay", + "edt_conf_smooth_updateFrequency_expl": "The output speed to your led controller.", + "edt_conf_smooth_updateFrequency_title": "Update frequency", + "edt_conf_v4l2_blueSignalThreshold_expl": "Darkens low blue values (recognized as black)", + "edt_conf_v4l2_blueSignalThreshold_title": "Blue signal threshold", + "edt_conf_v4l2_cecDetection_expl": "If enabled, USB capture will be temporarily disabled when CEC standby event received from HDMI bus.", + "edt_conf_v4l2_cecDetection_title": "CEC detection", + "edt_conf_v4l2_cropBottom_expl": "Count of pixels on the bottom side that are removed from the picture.", + "edt_conf_v4l2_cropBottom_title": "Crop bottom", + "edt_conf_v4l2_cropLeft_expl": "Count of pixels on the left side that are removed from the picture.", + "edt_conf_v4l2_cropLeft_title": "Crop left", + "edt_conf_v4l2_cropRight_expl": "Count of pixels on the right side that are removed from the picture.", + "edt_conf_v4l2_cropRight_title": "Crop right", + "edt_conf_v4l2_cropTop_expl": "Count of pixels on the top side that are removed from the picture.", + "edt_conf_v4l2_cropTop_title": "Crop top", + "edt_conf_v4l2_device_expl": "The path to the USB capture interface. Set to 'Automatic' for automatic detection. Example: '/dev/video0'", + "edt_conf_v4l2_device_title": "Device", + "edt_conf_v4l2_framerate_expl": "The supported frames per second of the active device", + "edt_conf_v4l2_framerate_title": "Frames per second", + "edt_conf_v4l2_greenSignalThreshold_expl": "Darkens low green values (recognized as black)", + "edt_conf_v4l2_greenSignalThreshold_title": "Green signal threshold", + "edt_conf_v4l2_heading_title": "USB Capture", + "edt_conf_v4l2_input_expl": "Select the video input of your device. 'Automatic' keeps the value chosen by the v4l2 interface.", + "edt_conf_v4l2_input_title": "Input", + "edt_conf_v4l2_redSignalThreshold_expl": "Darkens low red values (recognized as black)", + "edt_conf_v4l2_redSignalThreshold_title": "Red signal threshold", + "edt_conf_v4l2_resolution_expl": "A list of supported resolutions of the active device", + "edt_conf_v4l2_resolution_title": "Device Resolution", + "edt_conf_v4l2_sDHOffsetMax_expl": "Signal detection area horizontal maximum (0.0-1.0)", + "edt_conf_v4l2_sDHOffsetMax_title": "Signal Detection HMax", + "edt_conf_v4l2_sDHOffsetMin_expl": "Signal detection area horizontal minimum (0.0-1.0)", + "edt_conf_v4l2_sDHOffsetMin_title": "Signal Detection HMin", + "edt_conf_v4l2_sDVOffsetMax_expl": "Signal detection area vertical maximum (0.0-1.0)", + "edt_conf_v4l2_sDVOffsetMax_title": "Signal Detection VMax", + "edt_conf_v4l2_sDVOffsetMin_expl": "Signal detection area vertical minimum (0.0-1.0)", + "edt_conf_v4l2_sDVOffsetMin_title": "Signal Detection VMin", + "edt_conf_v4l2_signalDetection_expl": "If enabled, usb capture will be temporarily disabled when no signal was found. This will happen when the picture fall below the threshold value for a period of 4 seconds.", + "edt_conf_v4l2_signalDetection_title": "Signal detection", + "edt_conf_v4l2_sizeDecimation_expl": "The factor of size decimation. 1 means no decimation (keep original size)", + "edt_conf_v4l2_sizeDecimation_title": "Size decimation", + "edt_conf_v4l2_standard_expl": "Select the video standard for your region. 'Automatic' keeps the value chosen by the v4l2 interface.", + "edt_conf_v4l2_standard_title": "Video standard", + "edt_conf_v4l2_flip_expl": "This allows you to flip the image horizontally, vertically, or both.", + "edt_conf_v4l2_flip_title": "Image flip", + "edt_conf_v4l2_fpsSoftwareDecimation_title": "Software frame skipping", + "edt_conf_v4l2_fpsSoftwareDecimation_expl": "To save resources every n'th frame will be processed only. For ex. if grabber is set to 30FPS with this option set to 5 the final result will be around 6FPS (1 - disabled)", + "edt_conf_v4l2_encoding_title": "Encoding format", + "edt_conf_v4l2_encoding_expl": "Force video encoding for multiformat capable grabbers", + "edt_conf_v4l2_hardware_brightness_title": "Hardware brightness control", + "edt_conf_v4l2_hardware_brightness_expl": "Set hardware brightness if device supports it, check logs (0=disabled)", + "edt_conf_v4l2_hardware_contrast_title": "Hardware contrast control", + "edt_conf_v4l2_hardware_contrast_expl": "Set hardware contrast if device supports it, check logs (0=disabled)", + "edt_conf_v4l2_noSignalCounterThreshold_title": "Signal Counter Threshold", + "edt_conf_v4l2_noSignalCounterThreshold_expl": "Count of frames (check that with grabber's current FPS mode) after which the no signal is triggered", + "edt_conf_v4l2_hardware_saturation_title": "Hardware saturation control", + "edt_conf_v4l2_hardware_saturation_expl": "Set hardware saturation if device supports it, check logs (0=disabled)", + "edt_conf_v4l2_hardware_hue_title": "Hardware hue control", + "edt_conf_v4l2_hardware_hue_expl": "Set hardware hue if device supports it, check logs (0=disabled)", + "edt_conf_webc_crtPath_expl": "Path to the certification file (format should be PEM)", + "edt_conf_webc_crtPath_title": "Certificate path", + "edt_conf_webc_docroot_expl": "Local webinterface root path (just for webui developer)", + "edt_conf_webc_docroot_title": "Document Root", + "edt_conf_webc_heading_title": "Web Configuration", + "edt_conf_webc_keyPassPhrase_expl": "Optional: The key might be protected with a password", + "edt_conf_webc_keyPassPhrase_title": "Key password", + "edt_conf_webc_keyPath_expl": "Path to the key file (format PEM, encrypted with RSA)", + "edt_conf_webc_keyPath_title": "Private key path", + "edt_conf_webc_sslport_expl": "Port oft the HTTPS-Webserver", + "edt_conf_webc_sslport_title": "HTTPS Port", + "edt_dev_auth_key_title": "Authentication Token", + "edt_dev_enum_sub_min_cool_adjust": "Subtract cool white", + "edt_dev_enum_sub_min_warm_adjust": "Subtract warm white", + "edt_dev_enum_subtract_minimum": "Subtract minimum", + "edt_dev_enum_white_off": "White off", + "edt_dev_general_colorOrder_title": "RGB byte order", + "edt_dev_general_hardwareLedCount_title": "Hardware LED count", + "edt_dev_general_heading_title": "General Settings", + "edt_dev_general_name_title": "Configuration name", + "edt_dev_general_rewriteTime_title": "Refresh time", + "edt_dev_spec_FCledToOn_title": "Fadecandy LED set to on", + "edt_dev_spec_FCmanualControl_title": "Manual control of fadecandy LED", + "edt_dev_spec_FCsetConfig_title": "Set fadecandy configuration", + "edt_dev_spec_LBap102Mode_title": "LightBerry APA102 Mode", + "edt_dev_spec_PBFiFo_title": "Pi-Blaster FiFo", + "edt_dev_spec_baudrate_title": "Baudrate", + "edt_dev_spec_blackLightsTimeout_title": "Signal detection timeout on black", + "edt_dev_spec_brightnessFactor_title": "Brightness factor", + "edt_dev_spec_brightnessMax_title": "Brightness maximum", + "edt_dev_spec_brightnessMin_title": "Brightness minimum", + "edt_dev_spec_brightnessThreshold_title": "Signal detection brightness minimum", + "edt_dev_spec_chanperfixture_title": "Channels per Fixture", + "edt_dev_spec_cid_title": "CID", + "edt_dev_spec_clientKey_title": "Clientkey", + "edt_dev_spec_colorComponent_title": "Colour component", + "edt_dev_spec_debugLevel_title": "Debug Level", + "edt_dev_spec_debugStreamer_title": "Streamer Debug", + "edt_dev_spec_delayAfterConnect_title": "Delay after connect", + "edt_dev_spec_dithering_title": "Dithering", + "edt_dev_spec_dmaNumber_title": "DMA channel", + "edt_dev_spec_gamma_title": "Gamma", + "edt_dev_spec_globalBrightnessControlMaxLevel_title": "Max Current Level", + "edt_dev_spec_globalBrightnessControlThreshold_title": "Adaptive Current Threshold", + "edt_dev_spec_gpioBcm_title": "GPIO Pin", + "edt_dev_spec_gpioMap_title": "GPIO mapping", + "edt_dev_spec_gpioNumber_title": "GPIO number", + "edt_dev_spec_groupId_title": "Group ID", + "edt_dev_spec_header_title": "Specific Settings", + "edt_dev_spec_interpolation_title": "Interpolation", + "edt_dev_spec_intervall_title": "Interval", + "edt_dev_spec_invert_title": "Invert signal", + "edt_dev_spec_latchtime_title": "Latch time", + "edt_dev_spec_ledIndex_title": "LED index", + "edt_dev_spec_ledType_title": "LED Type", + "edt_dev_spec_lightid_itemtitle": "ID", + "edt_dev_spec_lightid_title": "Light ID(s)", + "edt_dev_spec_lights_itemtitle": "Light", + "edt_dev_spec_lights_name": "Name", + "edt_dev_spec_lights_title": "Light(s)", + "edt_dev_spec_maxPacket_title": "Max packet", + "edt_dev_spec_maximumLedCount_title": "Maximum LED count", + "edt_dev_spec_multicastGroup_title": "Multicast group", + "edt_dev_spec_networkDeviceName_title": "Network devicename", + "edt_dev_spec_networkDevicePort_title": "Port", + "edt_dev_spec_numberOfLeds_title": "Number of LEDs", + "edt_dev_spec_orbIds_title": "Orb ID(s)", + "edt_dev_spec_order_left_right_title": "2.", + "edt_dev_spec_order_top_down_title": "1.", + "edt_dev_spec_outputPath_title": "Output path", + "edt_dev_spec_panel_start_position": "Start panel [0-max panels]", + "edt_dev_spec_panelorganisation_title": "Panel numbering sequence", + "edt_dev_spec_pid_title": "PID", + "edt_dev_spec_port_title": "Port", + "edt_dev_spec_printTimeStamp_title": "Add timestamp", + "edt_dev_spec_pwmChannel_title": "PWM channel", + "edt_dev_spec_restoreOriginalState_title": "Restore lights' original state when disabled", + "edt_dev_spec_serial_title": "Serial number", + "edt_dev_spec_spipath_title": "SPI path", + "edt_dev_spec_sslHSTimeoutMax_title": "Streamer handshake timeout maximum", + "edt_dev_spec_sslHSTimeoutMin_title": "Streamer handshake timeout minimum", + "edt_dev_spec_sslReadTimeout_title": "Streamer read timeout", + "edt_dev_spec_switchOffOnBlack_title": "Switch off on black", + "edt_dev_spec_switchOffOnbelowMinBrightness_title": "Switch-off, below minimum", + "edt_dev_spec_targetIpHost_title": "Target IP/Hostname", + "edt_dev_spec_targetIp_title": "Target IP", + "edt_dev_spec_transeffect_title": "Transition effect", + "edt_dev_spec_transistionTimeExtra_title": "Extra time darkness", + "edt_dev_spec_transistionTime_title": "Transition time", + "edt_dev_spec_uid_title": "UID", + "edt_dev_spec_universe_title": "Universe", + "edt_dev_spec_useEntertainmentAPI_title": "Use Hue Entertainment API", + "edt_dev_spec_useOrbSmoothing_title": "Use orb smoothing", + "edt_dev_spec_useRgbwProtocol_title": "Use RGBW protocol", + "edt_dev_spec_username_title": "Username", + "edt_dev_spec_verbose_title": "Log all Hue commands", + "edt_dev_spec_vid_title": "VID", + "edt_dev_spec_whiteLedAlgor_title": "White LED algorithm", + "edt_dev_spec_whitepoint_title": "Whitepoint", + "edt_eff_alarmcolor": "Alarm color", + "edt_eff_backgroundColor": "Background Color", + "edt_eff_basecolorchange": "Base color change", + "edt_eff_basecolorchangerate": "BC change rate", + "edt_eff_basecolorrangeleft": "BC range left", + "edt_eff_basecolorrangeright": "BC range right", + "edt_eff_blobcount": "Blob count", + "edt_eff_brightness": "Brightness", + "edt_eff_candle_header": "Candle", + "edt_eff_candle_header_desc": "Shimmering candles", + "edt_eff_centerx": "Center X-Axis", + "edt_eff_centery": "Center Y-Axis", + "edt_eff_collision_header": "color collision", + "edt_eff_collision_header_desc": "Two color projectiles are sent from random positions and collide with each other", + "edt_eff_color": "Color", + "edt_eff_colorHour": "Color hour", + "edt_eff_colorMarker": "Marker color", + "edt_eff_colorMinute": "Color minute", + "edt_eff_colorSecond": "Color second", + "edt_eff_colorcount": "Color length", + "edt_eff_colorend": "Color end", + "edt_eff_colorendtime": "Time to hold start color", + "edt_eff_colorevel": "Color level", + "edt_eff_colorone": "Color one", + "edt_eff_colorrandom": "Random color", + "edt_eff_colorshift": "Color Shift", + "edt_eff_colorstart": "Color start", + "edt_eff_colorstarttime": "Time to hold end color", + "edt_eff_colortwo": "Color two", + "edt_eff_count": "Count", + "edt_eff_countries": "Countries", + "edt_eff_customColor": "Custom Color", + "edt_eff_enableSecondSwirl": "Second Swirl", + "edt_eff_enableshutdown": "Real shutdown", + "edt_eff_enum_all": "All", + "edt_eff_enum_all-together": "All together", + "edt_eff_enum_list": "LED List", + "edt_eff_explodeRadius": "Detonation Range ", + "edt_eff_fade_header": "Fade", + "edt_eff_fade_header_desc": "Fades between colors", + "edt_eff_fadefactor": "Fade factor", + "edt_eff_fadeintime": "Fade in time", + "edt_eff_fadeouttime": "Fade out time", + "edt_eff_flag_header": "Flags", + "edt_eff_flag_header_desc": "Let your LEDs shine bright in the colours of your country. You can select more than one flag and they will change based on the interval time.", + "edt_eff_fps": "Frames per seconds", + "edt_eff_frequency": "Frequency", + "edt_eff_gif_header": "GIF's", + "edt_eff_gif_header_desc": "This effect plays .gif files, provide a simple video like loop as effect.", + "edt_eff_height": "Height", + "edt_eff_huechange": "Color change", + "edt_eff_image": "Image file", + "edt_eff_interval": "Interval", + "edt_eff_knightrider_header": "Knight Rider", + "edt_eff_knightrider_header_desc": "K.I.T.T is back! The front-scanner of the well known car, this time not just in red.", + "edt_eff_ledlist": "Led List", + "edt_eff_ledtest_header": "Led Test", + "edt_eff_ledtest_header_desc": "Rotating output: Red, Blue, Green, White, Black", + "edt_eff_length": "Length", + "edt_eff_lightclock_header": "Light Clock", + "edt_eff_lightclock_header_desc": "A real clock as light! Adjust the colors of hours, minute, seconds. A optional 3/6/9/12 o'clock marker is also available. In case the clock is wrong, you need to check your system clock.", + "edt_eff_maintain_end_color": "Keep endcolor", + "edt_eff_margin": "Margin", + "edt_eff_markerDepth": "Marker depth", + "edt_eff_markerEnable": "Show Marker", + "edt_eff_markerWidth": "Marker width", + "edt_eff_max_len": "Maximal length", + "edt_eff_min_len": "Minimal length", + "edt_eff_moodblobs_header": "Mood Blobs", + "edt_eff_moodblobs_header_desc": "Relax at the evening with slow moving and color changing blobs.", + "edt_eff_offset": "Offset", + "edt_eff_pacman_header": "Pac-Man", + "edt_eff_pacman_header_desc": "Small hungry and yellow. Who will survive?", + "edt_eff_plasma_header": "Plasma", + "edt_eff_plasma_header_desc": "Color distortion in different directions", + "edt_eff_police_header": "Police", + "edt_eff_police_header_desc": "Lights like a police car in action", + "edt_eff_postcolor": "Post color", + "edt_eff_rainbowmood_header": "Rainbow Mood", + "edt_eff_rainbowmood_header_desc": "All LEDs rainbow mood", + "edt_eff_randomCenter": "Random Center", + "edt_eff_random_header": "Random", + "edt_eff_random_header_desc": "Pixel Dot, dot, dot...", + "edt_eff_repeat": "Repeat", + "edt_eff_repeatcount": "Repeat count", + "edt_eff_reverseRandomTime": "Reverse every", + "edt_eff_reversedirection": "Reverse direction", + "edt_eff_rotationtime": "Rotation time", + "edt_eff_saturation": "Saturation", + "edt_eff_showseconds": "Show seconds", + "edt_eff_sleeptime": "Sleep time", + "edt_eff_smooth_custom": "Enable smoothing", + "edt_eff_smooth_time_ms": "Smoothing time", + "edt_eff_smooth_updateFrequency": "Smoothing update frequency", + "edt_eff_snake_header": "Snake", + "edt_eff_snake_header_desc": "Where is something to eat?", + "edt_eff_sparks_header": "Sparks", + "edt_eff_sparks_header_desc": "Star-Sparking, choose between a static color or random. You could also adjust brightness, saturation and speed.", + "edt_eff_speed": "Speed", + "edt_eff_swirl_header": "Color Swirl", + "edt_eff_swirl_header_desc": "A swirl with custom colors. Colors are even spread to 360°, in between colors shifts will be calculated. Additional you can add a second swirl on top, be aware that you need partly transparency! Hint: A repeat of the same color results in a \"higher\" color area and a reduced color shift area.", + "edt_eff_systemshutdown_header": "System Shutdown", + "edt_eff_systemshutdown_header_desc": "A short animation with probably a real system shutdown", + "edt_eff_traces_header": "Color Traces", + "edt_eff_traces_header_desc": "Requires redesign", + "edt_eff_trails_header": "Falling stars", + "edt_eff_trails_header_desc": "Colored stars that fall from top to bottom", + "edt_eff_waves_header": "Waves", + "edt_eff_waves_header_desc": "Waves of color! Choose your colors, rotation time, direction reverse and more.", + "edt_eff_whichleds": "Which LEDs", + "edt_eff_whitelevel": "White level", + "edt_eff_x-mas_header": "X-Mas", + "edt_eff_x-mas_header_desc": "Touch of Christmas", + "edt_msg_button_add_row_title": "Add $1", + "edt_msg_button_collapse": "Collapse", + "edt_msg_button_delete_all": "All", + "edt_msg_button_delete_all_title": "Delete All", + "edt_msg_button_delete_last": "Last $1", + "edt_msg_button_delete_last_title": "Delete Last $1", + "edt_msg_button_delete_row_title": "Delete $1", + "edt_msg_button_delete_row_title_short": "Delete", + "edt_msg_button_expand": "Expand", + "edt_msg_button_move_down_title": "Move down", + "edt_msg_button_move_up_title": "Move up", + "edt_msg_error_additionalItems": "No additional items allowed in this array", + "edt_msg_error_additional_properties": "No additional properties allowed, but property $1 is set", + "edt_msg_error_anyOf": "Value must validate against at least one of the provided schemas", + "edt_msg_error_dependency": "Must have property $1", + "edt_msg_error_disallow": "Value must not be of type $1", + "edt_msg_error_disallow_union": "Value must not be one of the provided disallowed types", + "edt_msg_error_enum": "Value must be one of the enumerated values", + "edt_msg_error_maxItems": "Value must have at most $1 items", + "edt_msg_error_maxLength": "Value must be at most $1 characters long", + "edt_msg_error_maxProperties": "Object must have at most $1 properties", + "edt_msg_error_maximum_excl": "Value must be less than $1", + "edt_msg_error_maximum_incl": "Value must be at most $1", + "edt_msg_error_minItems": "Value must have at least $1 items", + "edt_msg_error_minLength": "Value must be at least $1 characters long", + "edt_msg_error_minProperties": "Object must have at least $1 properties", + "edt_msg_error_minimum_excl": "Value must be greater than $1", + "edt_msg_error_minimum_incl": "Value must be at least $1", + "edt_msg_error_multipleOf": "Value must be a multiple of $1", + "edt_msg_error_not": "Value must not validate against the provided schema", + "edt_msg_error_notempty": "Value required", + "edt_msg_error_notset": "Property must be set", + "edt_msg_error_oneOf": "Value must validate against exactly one of the provided schemas. It currently validates against $1 of the schemas.", + "edt_msg_error_pattern": "Value must match the pattern", + "edt_msg_error_required": "Object is missing the required property '$1'", + "edt_msg_error_type": "Value must be of type $1", + "edt_msg_error_type_union": "Value must be one of the provided types", + "edt_msg_error_uniqueItems": "Array must have unique items", + "effectsconfigurator_button_conttest": "Continuous test", + "effectsconfigurator_button_deleffect": "Delete Effect", + "effectsconfigurator_button_editeffect": "Load Effect", + "effectsconfigurator_button_saveeffect": "Save Effect", + "effectsconfigurator_button_starttest": "Start test", + "effectsconfigurator_button_stoptest": "Stop test", + "effectsconfigurator_editdeleff": "Delete/Load Effect", + "effectsconfigurator_label_chooseeff": "Choose Template", + "effectsconfigurator_label_effectname": "Effect name", + "effectsconfigurator_label_intro": "Create out of the base effects new effects that are tuned to your liking. Depending on Effect there are options like color, speed, direction and more available.", + "general_access_advanced": "Advanced", + "general_access_default": "Default", + "general_access_expert": "Expert", + "general_btn_back": "Back", + "general_btn_cancel": "Cancel", + "general_btn_continue": "Continue", + "general_btn_delete": "Delete", + "general_btn_denyAccess": "Deny Access", + "general_btn_grantAccess": "Grant Access", + "general_btn_iswitch": "Switch", + "general_btn_next": "Next", + "general_btn_off": "Off", + "general_btn_ok": "OK", + "general_btn_on": "On", + "general_btn_rename": "Rename", + "general_btn_restarthyperion": "Restart Hyperion", + "general_btn_save": "Save", + "general_btn_saveandreload": "Save and reload", + "general_btn_saverestart": "Save and restart", + "general_btn_start": "Start", + "general_btn_stop": "Stop", + "general_btn_yes": "Yes", + "general_button_savesettings": "Save settings", + "general_chars_needed": "more characters needed", + "general_col_blue": "blue", + "general_col_green": "green", + "general_col_red": "red", + "general_comp_BLACKBORDER": "Blackbar Detection", + "general_comp_BOBLIGHTSERVER": "Boblight Server", + "general_comp_FLATBUFSERVER": "Flatbuffers Server", + "general_comp_FORWARDER": "Forwarder", + "general_comp_GRABBER": "Platform Capture", + "general_comp_LEDDEVICE": "LED device", + "general_comp_PROTOSERVER": "Protocol Buffers Server", + "general_comp_SMOOTHING": "Smoothing", + "general_comp_V4L": "USB Capture", + "general_country_cn": "China", + "general_country_de": "Germany", + "general_country_es": "Spain", + "general_country_fr": "France", + "general_country_it": "Italy", + "general_country_nl": "Netherlands", + "general_country_ru": "Russia", + "general_country_uk": "United Kingdom", + "general_country_us": "United States", + "general_speech_cs": "Czech", + "general_speech_de": "German", + "general_speech_en": "English", + "general_speech_es": "Spanish", + "general_speech_fr": "French", + "general_speech_it": "Italian", + "general_speech_nl": "Dutch", + "general_speech_pl": "Polish", + "general_speech_ro": "Romanian", + "general_speech_ru": "Russian", + "general_speech_sv": "Swedish", + "general_speech_tr": "Turkish", + "general_speech_vi": "Vietnamese", + "general_speech_zh-CN": "Chinese (simplified)", + "general_webui_title": "Hyperion - Web Configuration", + "general_wiki_moreto": "More information to \"$1\" at our Wiki", + "infoDialog_checklist_title": "Checklist!", + "infoDialog_effconf_created_text": "The effect \"$1\" has been created successfully!", + "infoDialog_effconf_deleted_text": "The effect \"$1\" has been deleted successfully!", + "infoDialog_general_error_title": "Error", + "infoDialog_general_success_title": "Success", + "infoDialog_general_warning_title": "Warning", + "infoDialog_import_comperror_text": "Sad! Your browser doesn't support a import. Please try again with another browser.", + "infoDialog_import_confirm_text": "Are you sure to import \"$1\"? This process can't be reverted!", + "infoDialog_import_confirm_title": "Confirm import", + "infoDialog_import_hyperror_text": "The selected configuration file \"$1\" can't be imported. It's not compatible with Hyperion 2.0 and higher!", + "infoDialog_import_jsonerror_text": "The selected configuration file \"$1\" is no .json file or it's corrupted. Error message: ($2)", + "infoDialog_wizrgb_text": "Your RGB Byte Order is already well adjusted.", + "infoDialog_writeconf_error_text": "Saving your configuration failed.", + "infoDialog_writeimage_error_text": "The selected file \"$1\" is no image file or it's corrupted! Please select another image file.", + "info_404": "The page you requested is not available!", + "info_conlost_label_autorecon": "We reconnect again after Hyperion is available.", + "info_conlost_label_autorefresh": "This page will be automatically refreshed.", + "info_conlost_label_reason": "Possible reasons:", + "info_conlost_label_reason1": "- Bad WLAN connection", + "info_conlost_label_reason2": "- You perform an update", + "info_conlost_label_reason3": "- Hyperion isn't running", + "info_conlost_label_reload": "Auto reconnect stopped - limit exceeded, please refresh page or click me.", + "info_conlost_label_title": "Lost connection to Hyperion service!", + "info_restart_contus": "If you still hang around here after 20 seconds and you have no clue why please open a new topic at our support forum...", + "info_restart_contusa": "...with your last steps. Thank you!", + "info_restart_rightback": "Hyperion will be right back immediately!", + "info_restart_title": "Restarts currently...", + "main_ledsim_btn_togglelednumber": "LED numbers", + "main_ledsim_btn_toggleleds": "Show LEDs", + "main_ledsim_btn_togglelivevideo": "Live video", + "main_ledsim_text": "Live visualization of led colors and optional the current video stream of your capture device.", + "main_ledsim_title": "LED Visualization", + "main_menu_about_token": "About Hyperion", + "main_menu_colors_conf_token": "Image Processing", + "main_menu_configuration_token": "Configuration", + "main_menu_dashboard_token": "Dashboard", + "main_menu_effect_conf_token": "Effects", + "main_menu_effectsconfigurator_token": "Effects Configurator", + "main_menu_general_conf_token": "General", + "main_menu_grabber_conf_token": "Capturing Hardware", + "main_menu_input_selection_token": "Input Selection", + "main_menu_leds_conf_token": "LED Hardware", + "main_menu_logging_token": "Log", + "main_menu_network_conf_token": "Network Services", + "main_menu_remotecontrol_token": "Remote Control", + "main_menu_support_token": "Support", + "main_menu_system_token": "System", + "main_menu_update_token": "Update", + "main_menu_webconfig_token": "Web configuration", + "remote_adjustment_intro": "Modify color/brightness/compensation during runtime. $1", + "remote_adjustment_label": "Color adjustment", + "remote_color_button_reset": "Reset Color/Effect", + "remote_color_intro": "Set an effect or color. Also your self created effects are listed (if available). $1", + "remote_color_label": "Colors/Effects", + "remote_color_label_color": "Color:", + "remote_components_intro": "Enable and disable components of Hyperion during runtime. $1", + "remote_components_label": "Components control", + "remote_effects_label_effects": "Effect:", + "remote_effects_label_picture": "Picture:", + "remote_input_clearall": "Clear all Effects/Colors", + "remote_input_duration": "Duration:", + "remote_input_intro": "Hyperion uses a priority system to select a source. Everything you set has a priority (Effect/Color/Platform capture/USB capture and network sources). By default, Hyperion select sources depending on priority (lowest number reflects the current active source). Now you have the opportunity to select sources on your own. $1", + "remote_input_ip": "IP:", + "remote_input_label": "Source Selection", + "remote_input_label_autoselect": "Auto Selection", + "remote_input_origin": "Origin", + "remote_input_owner": "Type", + "remote_input_priority": "Priority", + "remote_input_setsource_btn": "Select Source", + "remote_input_sourceactiv_btn": "Source active", + "remote_input_status": "Status/Action", + "remote_losthint": "Note: All changes are lost after a restart.", + "remote_maptype_intro": "Usually the led layout defines which LED covers a specific picture area, you could change it here: $1.", + "remote_maptype_label": "Mapping type", + "remote_maptype_label_multicolor_mean": "Multicolor", + "remote_maptype_label_unicolor_mean": "Unicolor", + "remote_optgroup_syseffets": "Provided Effects", + "remote_optgroup_usreffets": "User Effects", + "remote_videoMode_2D": "2D", + "remote_videoMode_3DSBS": "3DSBS", + "remote_videoMode_3DTAB": "3DTAB", + "remote_videoMode_intro": "Switch between different video modes to enjoy 3D movies! Supported are all capture devices. $1", + "remote_videoMode_label": "Video mode", + "support_label_affinstr1": "Click on the appropriate link of your country", + "support_label_affinstr2": "Everything you buy (doesn't matter what) we get a small fee based on your turnover", + "support_label_affinstr3": "You ALWAYS pay the same price, there is absolutely no difference. Try it out!", + "support_label_btctext": "Address:", + "support_label_donate": "Donate or use our affiliate links", + "support_label_donationpp": "Donation:", + "support_label_fbtext": "Share our Hyperion Facebook page and get a notice when new updates are released", + "support_label_forumtext": "Showcases, discussions, help and more", + "support_label_forumtitle": "Forum", + "support_label_ggtext": "Circle us on Google +!", + "support_label_ghtext": "Visit us on GitHub", + "support_label_igtext": "Visit us on Instagram to watch the latest Hyperion pictures!", + "support_label_intro": "Hyperion is a free non-profit software. A small team is working on it and this is why we need your steady support.", + "support_label_spreadtheword": "Spread the word", + "support_label_title": "Support Hyperion", + "support_label_twtext": "Share and follow on Twitter, be always up to date with latest post about the Hyperion development", + "support_label_webpagetext": "Home of Hyperion", + "support_label_webpagetitle": "Webpage", + "support_label_webrestitle": "Information and help resources", + "support_label_wikitext": "The A to Z source for almost everything Hyperion related", + "support_label_wikititle": "Wiki", + "support_label_yttext": "Bored from pictures? Check out our YouTube channel!", + "update_button_changelog": "Full changelog", + "update_button_install": "Install", + "update_error_getting_versions": "We had trouble determining the latest available Version.", + "update_label_description": "Description:", + "update_label_intro": "Overview about all available Hyperion versions. On top you could update or downgrade your version of Hyperion whenever you want. Sorted from newest to oldest", + "update_label_type": "Type:", + "update_no_updates_for_branch": "No updates for selected version channel.", + "update_versreminder": "Your version: $1", + "wiz_atmoorb_desc2": "Now choose which Orbs should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.", + "wiz_atmoorb_intro1": "This wizards configures Hyperion for AtmoOrbs. Features are the AtmoOrb auto detection, setting each light to a specific position on your picture or disable it and optimise the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", + "wiz_atmoorb_title": "AtmoOrb Wizard", + "wiz_cc_adjustgamma": "Gamma: What you have to do is, adjust gamma levels of each channel until you have the same perceived amount of each channel. Hint: Neutral is 1.0! For example, if your Grey is a bit reddish it means that you have to increase red gamma to reduce the amount of red (the more gamma, the less amount of color).", + "wiz_cc_adjustit": "Adjust your \"$1\", until your are fine with it. Take notice: The more you adjust away from the default value the color spectrum will be limited (Also for all colors in between). Depending on TV/LED color spectrum the results will vary.", + "wiz_cc_backlight": "Additional you could define a backlight to sort out \"bad colors\" on nearly dark areas or if you don't like the switch between color and off during watching. Additional you could define if there should be some color in it or just white. This is disabled during the state \"Off\" ,\"Color\" and \"Effect\".", + "wiz_cc_btn_stop": "Stop video", + "wiz_cc_btn_switchpic": "Switch picture", + "wiz_cc_chooseid": "Define a name for this color profile.", + "wiz_cc_intro1": "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be sent directly to it. Prerequisite: You need to enable \"Allow remote control from applications on other systems\" in Kodi.
Alternatively, you might want downloading these files yourself and display them when the wizard asks you to adjust the setting.", + "wiz_cc_kodicon": "Kodi found, proceed with Kodi support.", + "wiz_cc_kodidiscon": "Kodi not found, proceed without Kodi support.", + "wiz_cc_kodidisconlink": "Download link pictures:", + "wiz_cc_kodimsg_start": "Test success - time to proceed!", + "wiz_cc_kodishould": "Kodi should show the following picture: $1", + "wiz_cc_kwebs": "Kodi webserver (Hostname or IP)", + "wiz_cc_lettvshow": "Let your TV show the following picture: $1", + "wiz_cc_lettvshowm": "Check this with the following pictures: $1", + "wiz_cc_link": "Click me!", + "wiz_cc_morethanone": "You have more than one profile, please choose the profile you want to calibrate.", + "wiz_cc_summary": "A conclusion of your settings. During video playback, you could change or test values again. If you are done, click on save.", + "wiz_cc_testintro": "Time for a real test!", + "wiz_cc_testintrok": "Push on a button below to start a test video.", + "wiz_cc_testintrowok": "Check out the following link to download test videos:", + "wiz_cc_title": "Colour calibration wizard", + "wiz_cololight_desc2": "Now choose which Cololights should be added. To identify single lights, press the button on the right.", + "wiz_cololight_intro1": "This wizards configures Hyperion for the Cololight system. Features are the Cololight auto detection and tune the Hyperion settings automatically! In short: All you need are some clicks and you are done!
Note: In case of Cololight Strip, you might need to manually correct the LED count and layout.", + "wiz_cololight_noprops": "Not able to get device properties - Define Hardware LED count manually", + "wiz_cololight_title": "Cololight Wizard", + "wiz_guideyou": "The $1 will guide you through the settings. Just press the button!", + "wiz_hue_blinkblue": "Let ID $1 light up blue", + "wiz_hue_clientkey": "Clientkey:", + "wiz_hue_create_user": "Create new User", + "wiz_hue_desc1": "It searches automatically for a Hue-Bridge, in case it can't find one you need to provide the IP-address and push the reload button on the right. Now you need a user ID, if you don't have one create a new one.", + "wiz_hue_desc2": "Now choose which lamps should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.", + "wiz_hue_e_clientkey_needed": "A clientkey that matches the username is required to use the entertainment API. Please enter an existing one or use the button below to create a new one.", + "wiz_hue_e_create_user": "Create new User and clientkey", + "wiz_hue_e_desc1": "It searches automatically for a hue bridge, in case it can't find one you need to provide the ip address and push the reload button on the right. Now you need a user id and the clientkey, if you don't have both, create a new one.", + "wiz_hue_e_desc2": "Now choose your entertainment group, which has all your lights inside for use with Hyperion.", + "wiz_hue_e_desc3": "Now you can choose in which position the respective lamp should be \"in the picture\". A preselection of the position was made based on the configured positions of the lights in the entertainment group. This is just a recommendation and can be customized as desired. You can therefore highlight them briefly by clicking on the right button to improve the selection.", + "wiz_hue_e_intro1": "This wizards configures Hyperion for the well known Philips Hue Entertainment system. Features are: Hue Bridge auto detection, user and clientkey creation, entertainment group selection, setting group lights to a specific position on your picture and optimise the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", + "wiz_hue_e_noapisupport": "The Wizard has disabled entertainment API support and will continue in classic mode.", + "wiz_hue_e_noapisupport_hint": "The option \"Use Hue Entertainment API\" was unchecked.", + "wiz_hue_e_noegrpids": "No entertainment groups in this Hue bridge defined.", + "wiz_hue_e_nogrpids": "This Hue bridge has no groups defined, please create at least one before with the Hue Apps.", + "wiz_hue_e_title": "Philips Hue Entertainment Wizard", + "wiz_hue_e_use_group": "Use group", + "wiz_hue_e_use_groupid": "Use group ID $1", + "wiz_hue_failure_connection": "Timeout: Please press the bridge button within the period of 30 seconds", + "wiz_hue_failure_ip": "No Bridge found, please type in a valid IP-Address", + "wiz_hue_failure_user": "User not found, create a new one with the button below or input a valid user id and press the \"reload\" symbol.", + "wiz_hue_intro1": "This wizards configures Hyperion for the well known Philips Hue system. Features are Hue Bridge auto detection, user creation, set each hue light to a specific position on your picture or disable it and tune the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", + "wiz_hue_ip": "Hue Bridge IP:", + "wiz_hue_noids": "This Hue bridge has no bulbs/stripes, please pair them before with the Hue Apps", + "wiz_hue_press_link": "Please press link button on the Hue Bridge.", + "wiz_hue_searchb": "Searching for bridge...", + "wiz_hue_title": "Philips Hue Wizard", + "wiz_hue_username": "User ID:", + "wiz_identify": "Identify", + "wiz_identify_light": "Identify $1", + "wiz_ids_disabled": "Deactivated", + "wiz_ids_entire": "Whole picture", + "wiz_noLights": "No $1 found! Please get the lights connected to the network or configure them manually.", + "wiz_pos": "Position/State", + "wiz_rgb_expl": "The color dot switches every x seconds the color (red, green), at the same time your LEDs switch the color too. Answer the questions at the bottom to check/correct your byte order.", + "wiz_rgb_intro1": "This wizard will guide you through the finding process of the correct color order for your leds. Click on continue to begin.", + "wiz_rgb_intro2": "When do you need this wizard? Example: You set the color red, but you get green or blue. You could also use it for first configuration.", + "wiz_rgb_q": "Which color show your LEDs, when the color dot above shows...", + "wiz_rgb_qgend": "...green?", + "wiz_rgb_qrend": "...red?", + "wiz_rgb_switchevery": "Switch color every...", + "wiz_rgb_title": "RGB Byte Order Wizard", + "wiz_wizavail": "Wizard available", + "wiz_yeelight_desc2": "Now choose which lamps should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.", + "wiz_yeelight_intro1": "This wizards configures Hyperion for the Yeelight system. Features are the Yeelighs' auto detection, setting each light to a specific position on your picture or disable it and tune the Hyperion settings automatically! So in short: All you need are some clicks and you are done!", + "wiz_yeelight_title": "Yeelight Wizard", + "wiz_yeelight_unsupported": "Unsupported" } diff --git a/assets/webconfig/js/content_grabber.js b/assets/webconfig/js/content_grabber.js index 8f12dd11..62c7a29a 100755 --- a/assets/webconfig/js/content_grabber.js +++ b/assets/webconfig/js/content_grabber.js @@ -3,214 +3,7 @@ $(document).ready(function () { var conf_editor_v4l2 = null; var conf_editor_fg = null; var conf_editor_instCapt = null; - var V4L2_AVAIL = window.serverInfo.grabbers.available.includes("v4l2"); - - if (V4L2_AVAIL) { - // Dynamic v4l2 enum schema - var v4l2_dynamic_enum_schema = { - "available_devices": - { - "type": "string", - "title": "edt_conf_v4l2_device_title", - "propertyOrder": 1, - "required": true, - "custom": true - }, - "device_inputs": - { - "type": "string", - "title": "edt_conf_v4l2_input_title", - "propertyOrder": 3, - "required": true, - "custom": false - }, - "encoding_format": - { - "type": "string", - "title": "edt_conf_v4l2_encoding_title", - "propertyOrder": 5, - "required": true, - "custom": false - }, - "resolutions": - { - "type": "string", - "title": "edt_conf_v4l2_resolution_title", - "propertyOrder": 9, - "required": true, - "custom": true - }, - "framerates": - { - "type": "string", - "title": "edt_conf_v4l2_framerate_title", - "propertyOrder": 12, - "required": true, - "custom": true - } - }; - - // Build dynamic v4l2 enum schema parts - var buildSchemaPart = function (key, schema, device) { - if (schema[key]) { - var enumVals = []; - var enumTitelVals = []; - var v4l2_properties = JSON.parse(JSON.stringify(window.serverInfo.grabbers.video_sources)); - - if (key == 'available_devices') { - for (var i = 0; i < v4l2_properties.length; i++) { - enumVals.push(v4l2_properties[i]['device']); - - v4l2_properties[i].hasOwnProperty('name') - ? enumTitelVals.push(v4l2_properties[i]['name']) - : enumTitelVals.push(v4l2_properties[i]['device']); - } - } else if (key == 'device_inputs') { - return; // TODO Fix V4L2 WebUI - for (var i = 0; i < v4l2_properties.length; i++) { - if (v4l2_properties[i]['device'] == device) { - for (var index = 0; index < v4l2_properties[i]['device_inputs'].length; index++) { - enumVals.push(v4l2_properties[i]['device_inputs'][index]['inputIndex'].toString()); - enumTitelVals.push(v4l2_properties[i]['device_inputs'][index]['inputName']); - } - break; - } - } - } else if (key == 'encoding_format') { - for (var i = 0; i < v4l2_properties.length; i++) { - if (v4l2_properties[i]['device'] == device) { - enumVals = enumTitelVals = v4l2_properties[i][key]; - break; - } - } - } - else if (key == 'resolutions') { - for (var i = 0; i < v4l2_properties.length; i++) { - if (v4l2_properties[i]['device'] == device) { - enumVals = enumTitelVals = v4l2_properties[i][key]; - break; - } - } - } else if (key == 'framerates') { - for (var i = 0; i < v4l2_properties.length; i++) { - if (v4l2_properties[i]['device'] == device) { - enumVals = enumTitelVals = v4l2_properties[i][key]; - break; - } - } - } - - window.schema.grabberV4L2.properties[key] = { - "type": schema[key].type, - "title": schema[key].title, - ...(schema[key].custom ? {"enum": [].concat(["auto"], enumVals, ["custom"]),} : {"enum": [].concat(["auto"], enumVals),}), - "options": - { - "enum_titles": [].concat(["edt_conf_enum_automatic"], enumTitelVals, ["edt_conf_enum_custom"]), - }, - "propertyOrder": schema[key].propertyOrder, - "required": schema[key].required - }; - } - }; - - // Switch between visible states - function toggleOption(option, state) { - $('[data-schemapath="root.grabberV4L2.' + option + '"]').toggle(state); - if (state) ( - $('[data-schemapath="root.grabberV4L2.' + option + '"]').addClass('col-md-12'), - $('label[for="root_grabberV4L2_' + option + '"]').css('left', '10px'), - $('[id="root_grabberV4L2_' + option + '"]').css('left', '10px') - ); - } - - // Watch all v4l2 dynamic fields - var setWatchers = function (schema) { - var path = 'root.grabberV4L2.'; - Object.keys(schema).forEach(function (key) { - conf_editor_v4l2.watch(path + key, function () { - var ed = conf_editor_v4l2.getEditor(path + key); - var val = ed.getValue(); - - if (key == 'available_devices') { - var V4L2properties = ['device_inputs', 'resolutions', 'framerates', 'encoding_format']; - if (val == 'custom') { - var grabberV4L2 = ed.parent; - V4L2properties.forEach(function (item) { - buildSchemaPart(item, v4l2_dynamic_enum_schema, 'none'); - grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item]; - grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item]; - conf_editor_v4l2.validator.schema.properties.grabberV4L2.properties[item] = window.schema.grabberV4L2.properties[item]; - - grabberV4L2.removeObjectProperty(item); - delete grabberV4L2.cached_editors[item]; - grabberV4L2.addObjectProperty(item); - - conf_editor_v4l2.getEditor(path + item).enable(); - }); - - conf_editor_v4l2.getEditor(path + 'standard').enable(); - toggleOption('device', true); - } else if (val == 'auto') { - V4L2properties.forEach(function (item) { - conf_editor_v4l2.getEditor(path + item).setValue('auto'); - conf_editor_v4l2.getEditor(path + item).disable(); - }); - - conf_editor_v4l2.getEditor(path + 'standard').setValue('auto'); - conf_editor_v4l2.getEditor(path + 'standard').disable(); - - (toggleOption('device', false), toggleOption('input', false), - toggleOption('width', false), toggleOption('height', false), - toggleOption('fps', false), toggleOption('encoding', false)); - } else { - var grabberV4L2 = ed.parent; - V4L2properties.forEach(function (item) { - buildSchemaPart(item, v4l2_dynamic_enum_schema, val); - grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item]; - grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item]; - conf_editor_v4l2.validator.schema.properties.grabberV4L2.properties[item] = window.schema.grabberV4L2.properties[item]; - - grabberV4L2.removeObjectProperty(item); - delete grabberV4L2.cached_editors[item]; - grabberV4L2.addObjectProperty(item); - - conf_editor_v4l2.getEditor(path + item).enable(); - }); - - conf_editor_v4l2.getEditor(path + 'standard').enable(); - toggleOption('device', false); - } - } - - if (key == 'resolutions') - val != 'custom' - ? (toggleOption('width', false), toggleOption('height', false)) - : (toggleOption('width', true), toggleOption('height', true)); - - if (key == 'framerates') - val != 'custom' - ? toggleOption('fps', false) - : toggleOption('fps', true); - - if (key == 'device_inputs') - val != 'custom' - ? toggleOption('input', false) - : toggleOption('input', true); - - if (key == 'encoding_format') - val != 'custom' - ? toggleOption('encoding', false) - : toggleOption('encoding', true); - }); - }); - }; - - // Insert dynamic v4l2 enum schema parts - Object.keys(v4l2_dynamic_enum_schema).forEach(function (key) { - buildSchemaPart(key, v4l2_dynamic_enum_schema, window.serverConfig.grabberV4L2.device); - }); - } + var VIDEOGRABBER_AVAIL = window.serverInfo.grabbers.available.includes("v4l2"); if (window.showOptHelp) { // Instance Capture @@ -224,7 +17,7 @@ $(document).ready(function () { $('#conf_cont_fg').append(createHelpTable(window.schema.framegrabber.properties, $.i18n("edt_conf_fg_heading_title"))); // V4L2 - hide if not available - if (V4L2_AVAIL) { + if (VIDEOGRABBER_AVAIL) { $('#conf_cont').append(createRow('conf_cont_v4l')); $('#conf_cont_v4l').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2')); $('#conf_cont_v4l').append(createHelpTable(window.schema.grabberV4L2.properties, $.i18n("edt_conf_v4l2_heading_title"))); @@ -233,7 +26,7 @@ $(document).ready(function () { $('#conf_cont').addClass('row'); $('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt')); $('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg')); - if (V4L2_AVAIL) { + if (VIDEOGRABBER_AVAIL) { $('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2')); } } @@ -244,14 +37,12 @@ $(document).ready(function () { }, true, true); // Hide V4L2 elements, if not available - if (!V4L2_AVAIL) { - var instCapOptions = conf_editor_instCapt; + if (!VIDEOGRABBER_AVAIL) { $('[data-schemapath*="root.instCapture.v4lEnable' + '"]').hide(); $('[data-schemapath*="root.instCapture.v4lPriority' + '"]').hide(); } conf_editor_instCapt.on('change', function () { - var systemEnable = conf_editor_instCapt.getEditor("root.instCapture.systemEnable").getValue(); if (systemEnable) { $('[data-schemapath*="root.instCapture.systemPriority' + '"]').show(); @@ -261,121 +52,40 @@ $(document).ready(function () { $('[data-schemapath*="root.instCapture.systemPriority' + '"]').hide(); } - if (V4L2_AVAIL) { + if (VIDEOGRABBER_AVAIL) { var v4lEnable = conf_editor_instCapt.getEditor("root.instCapture.v4lEnable").getValue(); if (v4lEnable) { $('[data-schemapath*="root.instCapture.v4lPriority' + '"]').show(); $('#conf_cont_v4l').show(); - } else { + } + else { $('[data-schemapath*="root.instCapture.v4lPriority' + '"]').hide(); $('#conf_cont_v4l').hide(); } } + conf_editor_instCapt.validate().length || window.readOnlyMode ? $('#btn_submit_instCapt').attr('disabled', true) : $('#btn_submit_instCapt').attr('disabled', false); }); + conf_editor_instCapt.watch('root.instCapture.v4lEnable', () => { + if (VIDEOGRABBER_AVAIL) { + var v4lEnable = conf_editor_instCapt.getEditor("root.instCapture.v4lEnable").getValue(); + if (v4lEnable) { + discoverInputSources("video"); + } + } + }); + $('#btn_submit_instCapt').off().on('click', function () { requestWriteConfig(conf_editor_instCapt.getValue()); }); - $('#btn_submit_fg').off().on('click', function () { - requestWriteConfig(conf_editor_fg.getValue()); - }); - - if (V4L2_AVAIL) { - conf_editor_v4l2 = createJsonEditor('editor_container_v4l2', { - grabberV4L2: window.schema.grabberV4L2 - }, true, true); - - conf_editor_v4l2.on('change', function () { - conf_editor_v4l2.validate().length || window.readOnlyMode ? $('#btn_submit_v4l2').attr('disabled', true) : $('#btn_submit_v4l2').attr('disabled', false); - }); - - conf_editor_v4l2.on('ready', function () { - setWatchers(v4l2_dynamic_enum_schema); - - if (window.serverConfig.grabberV4L2.available_devices == 'custom' && window.serverConfig.grabberV4L2.device != 'auto') - toggleOption('device', true); - - if (window.serverConfig.grabberV4L2.device == 'auto') - conf_editor_v4l2.getEditor('root.grabberV4L2.available_devices').setValue('auto'); - - if (window.serverConfig.grabberV4L2.available_devices == 'auto') { - ['device_inputs', 'standard', 'resolutions', 'framerates', 'encoding_format'].forEach(function (item) { - conf_editor_v4l2.getEditor('root.grabberV4L2.' + item).setValue('auto'); - conf_editor_v4l2.getEditor('root.grabberV4L2.' + item).disable(); - }); - } - - if (window.serverConfig.grabberV4L2.device_inputs == 'custom' && window.serverConfig.grabberV4L2.device != 'auto') - toggleOption('input', true); - - if (window.serverConfig.grabberV4L2.resolutions == 'custom' && window.serverConfig.grabberV4L2.device != 'auto') - (toggleOption('width', true), toggleOption('height', true)); - - if (window.serverConfig.grabberV4L2.framerates == 'custom' && window.serverConfig.grabberV4L2.device != 'auto') - toggleOption('fps', true); - - if (window.serverConfig.grabberV4L2.encoding_format == 'custom' && window.serverConfig.grabberV4L2.device != 'auto') - toggleOption('encoding', true); - }); - - $('#btn_submit_v4l2').off().on('click', function () { - var v4l2Options = conf_editor_v4l2.getValue(); - - if (v4l2Options.grabberV4L2.available_devices != 'custom' && v4l2Options.grabberV4L2.available_devices != 'auto') - v4l2Options.grabberV4L2.device = v4l2Options.grabberV4L2.available_devices; - - if (v4l2Options.grabberV4L2.available_devices == 'auto') - v4l2Options.grabberV4L2.device = 'auto'; - - if (v4l2Options.grabberV4L2.device_inputs != 'custom' && v4l2Options.grabberV4L2.device_inputs != 'auto' && v4l2Options.grabberV4L2.available_devices != 'auto') - v4l2Options.grabberV4L2.input = parseInt(v4l2Options.grabberV4L2.device_inputs); - - if (v4l2Options.grabberV4L2.device_inputs == 'auto') - v4l2Options.grabberV4L2.input = -1; - - if (v4l2Options.grabberV4L2.encoding_format != 'custom' && v4l2Options.grabberV4L2.encoding_format != 'auto' && v4l2Options.grabberV4L2.available_devices != 'auto') - v4l2Options.grabberV4L2.encoding = v4l2Options.grabberV4L2.encoding_format; - - if (v4l2Options.grabberV4L2.encoding_format == 'auto' || v4l2Options.grabberV4L2.encoding_format == 'NO_CHANGE') - v4l2Options.grabberV4L2.encoding = 'NO_CHANGE'; - - if (v4l2Options.grabberV4L2.resolutions != 'custom' && v4l2Options.grabberV4L2.resolutions != 'auto' && v4l2Options.grabberV4L2.available_devices != 'auto') - (v4l2Options.grabberV4L2.width = parseInt(v4l2Options.grabberV4L2.resolutions.split('x')[0]), - v4l2Options.grabberV4L2.height = parseInt(v4l2Options.grabberV4L2.resolutions.split('x')[1])); - - if (v4l2Options.grabberV4L2.resolutions == 'auto') - (v4l2Options.grabberV4L2.width = 0, v4l2Options.grabberV4L2.height = 0); - - if (v4l2Options.grabberV4L2.framerates != 'custom' && v4l2Options.grabberV4L2.framerates != 'auto' && v4l2Options.grabberV4L2.available_devices != 'auto') - v4l2Options.grabberV4L2.fps = parseInt(v4l2Options.grabberV4L2.framerates); - - if (v4l2Options.grabberV4L2.framerates == 'auto') - v4l2Options.grabberV4L2.fps = 15; - - requestWriteConfig(v4l2Options); - }); - } - - ////////////////////////////////////////////////// - - //create introduction - if (window.showOptHelp) { - createHint("intro", $.i18n('conf_grabber_fg_intro'), "editor_container_fg"); - if (V4L2_AVAIL) { - createHint("intro", $.i18n('conf_grabber_v4l_intro'), "editor_container_v4l2"); - } - } - // Framegrabber conf_editor_fg = createJsonEditor('editor_container_fg', { framegrabber: window.schema.framegrabber }, true, true); - conf_editor_fg.on('ready', function () { - var availableGrabbers = window.serverInfo.grabbers.available; var fgOptions = conf_editor_fg.getEditor('root.framegrabber'); var orginalGrabberTypes = fgOptions.schema.properties.type.enum; @@ -419,7 +129,6 @@ $(document).ready(function () { } function filerFgGrabberOptions(type) { - //hide specific options for grabbers found var grabbers = window.serverInfo.grabbers.available; if (grabbers.indexOf(type) > -1) { @@ -450,6 +159,344 @@ $(document).ready(function () { } }; - removeOverlay(); -}); + $('#btn_submit_fg').off().on('click', function () { + requestWriteConfig(conf_editor_fg.getValue()); + }); + // External Input Sources (Video-Grabbers) + + var configuredDevice = ""; + var discoveredInputSources = {}; + var deviceProperties = {}; + + if (VIDEOGRABBER_AVAIL) { + conf_editor_v4l2 = createJsonEditor('editor_container_v4l2', { + grabberV4L2: window.schema.grabberV4L2 + }, true, true); + + conf_editor_v4l2.on('ready', function () { + var v4lEnable = conf_editor_instCapt.getEditor("root.instCapture.v4lEnable").getValue(); + if (v4lEnable) { + discoverInputSources("video"); + } + }); + + conf_editor_v4l2.on('change', function () { + var deviceSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.available_devices").getValue(); + if (!conf_editor_v4l2.validate().length) { + if (deviceSelected !== "NONE") { + window.readOnlyMode ? $('#btn_submit_v4l2').attr('disabled', true) : $('#btn_submit_v4l2').attr('disabled', false); + } + } + }); + + conf_editor_v4l2.watch('root.grabberV4L2.available_devices', () => { + var deviceSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.available_devices").getValue(); + if (deviceSelected === "NONE" || deviceSelected === "") { + $('#btn_submit_v4l2').attr('disabled', true); + } + else { + var addSchemaElements = {}; + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + + //Update hidden input element + conf_editor_v4l2.getEditor("root.grabberV4L2.device").setValue(deviceProperties.device); + + var video_inputs = deviceProperties.video_inputs; + if (video_inputs.length <= 1) { + addSchemaElements.access = "expert"; + } + + for (const video_input of video_inputs) { + enumVals.push(video_input.inputIdx); + enumTitelVals.push(video_input.name); + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredVideoInput = window.serverConfig.grabberV4L2.input; + if ($.inArray(configuredVideoInput, enumVals) != -1) { + enumDefaultVal = configuredVideoInput; + } + } + updateJsonEditorSelection(conf_editor_v4l2.getEditor('root.grabberV4L2'), + 'device_inputs', addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_v4l2').attr('disabled', false); + } + } + }); + + conf_editor_v4l2.watch('root.grabberV4L2.device_inputs', () => { + var deviceSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.available_devices").getValue(); + var videoInputSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.device_inputs").getValue(); + + var addSchemaElements = {}; + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + var formats = deviceProperties.video_inputs[videoInputSelected].formats; + //Hide, if only one record available for selection + if (formats.length <= 1) { + addSchemaElements.access = "expert"; + } + + for (var i = 0; i < formats.length; i++) { + if (formats[i].format) { + enumVals.push(formats[i].format); + enumTitelVals.push(formats[i].format.toUpperCase()); + } + else { + enumVals.push("NONE"); + } + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredEncoding = window.serverConfig.grabberV4L2.encoding; + if ($.inArray(configuredEncoding, enumVals) != -1) { + enumDefaultVal = configuredEncoding; + } + } + updateJsonEditorSelection(conf_editor_v4l2.getEditor('root.grabberV4L2'), + 'encoding', addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, false); + } + + var enumVals = []; + var enumDefaultVal = ""; + + var standards = deviceProperties.video_inputs[videoInputSelected].standards; + if (!standards) { + enumVals.push("NONE"); + addSchemaElements.options = { "hidden": true }; + } else { + enumVals = standards; + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredStandard = window.serverConfig.grabberV4L2.standard; + if ($.inArray(configuredStandard, enumVals) != -1) { + enumDefaultVal = configuredStandard; + } + } + + updateJsonEditorSelection(conf_editor_v4l2.getEditor('root.grabberV4L2'), + 'standard', addSchemaElements, enumVals, [], enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_v4l2').attr('disabled', false); + } + }); + + conf_editor_v4l2.watch('root.grabberV4L2.encoding', () => { + var deviceSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.available_devices").getValue(); + var videoInputSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.device_inputs").getValue(); + var formatSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.encoding").getValue(); + + //Update hidden input element + conf_editor_v4l2.getEditor("root.grabberV4L2.input").setValue(parseInt(videoInputSelected)); + + var addSchemaElements = {}; + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + + var formats = deviceProperties.video_inputs[videoInputSelected].formats; + var formatIdx = 0; + if (formatSelected !== "NONE") { + formatIdx = formats.findIndex(x => x.format === formatSelected); + } + + var resolutions = formats[formatIdx].resolutions; + if (resolutions.length <= 1) { + addSchemaElements.access = "expert"; + } else { + resolutions.sort(compareTwoValues('width', 'height', 'asc')); + } + + for (var i = 0; i < resolutions.length; i++) { + enumVals.push(i); + var resolutionText = resolutions[i].width + "x" + resolutions[i].height; + enumTitelVals.push(resolutionText); + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredResolutionText = window.serverConfig.grabberV4L2.width + "x" + window.serverConfig.grabberV4L2.height; + var idx = $.inArray(configuredResolutionText, enumTitelVals) + if (idx != -1) { + enumDefaultVal = idx; + } + } + + updateJsonEditorSelection(conf_editor_v4l2.getEditor('root.grabberV4L2'), + 'resolutions', addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_v4l2').attr('disabled', false); + } + }); + + conf_editor_v4l2.watch('root.grabberV4L2.resolutions', () => { + var deviceSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.available_devices").getValue(); + var videoInputSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.device_inputs").getValue(); + var formatSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.encoding").getValue(); + var resolutionSelected = conf_editor_v4l2.getEditor("root.grabberV4L2.resolutions").getValue(); + + var addSchemaElements = {}; + var enumVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + + var formats = deviceProperties.video_inputs[videoInputSelected].formats; + var formatIdx = 0; + if (formatSelected !== "NONE") { + formatIdx = formats.findIndex(x => x.format === formatSelected); + } + + //Update hidden resolution related elements + var width = parseInt(formats[formatIdx].resolutions[resolutionSelected].width); + conf_editor_v4l2.getEditor("root.grabberV4L2.width").setValue(width); + + var height = parseInt(formats[formatIdx].resolutions[resolutionSelected].height); + conf_editor_v4l2.getEditor("root.grabberV4L2.height").setValue(height); + + var fps = formats[formatIdx].resolutions[resolutionSelected].fps; + if (!fps) { + enumVals.push("NONE"); + addSchemaElements.options = { "hidden": true }; + } else { + fps.sort((a, b) => a - b); + for (var i = 0; i < fps.length; i++) { + enumVals.push(fps[i]); + } + } + + if (enumVals.length <= 1) { + addSchemaElements.access = "expert"; + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredFps = window.serverConfig.grabberV4L2.fps; + if ($.inArray(configuredFps, enumVals) != -1) { + enumDefaultVal = configuredFps; + } + } + updateJsonEditorSelection(conf_editor_v4l2.getEditor('root.grabberV4L2'), + 'framerates', addSchemaElements, enumVals, [], enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_v4l2').attr('disabled', false); + } + }); + + conf_editor_v4l2.watch('root.grabberV4L2.framerates', () => { + //Update hidden fps element + var fps = 0; + var framerates = conf_editor_v4l2.getEditor("root.grabberV4L2.framerates").getValue(); + if (framerates !== "NONE") { + fps = parseInt(framerates); + } + + //Show Frameskipping only when more than 2 fps + if (fps > 2) { + $('[data-schemapath*="root.grabberV4L2.fpsSoftwareDecimation').toggle(true); + } + else { + $('[data-schemapath*="root.grabberV4L2.fpsSoftwareDecimation').toggle(false); + } + conf_editor_v4l2.getEditor("root.grabberV4L2.fps").setValue(fps); + }); + + $('#btn_submit_v4l2').off().on('click', function () { + var v4l2Options = conf_editor_v4l2.getValue(); + requestWriteConfig(v4l2Options); + }); + } + + ////////////////////////////////////////////////// + + //create introduction + if (window.showOptHelp) { + createHint("intro", $.i18n('conf_grabber_fg_intro'), "editor_container_fg"); + if (VIDEOGRABBER_AVAIL) { + createHint("intro", $.i18n('conf_grabber_v4l_intro'), "editor_container_v4l2"); + } + } + + removeOverlay(); + + // build dynamic enum + var updateVideoSourcesList = function (type, discoveryInfo) { + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + + if (jQuery.isEmptyObject(discoveryInfo)) { + enumVals.push("NONE"); + enumTitelVals.push($.i18n('edt_conf_grabber_discovered_none')); + + conf_editor_v4l2.getEditor('root.grabberV4L2').disable(); + } + else { + for (const device of discoveryInfo) { + enumVals.push(device.device_name); + } + conf_editor_v4l2.getEditor('root.grabberV4L2').enable(); + } + + if (enumVals.length > 0) { + configuredDevice = window.serverConfig.grabberV4L2.available_devices; + if ($.inArray(configuredDevice, enumVals) != -1) { + enumDefaultVal = configuredDevice; + } + + updateJsonEditorSelection(conf_editor_v4l2.getEditor('root.grabberV4L2'), + 'available_devices', {}, enumVals, enumTitelVals, enumDefaultVal, false); + } + } + + async function discoverInputSources(type, params) { + const result = await requestInputSourcesDiscovery(type, params); + + var discoveryResult; + if (result && !result.error) { + discoveryResult = result.info; + } + else { + discoveryResult = { + "video_sources": [] + } + } + discoveredInputSources = discoveryResult.video_sources; + + updateVideoSourcesList(type, discoveredInputSources); + } + + function getPropertiesOfDevice(deviceName) { + deviceProperties = {}; + for (const deviceRecord of discoveredInputSources) { + if (deviceRecord.device_name === deviceName) { + deviceProperties = deviceRecord; + break; + } + } + return deviceProperties; + } +}); diff --git a/assets/webconfig/js/hyperion.js b/assets/webconfig/js/hyperion.js index b38997ed..c488f073 100644 --- a/assets/webconfig/js/hyperion.js +++ b/assets/webconfig/js/hyperion.js @@ -35,35 +35,35 @@ tokenList = {}; function initRestart() { - $(window.hyperion).off(); - requestServerConfigReload(); - window.watchdog = 10; - connectionLostDetection('restart'); + $(window.hyperion).off(); + requestServerConfigReload(); + window.watchdog = 10; + connectionLostDetection('restart'); } function connectionLostDetection(type) { - if ( window.watchdog > 2 ) - { - var interval_id = window.setInterval(function(){clearInterval(interval_id);}, 9999); // Get a reference to the last - for (var i = 1; i < interval_id; i++) - window.clearInterval(i); - if(type == 'restart') - { - $("body").html($("#container_restart").html()); - // setTimeout delay for probably slower systems, some browser don't execute THIS action - setTimeout(restartAction,250); - } - else - { - $("body").html($("#container_connection_lost").html()); - connectionLostAction(); - } - } - else - { - $.get( "/cgi/cfg_jsonserver", function() {window.watchdog=0}).fail(function() {window.watchdog++;}); - } + if ( window.watchdog > 2 ) + { + var interval_id = window.setInterval(function(){clearInterval(interval_id);}, 9999); // Get a reference to the last + for (var i = 1; i < interval_id; i++) + window.clearInterval(i); + if(type == 'restart') + { + $("body").html($("#container_restart").html()); + // setTimeout delay for probably slower systems, some browser don't execute THIS action + setTimeout(restartAction,250); + } + else + { + $("body").html($("#container_connection_lost").html()); + connectionLostAction(); + } + } + else + { + $.get( "/cgi/cfg_jsonserver", function() {window.watchdog=0}).fail(function() {window.watchdog++;}); + } } setInterval(connectionLostDetection, 3000); @@ -72,107 +72,107 @@ setInterval(connectionLostDetection, 3000); function initWebSocket() { - if ("WebSocket" in window) - { - if (window.websocket == null) - { - window.jsonPort = ''; - if(document.location.port == '' && document.location.protocol == "http:") - window.jsonPort = '80'; - else if (document.location.port == '' && document.location.protocol == "https:") - window.jsonPort = '443'; - else - window.jsonPort = document.location.port; - window.websocket = (document.location.protocol == "https:") ? new WebSocket('wss://'+document.location.hostname+":"+window.jsonPort) : new WebSocket('ws://'+document.location.hostname+":"+window.jsonPort); + if ("WebSocket" in window) + { + if (window.websocket == null) + { + window.jsonPort = ''; + if(document.location.port == '' && document.location.protocol == "http:") + window.jsonPort = '80'; + else if (document.location.port == '' && document.location.protocol == "https:") + window.jsonPort = '443'; + else + window.jsonPort = document.location.port; + window.websocket = (document.location.protocol == "https:") ? new WebSocket('wss://'+document.location.hostname+":"+window.jsonPort) : new WebSocket('ws://'+document.location.hostname+":"+window.jsonPort); - window.websocket.onopen = function (event) { - $(window.hyperion).trigger({type:"open"}); + window.websocket.onopen = function (event) { + $(window.hyperion).trigger({type:"open"}); - $(window.hyperion).on("cmd-serverinfo", function(event) { - window.watchdog = 0; - }); - }; + $(window.hyperion).on("cmd-serverinfo", function(event) { + window.watchdog = 0; + }); + }; - window.websocket.onclose = function (event) { - // See http://tools.ietf.org/html/rfc6455#section-7.4.1 - var reason; - switch(event.code) - { - case 1000: reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled."; break; - case 1001: reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page."; break; - case 1002: reason = "An endpoint is terminating the connection due to a protocol error"; break; - case 1003: reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message)."; break; - case 1004: reason = "Reserved. The specific meaning might be defined in the future."; break; - case 1005: reason = "No status code was actually present."; break; - case 1006: reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame"; break; - case 1007: reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message)."; break; - case 1008: reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy."; break; - case 1009: reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process."; break; - case 1010: reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake.
Specifically, the extensions that are needed are: " + event.reason; break; - case 1011: reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request."; break; - case 1015: reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified)."; break; - default: reason = "Unknown reason"; - } - $(window.hyperion).trigger({type:"close", reason:reason}); - window.watchdog = 10; - connectionLostDetection(); - }; + window.websocket.onclose = function (event) { + // See http://tools.ietf.org/html/rfc6455#section-7.4.1 + var reason; + switch(event.code) + { + case 1000: reason = "Normal closure, meaning that the purpose for which the connection was established has been fulfilled."; break; + case 1001: reason = "An endpoint is \"going away\", such as a server going down or a browser having navigated away from a page."; break; + case 1002: reason = "An endpoint is terminating the connection due to a protocol error"; break; + case 1003: reason = "An endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message)."; break; + case 1004: reason = "Reserved. The specific meaning might be defined in the future."; break; + case 1005: reason = "No status code was actually present."; break; + case 1006: reason = "The connection was closed abnormally, e.g., without sending or receiving a Close control frame"; break; + case 1007: reason = "An endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629] data within a text message)."; break; + case 1008: reason = "An endpoint is terminating the connection because it has received a message that \"violates its policy\". This reason is given either if there is no other sutible reason, or if there is a need to hide specific details about the policy."; break; + case 1009: reason = "An endpoint is terminating the connection because it has received a message that is too big for it to process."; break; + case 1010: reason = "An endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake.
Specifically, the extensions that are needed are: " + event.reason; break; + case 1011: reason = "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request."; break; + case 1015: reason = "The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified)."; break; + default: reason = "Unknown reason"; + } + $(window.hyperion).trigger({type:"close", reason:reason}); + window.watchdog = 10; + connectionLostDetection(); + }; - window.websocket.onmessage = function (event) { - try - { - var response = JSON.parse(event.data); - var success = response.success; - var cmd = response.command; - var tan = response.tan - if (success || typeof(success) == "undefined") - { - $(window.hyperion).trigger({type:"cmd-"+cmd, response:response}); - } - else - { - // skip tan -1 error handling - if(tan != -1){ - var error = response.hasOwnProperty("error")? response.error : "unknown"; - $(window.hyperion).trigger({type:"error",reason:error}); - console.log("[window.websocket::onmessage] ",error) - } - } - } - catch(exception_error) - { - $(window.hyperion).trigger({type:"error",reason:exception_error}); - console.log("[window.websocket::onmessage] ",exception_error) - } - }; + window.websocket.onmessage = function (event) { + try + { + var response = JSON.parse(event.data); + var success = response.success; + var cmd = response.command; + var tan = response.tan + if (success || typeof(success) == "undefined") + { + $(window.hyperion).trigger({type:"cmd-"+cmd, response:response}); + } + else + { + // skip tan -1 error handling + if(tan != -1){ + var error = response.hasOwnProperty("error")? response.error : "unknown"; + $(window.hyperion).trigger({type:"error",reason:error}); + console.log("[window.websocket::onmessage] ",error) + } + } + } + catch(exception_error) + { + $(window.hyperion).trigger({type:"error",reason:exception_error}); + console.log("[window.websocket::onmessage] ",exception_error) + } + }; - window.websocket.onerror = function (error) { - $(window.hyperion).trigger({type:"error",reason:error}); - console.log("[window.websocket::onerror] ",error) - }; - } - } - else - { - $(window.hyperion).trigger("error"); - alert("Websocket is not supported by your browser"); - return; - } + window.websocket.onerror = function (error) { + $(window.hyperion).trigger({type:"error",reason:error}); + console.log("[window.websocket::onerror] ",error) + }; + } + } + else + { + $(window.hyperion).trigger("error"); + alert("Websocket is not supported by your browser"); + return; + } } function sendToHyperion(command, subcommand, msg) { - if (typeof subcommand != 'undefined' && subcommand.length > 0) - subcommand = ',"subcommand":"'+subcommand+'"'; - else - subcommand = ""; + if (typeof subcommand != 'undefined' && subcommand.length > 0) + subcommand = ',"subcommand":"'+subcommand+'"'; + else + subcommand = ""; - if (typeof msg != 'undefined' && msg.length > 0) - msg = ","+msg; - else - msg = ""; + if (typeof msg != 'undefined' && msg.length > 0) + msg = ","+msg; + else + msg = ""; - window.websocket.send('{"command":"'+command+'", "tan":'+window.wsTan+subcommand+msg+'}'); + window.websocket.send('{"command":"'+command+'", "tan":'+window.wsTan+subcommand+msg+'}'); } // Send a json message to Hyperion and wait for a matching response @@ -228,250 +228,256 @@ async function __sendAsync (data) { // Test if admin requires authentication function requestRequiresAdminAuth() { - sendToHyperion("authorize","adminRequired"); + sendToHyperion("authorize","adminRequired"); } // Test if the default password needs to be changed function requestRequiresDefaultPasswortChange() { - sendToHyperion("authorize","newPasswordRequired"); + sendToHyperion("authorize","newPasswordRequired"); } // Change password function requestChangePassword(oldPw, newPw) { - sendToHyperion("authorize","newPassword",'"password": "'+oldPw+'", "newPassword":"'+newPw+'"'); + sendToHyperion("authorize","newPassword",'"password": "'+oldPw+'", "newPassword":"'+newPw+'"'); } function requestAuthorization(password) { - sendToHyperion("authorize","login",'"password": "' + password + '"'); + sendToHyperion("authorize","login",'"password": "' + password + '"'); } function requestTokenAuthorization(token) { - sendToHyperion("authorize","login",'"token": "' + token + '"'); + sendToHyperion("authorize","login",'"token": "' + token + '"'); } function requestToken(comment) { - sendToHyperion("authorize","createToken",'"comment": "'+comment+'"'); + sendToHyperion("authorize","createToken",'"comment": "'+comment+'"'); } function requestTokenInfo() { - sendToHyperion("authorize","getTokenList",""); + sendToHyperion("authorize","getTokenList",""); } function requestGetPendingTokenRequests (id, state) { - sendToHyperion("authorize", "getPendingTokenRequests", ""); + sendToHyperion("authorize", "getPendingTokenRequests", ""); } function requestHandleTokenRequest(id, state) { - sendToHyperion("authorize","answerRequest",'"id":"'+id+'", "accept":'+state); + sendToHyperion("authorize","answerRequest",'"id":"'+id+'", "accept":'+state); } function requestTokenDelete(id) { - sendToHyperion("authorize","deleteToken",'"id":"'+id+'"'); + sendToHyperion("authorize","deleteToken",'"id":"'+id+'"'); } function requestInstanceRename(inst, name) { - sendToHyperion("instance", "saveName",'"instance": '+inst+', "name": "'+name+'"'); + sendToHyperion("instance", "saveName",'"instance": '+inst+', "name": "'+name+'"'); } function requestInstanceStartStop(inst, start) { - if(start) - sendToHyperion("instance","startInstance",'"instance": '+inst); - else - sendToHyperion("instance","stopInstance",'"instance": '+inst); + if(start) + sendToHyperion("instance","startInstance",'"instance": '+inst); + else + sendToHyperion("instance","stopInstance",'"instance": '+inst); } function requestInstanceDelete(inst) { - sendToHyperion("instance","deleteInstance",'"instance": '+inst); + sendToHyperion("instance","deleteInstance",'"instance": '+inst); } function requestInstanceCreate(name) { - sendToHyperion("instance","createInstance",'"name": "'+name+'"'); + sendToHyperion("instance","createInstance",'"name": "'+name+'"'); } function requestInstanceSwitch(inst) { - sendToHyperion("instance","switchTo",'"instance": '+inst); + sendToHyperion("instance","switchTo",'"instance": '+inst); } function requestServerInfo() { - sendToHyperion("serverinfo","",'"subscribe":["components-update","sessions-update","priorities-update", "imageToLedMapping-update", "adjustment-update", "videomode-update", "effects-update", "settings-update", "instance-update"]'); + sendToHyperion("serverinfo","",'"subscribe":["components-update","sessions-update","priorities-update", "imageToLedMapping-update", "adjustment-update", "videomode-update", "effects-update", "settings-update", "instance-update"]'); } function requestSysInfo() { - sendToHyperion("sysinfo"); + sendToHyperion("sysinfo"); } function requestServerConfigSchema() { - sendToHyperion("config","getschema"); + sendToHyperion("config","getschema"); } function requestServerConfig() { - sendToHyperion("config", "getconfig"); + sendToHyperion("config", "getconfig"); } function requestServerConfigReload() { - sendToHyperion("config", "reload"); + sendToHyperion("config", "reload"); } function requestLedColorsStart() { - window.ledStreamActive=true; - sendToHyperion("ledcolors", "ledstream-start"); + window.ledStreamActive=true; + sendToHyperion("ledcolors", "ledstream-start"); } function requestLedColorsStop() { - window.ledStreamActive=false; - sendToHyperion("ledcolors", "ledstream-stop"); + window.ledStreamActive=false; + sendToHyperion("ledcolors", "ledstream-stop"); } function requestLedImageStart() { - window.imageStreamActive=true; - sendToHyperion("ledcolors", "imagestream-start"); + window.imageStreamActive=true; + sendToHyperion("ledcolors", "imagestream-start"); } function requestLedImageStop() { - window.imageStreamActive=false; - sendToHyperion("ledcolors", "imagestream-stop"); + window.imageStreamActive=false; + sendToHyperion("ledcolors", "imagestream-stop"); } function requestPriorityClear(prio) { - if(typeof prio !== 'number') - prio = window.webPrio; + if(typeof prio !== 'number') + prio = window.webPrio; - sendToHyperion("clear", "", '"priority":'+prio+''); + sendToHyperion("clear", "", '"priority":'+prio+''); } function requestClearAll() { - requestPriorityClear(-1) + requestPriorityClear(-1) } function requestPlayEffect(effectName, duration) { - sendToHyperion("effect", "", '"effect":{"name":"'+effectName+'"},"priority":'+window.webPrio+',"duration":'+validateDuration(duration)+',"origin":"'+window.webOrigin+'"'); + sendToHyperion("effect", "", '"effect":{"name":"'+effectName+'"},"priority":'+window.webPrio+',"duration":'+validateDuration(duration)+',"origin":"'+window.webOrigin+'"'); } function requestSetColor(r,g,b,duration) { - sendToHyperion("color", "", '"color":['+r+','+g+','+b+'], "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+',"origin":"'+window.webOrigin+'"'); + sendToHyperion("color", "", '"color":['+r+','+g+','+b+'], "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+',"origin":"'+window.webOrigin+'"'); } function requestSetImage(data,duration,name) { - sendToHyperion("image", "", '"imagedata":"'+data+'", "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+', "format":"auto", "origin":"'+window.webOrigin+'", "name":"'+name+'"'); + sendToHyperion("image", "", '"imagedata":"'+data+'", "priority":'+window.webPrio+',"duration":'+validateDuration(duration)+', "format":"auto", "origin":"'+window.webOrigin+'", "name":"'+name+'"'); } function requestSetComponentState(comp, state) { - var state_str = state ? "true" : "false"; - sendToHyperion("componentstate", "", '"componentstate":{"component":"'+comp+'","state":'+state_str+'}'); + var state_str = state ? "true" : "false"; + sendToHyperion("componentstate", "", '"componentstate":{"component":"'+comp+'","state":'+state_str+'}'); } function requestSetSource(prio) { - if ( prio == "auto" ) - sendToHyperion("sourceselect", "", '"auto":true'); - else - sendToHyperion("sourceselect", "", '"priority":'+prio); + if ( prio == "auto" ) + sendToHyperion("sourceselect", "", '"auto":true'); + else + sendToHyperion("sourceselect", "", '"priority":'+prio); } function requestWriteConfig(config, full) { - if(full === true) - window.serverConfig = config; - else - { - jQuery.each(config, function(i, val) { - window.serverConfig[i] = val; - }); - } + if(full === true) + window.serverConfig = config; + else + { + jQuery.each(config, function(i, val) { + window.serverConfig[i] = val; + }); + } - sendToHyperion("config","setconfig", '"config":'+JSON.stringify(window.serverConfig)); + sendToHyperion("config","setconfig", '"config":'+JSON.stringify(window.serverConfig)); } function requestWriteEffect(effectName,effectPy,effectArgs,data) { - var cutArgs = effectArgs.slice(1, -1); - sendToHyperion("create-effect", "", '"name":"'+effectName+'", "script":"'+effectPy+'", '+cutArgs+',"imageData":"'+data+'"'); + var cutArgs = effectArgs.slice(1, -1); + sendToHyperion("create-effect", "", '"name":"'+effectName+'", "script":"'+effectPy+'", '+cutArgs+',"imageData":"'+data+'"'); } function requestTestEffect(effectName,effectPy,effectArgs,data) { - sendToHyperion("effect", "", '"effect":{"name":"'+effectName+'", "args":'+effectArgs+'}, "priority":'+window.webPrio+', "origin":"'+window.webOrigin+'", "pythonScript":"'+effectPy+'", "imageData":"'+data+'"'); + sendToHyperion("effect", "", '"effect":{"name":"'+effectName+'", "args":'+effectArgs+'}, "priority":'+window.webPrio+', "origin":"'+window.webOrigin+'", "pythonScript":"'+effectPy+'", "imageData":"'+data+'"'); } function requestDeleteEffect(effectName) { - sendToHyperion("delete-effect", "", '"name":"'+effectName+'"'); + sendToHyperion("delete-effect", "", '"name":"'+effectName+'"'); } function requestLoggingStart() { - window.loggingStreamActive=true; - sendToHyperion("logging", "start"); + window.loggingStreamActive=true; + sendToHyperion("logging", "start"); } function requestLoggingStop() { - window.loggingStreamActive=false; - sendToHyperion("logging", "stop"); + window.loggingStreamActive=false; + sendToHyperion("logging", "stop"); } function requestMappingType(type) { - sendToHyperion("processing", "", '"mappingType": "'+type+'"'); + sendToHyperion("processing", "", '"mappingType": "'+type+'"'); } function requestVideoMode(newMode) { - sendToHyperion("videomode", "", '"videoMode": "'+newMode+'"'); + sendToHyperion("videomode", "", '"videoMode": "'+newMode+'"'); } function requestAdjustment(type, value, complete) { - if(complete === true) - sendToHyperion("adjustment", "", '"adjustment": '+type+''); - else - sendToHyperion("adjustment", "", '"adjustment": {"'+type+'": '+value+'}'); + if(complete === true) + sendToHyperion("adjustment", "", '"adjustment": '+type+''); + else + sendToHyperion("adjustment", "", '"adjustment": {"'+type+'": '+value+'}'); } async function requestLedDeviceDiscovery(type, params) { - let data = { ledDeviceType: type, params: params }; + let data = { ledDeviceType: type, params: params }; - return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) ); + return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) ); } async function requestLedDeviceProperties(type, params) { - let data = { ledDeviceType: type, params: params }; + let data = { ledDeviceType: type, params: params }; - return sendAsyncToHyperion("leddevice", "getProperties", data, Math.floor(Math.random() * 1000)); + return sendAsyncToHyperion("leddevice", "getProperties", data, Math.floor(Math.random() * 1000)); } function requestLedDeviceIdentification(type, params) { - //sendToHyperion("leddevice", "identify", '"ledDeviceType": "'+type+'","params": '+JSON.stringify(params)+''); let data = { ledDeviceType: type, params: params }; - return sendAsyncToHyperion("leddevice", "identify", data, Math.floor(Math.random() * 1000)); + + return sendAsyncToHyperion("leddevice", "identify", data, Math.floor(Math.random() * 1000)); +} + +async function requestInputSourcesDiscovery(type, params) { + let data = { sourceType: type, params: params }; + + return sendAsyncToHyperion("inputsource", "discover", data, Math.floor(Math.random() * 1000)); } diff --git a/assets/webconfig/js/ui_utils.js b/assets/webconfig/js/ui_utils.js index ff5a50ba..1de5eeb1 100644 --- a/assets/webconfig/js/ui_utils.js +++ b/assets/webconfig/js/ui_utils.js @@ -2,481 +2,481 @@ var prevTag; function removeOverlay() { - $("#loading_overlay").removeClass("overlay"); + $("#loading_overlay").removeClass("overlay"); } function reload() { - location.reload(); + location.reload(); } function storageComp() { - if (typeof(Storage) !== "undefined") - return true; - return false; + if (typeof(Storage) !== "undefined") + return true; + return false; } function getStorage(item, session) { - if(storageComp()) - { - if(session === true) - return sessionStorage.getItem(item); - else - return localStorage.getItem(item); - } - return null; + if(storageComp()) + { + if(session === true) + return sessionStorage.getItem(item); + else + return localStorage.getItem(item); + } + return null; } function setStorage(item, value, session) { - if(storageComp()) - { - if(session === true) - sessionStorage.setItem(item, value); - else - localStorage.setItem(item, value); - } + if(storageComp()) + { + if(session === true) + sessionStorage.setItem(item, value); + else + localStorage.setItem(item, value); + } } function removeStorage(item, session) { - if(storageComp()) - { - if(session === true) - sessionStorage.removeItem(item); - else - localStorage.removeItem(item); - } + if(storageComp()) + { + if(session === true) + sessionStorage.removeItem(item); + else + localStorage.removeItem(item); + } } function debugMessage(msg) { - if (window.debugMessagesActive) - { - console.log(msg); - } + if (window.debugMessagesActive) + { + console.log(msg); + } } function updateSessions() { - var sess = window.serverInfo.sessions; - if (sess && sess.length) - { - window.wSess = []; - for(var i = 0; i 1) - $('#btn_instanceswitch').toggle(true); - else - $('#btn_instanceswitch').toggle(false); - } + if (window.wSess.length > 1) + $('#btn_instanceswitch').toggle(true); + else + $('#btn_instanceswitch').toggle(false); + } } function validateDuration(d) { - if(typeof d === "undefined" || d < 0) - return 0; - else - return d *= 1000; + if(typeof d === "undefined" || d < 0) + return 0; + else + return d *= 1000; } function getHashtag() { - if(getStorage('lasthashtag', true) != null) - return getStorage('lasthashtag', true); - else - { - var tag = document.URL; - tag = tag.substr(tag.indexOf("#") + 1); - if(tag == "" || typeof tag === "undefined" || tag.startsWith("http")) - tag = "dashboard" - return tag; - } + if(getStorage('lasthashtag', true) != null) + return getStorage('lasthashtag', true); + else + { + var tag = document.URL; + tag = tag.substr(tag.indexOf("#") + 1); + if(tag == "" || typeof tag === "undefined" || tag.startsWith("http")) + tag = "dashboard" + return tag; + } } function loadContent(event, forceRefresh) { - var tag; + var tag; - var lastSelectedInstance = getStorage('lastSelectedInstance', false); + var lastSelectedInstance = getStorage('lastSelectedInstance', false); - if (lastSelectedInstance && (lastSelectedInstance != window.currentHyperionInstance)) - if (typeof(window.serverInfo.instance[lastSelectedInstance].running) !== 'undefined' && window.serverInfo.instance[lastSelectedInstance].running) - instanceSwitch(lastSelectedInstance); - else - removeStorage('lastSelectedInstance', false); + if (lastSelectedInstance && (lastSelectedInstance != window.currentHyperionInstance)) + if (typeof(window.serverInfo.instance[lastSelectedInstance].running) !== 'undefined' && window.serverInfo.instance[lastSelectedInstance].running) + instanceSwitch(lastSelectedInstance); + else + removeStorage('lastSelectedInstance', false); - if(typeof event != "undefined") - { - tag = event.currentTarget.hash; - tag = tag.substr(tag.indexOf("#") + 1); - setStorage('lasthashtag', tag, true); - } - else - tag = getHashtag(); + if(typeof event != "undefined") + { + tag = event.currentTarget.hash; + tag = tag.substr(tag.indexOf("#") + 1); + setStorage('lasthashtag', tag, true); + } + else + tag = getHashtag(); - if(forceRefresh || prevTag != tag) - { - prevTag = tag; - $("#page-content").off(); - $("#page-content").load("/content/"+tag+".html", function(response,status,xhr){ - if(status == "error") - { - $("#page-content").html('

'+$.i18n('info_404')+'

'); - removeOverlay(); - } - updateUiOnInstance(window.currentHyperionInstance); - }); - } + if(forceRefresh || prevTag != tag) + { + prevTag = tag; + $("#page-content").off(); + $("#page-content").load("/content/"+tag+".html", function(response,status,xhr){ + if(status == "error") + { + $("#page-content").html('

'+$.i18n('info_404')+'

'); + removeOverlay(); + } + updateUiOnInstance(window.currentHyperionInstance); + }); + } } function getInstanceNameByIndex(index) { - var instData = window.serverInfo.instance - for(var key in instData) - { - if(instData[key].instance == index) - return instData[key].friendly_name; - } - return "unknown" + var instData = window.serverInfo.instance + for(var key in instData) + { + if(instData[key].instance == index) + return instData[key].friendly_name; + } + return "unknown" } function updateHyperionInstanceListing() { - var data = window.serverInfo.instance.filter(entry => entry.running); - $('#hyp_inst_listing').html(""); - for(var key in data) - { - var currInstMarker = (data[key].instance == window.currentHyperionInstance) ? "component-on" : ""; + var data = window.serverInfo.instance.filter(entry => entry.running); + $('#hyp_inst_listing').html(""); + for(var key in data) + { + var currInstMarker = (data[key].instance == window.currentHyperionInstance) ? "component-on" : ""; - var html = '
  • \ - \ -
    \ - \ - '+data[key].friendly_name+' \ -
    \ -
    \ -
  • ' + var html = '
  • \ + \ +
    \ + \ + '+data[key].friendly_name+' \ +
    \ +
    \ +
  • ' - if(data.length-1 > key) - html += '
  • ' + if(data.length-1 > key) + html += '
  • ' - $('#hyp_inst_listing').append(html); + $('#hyp_inst_listing').append(html); - $('#hyperioninstance_'+data[key].instance).off().on("click",function(e){ - var inst = e.currentTarget.id.split("_")[1] - instanceSwitch(inst) - }); - } + $('#hyperioninstance_'+data[key].instance).off().on("click",function(e){ + var inst = e.currentTarget.id.split("_")[1] + instanceSwitch(inst) + }); + } } function initLanguageSelection() { - // Initialise language selection list with languages supported - for (var i = 0; i < availLang.length; i++) - { - $("#language-select").append(''); - } + // Initialise language selection list with languages supported + for (var i = 0; i < availLang.length; i++) + { + $("#language-select").append(''); + } - var langLocale = storedLang; + var langLocale = storedLang; - // If no language has been set, resolve browser locale - if ( langLocale === 'auto' ) - { - langLocale = $.i18n().locale.substring(0,2); - } + // If no language has been set, resolve browser locale + if ( langLocale === 'auto' ) + { + langLocale = $.i18n().locale.substring(0,2); + } - // Resolve text for language code - var langText = 'Please Select'; + // Resolve text for language code + var langText = 'Please Select'; - //Test, if language is supported by hyperion - var langIdx = availLang.indexOf(langLocale); - if ( langIdx > -1 ) - { - langText = availLangText[langIdx]; - } - else - { - // If language is not supported by hyperion, try fallback language - langLocale = $.i18n().options.fallbackLocale.substring(0,2); - langIdx = availLang.indexOf(langLocale); - if ( langIdx > -1 ) - { - langText = availLangText[langIdx]; - } - } - //console.log("langLocale: ", langLocale, "langText: ", langText); + //Test, if language is supported by hyperion + var langIdx = availLang.indexOf(langLocale); + if ( langIdx > -1 ) + { + langText = availLangText[langIdx]; + } + else + { + // If language is not supported by hyperion, try fallback language + langLocale = $.i18n().options.fallbackLocale.substring(0,2); + langIdx = availLang.indexOf(langLocale); + if ( langIdx > -1 ) + { + langText = availLangText[langIdx]; + } + } + //console.log("langLocale: ", langLocale, "langText: ", langText); - $('#language-select').prop('title', langText); - $("#language-select").val(langIdx); - $("#language-select").selectpicker("refresh"); + $('#language-select').prop('title', langText); + $("#language-select").val(langIdx); + $("#language-select").selectpicker("refresh"); } function updateUiOnInstance(inst) { - if(inst != 0) - { - var currentURL = $(location).attr("href"); - if(currentURL.indexOf('#conf_network') != -1 || currentURL.indexOf('#update') != -1 || currentURL.indexOf('#conf_webconfig') != -1 || currentURL.indexOf('#conf_grabber') != -1 || currentURL.indexOf('#conf_logging') != -1) - $("#hyperion_global_setting_notify").fadeIn("fast"); - else - $("#hyperion_global_setting_notify").attr("style", "display:none"); + if(inst != 0) + { + var currentURL = $(location).attr("href"); + if(currentURL.indexOf('#conf_network') != -1 || currentURL.indexOf('#update') != -1 || currentURL.indexOf('#conf_webconfig') != -1 || currentURL.indexOf('#conf_grabber') != -1 || currentURL.indexOf('#conf_logging') != -1) + $("#hyperion_global_setting_notify").fadeIn("fast"); + else + $("#hyperion_global_setting_notify").attr("style", "display:none"); - $("#dashboard_active_instance_friendly_name").html($.i18n('dashboard_active_instance') + ': ' + window.serverInfo.instance[inst].friendly_name); - $("#dashboard_active_instance").removeAttr("style"); - } - else - { - $("#hyperion_global_setting_notify").fadeOut("fast"); - $("#dashboard_active_instance").attr("style", "display:none"); - } + $("#dashboard_active_instance_friendly_name").html($.i18n('dashboard_active_instance') + ': ' + window.serverInfo.instance[inst].friendly_name); + $("#dashboard_active_instance").removeAttr("style"); + } + else + { + $("#hyperion_global_setting_notify").fadeOut("fast"); + $("#dashboard_active_instance").attr("style", "display:none"); + } } function instanceSwitch(inst) { - requestInstanceSwitch(inst) - window.currentHyperionInstance = inst; - window.currentHyperionInstanceName = getInstanceNameByIndex(inst); - setStorage('lastSelectedInstance', inst, false) - updateHyperionInstanceListing() + requestInstanceSwitch(inst) + window.currentHyperionInstance = inst; + window.currentHyperionInstanceName = getInstanceNameByIndex(inst); + setStorage('lastSelectedInstance', inst, false) + updateHyperionInstanceListing() } function loadContentTo(containerId, fileName) { - $(containerId).load("/content/"+fileName+".html"); + $(containerId).load("/content/"+fileName+".html"); } function toggleClass(obj,class1,class2) { - if ( $(obj).hasClass(class1)) - { - $(obj).removeClass(class1); - $(obj).addClass(class2); - } - else - { - $(obj).removeClass(class2); - $(obj).addClass(class1); - } + if ( $(obj).hasClass(class1)) + { + $(obj).removeClass(class1); + $(obj).addClass(class2); + } + else + { + $(obj).removeClass(class2); + $(obj).addClass(class1); + } } function setClassByBool(obj,enable,class1,class2) { - if (enable) - { - $(obj).removeClass(class1); - $(obj).addClass(class2); - } - else - { - $(obj).removeClass(class2); - $(obj).addClass(class1); - } + if (enable) + { + $(obj).removeClass(class1); + $(obj).addClass(class2); + } + else + { + $(obj).removeClass(class2); + $(obj).addClass(class1); + } } function showInfoDialog(type,header,message) { - if (type=="success") - { - $('#id_body').html(''); - if(header == "") - $('#id_body').append('

    '+$.i18n('infoDialog_general_success_title')+'

    '); - $('#id_footer').html(''); - } - else if (type=="warning") - { - $('#id_body').html(''); - if(header == "") - $('#id_body').append('

    '+$.i18n('infoDialog_general_warning_title')+'

    '); - $('#id_footer').html(''); - } - else if (type=="error") - { - $('#id_body').html(''); - if(header == "") - $('#id_body').append('

    '+$.i18n('infoDialog_general_error_title')+'

    '); - $('#id_footer').html(''); - } - else if (type == "select") - { - $('#id_body').html('Redefine ambient light!'); - $('#id_footer').html(''); - $('#id_footer').append(''); - } - else if (type == "iswitch") - { - $('#id_body').html('Redefine ambient light!'); - $('#id_footer').html(''); - $('#id_footer').append(''); - } - else if (type == "uilock") - { - $('#id_body').html('Redefine ambient light!'); - $('#id_footer').html(''+$.i18n('InfoDialog_nowrite_foottext')+''); - } - else if (type == "import") - { - $('#id_body').html(''); - $('#id_footer').html(''); - $('#id_footer').append(''); - } - else if (type == "delInst") - { - $('#id_body').html(''); - $('#id_footer').html(''); - $('#id_footer').append(''); - } - else if (type == "renInst") - { - $('#id_body_rename').html('
    '); - $('#id_body_rename').append('

    '+header+'

    '); - $('#id_body_rename').append(''); - $('#id_footer_rename').html(''); - $('#id_footer_rename').append(''); - } - else if (type == "changePassword") - { - $('#id_body_rename').html('
    '); - $('#id_body_rename').append('

    '+header+'

    '); - $('#id_body_rename').append('
    '); - $('#id_body_rename').append(''); - $('#id_footer_rename').html(''); - $('#id_footer_rename').append(''); - } - else if (type == "checklist") - { - $('#id_body').html('Redefine ambient light!'); - $('#id_body').append('

    '+$.i18n('infoDialog_checklist_title')+'

    '); - $('#id_body').append(header); - $('#id_footer').html(''); - } - else if (type == "newToken") - { - $('#id_body').html('Redefine ambient light!'); - $('#id_footer').html(''); - } - else if (type == "grantToken") - { - $('#id_body').html('Redefine ambient light!'); - $('#id_footer').html(''); - $('#id_footer').append(''); - } + if (type=="success") + { + $('#id_body').html(''); + if(header == "") + $('#id_body').append('

    '+$.i18n('infoDialog_general_success_title')+'

    '); + $('#id_footer').html(''); + } + else if (type=="warning") + { + $('#id_body').html(''); + if(header == "") + $('#id_body').append('

    '+$.i18n('infoDialog_general_warning_title')+'

    '); + $('#id_footer').html(''); + } + else if (type=="error") + { + $('#id_body').html(''); + if(header == "") + $('#id_body').append('

    '+$.i18n('infoDialog_general_error_title')+'

    '); + $('#id_footer').html(''); + } + else if (type == "select") + { + $('#id_body').html('Redefine ambient light!'); + $('#id_footer').html(''); + $('#id_footer').append(''); + } + else if (type == "iswitch") + { + $('#id_body').html('Redefine ambient light!'); + $('#id_footer').html(''); + $('#id_footer').append(''); + } + else if (type == "uilock") + { + $('#id_body').html('Redefine ambient light!'); + $('#id_footer').html(''+$.i18n('InfoDialog_nowrite_foottext')+''); + } + else if (type == "import") + { + $('#id_body').html(''); + $('#id_footer').html(''); + $('#id_footer').append(''); + } + else if (type == "delInst") + { + $('#id_body').html(''); + $('#id_footer').html(''); + $('#id_footer').append(''); + } + else if (type == "renInst") + { + $('#id_body_rename').html('
    '); + $('#id_body_rename').append('

    '+header+'

    '); + $('#id_body_rename').append(''); + $('#id_footer_rename').html(''); + $('#id_footer_rename').append(''); + } + else if (type == "changePassword") + { + $('#id_body_rename').html('
    '); + $('#id_body_rename').append('

    '+header+'

    '); + $('#id_body_rename').append('
    '); + $('#id_body_rename').append(''); + $('#id_footer_rename').html(''); + $('#id_footer_rename').append(''); + } + else if (type == "checklist") + { + $('#id_body').html('Redefine ambient light!'); + $('#id_body').append('

    '+$.i18n('infoDialog_checklist_title')+'

    '); + $('#id_body').append(header); + $('#id_footer').html(''); + } + else if (type == "newToken") + { + $('#id_body').html('Redefine ambient light!'); + $('#id_footer').html(''); + } + else if (type == "grantToken") + { + $('#id_body').html('Redefine ambient light!'); + $('#id_footer').html(''); + $('#id_footer').append(''); + } - if(type != "renInst") - { - $('#id_body').append('

    '+header+'

    '); - $('#id_body').append(message); - } + if(type != "renInst") + { + $('#id_body').append('

    '+header+'

    '); + $('#id_body').append(message); + } - if(type == "select" || type == "iswitch") - $('#id_body').append(''); + if(type == "select" || type == "iswitch") + $('#id_body').append(''); - $(type == "renInst" || type == "changePassword" ? "#modal_dialog_rename" : "#modal_dialog").modal({ - backdrop : "static", - keyboard: false, - show: true - }); + $(type == "renInst" || type == "changePassword" ? "#modal_dialog_rename" : "#modal_dialog").modal({ + backdrop : "static", + keyboard: false, + show: true + }); - $(document).on('click', '[data-dismiss-modal]', function () { - var target = $(this).attr('data-dismiss-modal'); - $.find(target).modal.hide(); - }); + $(document).on('click', '[data-dismiss-modal]', function () { + var target = $(this).attr('data-dismiss-modal'); + $.find(target).modal.hide(); + }); } function createHintH(type, text, container) { - type = String(type); - if(type == "intro") - tclass = "introd"; + type = String(type); + if(type == "intro") + tclass = "introd"; - $('#'+container).prepend('

    '+text+'


    '); + $('#'+container).prepend('

    '+text+'


    '); } function createHint(type, text, container, buttonid, buttontxt) { - var fe, tclass; + var fe, tclass; - if(type == "intro") - { - fe = ''; - tclass = "intro-hint"; - } - else if(type == "info") - { - fe = '
    Information
    '; - tclass = "info-hint"; - } - else if(type == "wizard") - { - fe = '
    Information
    '; - tclass = "wizard-hint"; - } - else if(type == "warning") - { - fe = '
    Information
    '; - tclass = "warning-hint"; - } + if(type == "intro") + { + fe = ''; + tclass = "intro-hint"; + } + else if(type == "info") + { + fe = '
    Information
    '; + tclass = "info-hint"; + } + else if(type == "wizard") + { + fe = '
    Information
    '; + tclass = "wizard-hint"; + } + else if(type == "warning") + { + fe = '
    Information
    '; + tclass = "warning-hint"; + } - if(buttonid) - buttonid = '

    '; - else - buttonid = ""; + if(buttonid) + buttonid = '

    '; + else + buttonid = ""; - if(type == "intro") - $('#'+container).prepend('

    '+$.i18n("conf_helptable_expl")+'

    '+text+'
    '); - else if(type == "wizard") - $('#'+container).prepend('

    '+$.i18n("wiz_wizavail")+'

    '+$.i18n('wiz_guideyou',text)+buttonid+'
    '); - else - { - createTable('','htb',container, true, tclass); - $('#'+container+' .htb').append(createTableRow([fe ,text],false,true)); - } + if(type == "intro") + $('#'+container).prepend('

    '+$.i18n("conf_helptable_expl")+'

    '+text+'
    '); + else if(type == "wizard") + $('#'+container).prepend('

    '+$.i18n("wiz_wizavail")+'

    '+$.i18n('wiz_guideyou',text)+buttonid+'
    '); + else + { + createTable('','htb',container, true, tclass); + $('#'+container+' .htb').append(createTableRow([fe ,text],false,true)); + } } function createEffHint(title, text) { - return '

    '+title+'

    '+text+'
    '; + return '

    '+title+'

    '+text+'
    '; } function valValue(id,value,min,max) { - if(typeof max === 'undefined' || max == "") - max = 999999; + if(typeof max === 'undefined' || max == "") + max = 999999; - if(Number(value) > Number(max)) - { - $('#'+id).val(max); - showInfoDialog("warning","",$.i18n('edt_msg_error_maximum_incl',max)); - return max; - } - else if(Number(value) < Number(min)) - { - $('#'+id).val(min); - showInfoDialog("warning","",$.i18n('edt_msg_error_minimum_incl',min)); - return min; - } - return value; + if(Number(value) > Number(max)) + { + $('#'+id).val(max); + showInfoDialog("warning","",$.i18n('edt_msg_error_maximum_incl',max)); + return max; + } + else if(Number(value) < Number(min)) + { + $('#'+id).val(min); + showInfoDialog("warning","",$.i18n('edt_msg_error_minimum_incl',min)); + return min; + } + return value; } function readImg(input,cb) { if (input.files && input.files[0]) { var reader = new FileReader(); - // inject fileName property - reader.fileName = input.files[0].name + // inject fileName property + reader.fileName = input.files[0].name reader.onload = function (e) { - cb(e.target.result, e.target.fileName); + cb(e.target.result, e.target.fileName); } reader.readAsDataURL(input.files[0]); } @@ -484,60 +484,60 @@ function readImg(input,cb) function isJsonString(str) { - try - { - JSON.parse(str); - } - catch (e) - { - return e; - } - return ""; + try + { + JSON.parse(str); + } + catch (e) + { + return e; + } + return ""; } function createJsonEditor(container,schema,setconfig,usePanel,arrayre) { - $('#'+container).off(); - $('#'+container).html(""); + $('#'+container).off(); + $('#'+container).html(""); - if (typeof arrayre === 'undefined') - arrayre = true; + if (typeof arrayre === 'undefined') + arrayre = true; - var editor = new JSONEditor(document.getElementById(container), - { - theme: 'bootstrap3', - iconlib: "fontawesome4", - disable_collapse: 'true', - form_name_root: 'sa', - disable_edit_json: true, - disable_properties: true, - disable_array_reorder: arrayre, - no_additional_properties: true, - disable_array_delete_all_rows: true, - disable_array_delete_last_row: true, - access: storedAccess, - schema: { - title:'', - properties: schema - } - }); + var editor = new JSONEditor(document.getElementById(container), + { + theme: 'bootstrap3', + iconlib: "fontawesome4", + disable_collapse: 'true', + form_name_root: 'sa', + disable_edit_json: true, + disable_properties: true, + disable_array_reorder: arrayre, + no_additional_properties: true, + disable_array_delete_all_rows: true, + disable_array_delete_last_row: true, + access: storedAccess, + schema: { + title:'', + properties: schema + } + }); - if(usePanel) - { - $('#'+container+' .well').first().removeClass('well well-sm'); - $('#'+container+' h4').first().remove(); - $('#'+container+' .well').first().removeClass('well well-sm'); - } + if(usePanel) + { + $('#'+container+' .well').first().removeClass('well well-sm'); + $('#'+container+' h4').first().remove(); + $('#'+container+' .well').first().removeClass('well well-sm'); + } - if (setconfig) - { - for(var key in editor.root.editors) - { - editor.getEditor("root."+key).setValue(Object.assign({}, editor.getEditor("root."+key).value, window.serverConfig[key] )); - } - } + if (setconfig) + { + for(var key in editor.root.editors) + { + editor.getEditor("root."+key).setValue(Object.assign({}, editor.getEditor("root."+key).value, window.serverConfig[key] )); + } + } - return editor; + return editor; } function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTitelVals, newDefaultVal, addCustom) { @@ -549,9 +549,9 @@ function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTit { "type": "string", "enum": [], - "propertyOrder": 1, "required": true, - "options": { "enum_titles": [] } + "options": { "enum_titles": [], "infoText": "" }, + "propertyOrder": 1 }; //Add additional elements to overwrite defaults @@ -559,6 +559,21 @@ function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTit newSchema[key][item] = addElements[item]; } + if (orginalProperties) { + + if (orginalProperties["title"]) { + newSchema[key]["title"] = orginalProperties["title"]; + } + + if (orginalProperties["options"] && orginalProperties["options"]["infoText"]) { + newSchema[key]["options"]["infoText"] = orginalProperties["options"]["infoText"]; + } + + if (orginalProperties["propertyOrder"]) { + newSchema[key]["propertyOrder"] = orginalProperties["propertyOrder"]; + } + } + if (addCustom) { newEnumVals.push("custom"); newTitelVals.push("edt_conf_enum_custom"); @@ -580,8 +595,66 @@ function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTit newSchema[key]["default"] = newDefaultVal; } - editor.original_schema.properties = orginalProperties; - editor.schema.properties = newSchema; + editor.original_schema.properties[key] = orginalProperties; + editor.schema.properties[key] = newSchema[key]; + + editor.removeObjectProperty(key); + delete editor.cached_editors[key]; + editor.addObjectProperty(key); +} + +function updateJsonEditorMultiSelection(editor, key, addElements, newEnumVals, newTitelVals, newDefaultVal) { + + var orginalProperties = editor.schema.properties[key]; + + var newSchema = []; + newSchema[key] = + { + "type": "array", + "format": "select", + "items": { + "type": "string", + "enum": [], + "options": { "enum_titles": [] }, + }, + "options": { "infoText": "" }, + "default": [], + "propertyOrder": 1 + }; + + //Add additional elements to overwrite defaults + for (var item in addElements) { + newSchema[key][item] = addElements[item]; + } + + if (orginalProperties) { + if (orginalProperties["title"]) { + newSchema[key]["title"] = orginalProperties["title"]; + } + + if (orginalProperties["options"] && orginalProperties["options"]["infoText"]) { + newSchema[key]["options"]["infoText"] = orginalProperties["options"]["infoText"]; + } + + if (orginalProperties["propertyOrder"]) { + newSchema[key]["propertyOrder"] = orginalProperties["propertyOrder"]; + } + } + + if (newEnumVals) { + newSchema[key]["items"]["enum"] = newEnumVals; + } + + if (newTitelVals) { + newSchema[key]["items"]["options"]["enum_titles"] = newTitelVals; + } + + if (newDefaultVal) { + newSchema[key]["default"] = newDefaultVal; + } + + editor.original_schema.properties[key] = orginalProperties; + editor.schema.properties[key] = newSchema[key]; editor.removeObjectProperty(key); delete editor.cached_editors[key]; @@ -590,37 +663,37 @@ function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTit function buildWL(link,linkt,cl) { - var baseLink = "https://docs.hyperion-project.org/"; - var lang; + var baseLink = "https://docs.hyperion-project.org/"; + var lang; - if(typeof linkt == "undefined") - linkt = "Placeholder"; + if(typeof linkt == "undefined") + linkt = "Placeholder"; - if(storedLang == "de" || navigator.locale == "de") - lang = "de"; - else - lang = "en"; + if(storedLang == "de" || navigator.locale == "de") + lang = "de"; + else + lang = "en"; - if(cl === true) - { - linkt = $.i18n(linkt); - return '

    '+linkt+'

    '+$.i18n('general_wiki_moreto',linkt)+': '+linkt+'
    ' - } - else - return ': '+linkt+''; + if(cl === true) + { + linkt = $.i18n(linkt); + return '' + } + else + return ': '+linkt+''; } function rgbToHex(rgb) { - if(rgb.length == 3) - { - return "#" + - ("0" + parseInt(rgb[0],10).toString(16)).slice(-2) + - ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) + - ("0" + parseInt(rgb[2],10).toString(16)).slice(-2); - } - else - debugMessage('rgbToHex: Given rgb is no array or has wrong length'); + if(rgb.length == 3) + { + return "#" + + ("0" + parseInt(rgb[0],10).toString(16)).slice(-2) + + ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) + + ("0" + parseInt(rgb[2],10).toString(16)).slice(-2); + } + else + debugMessage('rgbToHex: Given rgb is no array or has wrong length'); } function hexToRgb(hex) { @@ -633,93 +706,93 @@ function hexToRgb(hex) { } /* - Show a notification - @param type Valid types are "info","success","warning","danger" - @param message The message to show - @param title A title (optional) - @param addhtml Add custom html to the notification end + Show a notification + @param type Valid types are "info","success","warning","danger" + @param message The message to show + @param title A title (optional) + @param addhtml Add custom html to the notification end */ function showNotification(type, message, title="", addhtml="") { - if(title == "") - { - switch(type) - { - case "info": - title = $.i18n('infoDialog_general_info_title'); - break; - case "success": - title = $.i18n('infoDialog_general_success_title'); - break; - case "warning": - title = $.i18n('infoDialog_general_warning_title'); - break; - case "danger": - title = $.i18n('infoDialog_general_error_title'); - break; - } - } + if(title == "") + { + switch(type) + { + case "info": + title = $.i18n('infoDialog_general_info_title'); + break; + case "success": + title = $.i18n('infoDialog_general_success_title'); + break; + case "warning": + title = $.i18n('infoDialog_general_warning_title'); + break; + case "danger": + title = $.i18n('infoDialog_general_error_title'); + break; + } + } - $.notify({ - // options - title: title, - message: message - },{ - // settings - type: type, - animate: { - enter: 'animated fadeInDown', - exit: 'animated fadeOutUp' - }, - placement:{ - align:'center' - }, - mouse_over : 'pause', - template: '' - }); + $.notify({ + // options + title: title, + message: message + },{ + // settings + type: type, + animate: { + enter: 'animated fadeInDown', + exit: 'animated fadeOutUp' + }, + placement:{ + align:'center' + }, + mouse_over : 'pause', + template: '' + }); } function createCP(id, color, cb) { - if(Array.isArray(color)) - color = rgbToHex(color); - else if(color == "undefined") - color = "#AA3399"; + if(Array.isArray(color)) + color = rgbToHex(color); + else if(color == "undefined") + color = "#AA3399"; - if(color.startsWith("#")) - { - $('#'+id).colorpicker({ - format: 'rgb', - customClass: 'colorpicker-2x', - color: color, - sliders: { - saturation: { - maxLeft: 200, - maxTop: 200 - }, - hue: { - maxTop: 200 - }, - } - }); - $('#'+id).colorpicker().on('changeColor', function(e) { - var rgb = e.color.toRGB(); - var hex = e.color.toHex(); - cb(rgb,hex,e); - }); - } - else - debugMessage('createCP: Given color is not legit'); + if(color.startsWith("#")) + { + $('#'+id).colorpicker({ + format: 'rgb', + customClass: 'colorpicker-2x', + color: color, + sliders: { + saturation: { + maxLeft: 200, + maxTop: 200 + }, + hue: { + maxTop: 200 + }, + } + }); + $('#'+id).colorpicker().on('changeColor', function(e) { + var rgb = e.color.toRGB(); + var hex = e.color.toHex(); + cb(rgb,hex,e); + }); + } + else + debugMessage('createCP: Given color is not legit'); } // Creates a table with thead and tbody ids @@ -729,24 +802,24 @@ function createCP(id, color, cb) // @param string bless: if true the table is borderless function createTable(hid, bid, cont, bless, tclass) { - var table = document.createElement('table'); - var thead = document.createElement('thead'); - var tbody = document.createElement('tbody'); + var table = document.createElement('table'); + var thead = document.createElement('thead'); + var tbody = document.createElement('tbody'); - table.className = "table"; - if(bless === true) - table.className += " borderless"; - if(typeof tclass !== "undefined") - table.className += " "+tclass; - table.style.marginBottom = "0px"; - if(hid != "") - thead.className = hid; - tbody.className = bid; - if(hid != "") - table.appendChild(thead); - table.appendChild(tbody); + table.className = "table"; + if(bless === true) + table.className += " borderless"; + if(typeof tclass !== "undefined") + table.className += " "+tclass; + table.style.marginBottom = "0px"; + if(hid != "") + thead.className = hid; + tbody.className = bid; + if(hid != "") + table.appendChild(thead); + table.appendChild(tbody); - $('#'+cont).append(table); + $('#'+cont).append(table); } // Creates a table row @@ -757,288 +830,331 @@ function createTable(hid, bid, cont, bless, tclass) // @return : with or as child(s) function createTableRow(list, head, align) { - var row = document.createElement('tr'); + var row = document.createElement('tr'); - for(var i = 0; i < list.length; i++) - { - if(head === true) - var el = document.createElement('th'); - else - var el = document.createElement('td'); + for(var i = 0; i < list.length; i++) + { + if(head === true) + var el = document.createElement('th'); + else + var el = document.createElement('td'); - if(align) - el.style.verticalAlign = "middle"; + if(align) + el.style.verticalAlign = "middle"; - el.innerHTML = list[i]; - row.appendChild(el); - } - return row; + el.innerHTML = list[i]; + row.appendChild(el); + } + return row; } function createRow(id) { - var el = document.createElement('div'); - el.className = "row"; - el.setAttribute('id', id); - return el; + var el = document.createElement('div'); + el.className = "row"; + el.setAttribute('id', id); + return el; } function createOptPanel(phicon, phead, bodyid, footerid) { - phead = ''+phead; - var pfooter = document.createElement('button'); - pfooter.className = "btn btn-primary"; - pfooter.setAttribute("id", footerid); - pfooter.innerHTML = ''+$.i18n('general_button_savesettings'); + phead = ''+phead; + var pfooter = document.createElement('button'); + pfooter.className = "btn btn-primary"; + pfooter.setAttribute("id", footerid); + pfooter.innerHTML = ''+$.i18n('general_button_savesettings'); - return createPanel(phead, "", pfooter, "panel-default", bodyid); + return createPanel(phead, "", pfooter, "panel-default", bodyid); +} + +function compareTwoValues(key1, key2, order = 'asc') { + + return function innerSort(a, b) { + if (!a.hasOwnProperty(key1) || !b.hasOwnProperty(key1)) { + // property key1 doesn't exist on either object + return 0; + } + + const varA1 = (typeof a[key1] === 'string') + ? a[key1].toUpperCase() : a[key1]; + const varB1 = (typeof b[key1] === 'string') + ? b[key1].toUpperCase() : b[key1]; + + let comparison = 0; + if (varA1 > varB1) { + comparison = 1; + } else { + if (varA1 < varB1) { + comparison = -1; + } else { + if (!a.hasOwnProperty(key2) || !b.hasOwnProperty(key2)) { + // property key2 doesn't exist on either object + return 0; + } + + const varA2 = (typeof a[key2] === 'string') + ? a[key2].toUpperCase() : a[key2]; + const varB2 = (typeof b[key1] === 'string') + ? b[key2].toUpperCase() : b[key2]; + + if (varA2 > varB2) { + comparison = 1; + } else { + comparison = -1; + } + } + } + return ( + (order === 'desc') ? (comparison * -1) : comparison + ); + }; } function sortProperties(list) { - for(var key in list) - { - list[key].key = key; - } - list = $.map(list, function(value, index) { - return [value]; - }); - return list.sort(function(a,b) { - return a.propertyOrder - b.propertyOrder; - }); + for(var key in list) + { + list[key].key = key; + } + list = $.map(list, function(value, index) { + return [value]; + }); + return list.sort(function(a,b) { + return a.propertyOrder - b.propertyOrder; + }); } function createHelpTable(list, phead){ - var table = document.createElement('table'); - var thead = document.createElement('thead'); - var tbody = document.createElement('tbody'); - list = sortProperties(list); + var table = document.createElement('table'); + var thead = document.createElement('thead'); + var tbody = document.createElement('tbody'); + list = sortProperties(list); - phead = ''+phead+' '+$.i18n("conf_helptable_expl"); + phead = ''+phead+' '+$.i18n("conf_helptable_expl"); - table.className = 'table table-hover borderless'; + table.className = 'table table-hover borderless'; - thead.appendChild(createTableRow([$.i18n('conf_helptable_option'), $.i18n('conf_helptable_expl')], true, false)); + thead.appendChild(createTableRow([$.i18n('conf_helptable_option'), $.i18n('conf_helptable_expl')], true, false)); - for (var key in list) - { - if(list[key].access != 'system') - { - // break one iteration (in the loop), if the schema has the entry hidden=true - if ("options" in list[key] && "hidden" in list[key].options && (list[key].options.hidden)) - continue; - if ("access" in list[key] && ((list[key].access == "advanced" && storedAccess == "default") || (list[key].access == "expert" && storedAccess != "expert"))) - continue; - var text = list[key].title.replace('title', 'expl'); - tbody.appendChild(createTableRow([$.i18n(list[key].title), $.i18n(text)], false, false)); + for (var key in list) + { + if(list[key].access != 'system') + { + // break one iteration (in the loop), if the schema has the entry hidden=true + if ("options" in list[key] && "hidden" in list[key].options && (list[key].options.hidden)) + continue; + if ("access" in list[key] && ((list[key].access == "advanced" && storedAccess == "default") || (list[key].access == "expert" && storedAccess != "expert"))) + continue; + var text = list[key].title.replace('title', 'expl'); + tbody.appendChild(createTableRow([$.i18n(list[key].title), $.i18n(text)], false, false)); - if(list[key].items && list[key].items.properties) - { - var ilist = sortProperties(list[key].items.properties); - for (var ikey in ilist) - { - // break one iteration (in the loop), if the schema has the entry hidden=true - if ("options" in ilist[ikey] && "hidden" in ilist[ikey].options && (ilist[ikey].options.hidden)) - continue; - if ("access" in ilist[ikey] && ((ilist[ikey].access == "advanced" && storedAccess == "default") || (ilist[ikey].access == "expert" && storedAccess != "expert"))) - continue; - var itext = ilist[ikey].title.replace('title', 'expl'); - tbody.appendChild(createTableRow([$.i18n(ilist[ikey].title), $.i18n(itext)], false, false)); - } - } - } - } - table.appendChild(thead); - table.appendChild(tbody); + if(list[key].items && list[key].items.properties) + { + var ilist = sortProperties(list[key].items.properties); + for (var ikey in ilist) + { + // break one iteration (in the loop), if the schema has the entry hidden=true + if ("options" in ilist[ikey] && "hidden" in ilist[ikey].options && (ilist[ikey].options.hidden)) + continue; + if ("access" in ilist[ikey] && ((ilist[ikey].access == "advanced" && storedAccess == "default") || (ilist[ikey].access == "expert" && storedAccess != "expert"))) + continue; + var itext = ilist[ikey].title.replace('title', 'expl'); + tbody.appendChild(createTableRow([$.i18n(ilist[ikey].title), $.i18n(itext)], false, false)); + } + } + } + } + table.appendChild(thead); + table.appendChild(tbody); - return createPanel(phead, table); + return createPanel(phead, table); } function createPanel(head, body, footer, type, bodyid){ - var cont = document.createElement('div'); - var p = document.createElement('div'); - var phead = document.createElement('div'); - var pbody = document.createElement('div'); - var pfooter = document.createElement('div'); + var cont = document.createElement('div'); + var p = document.createElement('div'); + var phead = document.createElement('div'); + var pbody = document.createElement('div'); + var pfooter = document.createElement('div'); - cont.className = "col-lg-6"; + cont.className = "col-lg-6"; - if(typeof type == 'undefined') - type = 'panel-default'; + if(typeof type == 'undefined') + type = 'panel-default'; - p.className = 'panel '+type; - phead.className = 'panel-heading'; - pbody.className = 'panel-body'; - pfooter.className = 'panel-footer'; + p.className = 'panel '+type; + phead.className = 'panel-heading'; + pbody.className = 'panel-body'; + pfooter.className = 'panel-footer'; - phead.innerHTML = head; + phead.innerHTML = head; - if(typeof bodyid != 'undefined') - { - pfooter.style.textAlign = 'right'; - pbody.setAttribute("id", bodyid); - } + if(typeof bodyid != 'undefined') + { + pfooter.style.textAlign = 'right'; + pbody.setAttribute("id", bodyid); + } - if(typeof body != 'undefined' && body != "") - pbody.appendChild(body); + if(typeof body != 'undefined' && body != "") + pbody.appendChild(body); - if(typeof footer != 'undefined') - pfooter.appendChild(footer); + if(typeof footer != 'undefined') + pfooter.appendChild(footer); - p.appendChild(phead); - p.appendChild(pbody); + p.appendChild(phead); + p.appendChild(pbody); - if(typeof footer != 'undefined') - { - pfooter.style.textAlign = "right"; - p.appendChild(pfooter); - } + if(typeof footer != 'undefined') + { + pfooter.style.textAlign = "right"; + p.appendChild(pfooter); + } - cont.appendChild(p); + cont.appendChild(p); - return cont; + return cont; } function createSelGroup(group) { - var el = document.createElement('optgroup'); - el.setAttribute('label', group); - return el; + var el = document.createElement('optgroup'); + el.setAttribute('label', group); + return el; } function createSelOpt(opt, title) { - var el = document.createElement('option'); - el.setAttribute('value', opt); - if (typeof title == 'undefined') - el.innerHTML = opt; - else - el.innerHTML = title; - return el; + var el = document.createElement('option'); + el.setAttribute('value', opt); + if (typeof title == 'undefined') + el.innerHTML = opt; + else + el.innerHTML = title; + return el; } function createSel(array, group, split) { - if (array.length != 0) - { - var el = createSelGroup(group); - for(var i=0; i", { - rel: "stylesheet", - type: "text/css", - href: "../css/darkMode.css" - }).appendTo("head"); + $("", { + rel: "stylesheet", + type: "text/css", + href: "../css/darkMode.css" + }).appendTo("head"); - setStorage("darkMode", "on", false); - $('#btn_darkmode_icon').removeClass('fa fa-moon-o'); - $('#btn_darkmode_icon').addClass('fa fa-sun-o'); + setStorage("darkMode", "on", false); + $('#btn_darkmode_icon').removeClass('fa fa-moon-o'); + $('#btn_darkmode_icon').addClass('fa fa-sun-o'); } diff --git a/include/api/JsonAPI.h b/include/api/JsonAPI.h index d7009a27..a68c9d90 100644 --- a/include/api/JsonAPI.h +++ b/include/api/JsonAPI.h @@ -278,6 +278,12 @@ private: /// void handleLedDeviceCommand(const QJsonObject &message, const QString &command, int tan); + /// Handle an incoming JSON message regarding Input Sources (Grabbers) + /// + /// @param message the incoming message + /// + void handleInputSourceCommand(const QJsonObject& message, const QString& command, int tan); + /// /// Handle an incoming JSON message of unknown type /// diff --git a/libsrc/api/JSONRPC_schema/schema-inputsource.json b/libsrc/api/JSONRPC_schema/schema-inputsource.json new file mode 100644 index 00000000..edb9eb7c --- /dev/null +++ b/libsrc/api/JSONRPC_schema/schema-inputsource.json @@ -0,0 +1,28 @@ +{ + "type":"object", + "required":true, + "properties": { + "command": { + "type": "string", + "required": true, + "enum": [ "inputsource" ] + }, + "tan": { + "type": "integer" + }, + "subcommand": { + "type": "string", + "required": true, + "enum": [ "discover", "getProperties" ] + }, + "sourceType": { + "type": "string", + "required": true + }, + "params": { + "type": "object", + "required": false + } + }, + "additionalProperties": false +} diff --git a/libsrc/api/JSONRPC_schema/schema.json b/libsrc/api/JSONRPC_schema/schema.json index e13982fe..12dcb6c1 100644 --- a/libsrc/api/JSONRPC_schema/schema.json +++ b/libsrc/api/JSONRPC_schema/schema.json @@ -5,7 +5,7 @@ "command": { "type" : "string", "required" : true, - "enum" : ["color", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "logging", "processing", "sysinfo", "videomode", "authorize", "instance", "leddevice", "transform", "correction" , "temperature"] + "enum": [ "color", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "logging", "processing", "sysinfo", "videomode", "authorize", "instance", "leddevice", "inputsource", "transform", "correction", "temperature" ] } } } diff --git a/libsrc/api/JSONRPC_schemas.qrc b/libsrc/api/JSONRPC_schemas.qrc index 2018684f..1f09fe1a 100644 --- a/libsrc/api/JSONRPC_schemas.qrc +++ b/libsrc/api/JSONRPC_schemas.qrc @@ -20,7 +20,8 @@ JSONRPC_schema/schema-videomode.json JSONRPC_schema/schema-authorize.json JSONRPC_schema/schema-instance.json - JSONRPC_schema/schema-leddevice.json + JSONRPC_schema/schema-leddevice.json + JSONRPC_schema/schema-inputsource.json JSONRPC_schema/schema-hyperion-classic.json JSONRPC_schema/schema-hyperion-classic.json diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp index b0bb863b..aca267f2 100644 --- a/libsrc/api/JsonAPI.cpp +++ b/libsrc/api/JsonAPI.cpp @@ -174,6 +174,8 @@ proceed: handleInstanceCommand(message, command, tan); else if (command == "leddevice") handleLedDeviceCommand(message, command, tan); + else if (command == "inputsource") + handleInputSourceCommand(message, command, tan); // BEGIN | The following commands are deprecated but used to ensure backward compatibility with hyperion Classic remote control else if (command == "clearall") @@ -487,75 +489,6 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString availableGrabbers.append(grabber); } -#endif - -#if defined(ENABLE_V4L2) || defined(ENABLE_MF) - - QJsonArray availableDevices; - for (const auto& devicePath : GrabberWrapper::getInstance()->getDevices()) - { - QJsonObject device; - device["device"] = devicePath; - device["device_name"] = GrabberWrapper::getInstance()->getDeviceName(devicePath); - device["type"] = "v4l2"; - - QJsonArray video_inputs; - - QMultiMap inputs = GrabberWrapper::getInstance()->getDeviceInputs(devicePath); - for (auto input = inputs.begin(); input != inputs.end(); input++) - { - QJsonObject in; - in["name"] = input.key(); - in["inputIdx"] = input.value(); - - QJsonArray standards; - QList videoStandards = GrabberWrapper::getInstance()->getAvailableDeviceStandards(devicePath, input.value()); - for (auto standard : videoStandards) - { - standards.append(VideoStandard2String(standard)); - } - - QJsonArray formats; - QStringList encodingFormats = GrabberWrapper::getInstance()->getAvailableEncodingFormats(devicePath, input.value()); - for (auto encodingFormat : encodingFormats) - { - QJsonObject format; - format["format"] = encodingFormat; - - QJsonArray resolutionArray; - QMultiMap deviceResolutions = GrabberWrapper::getInstance()->getAvailableDeviceResolutions(devicePath, input.value(), parsePixelFormat(encodingFormat)); - for (auto width_height = deviceResolutions.begin(); width_height != deviceResolutions.end(); width_height++) - { - QJsonObject resolution; - resolution["width"] = width_height.key(); - resolution["height"] = width_height.value(); - - QJsonArray fps; - QIntList framerates = GrabberWrapper::getInstance()->getAvailableDeviceFramerates(devicePath, input.value(), parsePixelFormat(encodingFormat), width_height.key(), width_height.value()); - for (auto framerate : framerates) - { - fps.append(framerate); - } - - resolution["fps"] = fps; - resolutionArray.append(resolution); - } - - format["resolutions"] = resolutionArray; - formats.append(format); - } - - in["standards"] = standards; - in["formats"] = formats; - video_inputs.append(in); - } - - device["video_inputs"] = video_inputs; - availableDevices.append(device); - } - - grabbers["video_sources"] = availableDevices; - #endif grabbers["available"] = availableGrabbers; @@ -1485,6 +1418,117 @@ void JsonAPI::handleLedDeviceCommand(const QJsonObject &message, const QString & } } +void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString& command, int tan) +{ + Debug(_log, "message: [%s]", QString(QJsonDocument(message).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + const QString& subc = message["subcommand"].toString().trimmed(); + const QString& sourceType = message["sourceType"].toString().trimmed(); + + QString full_command = command + "-" + subc; + + // TODO: Validate that source type is a valid one +/* if ( ! valid type ) + { + sendErrorReply("Unknown device", full_command, tan); + } + else +*/ { + if (subc == "discover") + { + QJsonObject inputSourcesDiscovered; + inputSourcesDiscovered.insert("sourceType", sourceType); + + QJsonArray videoInputs; + +#if defined(ENABLE_V4L2) || defined(ENABLE_MF) + + if (sourceType == "video" ) + { + //for (const auto& instance : GrabberWrapper::getInstance()->getDevices()) + //{ + + for (const auto& devicePath : GrabberWrapper::getInstance()->getDevices()) + { + + QJsonObject device; + device["device"] = devicePath; + device["device_name"] = GrabberWrapper::getInstance()->getDeviceName(devicePath); + device["type"] = "v4l2"; + + QJsonArray video_inputs; + + QMultiMap inputs = GrabberWrapper::getInstance()->getDeviceInputs(devicePath); + for (auto input = inputs.begin(); input != inputs.end(); input++) + { + QJsonObject in; + in["name"] = input.key(); + in["inputIdx"] = input.value(); + + QJsonArray standards; + QList videoStandards = GrabberWrapper::getInstance()->getAvailableDeviceStandards(devicePath, input.value()); + for (auto standard : videoStandards) + { + standards.append(VideoStandard2String(standard)); + } + if (!standards.isEmpty()) + { + in["standards"] = standards; + } + + QJsonArray formats; + QStringList encodingFormats = GrabberWrapper::getInstance()->getAvailableEncodingFormats(devicePath, input.value()); + for (auto encodingFormat : encodingFormats) + { + QJsonObject format; + format["format"] = encodingFormat; + + QJsonArray resolutionArray; + QMultiMap deviceResolutions = GrabberWrapper::getInstance()->getAvailableDeviceResolutions(devicePath, input.value(), parsePixelFormat(encodingFormat)); + for (auto width_height = deviceResolutions.begin(); width_height != deviceResolutions.end(); width_height++) + { + QJsonObject resolution; + resolution["width"] = width_height.key(); + resolution["height"] = width_height.value(); + + QJsonArray fps; + QIntList framerates = GrabberWrapper::getInstance()->getAvailableDeviceFramerates(devicePath, input.value(), parsePixelFormat(encodingFormat), width_height.key(), width_height.value()); + for (auto framerate : framerates) + { + fps.append(framerate); + } + + resolution["fps"] = fps; + resolutionArray.append(resolution); + } + + format["resolutions"] = resolutionArray; + formats.append(format); + } + in["formats"] = formats; + video_inputs.append(in); + + } + + device["video_inputs"] = video_inputs; + videoInputs.append(device); + } + } +#endif + inputSourcesDiscovered["video_sources"] = videoInputs; + + Debug(_log, "response: [%s]", QString(QJsonDocument(inputSourcesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + sendSuccessDataReply(QJsonDocument(inputSourcesDiscovered), full_command, tan); + } + else + { + sendErrorReply("Unknown or missing subcommand", full_command, tan); + } + } +} + + void JsonAPI::handleNotImplemented(const QString &command, int tan) { sendErrorReply("Command not implemented", command, tan); diff --git a/libsrc/hyperion/SettingsManager.cpp b/libsrc/hyperion/SettingsManager.cpp index 8a5b4a2b..7ced9b8c 100644 --- a/libsrc/hyperion/SettingsManager.cpp +++ b/libsrc/hyperion/SettingsManager.cpp @@ -234,5 +234,18 @@ bool SettingsManager::handleConfigUpgrade(QJsonObject& config) Debug(_log,"LED Layout migrated"); } } + + if (config.contains("grabberV4L2")) + { + QJsonObject newGrabberV4L2Config = config["grabberV4L2"].toObject(); + + if (newGrabberV4L2Config.contains("encoding_format")) + { + newGrabberV4L2Config.remove("encoding_format"); + config["grabberV4L2"] = newGrabberV4L2Config; + migrated = true; + Debug(_log, "GrabberV4L2 Layout migrated"); + } + } return migrated; } diff --git a/libsrc/hyperion/schema/schema-grabberV4L2.json b/libsrc/hyperion/schema/schema-grabberV4L2.json index 704b4e2b..4e27394a 100644 --- a/libsrc/hyperion/schema/schema-grabberV4L2.json +++ b/libsrc/hyperion/schema/schema-grabberV4L2.json @@ -2,345 +2,350 @@ "type" : "object", "required" : true, "title" : "edt_conf_v4l2_heading_title", - "properties" : - { - "device" : - { - "type" : "string", - "title" : "edt_conf_enum_custom", - "default" : "auto", - "options" : { - "hidden":true + "properties": { + "available_devices": { + "type": "string", + "title": "edt_conf_v4l2_device_title", + "propertyOrder": 1, + "required": true + }, + "device": { + "type": "string", + "title": "edt_conf_enum_custom", + "options": { + "hidden": true }, - "required" : true, - "propertyOrder" : 2, - "comment" : "The 'available_devices' settings are dynamically inserted into the WebUI under PropertyOrder '1'." + "required": true, + "comment": "The 'available_devices' settings are dynamically inserted into the WebUI under PropertyOrder '1'.", + "propertyOrder": 2 }, - "input" : - { - "type" : "integer", - "title" : "edt_conf_enum_custom", - "default" : 0, - "options" : { - "hidden":true + "device_inputs": { + "type": "string", + "title": "edt_conf_v4l2_input_title", + "propertyOrder": 3, + "required": true + }, + "input": { + "type": "integer", + "title": "edt_conf_enum_custom", + "default": 0, + "options": { + "hidden": true }, - "required" : true, - "propertyOrder" : 4, - "comment" : "The 'device_inputs' settings are dynamically inserted into the WebUI under PropertyOrder '3'." + "required": true, + "propertyOrder": 4, + "comment": "The 'device_inputs' settings are dynamically inserted into the WebUI under PropertyOrder '3'." }, - "encoding" : - { - "type" : "string", - "title" : "edt_conf_enum_custom", - "default" : "auto", - "options" : { - "hidden":true + + "standard": { + "type": "string", + "title": "edt_conf_v4l2_standard_title", + "default": "auto", + "required": true, + "propertyOrder": 5 + }, + "encoding": { + "type": "string", + "title": "edt_conf_v4l2_encoding_title", + "default": "auto", + "required": true, + "propertyOrder": 6 + }, + "resolutions": { + "type": "string", + "title": "edt_conf_v4l2_resolution_title", + "propertyOrder": 7, + "required": true + }, + "width": { + "type": "integer", + "title": "edt_conf_fg_width_title", + "default": 0, + "minimum": 0, + "append": "edt_append_pixel", + "options": { + "hidden": true }, - "required" : true, - "propertyOrder" : 6, - "comment" : "The 'device_encodings' settings are dynamically inserted into the WebUI under PropertyOrder '5'." + "required": true, + "propertyOrder": 8, + "comment": "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '7'." }, - "standard" : - { - "type" : "string", - "title" : "edt_conf_v4l2_standard_title", - "enum" : ["NO_CHANGE", "PAL","NTSC","SECAM"], - "default" : "NO_CHANGE", - "options" : { - "enum_titles" : ["edt_conf_enum_NO_CHANGE", "edt_conf_enum_PAL", "edt_conf_enum_NTSC", "edt_conf_enum_SECAM"] + "height": { + "type": "integer", + "title": "edt_conf_fg_height_title", + "default": 0, + "minimum": 0, + "append": "edt_append_pixel", + "options": { + "hidden": true }, - "required" : true, - "propertyOrder" : 7 + "required": true, + "propertyOrder": 9, + "comment": "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '7'." }, - "flip" : - { - "type" : "string", - "title" : "edt_conf_v4l2_flip_title", - "enum" : ["NO_CHANGE", "HORIZONTAL","VERTICAL","BOTH"], - "default" : "NO_CHANGE", - "options" : { - "enum_titles" : ["edt_conf_enum_NO_CHANGE", "edt_conf_enum_HORIZONTAL", "edt_conf_enum_VERTICAL", "edt_conf_enum_BOTH"] + "framerates": { + "type": "string", + "title": "edt_conf_v4l2_framerate_title", + "propertyOrder": 10, + "required": true + }, + "fps": { + "type": "integer", + "title": "edt_conf_enum_custom", + "default": 15, + "minimum": 0, + "append": "fps", + "options": { + "hidden": true }, - "required" : true, - "propertyOrder" : 8 + "required": true, + "propertyOrder": 11, + "comment": "The 'framerates' setting is dynamically inserted into the WebUI under PropertyOrder '10'." }, - "width" : - { - "type" : "integer", - "title" : "edt_conf_fg_width_title", - "default" : 0, - "minimum" : 0, - "append" : "edt_append_pixel", - "options" : { - "hidden":true + "fpsSoftwareDecimation": { + "type": "integer", + "title": "edt_conf_v4l2_fpsSoftwareDecimation_title", + "minimum": 0, + "maximum": 60, + "default": 0, + "required": true, + "access": "advanced", + "propertyOrder": 12 + }, + "flip": { + "type": "string", + "title": "edt_conf_v4l2_flip_title", + "enum": [ "NO_CHANGE", "HORIZONTAL", "VERTICAL", "BOTH" ], + "default": "NO_CHANGE", + "options": { + "enum_titles": [ "edt_conf_enum_NO_CHANGE", "edt_conf_enum_HORIZONTAL", "edt_conf_enum_VERTICAL", "edt_conf_enum_BOTH" ] }, - "required" : true, - "propertyOrder" : 10, - "comment" : "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '9'." + "required": true, + "access": "advanced", + "propertyOrder": 13 }, - "height" : - { - "type" : "integer", - "title" : "edt_conf_fg_height_title", - "default" : 0, - "minimum" : 0, - "append" : "edt_append_pixel", - "options" : { - "hidden":true - }, - "required" : true, - "propertyOrder" : 11, - "comment" : "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '9'." + "sizeDecimation": { + "type": "integer", + "title": "edt_conf_v4l2_sizeDecimation_title", + "minimum": 1, + "maximum": 30, + "default": 6, + "required": true, + "propertyOrder": 14 }, - "fps" : - { - "type" : "integer", - "title" : "edt_conf_enum_custom", - "default" : 15, - "minimum" : 1, - "append" : "fps", - "options" : { - "hidden":true - }, - "required" : true, - "propertyOrder" : 13, - "comment" : "The 'framerates' setting is dynamically inserted into the WebUI under PropertyOrder '12'." + "cropLeft": { + "type": "integer", + "title": "edt_conf_v4l2_cropLeft_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "required": true, + "access": "advanced", + "propertyOrder": 15 }, - "fpsSoftwareDecimation" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_fpsSoftwareDecimation_title", - "minimum" : 0, - "maximum" : 60, - "default" : 0, - "required" : true, - "propertyOrder" : 14 + "cropRight": { + "type": "integer", + "title": "edt_conf_v4l2_cropRight_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "required": true, + "access": "advanced", + "propertyOrder": 16 }, - "sizeDecimation" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_sizeDecimation_title", - "minimum" : 1, - "maximum" : 30, - "default" : 6, - "required" : true, - "propertyOrder" : 15 + "cropTop": { + "type": "integer", + "title": "edt_conf_v4l2_cropTop_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "required": true, + "access": "advanced", + "propertyOrder": 17 }, - "cropLeft" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_cropLeft_title", - "minimum" : 0, - "default" : 0, - "append" : "edt_append_pixel", - "required" : true, - "propertyOrder" : 16 + "cropBottom": { + "type": "integer", + "title": "edt_conf_v4l2_cropBottom_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "required": true, + "access": "advanced", + "propertyOrder": 18 }, - "cropRight" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_cropRight_title", - "minimum" : 0, - "default" : 0, - "append" : "edt_append_pixel", - "required" : true, - "propertyOrder" : 17 + "cecDetection": { + "type": "boolean", + "title": "edt_conf_v4l2_cecDetection_title", + "default": false, + "required": true, + "propertyOrder": 19 }, - "cropTop" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_cropTop_title", - "minimum" : 0, - "default" : 0, - "append" : "edt_append_pixel", - "required" : true, - "propertyOrder" : 18 + "signalDetection": { + "type": "boolean", + "title": "edt_conf_v4l2_signalDetection_title", + "default": false, + "required": true, + "access": "advanced", + "propertyOrder": 20 }, - "cropBottom" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_cropBottom_title", - "minimum" : 0, - "default" : 0, - "append" : "edt_append_pixel", - "required" : true, - "propertyOrder" : 19 - }, - "cecDetection" : - { - "type" : "boolean", - "title" : "edt_conf_v4l2_cecDetection_title", - "default" : false, - "required" : true, - "propertyOrder" : 20 - }, - "signalDetection" : - { - "type" : "boolean", - "title" : "edt_conf_v4l2_signalDetection_title", - "default" : false, - "required" : true, - "propertyOrder" : 21 - }, - "redSignalThreshold" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_redSignalThreshold_title", - "minimum" : 0, - "maximum" : 100, - "default" : 5, - "append" : "edt_append_percent", + "redSignalThreshold": { + "type": "integer", + "title": "edt_conf_v4l2_redSignalThreshold_title", + "minimum": 0, + "maximum": 100, + "default": 5, + "append": "edt_append_percent", "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 22 + "access": "advanced", + "required": true, + "propertyOrder": 21 }, - "greenSignalThreshold" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_greenSignalThreshold_title", - "minimum" : 0, - "maximum" : 100, - "default" : 5, - "append" : "edt_append_percent", + "greenSignalThreshold": { + "type": "integer", + "title": "edt_conf_v4l2_greenSignalThreshold_title", + "minimum": 0, + "maximum": 100, + "default": 5, + "append": "edt_append_percent", "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 23 + "required": true, + "access": "advanced", + "propertyOrder": 22 }, - "blueSignalThreshold" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_blueSignalThreshold_title", - "minimum" : 0, - "maximum" : 100, - "default" : 5, - "append" : "edt_append_percent", + "blueSignalThreshold": { + "type": "integer", + "title": "edt_conf_v4l2_blueSignalThreshold_title", + "minimum": 0, + "maximum": 100, + "default": 5, + "append": "edt_append_percent", "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 24 + "required": true, + "access": "advanced", + "propertyOrder": 23 }, - "noSignalCounterThreshold" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_noSignalCounterThreshold_title", - "minimum" : 1, - "maximum" : 1000, - "default" : 200, + "noSignalCounterThreshold": { + "type": "integer", + "title": "edt_conf_v4l2_noSignalCounterThreshold_title", + "minimum": 1, + "maximum": 1000, + "default": 200, "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 25 + "required": true, + "access": "advanced", + "propertyOrder": 24 }, - "sDVOffsetMin" : - { - "type" : "number", - "title" : "edt_conf_v4l2_sDVOffsetMin_title", - "minimum" : 0.0, - "maximum" : 1.0, - "default" : 0.25, - "step" : 0.01, + "sDVOffsetMin": { + "type": "number", + "title": "edt_conf_v4l2_sDVOffsetMin_title", + "minimum": 0.0, + "maximum": 1.0, + "default": 0.25, + "step": 0.01, "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 26 + "required": true, + "access": "advanced", + "propertyOrder": 25 }, - "sDVOffsetMax" : - { - "type" : "number", - "title" : "edt_conf_v4l2_sDVOffsetMax_title", - "minimum" : 0.0, - "maximum" : 1.0, - "default" : 0.75, - "step" : 0.01, + "sDVOffsetMax": { + "type": "number", + "title": "edt_conf_v4l2_sDVOffsetMax_title", + "minimum": 0.0, + "maximum": 1.0, + "default": 0.75, + "step": 0.01, "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 27 + "required": true, + "access": "advanced", + "propertyOrder": 26 }, - "sDHOffsetMin" : - { - "type" : "number", - "title" : "edt_conf_v4l2_sDHOffsetMin_title", - "minimum" : 0.0, - "maximum" : 1.0, - "default" : 0.25, - "step" : 0.01, + "sDHOffsetMin": { + "type": "number", + "title": "edt_conf_v4l2_sDHOffsetMin_title", + "minimum": 0.0, + "maximum": 1.0, + "default": 0.25, + "step": 0.01, "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 28 + "required": true, + "access": "advanced", + "propertyOrder": 27 }, - "sDHOffsetMax" : - { - "type" : "number", - "title" : "edt_conf_v4l2_sDHOffsetMax_title", - "minimum" : 0.0, - "maximum" : 1.0, - "default" : 0.75, - "step" : 0.01, + "sDHOffsetMax": { + "type": "number", + "title": "edt_conf_v4l2_sDHOffsetMax_title", + "minimum": 0.0, + "maximum": 1.0, + "default": 0.75, + "step": 0.01, "options": { "dependencies": { "signalDetection": true } }, - "required" : true, - "propertyOrder" : 29 + "required": true, + "propertyOrder": 28 }, - "hardware_brightness" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_hardware_brightness_title", - "default" : 0, - "required" : true, - "propertyOrder" : 30 + "hardware_brightness": { + "type": "integer", + "title": "edt_conf_v4l2_hardware_brightness_title", + "default": 0, + "required": true, + "access": "advanced", + "propertyOrder": 29 }, - "hardware_contrast" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_hardware_contrast_title", - "default" : 0, - "required" : true, - "propertyOrder" : 31 + "hardware_contrast": { + "type": "integer", + "title": "edt_conf_v4l2_hardware_contrast_title", + "default": 0, + "required": true, + "access": "advanced", + "propertyOrder": 30 }, - "hardware_saturation" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_hardware_saturation_title", - "default" : 0, - "required" : true, - "propertyOrder" : 32 + "hardware_saturation": { + "type": "integer", + "title": "edt_conf_v4l2_hardware_saturation_title", + "default": 0, + "required": true, + "access": "advanced", + "propertyOrder": 31 }, - "hardware_hue" : - { - "type" : "integer", - "title" : "edt_conf_v4l2_hardware_hue_title", - "default" : 0, - "required" : true, - "propertyOrder" : 33 + "hardware_hue": { + "type": "integer", + "title": "edt_conf_v4l2_hardware_hue_title", + "default": 0, + "required": true, + "access": "advanced", + "propertyOrder": 32 } }, - "additionalProperties" : true -} + "additionalProperties": true + }