diff --git a/Code/Formats.applescript b/Code/Formats.applescript new file mode 100644 index 0000000..366b864 --- /dev/null +++ b/Code/Formats.applescript @@ -0,0 +1,376 @@ +use AppleScript version "2.4" -- Yosemite (10.10) or later +use scripting additions +use script "Myriad Tables Lib" version "1.0.13" +property parent : AppleScript + + +---------------------------------------------------------------------------------- +-- +-- Show format chooser - user to select files for download +-- +---------------------------------------------------------------------------------- + +-- Handler to show format chooser - user can choose which available formats are to be downloaded - separate audio and video formats can be merged +on formats_Chooser(URL_user_entered, diag_Title, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL, DL_Use_YTDLP, shellPath, download_filename_formats, YTDL_credentials, window_Position, formats_reported, is_Livestream_Flag) + + + -- try + + -- v1.26 – Added "--no-playlist" to yt-dlp call as playlists are a nonsense for the formats chooser - doesn't seem to affect other kinds of downloads + set formats_reported to (do shell script shellPath & DL_Use_YTDLP & " " & YTDL_credentials & " --list-formats --no-playlist " & URL_user_entered) + + -- Need to remove extraneous spaces so that getting text items works - can't do a simple search and replace as number of consecutive spaces varies greatly + set character_count to count of characters of formats_reported + set formats_available to "" + repeat with x from 1 to character_count + set text_char to character x of formats_reported + if text_char is " " then + set text_next_char to character (x + 1) of formats_reported + if text_next_char is not " " then + set formats_available to formats_available & text_char + end if + else + set formats_available to formats_available & text_char + end if + end repeat + + + -- set testing_filename to "ContentOfListFormats.txt" as string + -- set save_path to path to desktop folder as string + -- set save_text_file_to to (save_path & testing_filename) + -- set testing_file to save_text_file_to as «class furl» + -- set testFile_refNum to missing value + -- set testFile_refNum to open for access testing_file with write permission + -- write (formats_available & return) to testFile_refNum starting at eof as «class utf8» + -- close access testFile_refNum + + set download_filename_fixed to replace_chars(download_filename_formats, "\\", "##") + set download_filename_fixed to replace_chars(download_filename_fixed, {"'", linefeed}, "") + set download_filename_fixed to replace_chars(download_filename_fixed, "_", " ") + set download_filename_fixed to replace_chars(download_filename_fixed, "##", "´") + + -- Need to drop first 6-7 paras which do not have file details - number of intro paras varies but one always starts with "ID" + -- Also need to find those sites which do not report file size e.g. ABC iView in Australia - there might be other cases of data not being present in which case this will probably show a mess + set file_size_present to false + repeat with x from 1 to count paragraphs of formats_available + set test_paragraph to paragraph x of formats_available + if test_paragraph starts with "ID" then + set z to (x + 1) + if test_paragraph contains "FILESIZE" then set file_size_present to true + end if + end repeat + + -- Initialise lists and get count of paragraphs + set numParas to count paragraphs of formats_available + set full_ID_list to {} + set all_table_rows to {} + repeat (numParas - z) times + set end of full_ID_list to "" + end repeat + + -- Parse each paragraph for desired data - work up from bottom of the list + set AppleScript's text item delimiters to " " + repeat with x from -1 to (-(numParas - z)) by -1 + + set full_file_format to paragraph (x) of formats_available + + -- Get file id - abbreviate if longer than 12 characters for the display + set file_id_test to text item 1 of full_file_format + set item x of full_ID_list to file_id_test + if length of file_id_test is greater than 12 then + set file_id to text 1 thru 9 of file_id_test as string + else + set file_id to file_id_test + end if + + -- Get file extension + set file_ext to text item 2 of full_file_format + + -- Get video resolution + if text item 4 of full_file_format is "only" then + set file_res to "Audio only" + else + set file_res to (text item 3 of full_file_format & " ") + end if + + -- Get file size if present then total bitrate, video and audio codecs + set file_size to "" + set test1_for_size to text item 6 of full_file_format + set test2_for_size to text item 7 of full_file_format + set file_vcodec to "" + set file_acodec to "" + if file_size_present is true then + if test2_for_size is "~" or test2_for_size is "≈" then -- Some layouts have a space between "~" or "≈" and file size - 29/8/23 added "≈" v1.25 here and below + set file_size to text item 8 of full_file_format + set total_bitrate to text item 9 of full_file_format + else if test1_for_size is "|" then -- audio only + files with both v and a codecs + set file_size to (text item 7 of full_file_format) + set total_bitrate to (text item 8 of full_file_format) + else if character -1 of test1_for_size is "B" then -- YouTube video only files & small 7Plus files + if text item 5 of full_file_format is "~" or text item 5 of full_file_format is "≈" then + set file_size to ("~" & test1_for_size) + set total_bitrate to (text item 7 of full_file_format) + else + set file_size to test1_for_size + set total_bitrate to (text item 7 of full_file_format) + end if + else if text item 4 of full_file_format is "|" then + set file_size to (text item 5 of full_file_format) + set total_bitrate to (text item 6 of full_file_format) + else if text item 5 of full_file_format is "~" or text item 5 of full_file_format is "≈" then + set file_size to ("~" & text item 6 of full_file_format) + set total_bitrate to (text item 7 of full_file_format) + else if text item 6 of full_file_format is "~" or text item 6 of full_file_format is "≈" then -- 7Plus layout + set file_size to ("~" & text item 7 of full_file_format) + set total_bitrate to (text item 8 of full_file_format) + end if + + -- Get video codec + if text item 9 of full_file_format is "|" then -- YouTube & some 7Plus + set file_vcodec to text item 10 of full_file_format + else if text item 9 of full_file_format is not "storyboard" and text item 10 of full_file_format is "|" and file_res is not "Audio only" then -- YT both codecs + set file_vcodec to (text item 11 of full_file_format) + -- Exclude Daily Motion and 9Now videos which don't return 11 items + else if URL_user_entered does not contain "dailymotion" and URL_user_entered does not contain "9Now" then + if text item 9 of full_file_format is not "storyboard" and text item 11 of full_file_format is "|" and file_res is not "Audio only" then -- YT both codecs with "~" + set file_vcodec to (text item 12 of full_file_format) + end if + else if text item 9 of full_file_format is "storyboard" then + set file_vcodec to (tab & "Storyboard") + end if + if text item 8 of full_file_format is "|" then + set file_vcodec to (text item 9 of full_file_format) + end if + + -- Get audio codec + if file_res is "audio only" and full_file_format does not contain "Default" then -- For YouTube and 7Plus - 30/8/23 v1.25 - added check for default + set file_acodec to text item 13 of full_file_format + end if + if test1_for_size is "|" then -- audio only + files with both v and a codecs + set file_acodec to text item 13 of full_file_format + if text item 7 of full_file_format is "~" or text item 7 of full_file_format is "≈" then + set file_acodec to text item 14 of full_file_format + end if + end if + if test1_for_size is not "|" and URL_user_entered contains "sbs.com.au/ondemand" then -- 29/8/23 v1.25 - SBS format has changed + set file_acodec to text item 11 of full_file_format + end if + if file_vcodec is not (tab & "Storyboard") and full_file_format does not contain "Default" and full_file_format contains "Video" then -- For YouTube and 7Plus - 30/8/23 v1.25 - added check for default + for SBS added test for Video + if text item 11 of full_file_format is "video" or text item 12 of full_file_format is "video" or text item 13 of full_file_format is "video" then + set file_acodec to "Video only" + end if + end if + -- To reduce complexity of parsing, decided to put this If block into a Try block + try + if text item 10 of full_file_format contains "mp4a" then -- For 9Now in Oz and maybe others + set file_acodec to text item 10 of full_file_format + else if text item 11 of full_file_format contains "mp4a" then -- For 10Play in Oz and maybe others + set file_acodec to text item 11 of full_file_format + else if text item 12 of full_file_format contains "mp4a" then -- For some YouTube videos + set file_acodec to text item 12 of full_file_format + else if text item 13 of full_file_format contains "mp4a" then -- For some YouTube videos + set file_acodec to text item 13 of full_file_format + end if + end try + else + -- Get bitrate, audio and video codec details for cases which have no file size e.g. iView + if text item 7 of full_file_format is "|" then + set total_bitrate to text item 5 of full_file_format + set file_vcodec to text item 8 of full_file_format + if formats_available contains "VBR" then -- 29/8/23 - v1.25 - added VBR test as some iView URLs do not have VBR or ABR + set file_acodec to text item 10 of full_file_format + else + set file_acodec to text item 9 of full_file_format + end if + end if + end if + + -- This is all the text for a single row + set fileformat_item to {false, file_id, file_ext, file_res, file_size, total_bitrate, file_vcodec, file_acodec} + -- This adds each row to the list of rows - add to beginning so that no need to design a new iteration method + set beginning of all_table_rows to fileformat_item + + end repeat + set AppleScript's text item delimiters to "" + + if is_Livestream_Flag is "True" then + set instructions_text to localized string "Select one format live stream you wish to download then click on Download. You can skip choosing or cancel the download and return to the Main Dialog." in bundle file path_to_MacYTDL from table "MacYTDL" + else + set instructions_text to localized string "Select which formats you wish to download then click on Download. You can skip choosing formats or cancel the download and return to the Main Dialog." in bundle file path_to_MacYTDL from table "MacYTDL" + end if + set theFormatsDiagPromptLabelPart1 to localized string "Choose Formats" in bundle file path_to_MacYTDL from table "MacYTDL" + set theFormatsDiagPromptLabelPart2 to localized string "Downloading file" in bundle file path_to_MacYTDL from table "MacYTDL" + -- set theButtonDownloadLabel to localized string "Download" from table "MacYTDL" + -- set theButtonReturnLabel to localized string "Return" from table "MacYTDL" + set theButtonSkipLabel to localized string "Skip" in bundle file path_to_MacYTDL from table "MacYTDL" + -- set theMergeCheckboxLabel to localized string "Merge formats ? [Recommended]" in bundle file path_to_MacYTDL from table "MacYTDL" + set theMergeCheckboxLabel to localized string "Merge ?" in bundle file path_to_MacYTDL from table "MacYTDL" + set theHeadingExtensionLabel to localized string "Extension" in bundle file path_to_MacYTDL from table "MacYTDL" + set theHeadingResolutionLabel to localized string "Resolution" in bundle file path_to_MacYTDL from table "MacYTDL" + set theHeadingFilesizeLabel to localized string "File size" in bundle file path_to_MacYTDL from table "MacYTDL" + set theHeadingTotalBitrateLabel to localized string "Bitrate" in bundle file path_to_MacYTDL from table "MacYTDL" + set theHeadingTotalVCodecLabel to localized string "Video Codec" in bundle file path_to_MacYTDL from table "MacYTDL" + set theHeadingTotalACodecLabel to localized string "Audio Codec" in bundle file path_to_MacYTDL from table "MacYTDL" + + -- Can't find a way to insert a return before the checkbox - Myriad Tables expects just one data class in each cell of each column + set end of all_table_rows to {true, (theMergeCheckboxLabel & return & return)} + + set theFormatsDiagPromptLabel to (tab & tab & tab & tab & tab & tab & theFormatsDiagPromptLabelPart1 & return & return & theFormatsDiagPromptLabelPart2 & ": " & "\"" & download_filename_fixed & "\"" & return & return & instructions_text) + + set format_chooser_headings to {"", "ID", theHeadingExtensionLabel, theHeadingResolutionLabel, theHeadingFilesizeLabel, theHeadingTotalBitrateLabel, theHeadingTotalVCodecLabel, theHeadingTotalACodecLabel} + + set repeat_loop_flag to "" + + + -- set AppleScript's text item delimiters to ", " + -- set table_data to items of all_table_rows as text + -- set testFile_refNum to open for access testing_file with write permission + -- write (table_data & return) to testFile_refNum starting at eof as «class utf8» + -- close access testFile_refNum + -- set AppleScript's text item delimiters to "" + + + repeat until repeat_loop_flag is "Finished" + try + set my_table to make new table with data all_table_rows editable columns {1} column headings format_chooser_headings with prompt theFormatsDiagPromptLabel with title diag_Title with empty selection allowed and multiple lines allowed + modify table my_table initial position window_Position OK button name theButtonDownloadLabel cancel button name theButtonReturnLabel extra button name theButtonSkipLabel + modify columns in table my_table columns list {2, 3, 4, 5, 6, 7, 8} head alignment align center sort method sort none + modify columns in table my_table columns list {1} column width 35 + set theResult to display table my_table giving up after 600 + set button_returned to button number of theResult -- Shows no need to iterate through results just to get button number pressed + set rows_returned to values returned of theResult -- A list of lists which can be parsed to get IDs of formats the user ticked + on error number -128 + -- Go back to Main + if skip_Main_dialog is true then error number -128 -- This is relevant when user has come from Auto-download - need to just quit the applet + set branch_execution to "Main" + return branch_execution + end try + + set file_formats_selected to "" + set user_wants_choose to false + + -- User chose formats and wants to download - form up list of selected formats – add merge indicatory between format IDs – "+" indicates merge and "," indicates keep separate + if button_returned is 1 then + -- Iterate through the values returned to find those chosen by user plus the response to the merger question + set count_choices to 0 + set number_of_formats_requested to (number of items in rows_returned) + if item 1 of item number_of_formats_requested of rows_returned is true then + set merger_choice to "+" + set add_to_output_template to "" + else + set merger_choice to "," + set add_to_output_template to "%(format_id)s" -- Always add format id to file names because file names are the same for all formats + end if + repeat with x from 1 to (number_of_formats_requested - 1) -- Last item is the merger choice + if item 1 of item x of rows_returned is true then + set count_choices to count_choices + 1 + if count_choices is 1 then + set file_formats_selected to item x of full_ID_list + else + set file_formats_selected to file_formats_selected & merger_choice & item x of full_ID_list + end if + end if + end repeat + set branch_execution to "Download" & " " & file_formats_selected & " " & add_to_output_template + + if is_Livestream_Flag is "True" and count_choices is greater than 1 then + set theFormatsChoiceLabel to localized string "You have chosen to download multiple formats" in bundle file path_to_MacYTDL from table "MacYTDL" + set theManyFormatsLabel to localized string "Sorry but, only one format can be downloaded for live streams. Do you wish to download the first format, choose again or cancel and return to the Main dialog ?" in bundle file path_to_MacYTDL from table "MacYTDL" + set theFirstLabel to localized string "First" in bundle file path_to_MacYTDL from table "MacYTDL" + set theChooseLabel to localized string "Choose" in bundle file path_to_MacYTDL from table "MacYTDL" + set manyFormatsButton to button returned of (display dialog (theFormatsDiagPromptLabelPart1 & return & return & theFormatsChoiceLabel & ": " & file_formats_selected & return & return & theManyFormatsLabel) with title diag_Title buttons {theFirstLabel, theChooseLabel, theButtonReturnLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + if manyFormatsButton is theButtonReturnLabel then + if skip_Main_dialog is true then error number -128 + set branch_execution to "Main" + set repeat_loop_flag to "Finished" + return branch_execution + else if manyFormatsButton is theFirstLabel then + -- Keep first two format choices and download them - YT-DLP will download the first two formats and ignore the others + set branch_execution to "Download" & " " & file_formats_selected & " " & add_to_output_template + set repeat_loop_flag to "Finished" + return branch_execution + end if + -- User must have clicked on theChooseLabel - try to get back to beginning of the repeat loop without doing anything + set user_wants_choose to true + end if + if count_choices is greater than 2 and merger_choice is "+" then + set theFormatsChoiceLabel to localized string "You have chosen to merge these formats" in bundle file path_to_MacYTDL from table "MacYTDL" + set theManyFormatsLabel to localized string "Sorry but, three or more formats cannot be merged. Do you wish to merge the first two and ignore the other(s), choose again or cancel and return to the Main dialog ?" in bundle file path_to_MacYTDL from table "MacYTDL" + set theIgnoreLabel to localized string "Ignore" in bundle file path_to_MacYTDL from table "MacYTDL" + set theChooseLabel to localized string "Choose" in bundle file path_to_MacYTDL from table "MacYTDL" + set manyFormatsButton to button returned of (display dialog (theFormatsDiagPromptLabelPart1 & return & return & theFormatsChoiceLabel & ": " & file_formats_selected & return & return & theManyFormatsLabel) with title diag_Title buttons {theButtonReturnLabel, theChooseLabel, theIgnoreLabel} default button 3 with icon file MacYTDL_custom_icon_file giving up after 600) + if manyFormatsButton is theButtonReturnLabel then + if skip_Main_dialog is true then error number -128 + set branch_execution to "Main" + set repeat_loop_flag to "Finished" + return branch_execution + else if manyFormatsButton is theIgnoreLabel then + -- Keep first two format choices and download them - YT-DLP will download the first two formats and ignore the others + set branch_execution to "Download" & " " & file_formats_selected & " " & add_to_output_template + set repeat_loop_flag to "Finished" + return branch_execution + end if + -- User must have clicked on theChooseLabel - try to get back to beginning of the repeat loop without doing anything + set user_wants_choose to true + end if + if file_formats_selected is "" then + set theChooseLabel to localized string "Choose" in bundle file path_to_MacYTDL from table "MacYTDL" + set theNoFormatsLabel to localized string "You didn't select any formats. Do you wish to choose formats, skip and continue to download or cancel and return to Main ?" in bundle file path_to_MacYTDL from table "MacYTDL" + set noFormatsButton to button returned of (display dialog theNoFormatsLabel with title diag_Title buttons {theButtonReturnLabel, theButtonSkipLabel, theChooseLabel} default button 3 with icon file MacYTDL_custom_icon_file giving up after 600) + if noFormatsButton is theButtonReturnLabel then + if skip_Main_dialog is true then error number -128 + set branch_execution to "Main" + set repeat_loop_flag to "Finished" + return branch_execution + else if noFormatsButton is theButtonSkipLabel then + -- Skip the chooser and go back to calling point in download_video - download with existing settings + set branch_execution to "Skip" + set repeat_loop_flag to "Finished" + return branch_execution + end if + -- User must have clicked on theChooseLabel - try to get back to beginning of the repeat loop without doing anything + set user_wants_choose to true + end if + + -- This is the end of the "button_returned is 1" block - User gets here if they clicked on "Download" and made no mistakes with their choice - branch_execution contains the choice + if user_wants_choose is false then + return branch_execution + end if + + -- Skip the chooser and go back to calling point in download_video to download with existing settings + else if button_returned is 2 then + set branch_execution to "Skip" + set repeat_loop_flag to "Finished" + end if + end repeat + + return branch_execution + -- Finished with chooser - head off to download with or without formats or to just return to Main + + + + + -- on error errMsg + -- display dialog errMsg + -- end try + + + + +end formats_Chooser + +--------------------------------------------------- +-- +-- Find and Replace +-- +--------------------------------------------------- + +-- Handler to find-replace text inside a string +on replace_chars(this_text, search_string, replacement_string) + set AppleScript's text item delimiters to the search_string + set the item_list to every text item of this_text + set AppleScript's text item delimiters to the replacement_string + set this_text to the item_list as string + set AppleScript's text item delimiters to "" + return this_text +end replace_chars diff --git a/Code/Monitor.applescript b/Code/Monitor.applescript new file mode 100644 index 0000000..62ce943 --- /dev/null +++ b/Code/Monitor.applescript @@ -0,0 +1,1053 @@ +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- MacYTDL +-- A GUI for the Python Scripts youtube-dl and yt-dlp. Many thanks to Shane Stanley, Adam Albrec, kopurando and Michael Page +-- This is the Download Monitor +-- This script provides a download Monitor for each video file download requested by user - it is called by main.scpt +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- Include libraries - needed for Shane Staney's Dialog Toolkit +use AppleScript version "2.4" -- Yosemite (10.10) or later +use scripting additions +use script "DialogToolkitMacYTDL" -- Yosemite (10.10) or later + +-- Run the Monitor when the script is called +on run {downloadsFolder_Path_monitor, MacYTDL_preferences_path_monitor, YTDL_TimeStamps_monitor, ytdl_settings_monitor, URL_user_entered_monitor, YTDL_log_file_monitor, download_filename_monitor, download_filename_new_monitor, MacYTDL_custom_icon_file_posix_monitor, monitor_dialog_position, YTDL_simulate_log_monitor, diag_Title_quoted_monitor, is_Livestream_Flag_monitor, screen_width, screen_height, DL_Use_YTDLP, path_to_MacYTDL, YTDL_Delete_Partial} + + + -- try + + + --***************** + -- Dialog for testing that parameters were passed correctly by the calling script + -- display dialog "downloadsFolder_Path_monitor: " & downloadsFolder_Path_monitor & return & return & "MacYTDL_preferences_path_monitor: " & MacYTDL_preferences_path_monitor & return & return & "timestamps: " & YTDL_TimeStamps_monitor & return & return & "ytdl_settings_monitor: " & ytdl_settings_monitor & return & return & "URL_user_entered_monitor: " & URL_user_entered_monitor & return & return & "YTDL_log_file_monitor: " & YTDL_log_file_monitor & return & return & "download_filename_monitor: " & "\"" & download_filename_monitor & "\"" & return & return & "download_filename_new_monitor: " & download_filename_new_monitor & return & return & "MacYTDL_custom_icon_file_posix_monitor: " & MacYTDL_custom_icon_file_posix_monitor & return & return & "monitor_dialog_position: " & monitor_dialog_position & return & return & "YTDL_simulate_log_monitor: " & YTDL_simulate_log_monitor & return & return & "diag_Title_quoted_monitor: " & diag_Title_quoted_monitor & return & return & "is_Livestream_Flag_monitor: " & is_Livestream_Flag_monitor & return & return & "screen_width: " & screen_width & return & return & "screen_height: " & screen_height & return & return & "DL_Use_YTDLP: " & DL_Use_YTDLP & return & return & "path_to_MacYTDL: " & path_to_MacYTDL & return & return & "Delete partial: " & YTDL_Delete_Partial with title "Monitor" + --***************** + + -- Set variable to contain path to MacYTDL bundle and the ets executable + set pathToBundle to (path to me) as text + set pathToBundleShort to text 1 thru -40 of pathToBundle + + -- Calculate the number of monitor dialogs per column which is also the maximum number of rows + set number_of_monitors_per_column to round (screen_height / 200) + -- Calculate the column number + set column_number to (round (monitor_dialog_position / number_of_monitors_per_column) rounding up) + -- Set the X_position + set X_position_monitor to screen_width - (250 * column_number) + -- Work out which row is to be used - starts at row 0 which is the top of the screen + set row_number to (monitor_dialog_position - (number_of_monitors_per_column * (column_number - 1))) - 1 + -- Calculate the Y_position + set Y_position_monitor to (row_number * 150) + + -- This variable is never set to Yes so, why keep it ? + set download_finished to "No" + + -- Set more variables to enable passing to shell + set YTDL_log_file_monitor_posix to POSIX file YTDL_log_file_monitor + set MacYTDL_custom_icon_file_not_posix_monitor to POSIX file MacYTDL_custom_icon_file_posix_monitor as text + + -- Set paths for shell command - probably don't need all of these - need to test reomving some + set shellPath to "PATH=$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin:~/opt/bin:~/opt/sbin:/opt/local/bin:/opt/local/sbin:/opt/homebrew/bin:" & quoted form of (POSIX path of ((path to me as text) & "::")) & "; " + + -- Need quoted form so that paths and strings with spaces are handled correctly by the shell + set downloadsFolder_Path_monitor_quoted to quoted form of downloadsFolder_Path_monitor + set YTDL_log_file_monitor_quoted to quoted form of YTDL_log_file_monitor + set diag_Title_monitor to quoted form of diag_Title_quoted_monitor + set diag_Title_quoted_monitor to quoted form of diag_Title_quoted_monitor + if YTDL_TimeStamps_monitor is not "" then + set YTDL_TimeStamps_monitor_quoted to quoted form of YTDL_TimeStamps_monitor + else + set YTDL_TimeStamps_monitor_quoted to "" + end if + set MacYTDL_custom_icon_file_not_posix_monitor_quoted to quoted form of MacYTDL_custom_icon_file_not_posix_monitor -- Passed to Adviser for display dialog + + -- Revert download show name to spaces so it looks nice in dialog + if download_filename_new_monitor contains "_" then + set download_filename_new_monitor_plain to my replace_chars(download_filename_new_monitor, "_", " ") + else + set download_filename_new_monitor_plain to download_filename_new_monitor + end if + + -- Put single quotes around each URL - mainly because the ampersand in some Youtube URLs ends up being treated as a delimiter - crude but effective + -- 19 October 2019 - Restricted adding quotes to case where URL contains ampersands - all others go through without + if URL_user_entered_monitor contains "&" then + set AppleScript's text item delimiters to " " + set number_of_URLs to number of text items in URL_user_entered_monitor + if number_of_URLs is greater than 1 then + set URL_user_entered_monitor_quoted to "" + repeat with current_URL in text items of URL_user_entered_monitor + set current_URL to "'" & current_URL & "'" + set URL_user_entered_monitor_quoted to URL_user_entered_monitor_quoted & current_URL & " " + end repeat + else + set URL_user_entered_monitor_quoted to quoted form of URL_user_entered_monitor + end if + set AppleScript's text item delimiters to "" + else + set URL_user_entered_monitor_quoted to URL_user_entered_monitor + end if + + -- Initialise flag to indicate kind of Monitor is being displayed + set monitor_state_flag to "Downloading" + + + -- Remove quotes from around ytdl_settings_monitor as they cause problems with running youtube-dl/yt-dlp command from shell + set ytdl_settings_monitor to items 2 thru -1 of ytdl_settings_monitor as string + + -- Blank out URL_user_entered_monitor_quoted - is set to Null when downloading a batch + if URL_user_entered_monitor_quoted is "Null" then + set URL_user_entered_monitor_quoted to "" + end if + + -- Sometimes, there is a linefeed at the end of the file name - remove it + if character -1 of download_filename_monitor is linefeed then + set download_filename_monitor to text 1 thru -2 of download_filename_monitor + end if + + -- Change extension in download file name and displayed file name if user requested a remux - simulate often has the old extension - need to match the final after remux so that Adviser can play it - Need to handle batches which have different remux setting to original add to batch - But not for playlists + -- 1.24 - This If block caused problems with SBS/ABC Chooser downloads in which the download_filename_monitor has no extension - decided to add code looking for the "." character positioned 3 or 4 characters from end of the name + if ytdl_settings_monitor contains "--recode-video" then + set look_for_extension_1 to character -4 of download_filename_monitor + set look_for_extension_2 to character -5 of download_filename_monitor + if look_for_extension_1 is "." or look_for_extension_2 is "." then + -- Get new extension - always follows the word recode + set all_words to words in ytdl_settings_monitor + repeat with i from 1 to the length of all_words + if item i of all_words is "recode" then exit repeat + end repeat + set new_extension to item (i + 2) in all_words + -- Get old extension - with multiple downloads and playlists, only need to find the first as the Adviser only plays the first file + set the_first_file_name to first paragraph of download_filename_monitor + set AppleScript's text item delimiters to {"."} + set old_extension to last text item of the_first_file_name + set AppleScript's text item delimiters to {""} + if old_extension is not equal to new_extension then + -- Following code changed in v1.23.1 - For a batch need to get download file name from different variable + if download_filename_new_monitor_plain is "the saved batch" then + set download_filename_monitor to replace_chars(download_filename_monitor, old_extension, new_extension) + end if + set download_filename_new_monitor_plain to replace_chars(download_filename_new_monitor_plain, old_extension, new_extension) + end if + end if + end if + + -- Change extension in download file name if user requested a particular audio format - simulate often has the old format extension - need to match the final after post processing so that Adviser can play it + if ytdl_settings_monitor contains "--audio-format" then + -- Get new extension - always follows the word audio-format + set AppleScript's text item delimiters to {"audio-format ", " --audio-quality"} + set new_extension to second text item of ytdl_settings_monitor + -- Get old extension - with multiple downloads and playlists, only need to find the first as the Adviser only plays the first file + set the_first_file_name to first paragraph of download_filename_monitor + set AppleScript's text item delimiters to {"."} + set old_extension to last text item of the_first_file_name + set AppleScript's text item delimiters to {""} + if old_extension is not equal to new_extension then + set download_filename_monitor to replace_chars(download_filename_monitor, old_extension, new_extension) + end if + end if + + -- ***************************************** + -- Dialog for testing content of parameters about to be sent to shell to do download + --display dialog "shellPath: " & shellPath & return & return & "downloadsFolder_Path_monitor_quoted: " & downloadsFolder_Path_monitor_quoted & return & return & "YTDL_TimeStamps_monitor_quoted: " & YTDL_TimeStamps_monitor_quoted & return & return & "DL_Use_YTDLP: " & DL_Use_YTDLP & return & return & "ytdl_settings_monitor: " & ytdl_settings_monitor & return & return & "URL_user_entered_monitor_quoted: " & URL_user_entered_monitor_quoted & return & return & "YTDL_log_file_monitor_quoted: " & YTDL_log_file_monitor_quoted + -- ***************************************** + + -- Convert name of YT-DLP-Legacy to make life easier from here on + if DL_Use_YTDLP is "yt-dlp-legacy" then + set monitor_DL_Use_YTDLP to "yt-dlp" + else + set monitor_DL_Use_YTDLP to DL_Use_YTDLP + end if + + -- Get pid of this Monitor instance to send to Adviser + -- Might get the wrong pid if there are two osascript processes underway + complicated by the "ets" process - but as of 25/1/22 it seems to work and can't think of another way + try + set monitor_pid to do shell script "pgrep -n osascript &" + on error errtext + display dialog "There was an error with the pgrep:" & errtext + end try + + + -- ******************************************************************************************************************************************************* + -- Parallel downloads - parse download_filename_new_monitor to get multiple URLs, files names and log file names - use a repeat loop + set batch_parallel_flag to false + -- Set up for parallel download of playlists + if download_filename_new_monitor contains "#$" then -- This is a playlist to be downloaded in parallel + set number_paragraphs to ((count of paragraphs of download_filename_new_monitor) - 1) -- Always has a return at the end + -- Need a list of process ids, file names, playlist name and log file names to check after they have all started and show in Monitor dialog - only works if list items are initialised + set ytdl_parallel_pid to {} + set download_logfile_Parallel_List to {} + set download_filename_Parallel_List to {} + repeat (number_paragraphs) times + set end of ytdl_parallel_pid to "" + set end of download_logfile_Parallel_List to "" + set end of download_filename_Parallel_List to "" + end repeat + + set AppleScript's text item delimiters to {"##", "#$"} -- This is the delimiter added by Main to download_filename_new_monitor when user wants parallel downloads + repeat with x from 1 to number_paragraphs + set download_filename_new_monitor_item to paragraph x of download_filename_new_monitor + + set playlist_parallel_name to text item 1 of download_filename_new_monitor_item + set download_filename_parallel to text item 2 of download_filename_new_monitor_item + set item x of download_filename_Parallel_List to (playlist_parallel_name & "#$" & download_filename_parallel) -- show_parallel_Monitor() needs to find these cases + + set download_URL_parallel_quoted to quoted form of (text item 3 of download_filename_new_monitor_item) + + set download_logfile_Parallel_not_quoted to (text item 4 of download_filename_new_monitor_item) + set download_logfile_Parallel_quoted to quoted form of download_logfile_Parallel_not_quoted + set item x of download_logfile_Parallel_List to download_logfile_Parallel_not_quoted -- Test of not adding quotes - WORKS + + -- Issue yt-dlp command to download the requested video file in background - returns PID of Python process + errors; anything else returned by yt-dlp goes into log file + set item x of ytdl_parallel_pid to do shell script shellPath & "cd " & downloadsFolder_Path_monitor_quoted & " ; " & YTDL_TimeStamps_monitor_quoted & " " & monitor_DL_Use_YTDLP & " " & ytdl_settings_monitor & " " & download_URL_parallel_quoted & " &> " & download_logfile_Parallel_quoted & " & echo $!" + end repeat + set AppleScript's text item delimiters to {""} + + show_parallel_Monitor(download_logfile_Parallel_List, download_filename_Parallel_List, pathToBundleShort, MacYTDL_custom_icon_file_posix_monitor, X_position_monitor, Y_position_monitor, ytdl_parallel_pid, MacYTDL_preferences_path_monitor, batch_parallel_flag, downloadsFolder_Path_monitor, YTDL_Delete_Partial) + + -- Set up for parallel downloads of batches and multiple downloads + else if download_filename_new_monitor contains "##" then -- Parallel download of multiple URLs or batch + set number_paragraphs to ((count of paragraphs of download_filename_new_monitor) - 1) -- Always has a return at the end + -- Need a list of process ids, file names and log file names to check after they have all started and show in Monitor dialog - only works if list items are initialised + set ytdl_parallel_pid to {} + set download_logfile_Parallel_List to {} + set download_filename_Parallel_List to {} + repeat (number_paragraphs) times + set end of ytdl_parallel_pid to "" + set end of download_logfile_Parallel_List to "" + set end of download_filename_Parallel_List to "" + end repeat + + -- Remove any single quotes surrounding download_filename_new_monitor + if character 1 of download_filename_new_monitor is "'" then + set download_filename_new_monitor to text 2 thru -2 of download_filename_new_monitor + end if + + set AppleScript's text item delimiters to {"##"} -- This is the delimiter added by Main to download_filename_new_monitor when user wants parallel downloads + repeat with x from 1 to number_paragraphs + set download_filename_parallel to text item 1 of paragraph x of download_filename_new_monitor + set item x of download_filename_Parallel_List to download_filename_parallel + set download_URL_parallel_quoted to quoted form of (text item 2 of paragraph x of download_filename_new_monitor) + set download_logfile_Parallel_not_quoted to (text item 3 of paragraph x of download_filename_new_monitor) + set download_logfile_Parallel_quoted to quoted form of download_logfile_Parallel_not_quoted + set item x of download_logfile_Parallel_List to download_logfile_Parallel_not_quoted -- Test of not adding quotes - WORKS + + -- Issue yt-dlp command to download the requested video file in background - returns PID of Python process + errors; anything else returned by yt-dlp goes into log file + set item x of ytdl_parallel_pid to do shell script shellPath & "cd " & downloadsFolder_Path_monitor_quoted & " ; " & YTDL_TimeStamps_monitor_quoted & " " & monitor_DL_Use_YTDLP & " " & ytdl_settings_monitor & " " & download_URL_parallel_quoted & " &> " & download_logfile_Parallel_quoted & " & echo $!" + end repeat + set AppleScript's text item delimiters to {""} + + if URL_user_entered_monitor is null then set batch_parallel_flag to true + + show_parallel_Monitor(download_logfile_Parallel_List, download_filename_Parallel_List, pathToBundleShort, MacYTDL_custom_icon_file_posix_monitor, X_position_monitor, Y_position_monitor, ytdl_parallel_pid, MacYTDL_preferences_path_monitor, batch_parallel_flag, downloadsFolder_Path_monitor, YTDL_Delete_Partial) + + -- Set up for parallel download of iView and SBS episodes - download_filename_new_monitor is not used any further and so can be used to store the parallel flag which would otherwise cause grief with parsing + else if download_filename_new_monitor contains "$$" then + set number_paragraphs to count of paragraphs of download_filename_monitor + -- Need a list of process ids, file names and log file names to check after they have all started and show in Monitor dialog - only works if list items are initialised + set ytdl_parallel_pid to {} + set download_logfile_Parallel_List to {} + set download_filename_Parallel_List to {} + repeat (number_paragraphs) times + set end of ytdl_parallel_pid to "" + set end of download_logfile_Parallel_List to "" + set end of download_filename_Parallel_List to "" + end repeat + + -- Remove any single quotes surrounding download_filename_new_monitor + if character 1 of download_filename_monitor is "'" then + set download_filename_monitor to text 2 thru -2 of download_filename_monitor + end if + -- Setting delimiters done for each iteration as otherwise it pollutes the offset command + repeat with x from 1 to number_paragraphs + set download_filename_parallel to paragraph x of download_filename_monitor + set item x of download_filename_Parallel_List to download_filename_parallel + set AppleScript's text item delimiters to {" "} + set download_URL_parallel_quoted to quoted form of (text item x of URL_user_entered_monitor) + set AppleScript's text item delimiters to {""} + + -- Need to trim off ".[extension]" from file name before making name of log file + set download_filename_parallel_trimmed to text 1 thru ((download_filename_parallel's length) - (offset of "." in (the reverse of every character of download_filename_parallel) as text)) of download_filename_parallel + set download_filename_parallel_trimmed_not_quoted to replace_chars(download_filename_parallel_trimmed, " ", "_") + set download_date_time to get_Date_Time() + set download_logfile_Parallel to MacYTDL_preferences_path_monitor & "ytdl_log-" & download_filename_parallel_trimmed_not_quoted & "-" & download_date_time & ".txt" + set download_logfile_Parallel_quoted to quoted form of download_logfile_Parallel + set item x of download_logfile_Parallel_List to download_logfile_Parallel + + -- Issue yt-dlp command to download the requested video file in background - returns PID of Python process + errors; anything else returned by yt-dlp goes into log file + set item x of ytdl_parallel_pid to do shell script shellPath & "cd " & downloadsFolder_Path_monitor_quoted & " ; " & YTDL_TimeStamps_monitor_quoted & " " & monitor_DL_Use_YTDLP & " " & ytdl_settings_monitor & " " & download_URL_parallel_quoted & " &> " & download_logfile_Parallel_quoted & " & echo $!" + end repeat + + if URL_user_entered_monitor is null then set batch_parallel_flag to true + + show_parallel_Monitor(download_logfile_Parallel_List, download_filename_Parallel_List, pathToBundleShort, MacYTDL_custom_icon_file_posix_monitor, X_position_monitor, Y_position_monitor, ytdl_parallel_pid, MacYTDL_preferences_path_monitor, batch_parallel_flag, downloadsFolder_Path_monitor, YTDL_Delete_Partial) + + + + -- ******************************************************************************************************************************************************* + + + + + else + -- Issue youtube-dl/yt-dlp command to download the requested video file in background - returns PID of Python process + errors; anything else returned by youtube-dl/yt-dlp goes into log file + set youtubedl_pid to do shell script shellPath & "cd " & downloadsFolder_Path_monitor_quoted & " ; " & YTDL_TimeStamps_monitor_quoted & " " & monitor_DL_Use_YTDLP & " " & ytdl_settings_monitor & " " & URL_user_entered_monitor_quoted & " &> " & YTDL_log_file_monitor_quoted & " & echo $!" + + -- Set up for starting the Adviser - get path to adviser script, set parameters to be passed, start the Adviser + -- Prepare to call on the Adviser + + -- Test whether user wants a description file - transmit to Adviser so it can fix the file name after download + set DL_description_monitor to "No" + if ytdl_settings_monitor contains "description" then + set DL_description_monitor to "Yes" + end if + + -- ***************************************** + set path_to_monitor to (path to me) as string -- <= Duplicates line of code at beginning of this script except "string" instead of "text" + -- ***************************************** + + -- Make quoted forms of variables so they are passed corectly into the Adviser shell script + set path_to_scripts to text 1 thru -13 of path_to_monitor + set myAdviserScriptAsString to quoted form of POSIX path of (path_to_scripts & "adviser.scpt") + set download_filename_monitor_quoted to quoted form of download_filename_monitor + set download_filename_new_monitor to quoted form of download_filename_new_monitor + set download_filename_new_monitor_plain_quoted to quoted form of download_filename_new_monitor_plain + set YTDL_simulate_log_monitor_quoted to quoted form of YTDL_simulate_log_monitor + set MacYTDL_preferences_path_monitor_quoted to quoted form of MacYTDL_preferences_path_monitor + set adviser_params to monitor_pid & " " & youtubedl_pid & " " & MacYTDL_custom_icon_file_not_posix_monitor_quoted & " " & MacYTDL_preferences_path_monitor_quoted & " " & YTDL_log_file_monitor_quoted & " " & downloadsFolder_Path_monitor_quoted & " " & diag_Title_quoted_monitor & " " & DL_description_monitor & " " & is_Livestream_Flag_monitor & " " & download_filename_monitor_quoted & " " & download_filename_new_monitor & " " & download_filename_new_monitor_plain_quoted & " " & YTDL_simulate_log_monitor_quoted + + -- Production call to Adviser + set adviser_pid to do shell script "osascript -s s " & myAdviserScriptAsString & " " & adviser_params & " " & " > /dev/null 2> /dev/null & echo $!" + + -- Test call to Adviser - often not useful + -- set adviser_pid to do shell script "osascript -s s " & myAdviserScriptAsString & " " & adviser_params & " " & " echo $!" + + + -- Set text for localization + set theProgressLabel to localized string "Progress:" in bundle file pathToBundleShort from table "MacYTDL" + set theProgressingLabel to localized string "Progressing" in bundle file pathToBundleShort from table "MacYTDL" + set theDownloadInLabel to localized string "downloaded in" in bundle file pathToBundleShort from table "MacYTDL" + set theDownloadOfLabel to localized string "downloaded of" in bundle file pathToBundleShort from table "MacYTDL" + set theMinutesLabel to localized string "minutes." in bundle file pathToBundleShort from table "MacYTDL" + set theInLabel to localized string "in" in bundle file pathToBundleShort from table "MacYTDL" + set theOKLabel to localized string "OK" in bundle file pathToBundleShort from table "MacYTDL" + set theMonitorIntroTextLabel1 to localized string "Your download of" in bundle file pathToBundleShort from table "MacYTDL" + set theMonitorIntroTextLabel2 to localized string "has started." in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsPauseLabel to localized string "Pause" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsResumeLabel to localized string "Resume" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsLogLabel to localized string "Log" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsStopLabel to localized string "Stop" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsCloseLabel to localized string "Close" in bundle file pathToBundleShort from table "MacYTDL" + set theRunningLabel to localized string "Running" in bundle file pathToBundleShort from table "MacYTDL" + set thePercentSymbolLabel to localized string "%" in bundle file pathToBundleShort from table "MacYTDL" + set theMBSymbolLabel to localized string "MB" in bundle file pathToBundleShort from table "MacYTDL" + set theGBSymbolLabel to localized string "GB" in bundle file pathToBundleShort from table "MacYTDL" + + -- Prepare and display the download monitor dialog - set starting variables + set seconds_running to 0 + set time_running to 0 + set progress_percentage to "" + set downloadFileSize to "" + set monitor_diag_Title to "MacYTDL" + set diag_intro_text_1 to theMonitorIntroTextLabel1 & " \"" & download_filename_new_monitor_plain & "\" " & theMonitorIntroTextLabel2 + set accViewWidth to 100 + set accViewInset to 0 + set the_date_start to current date + set the_time_start to time of the_date_start + + -- Set buttons + if is_Livestream_Flag_monitor is "True" then + set {theButtons, minWidth} to create buttons {theButtonsLogLabel, theButtonsStopLabel} button keys {"l", "S"} + set minWidth to 250 + else + set {theButtons, minWidth} to create buttons {theButtonsLogLabel, theButtonsStopLabel, theButtonsPauseLabel, theButtonsCloseLabel} button keys {"l", "S", "P", ""} default button 4 + end if + if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit + + -- It can take time for log file to get content - delay Monitor a bit + delay 2 + + -- Repeat loop to display monitor every 5 seconds (set in create enhanced window call), update with progress, redisplay - can close dialog, stop download, pause download or open logs folder - automatically closed by Adviser.scpt when download finished + repeat + -- Get YTDL log up to this point - if file is empty, Monitor will show "Progressing" + set size_of_log to get eof YTDL_log_file_monitor_posix + if size_of_log is less than 5 then + set YTDL_log to "No log" + else + try + set YTDL_log to read file YTDL_log_file_monitor_posix as text + on error errMsg + display dialog "Error in Monitor reading log file: " & YTDL_log_file_monitor_posix & return & "Error message: " & errMsg + end try + end if + + -- Get time running since start, convert into minutes + set the_time to time of (current date) + set seconds_running to the_time - the_time_start + set time_running to seconds_running / minutes + set round_factor to 0.1 + set time_running to (round time_running / round_factor) * round_factor + + --A default display when there are no progress details available in log file + set progress_percentage to "" + set diag_intro_text_2 to theProgressingLabel + + -- Use content of log to fashion text to appear in Monitor dialog + if YTDL_log is not "No log" then + set YTDL_log_lastParapraph to paragraph -2 of YTDL_log + -- If progress meter available, get current percentage and file size - trim leading spaces from percentage - convert [MiB to MB]/[GiB to GB] in file size to match Finder + if YTDL_log_lastParapraph contains "[download]" and YTDL_log_lastParapraph contains "%" and YTDL_log_lastParapraph contains "at" then + set progress_percentage to last word in (text 1 thru (offset of "%" in YTDL_log_lastParapraph) of YTDL_log_lastParapraph) + set o to (offset of "." in progress_percentage) + if ((o > 0) and (0.0 as text is "0,0")) then set progress_percentage to (text 1 thru (o - 1) of progress_percentage & "," & text (o + 1) thru -1 of progress_percentage) + -- YTDL Progress meter reports estimated size of download in GiB or MiB + set GiBPositionAfterSize to offset of "GiB" in YTDL_log_lastParapraph -- Crude but does work + if GiBPositionAfterSize is not 0 then + set downloadFileSizeGiB to last word in (text 22 thru (GiBPositionAfterSize - 1) of YTDL_log_lastParapraph) + set approxIndicator to character 1 of downloadFileSizeGiB + if approxIndicator is "~" then + set downloadFileSizeGiB to text 2 thru end of downloadFileSizeGiB + set o to (offset of "." in downloadFileSizeGiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeGiB to (text 1 thru (o - 1) of downloadFileSizeGiB & "," & text (o + 1) thru -1 of downloadFileSizeGiB) + set downloadFileSizeGiB to downloadFileSizeGiB as number + set downloadFileSizeGB to downloadFileSizeGiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeGB to (round downloadFileSizeGB / round_factor) * round_factor + else + set approxIndicator to "" + set o to (offset of "." in downloadFileSizeGiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeGiB to (text 1 thru (o - 1) of downloadFileSizeGiB & "," & text (o + 1) thru -1 of downloadFileSizeGiB) + set downloadFileSizeGiB to downloadFileSizeGiB as number + set downloadFileSizeGB to downloadFileSizeGiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeGB to (round downloadFileSizeGB / round_factor) * round_factor + end if + set diag_intro_text_2 to theProgressLabel & " " & progress_percentage & thePercentSymbolLabel & " " & theDownloadOfLabel & " " & approxIndicator & downloadFileSizeGB & theGBSymbolLabel & " " & theInLabel & " " & time_running & " " & theMinutesLabel + else + set MiBPositionAfterSize to offset of "MiB" in YTDL_log_lastParapraph + set downloadFileSizeMiB to last word in (text 22 thru (MiBPositionAfterSize - 1) of YTDL_log_lastParapraph) + set approxIndicator to character 1 of downloadFileSizeMiB + if approxIndicator is "~" then + set downloadFileSizeMiB to text 2 thru end of downloadFileSizeMiB + set o to (offset of "." in downloadFileSizeMiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeMiB to (text 1 thru (o - 1) of downloadFileSizeMiB & "," & text (o + 1) thru -1 of downloadFileSizeMiB) + set downloadFileSizeMiB to downloadFileSizeMiB as number + set downloadFileSizeMB to downloadFileSizeMiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeMB to (round downloadFileSizeMB / round_factor) * round_factor + else + set approxIndicator to "" + set o to (offset of "." in downloadFileSizeMiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeMiB to (text 1 thru (o - 1) of downloadFileSizeMiB & "," & text (o + 1) thru -1 of downloadFileSizeMiB) + set downloadFileSizeMiB to downloadFileSizeMiB as number + set downloadFileSizeMB to downloadFileSizeMiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeMB to (round downloadFileSizeMB / round_factor) * round_factor + end if + set diag_intro_text_2 to theProgressLabel & " " & progress_percentage & thePercentSymbolLabel & " " & theDownloadOfLabel & " " & approxIndicator & downloadFileSizeMB & theMBSymbolLabel & " " & theInLabel & " " & time_running & " " & theMinutesLabel + end if + else if YTDL_log_lastParapraph contains "[Merger] Merging formats into" then + set diag_intro_text_2 to "FFmpeg merging formats ...." + else if YTDL_log_lastParapraph contains "[VideoConvertor] Converting video from" then + set diag_intro_text_2 to "Converting download ...." + else if YTDL_log_lastParapraph contains "[ThumbnailsConvertor] Converting thumbnail" then + set diag_intro_text_2 to "Converting thumbnail ...." + else if YTDL_log_lastParapraph contains "[EmbedThumbnail] mutagen:" then + set diag_intro_text_2 to "Embedding thumbnail ...." + else if YTDL_log_lastParapraph contains "[ExtractAudio] Destination:" then + set diag_intro_text_2 to "Extracting audio ...." + else if YTDL_log_lastParapraph contains "[ffmpeg] Fixing malformed" then + set diag_intro_text_2 to "FFmpeg fixing bitstream ...." + else if YTDL_log_lastParapraph contains "[ffmpeg] Merging formats into" then + set diag_intro_text_2 to "FFmpeg merging formats ...." + else if YTDL_log_lastParapraph contains "[FixupM3u8] Fixing" then + set diag_intro_text_2 to "Fixing container ...." + else if YTDL_log_lastParapraph contains "[info] Downloading video thumbnail" or YTDL_log_lastParapraph contains "[info] Writing video thumbnail" then + set diag_intro_text_2 to "Writing thumbnail ...." + else if YTDL_log_lastParapraph contains "[debug] Invoking downloader on" then + set diag_intro_text_2 to "Starting download ...." + else if YTDL_log_lastParapraph contains "[debug] ffmpeg command line" then + set diag_intro_text_2 to (theRunningLabel & " FFmpeg ....") + else if YTDL_log contains "size= " then + -- FFMpeg regularly reports amount downloaded - find latest report - convert kibibytes to kilobytes to match size reported by Finder + set numParasInlog to count of paragraphs in YTDL_log + repeat with i from 1 to numParasInlog + set lastParaInlog to paragraph (-i) of YTDL_log + if lastParaInlog contains "size=" then + set offsetOfSize to offset of "size" in lastParaInlog + set sizeOfDownloadProgress to text (offsetOfSize + 5) thru (offsetOfSize + 12) of lastParaInlog + set sizeOfDownloadProgress to (sizeOfDownloadProgress * 1.024) as integer + exit repeat + else + set i to i + 1 + end if + end repeat + set sizeOfdownloadProgressDelimited to convertNumberToCommaDelimitedString(sizeOfDownloadProgress) + set diag_intro_text_2 to theProgressLabel & " " & sizeOfdownloadProgressDelimited & "KB" & " " & theDownloadInLabel & " " & time_running & " " & theMinutesLabel + end if + end if + + -- Set variables for Monitor dialog which need to be updated with each repeat + -- v1.25 – Move intro_label2 down the Monitor ie increase theTop variable if intro_label1 is one line - prevents overlap with image + --set {intro_label2, theTop} to create label diag_intro_text_2 left inset 0 bottom 5 max width minWidth - 20 aligns center aligned control size mini size with multiline + set {intro_label2, theTop} to create label diag_intro_text_2 left inset 0 bottom 5 max width minWidth - 20 aligns center aligned control size small size with multiline + set intro_label2_thTop to theTop + --set {intro_label1, theTop} to create label diag_intro_text_1 left inset 50 bottom theTop + 10 max width minWidth - 51 control size mini size + set {intro_label1, theTop} to create label diag_intro_text_1 left inset 50 bottom theTop + 10 max width minWidth - 51 control size small size + set intro_label1_thTop to theTop + if (intro_label1_thTop - intro_label2_thTop) < 25 then set theTop to (theTop + 12) -- Calculate height added by intro_label1 + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix_monitor left inset 0 bottom theTop - 40 view width 40 view height 40 scale image scale proportionally + + -- Display the monitor dialog - set give up @ 5 seconds so that code can continue the repeat loop - but not if paused + if monitor_state_flag is "Downloading" then + set {monitor_button_returned, buttonNumber, controlResults, finalPosition} to display enhanced window monitor_diag_Title buttons theButtons giving up after 5 acc view width accViewWidth acc view height theTop acc view controls {intro_label2, intro_label1, MacYTDL_icon} initial position {X_position_monitor, Y_position_monitor} + else if monitor_state_flag is "Paused" then + set {theButtons} to create buttons {theButtonsLogLabel, theButtonsResumeLabel, theButtonsCloseLabel} button keys {"l", "R", ""} default button 3 + set {monitor_button_returned, buttonNumber, controlResults, finalPosition} to display enhanced window monitor_diag_Title buttons theButtons acc view width accViewWidth acc view height theTop acc view controls {intro_label2, intro_label1, MacYTDL_icon} initial position {X_position_monitor, Y_position_monitor} + end if + + -- User clicked on the Pause download button - This kills the Python process and all child FFmpeg processes - Suppress the Adviser - Leave alone partially downloaded file + if monitor_button_returned is theButtonsPauseLabel then + -- Try to kill the download processes but, ignore if process already gone - YTDL and yt-dlp have different process child-parent structures + -- Kill the adviser as it's not needed except for live streams - force kill because during auto-dowloads it cannot be terminated normally + -- Re-display the Monitor but with Resume instead of Stop + set monitor_state_flag to "Paused" + try + if is_Livestream_Flag_monitor is not "True" then + do shell script "kill -9 " & adviser_pid + end if + end try + + -- Both YTDL and yt-dlp spawn a child process + try + set ffmpeg_child_pid to do shell script "pgrep -P " & youtubedl_pid + end try + --yt-dlp often has an FFmpeg process which is a child of a child of youtubedl_pid - ignore any errors e.g. there is no child or grandchild process + try + if monitor_DL_Use_YTDLP is "yt-dlp" then + set ffmpeg_grandchild_pid to do shell script "pgrep -P " & ffmpeg_child_pid + end if + end try + -- Try to killl everything and ignore errors e.g. process doesn't exist + try + do shell script "kill " & ffmpeg_grandchild_pid + end try + try + do shell script "kill " & ffmpeg_child_pid + end try + try + do shell script "kill " & youtubedl_pid + end try + -- Now it returns to start of this repeat loop and redisplays Monitor but with different buttons + else if monitor_button_returned is theButtonsResumeLabel then + + -- Spawn another Monitor to resume download - this instance should die - YT-DLP will by default resume partially downloaded file + -- Need to form up content of myMonitorScriptAsString and my_params + -- Other variables might need some tweaking to get right + + -- Need to form up some variables to send to the next Monitor + set monitor_state_flag to "Resumed" + set ytdl_settings_monitor to (" " & ytdl_settings_monitor) + -- Trim extension off download filename and remove extraneous quotes - for log file name + set download_filename_new_monitor_noquotes_trimmed to text 2 thru ((download_filename_new_monitor's length) - (offset of "." in (the reverse of every character of download_filename_new_monitor) as text)) of download_filename_new_monitor + -- Remove extraneous quotes from download_filename_new_monitor and diag_Title_quoted_monitor which gets quoted in next call to Monitor.scpt - safer that way + if last character of diag_Title_quoted_monitor is "'" then + set diag_Title_quoted_monitor to text 2 through ((length of diag_Title_quoted_monitor) - 1) of diag_Title_quoted_monitor + end if + if last character of download_filename_new_monitor is "'" then + set download_filename_new_monitor to text 2 through ((length of download_filename_new_monitor) - 1) of download_filename_new_monitor + end if + set download_date_time to get_Date_Time() + set myMonitorScriptAsString to quoted form of ((POSIX path of path_to_MacYTDL) & "Contents/Resources/Scripts/Monitor.scpt") + set YTDL_log_file_resume to MacYTDL_preferences_path_monitor & "youtube-dl_log-" & download_filename_new_monitor_noquotes_trimmed & "-" & download_date_time & ".txt" + + set my_params to quoted form of downloadsFolder_Path_monitor & " " & quoted form of MacYTDL_preferences_path_monitor & " " & quoted form of YTDL_TimeStamps_monitor & " " & quoted form of ytdl_settings_monitor & " " & quoted form of URL_user_entered_monitor & " " & quoted form of YTDL_log_file_resume & " " & quoted form of download_filename_monitor & " " & quoted form of download_filename_new_monitor & " " & quoted form of MacYTDL_custom_icon_file_posix_monitor & " " & monitor_dialog_position & " " & quoted form of YTDL_simulate_log_monitor & " " & quoted form of diag_Title_quoted_monitor & " " & is_Livestream_Flag_monitor & " " & screen_width & " " & screen_height & " " & monitor_DL_Use_YTDLP & " " & quoted form of path_to_MacYTDL + + do shell script "osascript -s s " & myMonitorScriptAsString & " " & my_params & " " & " > /dev/null 2> /dev/null &" + -- Now return to beginning of repeat loop to re-display the Monitor dialog + + -- User clicked on the Stop download button - This kills the Python process and all child FFmpeg processes, then moves to Trash all ".part" files related to the download - Suppress the Adviser + else if monitor_button_returned is theButtonsStopLabel then + -- Try to kill the processes but, ignore if process already gone - YTDL and yt-dlp have different process child-parent structures + -- Kill the adviser as it's not needed except for live streams - force kill because during auto-dowloads it cannot be terminated normally + + set monitor_state_flag to "Stopped" + try + if is_Livestream_Flag_monitor is not "True" then + do shell script "kill -9 " & adviser_pid + end if + end try + + -- Both YTDL and yt-dlp spawn a child process + try + set ffmpeg_child_pid to do shell script "pgrep -P " & youtubedl_pid + end try + --yt-dlp often has an FFmpeg process which is a child of a child of youtubedl_pid - ignore any errors e.g. there is no child or grandchild process + try + if monitor_DL_Use_YTDLP is "yt-dlp" then + set ffmpeg_grandchild_pid to do shell script "pgrep -P " & ffmpeg_child_pid + end if + end try + -- Try to killl everything and ignore errors e.g. process doesn't exist + try + do shell script "kill " & ffmpeg_grandchild_pid + end try + try + do shell script "kill " & ffmpeg_child_pid + end try + try + do shell script "kill " & youtubedl_pid + end try + -- WORK IN PROGRESS - SOMETIMES FAILS TO DELETE PARTIAL FILES - BUT NOT SURE THAT'S A BAD THING + if download_finished is "No" then + -- Partly completed download process will leave behind "part" and/or "ytdl" files which are be moved to Trash if user wishes + -- Completed downloads should be left alone + -- Handle multiple downloads separately as the name for the file spec comes from simulate.txt instead of the download_filename_new_monitor variable + -- Need to trim off file extension in name search because YTDL sometimes has part files with part numbers between the name and the extension - works for 3 and 4 character extensions + if (download_filename_new_monitor_plain is "the multiple videos" or download_filename_new_monitor_plain is "the-playlist") and YTDL_Delete_Partial is "true" then + repeat with each_filename in (get paragraphs of YTDL_simulate_log_monitor) + set each_filename to text 1 thru -5 of each_filename + if each_filename does not contain "WARNING" then + set part_files to do shell script "find " & downloadsFolder_Path_monitor_quoted & " -maxdepth 1 -type f -iname *" & quoted form of each_filename & "*.part* -or -iname " & quoted form of each_filename & "*.ytdl*" + repeat with each_part_files in (get paragraphs of part_files) + do shell script "mv " & quoted form of each_part_files & " ~/.trash/" + end repeat + end if + end repeat + -- Handle ABC & SBS show pages separately as file names are not in simulate nor in download_filename_new_monitor but in download_filename_monitor + else if (YTDL_simulate_log_monitor contains "ERROR: Unsupported URL: https://iview" or YTDL_simulate_log_monitor contains "ERROR: Unsupported URL: https://www.sbs") and YTDL_Delete_Partial is "true" then + repeat with each_filename in (get paragraphs of download_filename_monitor) + set each_filename to text 1 thru -1 of each_filename + if each_filename does not contain "WARNING:" then + set part_files to do shell script "find " & downloadsFolder_Path_monitor_quoted & " -maxdepth 1 -type f -iname *" & (quoted form of each_filename) & "*part* -or -iname *" & (quoted form of each_filename) & "*.ytdl* -or -iname *" & (quoted form of each_filename) & "*-Frag* -or -iname *" & (quoted form of each_filename) & "*f???*" + repeat with each_part_files in (get paragraphs of part_files) + do shell script "mv " & quoted form of each_part_files & " ~/.trash/" + end repeat + end if + end repeat + -- All other kinds of download - Monitor currently cannot delete partly downloaded files left by batch download + else if download_filename_new_monitor is not "the saved batch" and is_Livestream_Flag_monitor is "False" and YTDL_Delete_Partial is "true" then + -- Look for all files in DL folder that meet file spec + set download_filename_monitor_trimmed to text 1 thru -5 of download_filename_monitor + set part_files to do shell script "find " & downloadsFolder_Path_monitor_quoted & " -maxdepth 1 -type f -iname *" & (quoted form of download_filename_monitor_trimmed) & "*part* -or -iname *" & (quoted form of download_filename_monitor_trimmed) & "*.ytdl* -or -iname *" & (quoted form of download_filename_monitor_trimmed) & "*-Frag* -or -iname *" & (quoted form of download_filename_monitor_trimmed) & "*f???*" + repeat with each_part_files in (get paragraphs of part_files) + do shell script "mv " & quoted form of each_part_files & " ~/.trash/" + end repeat + end if + end if + exit repeat + + -- Open log folder and continue to display Monitor - Would be nice to open log file for currently downloading file – the Adviser has code for that + else if monitor_button_returned is theButtonsLogLabel then + tell application "Finder" + activate + open (MacYTDL_preferences_path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + -- end if + + else if monitor_button_returned is theButtonsCloseLabel then + exit repeat + end if + + + -- Check whether the download has finished - if it has, the download process has gone and a "ps" command will bang an error - keep monitor open if user paused DL + -- This try/on error block checks for presence of the "ets" process - that's the pid returned by the do shell script which starts the downloads + if monitor_state_flag is not "Paused" then + try + -- does the PID exist? + do shell script "ps -p " & youtubedl_pid + on error + exit repeat + end try + end if + end repeat + end if + + + + + + -- on error errMsg + -- display dialog errMsg + -- end try + + + + +end run + +-- Handler to show Monitor dialog for parallel downloads +on show_parallel_Monitor(download_logfile_Parallel_List, download_filename_Parallel_List, pathToBundleShort, MacYTDL_custom_icon_file_posix_monitor, X_position_monitor, Y_position_monitor, ytdl_parallel_pid, MacYTDL_preferences_path_monitor, batch_parallel_flag, downloadsFolder_Path_monitor, YTDL_Delete_Partial) + + -- Set text for localization + set theProgressLabel to localized string "Progress:" in bundle file pathToBundleShort from table "MacYTDL" + set theProgressingLabel to localized string "Progressing" in bundle file pathToBundleShort from table "MacYTDL" + set theDownloadInLabel to localized string "downloaded in" in bundle file pathToBundleShort from table "MacYTDL" + set theDownloadOfLabel to localized string "downloaded of" in bundle file pathToBundleShort from table "MacYTDL" + set theMinutesLabel to localized string "minutes." in bundle file pathToBundleShort from table "MacYTDL" + set theInLabel to localized string "in" in bundle file pathToBundleShort from table "MacYTDL" + set theOKLabel to localized string "OK" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsPauseLabel to localized string "Pause" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsResumeLabel to localized string "Resume" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsLogLabel to localized string "Log" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsStopLabel to localized string "Stop" in bundle file pathToBundleShort from table "MacYTDL" + set theButtonsCloseLabel to localized string "Close" in bundle file pathToBundleShort from table "MacYTDL" + set theRunningLabel to localized string "Running" in bundle file pathToBundleShort from table "MacYTDL" + set thePercentSymbolLabel to localized string "%" in bundle file pathToBundleShort from table "MacYTDL" + set theMBSymbolLabel to localized string "MB" in bundle file pathToBundleShort from table "MacYTDL" + set theGBSymbolLabel to localized string "GB" in bundle file pathToBundleShort from table "MacYTDL" + + -- Prepare and display the download monitor dialog - set starting variables + set seconds_running to 0 + set time_running to 0 + set progress_percentage to "" + set downloadFileSize to "" + set monitor_diag_Title to "MacYTDL" + -- set diag_intro_text_1 to theMonitorIntroTextLabel1 & " \"" & download_filename_new_monitor_plain & "\" " & theMonitorIntroTextLabel2 + set accViewWidth to 150 + set accViewInset to 0 + set the_date_start to current date + set the_time_start to time of the_date_start + set number_of_downloads to number of items in download_logfile_Parallel_List + + -- Initialise counter to track completed downloads + set download_completed_flag to {} + repeat (number_of_downloads) times + set end of download_completed_flag to "" + end repeat + + -- Set buttons + set {theButtons, minWidth} to create buttons {theButtonsLogLabel, theButtonsStopLabel, theButtonsCloseLabel} button keys {"l", "S", ""} cancel button 3 + if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit + + -- It can take time for log file to get content - delay Monitor a bit + delay 2 + + -- Repeat loop to display monitor every 3 seconds (delay is set in "create enhanced window"), update with progress, redisplay - can close dialog, stop download or open logs folder + repeat + + -- Need to reset diag_progress_text after showing the dialog for each iteration + set diag_progress_text to "" + + -- Nest another repeat loop which iterates through the multiple log files to get progress on each download them format that into the one Monitor dialog + -- Find last line of each log file, add to diag_progress_text [a string] which will be shown in Monitor dialog + repeat with x from 1 to number_of_downloads + + set download_filename_truncated to (item x of download_filename_Parallel_List) + set playlist_name to "" + -- Trim playlist details from download filename + if download_filename_truncated contains "#$" then + set AppleScript's text item delimiters to {"#$"} + set playlist_name to text item 1 of download_filename_truncated + set download_filename_truncated to text item 2 of download_filename_truncated + set AppleScript's text item delimiters to {""} + end if + if length of download_filename_truncated is greater than 35 then + set download_filename_truncated to text 1 thru 35 of download_filename_truncated & "..." + end if + set download_filename_truncated to replace_chars(download_filename_truncated, "_", " ") -- So that file name in Monitor dialog looks better and takes less space + + set YTDL_log_file_monitor to item x of download_logfile_Parallel_List + set YTDL_log_file_monitor_posix to POSIX file YTDL_log_file_monitor + + -- Get YTDL log up to this point - if file is empty, Monitor will show "Progressing" + set size_of_log to get eof YTDL_log_file_monitor_posix + if size_of_log is less than 5 then + set YTDL_log to "No log" + else + try + set YTDL_log to read file YTDL_log_file_monitor_posix as text + on error errMsg + display dialog "Error in Monitor reading log file: " & YTDL_log_file_monitor_posix & return & "Error message: " & errMsg + end try + end if + + -- Get time running since start, convert into minutes + set the_time to time of (current date) + set seconds_running to the_time - the_time_start + set time_running to seconds_running / minutes + set round_factor to 0.1 + set time_running to (round time_running / round_factor) * round_factor + + --A default display when there are no progress details available in log file + set progress_percentage to "" + set diag_intro_text_2 to download_filename_truncated & return & theProgressingLabel + + if item x of download_completed_flag is true then + set diag_intro_text_2 to download_filename_truncated & return & "Completed" + end if + + -- Use content of log to fashion text to appear in Monitor dialog - log file always has a blank paragraph at end - so, need to find the second last paragraph for latest progress report + if YTDL_log is not "No log" then + set YTDL_log_lastParapraph to paragraph -2 of YTDL_log + -- If progress meter available, get current percentage and file size - trim leading spaces from percentage - convert [MiB to MB]/[GiB to GB] in file size to match Finder + if YTDL_log_lastParapraph contains "[download]" and YTDL_log_lastParapraph contains "%" and YTDL_log_lastParapraph contains "at" then + set progress_percentage to last word in (text 1 thru (offset of "%" in YTDL_log_lastParapraph) of YTDL_log_lastParapraph) + set o to (offset of "." in progress_percentage) + if ((o > 0) and (0.0 as text is "0,0")) then set progress_percentage to (text 1 thru (o - 1) of progress_percentage & "," & text (o + 1) thru -1 of progress_percentage) + -- YTDL Progress meter reports estimated size of download in GiB or MiB + set GiBPositionAfterSize to offset of "GiB" in YTDL_log_lastParapraph -- Crude but does work + if GiBPositionAfterSize is not 0 then + set downloadFileSizeGiB to last word in (text 22 thru (GiBPositionAfterSize - 1) of YTDL_log_lastParapraph) + set approxIndicator to character 1 of downloadFileSizeGiB + if approxIndicator is "~" then + set downloadFileSizeGiB to text 2 thru end of downloadFileSizeGiB + set o to (offset of "." in downloadFileSizeGiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeGiB to (text 1 thru (o - 1) of downloadFileSizeGiB & "," & text (o + 1) thru -1 of downloadFileSizeGiB) + set downloadFileSizeGiB to downloadFileSizeGiB as number + set downloadFileSizeGB to downloadFileSizeGiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeGB to (round downloadFileSizeGB / round_factor) * round_factor + else + set approxIndicator to "" + set o to (offset of "." in downloadFileSizeGiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeGiB to (text 1 thru (o - 1) of downloadFileSizeGiB & "," & text (o + 1) thru -1 of downloadFileSizeGiB) + set downloadFileSizeGiB to downloadFileSizeGiB as number + set downloadFileSizeGB to downloadFileSizeGiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeGB to (round downloadFileSizeGB / round_factor) * round_factor + end if + set diag_intro_text_2 to download_filename_truncated & return & progress_percentage & thePercentSymbolLabel & " " & theDownloadOfLabel & " " & approxIndicator & downloadFileSizeGB & theGBSymbolLabel + else + set MiBPositionAfterSize to offset of "MiB" in YTDL_log_lastParapraph + set downloadFileSizeMiB to last word in (text 22 thru (MiBPositionAfterSize - 1) of YTDL_log_lastParapraph) + set approxIndicator to character 1 of downloadFileSizeMiB + if approxIndicator is "~" then + set downloadFileSizeMiB to text 2 thru end of downloadFileSizeMiB + set o to (offset of "." in downloadFileSizeMiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeMiB to (text 1 thru (o - 1) of downloadFileSizeMiB & "," & text (o + 1) thru -1 of downloadFileSizeMiB) + set downloadFileSizeMiB to downloadFileSizeMiB as number + set downloadFileSizeMB to downloadFileSizeMiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeMB to (round downloadFileSizeMB / round_factor) * round_factor + else + set approxIndicator to "" + set o to (offset of "." in downloadFileSizeMiB) + if ((o > 0) and (0.0 as text is "0,0")) then set downloadFileSizeMiB to (text 1 thru (o - 1) of downloadFileSizeMiB & "," & text (o + 1) thru -1 of downloadFileSizeMiB) + set downloadFileSizeMiB to downloadFileSizeMiB as number + set downloadFileSizeMB to downloadFileSizeMiB * 1.04858 as number + set round_factor to 0.01 + set downloadFileSizeMB to (round downloadFileSizeMB / round_factor) * round_factor + end if + set diag_intro_text_2 to download_filename_truncated & return & progress_percentage & thePercentSymbolLabel & " " & theDownloadOfLabel & " " & approxIndicator & downloadFileSizeMB & theMBSymbolLabel + end if + else if YTDL_log_lastParapraph contains "[Merger] Merging formats into" then + set diag_intro_text_2 to download_filename_truncated & return & "FFmpeg merging formats ...." + else if YTDL_log_lastParapraph contains "[VideoConvertor] Converting video from" then + set diag_intro_text_2 to download_filename_truncated & return & "Converting download ...." + else if YTDL_log_lastParapraph contains "[ThumbnailsConvertor] Converting thumbnail" then + set diag_intro_text_2 to download_filename_truncated & return & "Converting thumbnail ...." + else if YTDL_log_lastParapraph contains "[EmbedThumbnail] mutagen:" then + set diag_intro_text_2 to download_filename_truncated & return & "Embedding thumbnail ...." + else if YTDL_log_lastParapraph contains "[ExtractAudio] Destination:" then + set diag_intro_text_2 to download_filename_truncated & return & "Extracting audio ...." + else if YTDL_log_lastParapraph contains "[ffmpeg] Fixing malformed" then + set diag_intro_text_2 to download_filename_truncated & return & "FFmpeg fixing bitstream ...." + else if YTDL_log_lastParapraph contains "[ffmpeg] Merging formats into" then + set diag_intro_text_2 to download_filename_truncated & return & "FFmpeg merging formats ...." + else if YTDL_log_lastParapraph contains "[FixupM3u8] Fixing" then + set diag_intro_text_2 to download_filename_truncated & return & "Fixing container ...." + else if YTDL_log_lastParapraph contains "[info] Downloading video thumbnail" or YTDL_log_lastParapraph contains "[info] Writing video thumbnail" then + set diag_intro_text_2 to download_filename_truncated & return & "Writing thumbnail ...." + else if YTDL_log_lastParapraph contains "[debug] Invoking downloader on" then + set diag_intro_text_2 to download_filename_truncated & return & "Starting download ...." + else if YTDL_log_lastParapraph contains "[debug] ffmpeg command line" then + set diag_intro_text_2 to download_filename_truncated & return & (theRunningLabel & " FFmpeg ....") + else if YTDL_log contains "size= " then + -- FFMpeg regularly reports amount downloaded - find latest report - convert kibibytes to kilobytes to match size reported by Finder + set numParasInlog to count of paragraphs in YTDL_log + repeat with i from 1 to numParasInlog + set lastParaInlog to paragraph (-i) of YTDL_log + if lastParaInlog contains "size=" then + set offsetOfSize to offset of "size" in lastParaInlog + set sizeOfDownloadProgress to text (offsetOfSize + 5) thru (offsetOfSize + 12) of lastParaInlog + set sizeOfDownloadProgress to (sizeOfDownloadProgress * 1.024) as integer + exit repeat + else + set i to i + 1 + end if + end repeat + set sizeOfdownloadProgressDelimited to convertNumberToCommaDelimitedString(sizeOfDownloadProgress) + set diag_intro_text_2 to download_filename_truncated & return & " " & sizeOfdownloadProgressDelimited & "KB" + end if + end if + -- Form up diag_progress_text which will be shown in Monitor dialog - hold progress details from all the log files + set diag_progress_text to diag_progress_text & diag_intro_text_2 & return + end repeat + + -- Set variables for Monitor dialog which need to be updated with each repeat + -- set {intro_label2, theTop} to create label diag_progress_text left inset 0 bottom 5 max width minWidth - 20 aligns center aligned control size mini size with multiline + set {intro_label2, theTop} to create label diag_progress_text left inset 0 bottom 1 max width accViewWidth aligns center aligned control size mini size without multiline + set intro_label2_thTop to theTop + + if playlist_name is "" then + set diag_intro_text_1 to localized string "Parallel download:" in bundle file pathToBundleShort from table "MacYTDL" + else + set diag_intro_text_1 to localized string "Parallel download of playlist:" in bundle file pathToBundleShort from table "MacYTDL" + end if + if batch_parallel_flag is true then set diag_intro_text_1 to localized string "Parallel download of batch:" in bundle file pathToBundleShort from table "MacYTDL" + set {intro_label1, theTop} to create label diag_intro_text_1 left inset 35 bottom theTop + 10 max width minWidth - 51 control size small size + set intro_label1_thTop to theTop + if (intro_label1_thTop - intro_label2_thTop) < 25 then set theTop to (theTop + 12) -- Calculate height added by intro_label1 + + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix_monitor left inset 0 bottom theTop - 30 view width 30 view height 30 scale image scale proportionally + + -- Display the monitor dialog - set giving up @ 3 seconds so that code can continue the repeat loop + set {monitor_button_returned, buttonNumber, controlResults, finalPosition} to display enhanced window monitor_diag_Title buttons theButtons giving up after 3 acc view width accViewWidth acc view height theTop acc view controls {intro_label2, intro_label1, MacYTDL_icon} initial position {X_position_monitor, Y_position_monitor} + + if monitor_button_returned is theButtonsStopLabel then + -- Try to kill the processes but, ignore if process already gone - YTDL and yt-dlp have different process child-parent structures + -- Repeat through all the parent processes - kill them and all the child processes + repeat with x from 1 to number_of_downloads + set youtubedl_pid to (item x of ytdl_parallel_pid) + try + set ffmpeg_child_pid to do shell script "pgrep -P " & youtubedl_pid + end try + --yt-dlp often has an FFmpeg process which is a child of a child of youtubedl_pid - ignore any errors e.g. there is no child or grandchild process + try + if monitor_DL_Use_YTDLP is "yt-dlp" then + set ffmpeg_grandchild_pid to do shell script "pgrep -P " & ffmpeg_child_pid + end if + end try + -- Try to killl everything and ignore errors e.g. process doesn't exist + try + do shell script "kill " & ffmpeg_grandchild_pid + end try + try + do shell script "kill " & ffmpeg_child_pid + end try + try + do shell script "kill " & youtubedl_pid + end try + -- Get filename, clean it and try to move all related partial files to trash + if YTDL_Delete_Partial is "true" then + set download_filename to (item x of download_filename_Parallel_List) + -- Trim playlist details from download filename + if download_filename contains "#$" then + set AppleScript's text item delimiters to {"#$"} + set download_filename to text item 2 of download_filename + set AppleScript's text item delimiters to {""} + end if + set download_filename to replace_chars(download_filename, "_", " ") -- So that file name in Monitor dialog looks better and takes less space + -- Look for all files in DL folder that meet file spec - remove file extensions + set download_filename_trimmed to text 1 thru -5 of download_filename + set part_files to do shell script "find " & downloadsFolder_Path_monitor & " -maxdepth 1 -type f -iname *" & (quoted form of download_filename_trimmed) & "*part* -or -iname *" & (quoted form of download_filename_trimmed) & "*ytdl* -or -iname *" & (quoted form of download_filename_trimmed) & "*-Frag* -or -iname *" & (quoted form of download_filename_trimmed) & "*f???*" + repeat with each_part_files in (get paragraphs of part_files) + do shell script "mv " & quoted form of each_part_files & " ~/.trash/" + end repeat + end if + end repeat + + -- Open log folder and continue to display Monitor + else if monitor_button_returned is theButtonsLogLabel then + tell application "Finder" + activate + open (MacYTDL_preferences_path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + + -- User clicked on Close - close Monitor but continue downloads + else if monitor_button_returned is theButtonsCloseLabel then + exit repeat + end if + + -- Report back when all processes have finished - crude but works + set process_finished_count to 0 + repeat with x from 1 to number_of_downloads + try + -- does the PID exist? + do shell script "ps -p" & (item x of ytdl_parallel_pid) + on error + set process_finished_count to process_finished_count + 1 + set item x of download_completed_flag to true + end try + end repeat + -- If all processes have finished, close Monitor dialog - show Adviser but not if user stopped the download - Kill Monitor which otherwise will stay on screen for 3 seconds thus perhaps overlapping the Adviser alert + if process_finished_count is number_of_downloads then + if monitor_button_returned is not theButtonsStopLabel then + -- Need a way to close the Monitor dialog so it no longer underlies the Adviser + show_Adviser(pathToBundleShort, theButtonsCloseLabel, downloadsFolder_Path_monitor, download_logfile_Parallel_List) + end if + exit repeat + end if + + -- This ends the repeat loop which shows the Monitor - Monitor has closed because user clicked on "Close" or because downloads have finished - now return to on run() + end repeat + +end show_parallel_Monitor + +-- Handler to show an advice that downloads have finished +on show_Adviser(pathToBundleShort, theButtonsCloseLabel, downloadsFolder_Path_monitor, download_logfile_Parallel_List) + set alerterPath to quoted form of (POSIX path of (pathToBundleShort & "Contents:Resources:")) + -- Try to reduce Advsier overlapping with Monitor – don't know why/how they can be displayed at same time ! + delay 1 + -- Check log files for errors + set error_count to 0 + set number_of_downloads to number of items in download_logfile_Parallel_List + repeat with y from 1 to number_of_downloads + set final_logfile to item y of download_logfile_Parallel_List + set final_logfile_posix to POSIX file final_logfile + try + set YTDL_log to read file final_logfile_posix as text + on error errMsg + display dialog "Error in Monitor reading log file: " & final_logfile & return & "Error message: " & errMsg + end try + if YTDL_log contains "ERROR: " then set error_count to (error_count + 1) + -- if YTDL_log does not contain "ERROR: " then set error_count to (error_count + 1) -- For testing the alert + end repeat + + -- set subtitleText to quoted form of ("“" & download_filename_new_monitor_plain & "”") -- Might be able to provide playlist name or similar + if error_count is greater than 0 then + set theAdviserTextLabel1 to quoted form of (localized string "There was an error in the download." in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserTextLabel2 to quoted form of (localized string "Click to open downloads folder" in bundle file pathToBundleShort from table "MacYTDL") + set subtitleText to quoted form of ((localized string "There were errors with" in bundle file pathToBundleShort from table "MacYTDL") & " " & error_count & " " & (localized string "files" in bundle file pathToBundleShort from table "MacYTDL") & ".") + else + set subtitleText to quoted form of ((number_of_downloads as string) & (localized string " downloads." in bundle file pathToBundleShort from table "MacYTDL")) + set theAdviserTextLabel1 to quoted form of (localized string "MacYTDL parallel download finished:" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserTextLabel2 to quoted form of (localized string "Click to open downloads folder" in bundle file pathToBundleShort from table "MacYTDL") + end if + -- Might add actions when able to play one of the downloads + --set theAdviserButtonsCloseLabel2 to localized string "Play" in bundle file pathToBundleShort from table "MacYTDL" + -- set adviser_button to do shell script alerterPath & "/alerter -message " & theAdviserTextLabel2 & " -title " & theAdviserTextLabel1 & " -subtitle " & subtitleText & " -closeLabel " & theButtonsCloseLabel & " -timeout 10 -sender com.apple.script.id.MacYTDL -actions " & theAdviserButtonsCloseLabel2 + set adviser_button to do shell script alerterPath & "/alerter -message " & theAdviserTextLabel2 & " -title " & theAdviserTextLabel1 & " -subtitle " & subtitleText & " -actions " & theButtonsCloseLabel & " -timeout 10 -sender com.apple.script.id.MacYTDL" + if adviser_button is "@CONTENTCLICKED" then + tell application "Finder" + activate + open (downloadsFolder_Path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + end if +end show_Adviser + +-- Handler to find-replace text inside a string +on replace_chars(this_text, search_string, replacement_string) + set AppleScript's text item delimiters to the search_string + set the item_list to every text item of this_text + set AppleScript's text item delimiters to the replacement_string + set this_text to the item_list as string + set AppleScript's text item delimiters to "" + return this_text +end replace_chars +-- Handler to add comma delimiters to a number +on convertNumberToCommaDelimitedString(theNumber) + set theNumber to theNumber as string + set theNumberLength to length of theNumber + set theNumber to (reverse of every character of theNumber) as string + set commaDelimitedNumber to "" + repeat with a from 1 to theNumberLength + if a is theNumberLength or (a mod 3) is not 0 then + set commaDelimitedNumber to (character a of theNumber & commaDelimitedNumber) as string + else + set commaDelimitedNumber to ("," & character a of theNumber & commaDelimitedNumber) as string + end if + end repeat + return commaDelimitedNumber +end convertNumberToCommaDelimitedString +-- Handler to get and format current date-time - needs all special characters replaced with underscores +on get_Date_Time() + set download_date_time to (current date) as string + set AppleScript's text item delimiters to {", ", " ", ":", ","} + set the item_list to every text item of download_date_time + set AppleScript's text item delimiters to "_" + set download_date_time to the item_list as string + set AppleScript's text item delimiters to "" + return download_date_time +end get_Date_Time diff --git a/Code/Utilities.applescript b/Code/Utilities.applescript new file mode 100644 index 0000000..60879a6 --- /dev/null +++ b/Code/Utilities.applescript @@ -0,0 +1,2338 @@ +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- MacYTDL +-- A GUI for the Python Scripts youtube-dl and yt-dlp. Many thanks to Shane Stanley. +-- This is contains utilities for installing components etc. +-- Handlers in this script are called by main.scpt +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- Include libraries +use AppleScript version "2.4" -- Yosemite (10.10) or later +use scripting additions +use script "DialogToolkitMacYTDL" +property parent : AppleScript + +-- Define variables to be filled by the read_settings() handler below - makes these variables available to main.scpt +global DL_audio_only +global DL_audio_codec +global DL_YTDL_auto_check +global DL_description +global downloadsFolder_Path +global resourcesPath +global DL_format +global DL_Remux_original +global DL_over_writes +global DL_Remux_format +global DL_subtitles_format +global DL_subtitles +global DL_STLanguage +global DL_STEmbed +global DL_YTAutoST +global DL_Thumbnail_Embed +global DL_Thumbnail_Write +global DL_verbose +global DL_Limit_Rate +global DL_Limit_Rate_Value +global DL_Show_Settings +global DL_Add_Metadata +global DL_Cookies_Location +global DL_Use_Cookies +global DL_Proxy_URL +global DL_Use_Proxy +global DL_Use_YTDLP +global DL_TimeStamps +global DL_Use_Custom_Template +global DL_Custom_Template +global DL_Use_Custom_Settings +global DL_Custom_Settings +global DL_Saved_Settings_Location +global DL_Settings_In_Use +global DL_QT_Compat +global DL_formats_list +global DL_discard_URL +global DL_Resolution_Limit +global DL_Dont_Use_Parts +global DL_Parallel +global DL_No_Warnings +global DL_Delete_Partial +global YTDL_version +global DL_auto +global window_Position +global myNum +global SBS_show_URLs +global SBS_show_name +global ABC_show_URLs +global ABC_show_name +global file_formats_selected +global add_to_output_template +global ffmpeg_version +global ffprobe_version + + +-- On run handler in case I need to use it in the auto-download process +-- handler_to_run would be passed from the Service +--on run {handler_to_run} +-- display dialog "This should not appear !!" +--end run + + +--------------------------------------------------- +-- +-- Auto-download +-- +-- Might move this to a separate script file one day so +-- Service doesn't need to load all the other handlers in this script file +-- +--------------------------------------------------- + +-- Handler called by Service to do the auto download +on auto_Download(MacYTDL_prefs_file, URL_user_entered_clean, path_to_MacYTDL) + + + -- try + + read_settings(MacYTDL_prefs_file) + set DL_format to localized string DL_format from table "MacYTDL" + set DL_subtitles_format to localized string DL_subtitles_format from table "MacYTDL" + set DL_Remux_format to localized string DL_Remux_format from table "MacYTDL" + set theBestLabel to localized string "Best" from table "MacYTDL" + set DL_audio_codec to localized string DL_audio_codec from table "MacYTDL" + set DL_Show_Settings to false + + -- ***************************************************************************** + -- These preliminary bits might end up in a separate handler which is also called by Main - to reduce duplication + -- ***************************************************************************** + + set path_to_Main to (path_to_MacYTDL & ":Contents:Resources:Scripts:Main.scpt") as alias + + -- ***************************************************************************** + -- Just loading main.scpt until a better way is settled - probably an osascript call into background + set run_Main_handlers to load script path_to_Main + -- ***************************************************************************** + + set resourcesPath to POSIX path of (path_to_MacYTDL & ":Contents:Resources:") + set shellPath to "PATH=$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin:~/opt/bin:~/opt/sbin:/opt/local/bin:/opt/local/sbin:" & quoted form of (POSIX path of (path_to_MacYTDL & "::")) & "; " + set MacYTDL_preferences_folder to "Library/Preferences/MacYTDL/" + set MacYTDL_preferences_path to (POSIX path of (path to home folder) & MacYTDL_preferences_folder) + set YTDL_simulate_file to MacYTDL_preferences_path & "ytdl_simulate.txt" + -- set monitor_dialog_position to 0 + set bundle_file to (path_to_MacYTDL & ":contents:Info.plist") as string + tell application "System Events" + set MacYTDL_copyright to value of property list item "NSHumanReadableCopyright" of contents of property list file bundle_file + set MacYTDL_version to value of property list item "CFBundleShortVersionString" of contents of property list file bundle_file + end tell + set MacYTDL_date_position to (offset of "," in MacYTDL_copyright) + 2 + set MacYTDL_date to text MacYTDL_date_position thru end of MacYTDL_copyright + set MacYTDL_date_day to word 1 of MacYTDL_date + set MacYTDL_date_month to word 2 of MacYTDL_date + set MacYTDL_date_year to word 3 of MacYTDL_date + set thedateLabel to localized string MacYTDL_date_month from table "MacYTDL" + set MacYTDL_date to MacYTDL_date_day & " " & thedateLabel & " " & MacYTDL_date_year + set theVersionLabel to localized string "Version" from table "MacYTDL" + set diag_Title to "MacYTDL, " & theVersionLabel & " " & MacYTDL_version & ", " & MacYTDL_date + -- Set path and name for custom icon for dialogs + set MacYTDL_custom_icon_file to (path_to_MacYTDL & ":Contents:Resources:macytdl.icns") + -- Set path and name for custom icon for enhanced window statements + set MacYTDL_custom_icon_file_posix to POSIX path of MacYTDL_custom_icon_file + set screen_size to run_Main_handlers's get_screensize() + set X_position to item 1 of screen_size as integer + set Y_position to item 2 of screen_size as integer + set screen_width to item 3 of screen_size as integer + set screen_height to item 4 of screen_size as integer + + -- Trim any trailing spaces from URL entered by user - reduces errors later on + if URL_user_entered_clean is not "" and URL_user_entered_clean is not " " then + if text item -1 of URL_user_entered_clean is " " then set URL_user_entered_clean to text 1 thru -2 of URL_user_entered_clean + end if + set URL_user_entered to quoted form of URL_user_entered_clean -- Quoted form needed in case the URL contains ampersands etc - but really need to get quoted form of each URL when more than one + -- Convert settings to format that can be used as youtube-dl/yt-dlp parameters + define variables + if DL_description is true then + set YTDL_description to "--write-description " + else + set YTDL_description to "" + end if + set YTDL_audio_only to "" + set YTDL_audio_codec to "" + if DL_over_writes is true and DL_Use_YTDLP is "YT-DLP" then + set YTDL_over_writes to "--force-overwrites " + else + set YTDL_over_writes to "" + end if + + set YTDL_subtitles to "" + set YTDL_credentials to "" + set DL_batch_status to false + + if DL_STEmbed is true then + set YTDL_STEmbed to "--embed-subs " + else + set YTDL_STEmbed to "" + end if + -- Prepare User's download settings - using current settings - yt-dlp prefers to have name of post processor + if DL_Remux_format is not "No remux" then + if DL_Use_YTDLP is "yt-dlp" then + set YTDL_remux_format to "--recode-video " & DL_Remux_format & " " & "--postprocessor-args \"ffmpeg:-codec copy\" " + else + set YTDL_remux_format to "--recode-video " & DL_Remux_format & " " & "--postprocessor-args \"-codec copy\" " + end if + else + set YTDL_remux_format to "" + end if + if DL_Remux_original is true then + set YTDL_Remux_original to "--keep-video " + else + set YTDL_Remux_original to "" + end if + -- Set YTDL format parameter desired format + set separate YTDL_format_pref variable for use in simulate stage + if DL_format is not "Default" then + set YTDL_format to "-f bestvideo[ext=" & DL_format & "]+bestaudio/best[ext=" & DL_format & "]/best " + set YTDL_format_pref to "-f " & DL_format & " " + else + set YTDL_format_pref to "" + set YTDL_format to "" + end if + -- Set format sort parameter to desired maximum - not used in Simulate + if DL_Resolution_Limit is "Best" then + set YTDL_Resolution_Limit to "" + else + set YTDL_Resolution_Limit to "-S \"res:" & DL_Resolution_Limit & "\" " + end if + if DL_Thumbnail_Embed is true then + set YTDL_Thumbnail_Embed to "--embed-thumbnail " + else + set YTDL_Thumbnail_Embed to "" + end if + if DL_Thumbnail_Write is true then + set YTDL_Thumbnail_Write to "--write-thumbnail " + else + set YTDL_Thumbnail_Write to "" + end if + if DL_verbose is true then + set YTDL_verbose to "--verbose " + else + set YTDL_verbose to "" + end if + if DL_TimeStamps is true then + set YTDL_TimeStamps to resourcesPath & "ets" + else + set YTDL_TimeStamps to "" + end if + if DL_Limit_Rate is true then + set YTDL_limit_rate_value to ("--limit-rate " & DL_Limit_Rate_Value & "m ") + else + set YTDL_limit_rate_value to "" + end if + if DL_Add_Metadata is true then + set YTDL_metadata to "--add-metadata " + else + set YTDL_metadata to "" + end if + if DL_No_Warnings is true then + set YTDL_No_Warnings to "--no-warnings " + else + set YTDL_No_Warnings to "" + end if + if DL_Dont_Use_Parts is true then + set YTDL_Use_Parts to "--no-part " + else + set YTDL_Use_Parts to "" + end if + if DL_Use_Proxy is true then + set YTDL_Use_Proxy to ("--proxy " & DL_Proxy_URL & " ") + else + set YTDL_Use_Proxy to "" + end if + if DL_Use_Cookies is true then + set YTDL_Use_Cookies to ("--cookies " & DL_Cookies_Location & " ") + else + set YTDL_Use_Cookies to "" + end if + if DL_Use_Custom_Settings is true then + set YTDL_Custom_Settings to (DL_Custom_Settings & " ") + else + set YTDL_Custom_Settings to "" + end if + if DL_Use_Custom_Template is true then + set YTDL_Custom_Template to DL_Custom_Template + else + set YTDL_Custom_Template to "" + end if + -- If user wants QT compatibility, must turn off remux + if DL_QT_Compat is true then + set YTDL_QT_Compat to "--recode-video \"mp4\" --ppa \"VideoConvertor:-vcodec libx264 -acodec aac\"" + set YTDL_remux_format to "" + else + set YTDL_QT_Compat to "" + end if + + set YTDL_no_part to "" + + -- Set settings to enable audio only download - gets a format list - use post-processing if necessary - need to ignore all errors here which are usually due to missing videos etc. + if DL_audio_only is true then + try + set YTDL_get_formats to do shell script shellPath & DL_Use_YTDLP & " --list-formats --ignore-errors " & URL_user_entered & " 2>&1" + on error errStr + set YTDL_get_formats to errStr + end try + -- To get a straight audio-only download - rely on YTDL to get best available audio only file - if user also requests remux, container will contain audio in best format + if YTDL_get_formats contains "audio only" and DL_audio_codec is theBestLabel then + set YTDL_audio_only to "--format bestaudio " + set YTDL_format to "" + else + -- If audio only file not available and/or user wants specific format, extract audio only file in desired format from best container and, if needed, convert in post-processing to desired format + set YTDL_audio_codec to "--extract-audio --audio-format " & DL_audio_codec & " --audio-quality 0 " + end if + end if + + -- Generalise the DL_Use_YTDLP variable - only need the legacy form when updating the YT-DLP script + if DL_Use_YTDLP is "yt-dlp-legacy" then + set DL_Use_YTDLP to "yt-dlp" + else + set DL_Use_YTDLP to DL_Use_YTDLP + end if + + set theButtonOKLabel to localized string "OK" from table "MacYTDL" + set theButtonCancelLabel to localized string "Cancel" from table "MacYTDL" + set theButtonDownloadLabel to localized string "Download" from table "MacYTDL" + set theButtonReturnLabel to localized string "Return" from table "MacYTDL" + set theButtonQuitLabel to localized string "Quit" from table "MacYTDL" + set theButtonContinueLabel to localized string "Continue" from table "MacYTDL" + set path_to_MacYTDL to (path_to_MacYTDL & ":") + + set skip_Main_dialog to true + + run_Main_handlers's check_download_folder(downloadsFolder_Path, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, diag_Title, MacYTDL_custom_icon_file, skip_Main_dialog) + if DL_Use_Cookies is true then run_Main_handlers's check_cookies_file(DL_Cookies_Location) + + + -- ***************************************************************************** + -- download_video might end up being moved to Utilities + -- ***************************************************************************** + + run_Main_handlers's download_video(shellPath, path_to_MacYTDL, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, screen_width, screen_height, YTDL_simulate_file, URL_user_entered, URL_user_entered_clean, downloadsFolder_Path, diag_Title, DL_batch_status, DL_Remux_format, DL_subtitles, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format_pref, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, skip_Main_dialog, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, theButtonReturnLabel, theButtonQuitLabel, theButtonContinueLabel, YTDL_QT_Compat, DL_Use_YTDLP, theBestLabel, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + + -- on error errMsg + -- display dialog "Error in auto_Download handler: " & errMsg + -- end try + + +end auto_Download + + +-- If version of DTP library is old, replace with new - called on startup - uses short version +on check_DTP(DTP_file, path_to_MacYTDL) + set DTP_library_MacYTDL to quoted form of ((POSIX path of path_to_MacYTDL) & "Contents/Resources/Script Libraries/DialogToolkitMacYTDL.scptd") + set libraries_folder to quoted form of (POSIX path of (path to home folder) & "Library/Script Libraries/") + set libraries_folder_nonposix to text 3 thru -2 of (POSIX path of libraries_folder) + set DTP_library_MacYTDL_trimmed to text 2 thru -2 of DTP_library_MacYTDL + set DTP_library_MacYTDL_trimmed_nonposix to POSIX file DTP_library_MacYTDL_trimmed as string + set alias_new_DTP_file to DTP_library_MacYTDL_trimmed_nonposix as alias + set alias_DTP_file to DTP_file as alias + tell application "System Events" + set old_DTP_version to get the short version of alias_DTP_file + set new_DTP_version to get the short version of alias_new_DTP_file + end tell + if old_DTP_version is not new_DTP_version then + do shell script "rm -R " & (quoted form of (POSIX path of DTP_file)) + do shell script "cp -a " & DTP_library_MacYTDL & " " & libraries_folder + end if +end check_DTP + + +--------------------------------------------------- +-- +-- Install youtube-dl/yt-dlp +-- +--------------------------------------------------- + +-- Handler to install yt-dlp - install if user agrees but can't run MacYTDL without it - when needed is called by main thread before Main dialog displayed - Return the version and name of tool installed - Not called if user has Homebrew +-- v1.24 - No longer installing youtube-dl - but, note, users who have it can keep it +on check_ytdl_installed(usr_bin_folder, diag_Title, youtubedl_file, ytdlp_file, theButtonQuitLabel, theButtonYesLabel, path_to_MacYTDL, theButtonOKLabel, resourcesPath, show_yt_dlp, MacYTDL_custom_icon_file) + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Download and install of " & show_yt_dlp from table "MacYTDL") + do shell script resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + tell me to activate + -- Make the /usr/local/bin/ folder if it doesn't exist + try + tell application "System Events" + if not (exists folder usr_bin_folder) then + tell current application to do shell script "mkdir -p " & usr_bin_folder with administrator privileges + end if + end tell + end try + -- If user is on 10.15+ install yt-dlp otherwise install yt-dlp-legacy + try + set theYTDLDownloadProblemFlag to "" + set ytdlp_file_install to ("/usr/local/bin/yt-dlp" as text) + set YTDL_site_URL to "https://github.com/yt-dlp/yt-dlp/releases" + set YTDL_releases_page to do shell script "curl " & YTDL_site_URL & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + if YTDL_releases_page is "" then + set theYTDLDownloadProblemFlag to "NoReturnFromCurl" + error number -128 + end if + set AppleScript's text item delimiters to "Latest" + set YTDL_releases_text to text item 1 of YTDL_releases_page + set numParas to count paragraphs in YTDL_releases_text + set version_para to paragraph (numParas) of YTDL_releases_text + set AppleScript's text item delimiters to " " + set YTDL_version_check to text item 2 of version_para + set AppleScript's text item delimiters to "" + + -- User on 10.15+ - install universal yt-dlp - can probably simplify if tests here but, leave as is for clarity + -- 4/3/23 - Now assuming the yt-dlp_macos is in place - because YTDL_releases_page no longer shows by default all the assets including the macOS executables + if show_yt_dlp is "yt-dlp" then + set curl_YTDLP to ("curl -L " & YTDL_site_URL & "/download/" & YTDL_version_check & "/yt-dlp_macos" & " -o /usr/local/bin/yt-dlp") + end if + + -- User on 10.9-10.14.6 - install yt-dlp-legacy + if show_yt_dlp is "yt-dlp-legacy" then + set curl_YTDLP to ("curl -L " & YTDL_site_URL & "/download/" & YTDL_version_check & "/yt-dlp_macos_legacy" & " -o /usr/local/bin/yt-dlp") + end if + try + do shell script curl_YTDLP with administrator privileges + do shell script "chmod a+x /usr/local/bin/yt-dlp" with administrator privileges + on error number 6 + -- Trap cases in which user is not able to access the web site + set theYTDLDownloadProblemFlag to "NoReturnFromDownload" + error number -128 + end try + + set YTDL_ytdlp_version to (do shell script ytdlp_file_install & " --version") & " ytdlp" + + on error number -128 + if theYTDLDownloadProblemFlag is "NoReturnFromCurl" then + set theYTDLDownloadProblemLabel to localized string "There was a problem with downloading yt-dlp. Perhaps you are not connected to the internet, you have a rule in LittleSnitch denying connection or the server is currently not available. When you are sure you are connected to the internet, re-open MacYTDL then try to install yt-dlp." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theYTDLDownloadProblemLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + else if theYTDLDownloadProblemFlag is "NoReturnFromDownload" then + set theYTDLDownloadProblemLabel to localized string "There was a problem with downloading yt-dlp. Perhaps you are not connected to the internet or the server is currently not available. When you are sure you are connected to the internet, re-open MacYTDL then try to install yt-dlp." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theYTDLDownloadProblemLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + else + -- User cancels credentials dialog - just quit as can't run MacYTDL without yt-dlp + set theYTDLInstallCancelLabel to localized string "You've cancelled installing yt-dlp. If you wish to use MacYTDL, restart and enter your administrator credentials when asked so that yt-dlp can be installed." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theYTDLInstallCancelLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + end if + error number -128 + end try +end check_ytdl_installed + + +--------------------------------------------------- +-- +-- Install FFMpeg & FFprobe - Fork +-- +--------------------------------------------------- + +-- Handler for forking to correct FFmpeg and FFprobe installer - called by main thread on startup if either or both FF files are missing +on install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, user_system_arch) + if user_system_arch is "Intel" then + install_ffmpeg_ffprobe_intel(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os) + else + install_ffmpeg_ffprobe_arm(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os) + end if +end install_ffmpeg_ffprobe + +--------------------------------------------------- +-- +-- Install FFMpeg & FFprobe - ARM64 +-- +--------------------------------------------------- + +-- Handler for installing FFmpeg and FFprobe - called by install_ffmpeg_ffprobe() - for users on Apple Silicon +on install_ffmpeg_ffprobe_arm(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os) + set ffmpeg_site to "https://ffmpeg.martin-riedl.de" + set ffprobe_site to "https://ffmpeg.martin-riedl.de" + set FFmpeg_page to do shell script "curl " & ffmpeg_site & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + -- Trap case in which user is offline + if FFmpeg_page is "" then + set theFFmpegDownloadProblemLabel to localized string "There was a problem with downloading FFmpeg. Perhaps you are not connected to the internet or the server is currently not available. MacYTDL can't run and will have to quit. When you are sure you are connected to the internet, re-open MacYTDL. MacYTDL, will then try to install FFmpeg." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theFFmpegDownloadProblemLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + error number -128 + else + set AppleScript's text item delimiters to {"macOS (Apple Silicon/arm64)"} + set release_build_text_FFmpeg to paragraph 2 of text item 3 of FFmpeg_page + set AppleScript's text item delimiters to {" "} + set release_build_version_FFmpeg to text item 2 of release_build_text_FFmpeg + set AppleScript's text item delimiters to {""} + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Download and install of FFmpeg" from table "MacYTDL") + do shell script quoted form of resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + set ffmpeg_download_file to quoted form of (usr_bin_folder & "ffmpeg.zip") + try + -- Download latest FFmpeg zip file to usr/local/bin, unzip, fix permissions, rm zip file + set ffmpeg_arm_latest to "https://ffmpeg.martin-riedl.de/redirect/latest/macos/arm64/release/ffmpeg.zip" + do shell script "curl -L " & ffmpeg_arm_latest & " -o " & ffmpeg_download_file with administrator privileges + do shell script "unzip -o " & ffmpeg_download_file & " -d " & usr_bin_folder with administrator privileges + do shell script "rm " & ffmpeg_download_file with administrator privileges + set ffmpeg_version to release_build_version_FFmpeg + on error errStr number errorNumber + if errorNumber is -128 then + -- User cancels credentials dialog + try + do shell script "rm " & ffmpeg_download_file with administrator privileges + end try + else + -- trap any other kind of error including "Operation not permitted" and trap case in which zip file is not downloaded and saved + try + do shell script "rm " & ffmpeg_download_file with administrator privileges + end try + set theFFmpegInstallProblemTextLabel1 to localized string "There was a problem with installing FFmpeg. This was the error message: " in bundle file path_to_MacYTDL from table "MacYTDL" + set theFFmpegInstallProblemTextLabel2 to localized string "MacYTDL can't run and will have to quit. When you next start MacYTDL, it will try again to install FFmpeg." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog "" & errorNumber & " " & errStr & return & return & theFFmpegInstallProblemTextLabel2 buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + end if + error number -128 + end try + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Download and install of FFprobe" from table "MacYTDL") + do shell script quoted form of resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + set ffprobe_download_file to quoted form of (usr_bin_folder & "ffprobe.zip") + set ffprobe_site_latest to "https://ffmpeg.martin-riedl.de/redirect/latest/macos/arm64/release/ffprobe.zip" + try + do shell script "curl -L " & ffprobe_site_latest & " -o " & ffprobe_download_file with administrator privileges + do shell script "unzip -o " & ffprobe_download_file & " -d " & usr_bin_folder with administrator privileges + do shell script "rm " & ffprobe_download_file with administrator privileges + set ffprobe_version to release_build_version_FFmpeg + on error errStr number errorNumber + if errorNumber is -128 then + -- User cancels credentials dialog + try + do shell script "rm " & ffprobe_download_file with administrator privileges + end try + else + -- trap any other kind of error including "Operation not permitted" + try + do shell script "rm " & ffmpeg_download_file with administrator privileges + end try + set theFFProbeInstallProblemTextLabel1 to localized string "There was a problem with installing FFprobe. This was the error message: " in bundle file path_to_MacYTDL from table "MacYTDL" + set theFFProbeInstallProblemTextLabel2 to localized string "MacYTDL can't run and will have to quit. When you next start MacYTDL, it will try again to install FFprobe." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theFFProbeInstallProblemTextLabel1 & errorNumber & " " & errStr & return & return & theFFProbeInstallProblemTextLabel2 buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + end if + error number -128 + end try + end if +end install_ffmpeg_ffprobe_arm + +--------------------------------------------------- +-- +-- Install FFMpeg & FFprobe - Intel +-- +--------------------------------------------------- + +-- Handler for installing FFmpeg and FFprobe - called by install_ffmpeg_ffprobe() - for users on Intel +on install_ffmpeg_ffprobe_intel(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os) + set ffmpeg_site to "https://evermeet.cx/pub/ffmpeg/" + set ffprobe_site to "https://evermeet.cx/pub/ffprobe/" + set FFmpeg_page to do shell script "curl " & ffmpeg_site & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + -- Trap case in which user is offline + if FFmpeg_page is "" then + set theFFmpegDownloadProblemLabel to localized string "There was a problem with downloading FFmpeg. Perhaps you are not connected to the internet or the server is currently not available. MacYTDL can't run and will have to quit. When you are sure you are connected to the internet, re-open MacYTDL. MacYTDL, will then try to install FFmpeg." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theFFmpegDownloadProblemLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + error number -128 + else + set ffmpeg_version_start to (offset of "version" in FFmpeg_page) + 8 + set ffmpeg_version_end to (offset of "-tessus" in FFmpeg_page) - 1 + set ffmpeg_version_new to text ffmpeg_version_start thru ffmpeg_version_end of FFmpeg_page + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Download and install of FFmpeg" from table "MacYTDL") + do shell script quoted form of resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + set ffmpeg_download_file to quoted form of (usr_bin_folder & "ffmpeg-" & ffmpeg_version_new & ".zip") + try + set ignore_certifcates to "" + if user_on_old_os is true then set ignore_certifcates to " -k " + -- Download latest FFmpeg zip file to usr/local/bin, unzip, fix permissions, rm zip file + do shell script "curl -L " & ffmpeg_site & "ffmpeg-" & ffmpeg_version_new & ".zip" & ignore_certifcates & " -o " & ffmpeg_download_file with administrator privileges + do shell script "unzip -o " & ffmpeg_download_file & " -d " & usr_bin_folder with administrator privileges + do shell script "chmod a+x /usr/local/bin/ffmpeg" with administrator privileges + do shell script "rm " & ffmpeg_download_file with administrator privileges + set ffmpeg_version to ffmpeg_version_new + on error errStr number errorNumber + if errorNumber is -128 then + -- User cancels credentials dialog + try + do shell script "rm " & ffmpeg_download_file with administrator privileges + end try + else + -- trap any other kind of error including "Operation not permitted" and trap case in which zip file is not downloaded and saved + try + do shell script "rm " & ffmpeg_download_file with administrator privileges + end try + set theFFmpegInstallProblemTextLabel1 to localized string "There was a problem with installing FFmpeg. This was the error message: " in bundle file path_to_MacYTDL from table "MacYTDL" + set theFFmpegInstallProblemTextLabel2 to localized string "MacYTDL can't run and will have to quit. When you next start MacYTDL, it will try again to install FFmpeg." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog "" & errorNumber & " " & errStr & return & return & theFFmpegInstallProblemTextLabel2 buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + end if + error number -128 + end try + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Download and install of FFprobe" from table "MacYTDL") + do shell script quoted form of resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + set ffprobe_version_new to ffmpeg_version_new + set ffprobe_download_file to quoted form of (usr_bin_folder & "ffprobe-" & ffprobe_version_new & ".zip") + set ignore_certifcates to "" + if user_on_old_os is true then set ignore_certifcates to " -k " + do shell script "curl -L " & ffprobe_site & "ffprobe-" & ffprobe_version_new & ".zip" & ignore_certifcates & " -o " & ffprobe_download_file with administrator privileges + try + do shell script "unzip -o " & ffprobe_download_file & " -d " & usr_bin_folder with administrator privileges + do shell script "chmod a+x /usr/local/bin/ffprobe" with administrator privileges + do shell script "rm " & ffprobe_download_file with administrator privileges + set ffprobe_version to ffprobe_version_new + on error errStr number errorNumber + if errorNumber is -128 then + -- User cancels credentials dialog + try + do shell script "rm " & ffprobe_download_file with administrator privileges + end try + else + -- trap any other kind of error including "Operation not permitted" + try + do shell script "rm " & ffmpeg_download_file with administrator privileges + end try + set theFFProbeInstallProblemTextLabel1 to localized string "There was a problem with installing FFprobe. This was the error message: " in bundle file path_to_MacYTDL from table "MacYTDL" + set theFFProbeInstallProblemTextLabel2 to localized string "MacYTDL can't run and will have to quit. When you next start MacYTDL, it will try again to install FFprobe." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theFFProbeInstallProblemTextLabel1 & errorNumber & " " & errStr & return & return & theFFProbeInstallProblemTextLabel2 buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + end if + error number -128 + end try + end if +end install_ffmpeg_ffprobe_intel + + +------------------------------------------------------------------------------------ +-- +-- Install/Update Dialog Toolkit - must be installed for MacYTDL to work +-- +------------------------------------------------------------------------------------ + +-- Handler to install Shane Stanley's Dialog Toolkit Plus in user's Script Library - as altered for MacYTDL - delete version before alterations - update if new version available +-- Can't rely on copy in Resources because Monitor dialog (running from osascript) cannot see locations inside this applet +on install_DTP(DTP_file, path_to_MacYTDL, resourcesPath) + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Installing Dialog Toolkit" from table "MacYTDL") + do shell script resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + set libraries_folder to (POSIX path of (path to home folder) & "Library/Script Libraries/") + set libraries_folder_quoted to quoted form of libraries_folder + set DTP_library_MacYTDL to quoted form of ((POSIX path of path_to_MacYTDL) & "Contents/Resources/Script Libraries/DialogToolkitMacYTDL.scptd") as string + tell application "System Events" + if not (the folder libraries_folder exists) then + tell current application to do shell script "mkdir " & libraries_folder_quoted + end if + end tell + do shell script "cp -R " & DTP_library_MacYTDL & " " & libraries_folder_quoted +end install_DTP + + +------------------------------------------------------------------------------------------------------------------------------------------ +-- +-- Install Myriad Tables Lib - must be installed for formats.scpt to work with Auto download +-- +------------------------------------------------------------------------------------------------------------------------------------------ + +-- Handler to install Shane Stanley's Myriad Tables Lib in user's Script Library - called on startup and by set_settings() +-- Can't use copy in Resources because the Service (which might call formats.scpt) cannot see script libraries inside this applet +on install_Myriad(Myriad_file, path_to_MacYTDL, resourcesPath) + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Installing Myriad Tables Lib" from table "MacYTDL") + do shell script resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 3 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + set libraries_folder to (POSIX path of (path to home folder) & "Library/Script Libraries/") + set libraries_folder_quoted to quoted form of libraries_folder + set Myriad_library_MacYTDL to quoted form of ((POSIX path of path_to_MacYTDL) & "Contents/Resources/Script Libraries/Myriad Tables Lib.scptd") as string + tell application "System Events" + if not (the folder libraries_folder exists) then + tell current application to do shell script "mkdir " & libraries_folder_quoted + end if + end tell + do shell script "cp -R " & Myriad_library_MacYTDL & " " & libraries_folder_quoted +end install_Myriad + + +--------------------------------------------------- +-- +-- Check for MacYTDL updates +-- +--------------------------------------------------- + +-- Handler that checks for new version of MacYTDL and downloads if user agrees - called by Utilities() +on check_MacYTDL(downloadsFolder_Path, diag_Title, theButtonOKLabel, theButtonNoLabel, theButtonYesLabel, MacYTDL_version, MacYTDL_custom_icon_file) + -- Get version of MacYTDL available from GitHub + -- If user is offline or another error, returns to main_dialog() + set MacYTDL_site_URL to "https://github.com/section83/MacYTDL/releases/" + try + set MacYTDL_releases_page to do shell script "curl " & MacYTDL_site_URL & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + on error errMsg + set theMacYTDLCurlErrorLabel to localized string "There was an error with looking for the MacYTDL web page. The error was: " & errMsg & ", and the URL that produced the error was: " & MacYTDL_site_URL & ". Try again later and/or send a message to macytdl@gmail.com with the details." from table "MacYTDL" + display dialog theMacYTDLCurlErrorLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + end try + if MacYTDL_releases_page is "" then + set theMacYTDLPageErrorLabel to localized string "There was a problem with checking for MacYTDL updates. Perhaps you are not connected to the internet or GitHub is currently not available." from table "MacYTDL" + display dialog theMacYTDLPageErrorLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + else + set MacYTDL_version_start to (offset of "Version" in MacYTDL_releases_page) + 8 + set MacYTDL_version_end to (offset of " – " in MacYTDL_releases_page) - 1 + set MacYTDL_version_check to text MacYTDL_version_start thru MacYTDL_version_end of MacYTDL_releases_page + if MacYTDL_version_check is not equal to MacYTDL_version then + set theMacYTDLNewVersionAvailLabel1 to localized string "A new version of MacYTDL is available. You have version" from table "MacYTDL" + set theMacYTDLNewVersionAvailLabel2 to localized string "The current version is" from table "MacYTDL" + set theMacYTDLNewVersionAvailLabel3 to localized string "Would you like to download it now ?" from table "MacYTDL" + set MacYTDL_update_text to theMacYTDLNewVersionAvailLabel1 & " " & MacYTDL_version & ". " & theMacYTDLNewVersionAvailLabel2 & " " & MacYTDL_version_check & "." & return & return & theMacYTDLNewVersionAvailLabel3 + tell me to activate + set MacYTDL_install_answ to button returned of (display dialog MacYTDL_update_text buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if MacYTDL_install_answ is theButtonYesLabel then + set MacYTDL_download_file to quoted form of (downloadsFolder_Path & "/MacYTDL-v" & MacYTDL_version_check & ".dmg") + do shell script "curl -L " & MacYTDL_site_URL & "download/" & MacYTDL_version_check & "/MacYTDL-v" & MacYTDL_version_check & ".dmg -o " & MacYTDL_download_file + set theMacYTDLDownloadedTextLabel1 to localized string "A copy of version" from table "MacYTDL" + set theMacYTDLDownloadedTextLabel2 to localized string "of MacYTDL has been saved into your MacYTDL downloads folder." from table "MacYTDL" + display dialog theMacYTDLDownloadedTextLabel1 & " " & MacYTDL_version_check & " " & theMacYTDLDownloadedTextLabel2 with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + end if + else + set theMacYTDLUpToDateLabel to localized string "Your copy of MacYTDL is up to date. It is version " from table "MacYTDL" + display dialog theMacYTDLUpToDateLabel & MacYTDL_version with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + end if + end if +end check_MacYTDL + + +--------------------------------------------------- +-- +-- Invite user to install AtomicParsley +-- +--------------------------------------------------- + +-- If AtomicParsley is not installed, ask user if they want it. If so, go to install_MacYTDLatomic handler. Only applies if user has youtube-dl. +on ask_user_install_Atomic(usr_bin_folder, path_to_MacYTDL, diag_Title, MacYTDL_custom_icon_file, theButtonOKLabel, theButtonYesLabel) + tell me to activate + set macYTDL_Atomic_file to usr_bin_folder & "AtomicParsley" + tell application "System Events" + if not (exists file macYTDL_Atomic_file) then + set no_Parsley to "No" + else + set no_Parsley to "Yes" + end if + end tell + if no_Parsley is "No" then + set theAtomicNotInstalledTextlabel1 to localized string "Atomic Parsley is not installed. It's not critical but enables thumbnail images provided by web sites to be embedded in downloaded files." in bundle file path_to_MacYTDL from table "MacYTDL" + set theAtomicNotInstalledTextlabel2 to localized string "Would you like Atomic Parsley installed ? You can install it later on if you prefer. Note: You may need to provide administrator credentials." in bundle file path_to_MacYTDL from table "MacYTDL" + set theAtomicNotInstalledButtonNolabel to localized string "No thanks" in bundle file path_to_MacYTDL from table "MacYTDL" + set Install_Atomic_text to theAtomicNotInstalledTextlabel1 & return & return & theAtomicNotInstalledTextlabel2 + set Install_MacYTDL_Atomic to button returned of (display dialog Install_Atomic_text buttons {theAtomicNotInstalledButtonNolabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if Install_MacYTDL_Atomic is theButtonYesLabel then + my install_MacYTDLatomic(diag_Title, theButtonOKLabel, path_to_MacYTDL, usr_bin_folder) + end if + end if +end ask_user_install_Atomic + + +--------------------------------------------------- +-- +-- Install Atomic Parsley +-- +--------------------------------------------------- + +-- Handler for installing Atomic Parsley and updating Service menu - copy from Resource folder to /user/local/bin - separated out to avoid conflict with System Events - also called by Utilities dialog +on install_MacYTDLatomic(diag_Title, theButtonOKLabel, path_to_MacYTDL, usr_bin_folder) + set getAtomic to quoted form of (POSIX path of path_to_MacYTDL) & "Contents/Resources/AtomicParsley" + try + do shell script "cp -R " & getAtomic & " " & usr_bin_folder with administrator privileges + -- trap case where user cancels credentials dialog + on error number -128 + return + end try +end install_MacYTDLatomic + + +--------------------------------------------------- +-- +-- Remove Atomic Parsley +-- +--------------------------------------------------- + +on remove_MacYTDLatomic(path_to_MacYTDL, theButtonOKLabel, diag_Title, MacYTDL_custom_icon_file) + set getAtomic to quoted form of (POSIX path of path_to_MacYTDL) & "Contents/Resources/AtomicParsley" + try + do shell script "mv /usr/local/bin/AtomicParsley" & " ~/.trash/AtomicParsley" with administrator privileges + set theAtomicRemovedlabel to localized string "Atomic Parsley has been removed." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theAtomicRemovedlabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + -- trap case where user cancels credentials dialog + on error number -128 + return + end try +end remove_MacYTDLatomic + + +--------------------------------------------------- +-- +-- Invite user to install Service +-- +--------------------------------------------------- + +-- Ask user if they would like the MacYTDL service installed. If so, copy from Resource folder to user's Services folder - only ask once +on ask_user_install_service(path_to_MacYTDL, theButtonYesLabel, diag_Title, MacYTDL_custom_icon_file) + tell me to activate + set services_Folder to (POSIX path of (path to home folder) & "/Library/Services/") + set macYTDL_service_file to services_Folder & "Send-URL-To-MacYTDL.workflow" + tell application "System Events" + if not (exists file macYTDL_service_file) then + set theInstallServiceTextLabel1 to localized string "The MacYTDL Service is not installed. It's not critical but enables calling MacYTDL from within the web browser and you can also assign a keystroke shortcut to copy a video URL and run MacYTDL. However, after the Service is installed, you will need to grant Assistive Access to another part of MacYTDL. There are instructions in the Help file." in bundle file path_to_MacYTDL from table "MacYTDL" + set theInstallServiceTextLabel2 to localized string "Would you like the Service installed ? You can install the Service later on if you prefer." in bundle file path_to_MacYTDL from table "MacYTDL" + set theServiceNotInstalledButtonNolabel to localized string "No thanks" in bundle file path_to_MacYTDL from table "MacYTDL" + set Install_service_buttons to {theServiceNotInstalledButtonNolabel, theButtonYesLabel} + set Install_MacYTDL_service to button returned of (display dialog theInstallServiceTextLabel1 & return & return & theInstallServiceTextLabel2 buttons Install_service_buttons default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if Install_MacYTDL_service is theButtonYesLabel then + my install_MacYTDLservice(path_to_MacYTDL) + end if + end if + end tell +end ask_user_install_service + + +--------------------------------------------------- +-- +-- Install Service +-- +--------------------------------------------------- + +-- Handler for installing the Service and updating Services menu - called by ask_user_install_service() when first running MacYTDL; by Settings and Utilities dialogs +on install_MacYTDLservice(path_to_MacYTDL) + set services_Folder to (POSIX path of (path to home folder) & "Library/Services") + tell application "System Events" + if not (the folder services_Folder exists) then + tell current application to do shell script "mkdir -p " & services_Folder + end if + end tell + set getURL_service to quoted form of (POSIX path of path_to_MacYTDL) & "Contents/Resources/Send-URL-To-MacYTDL.workflow" + do shell script "cp -R " & getURL_service & " " & services_Folder & ";sleep 1;killall pbs;/System/Library/CoreServices/pbs -flush" +end install_MacYTDLservice + + +------------------------------------------------------------------------------------------------------------------ +-- +-- Check version of MacYTDL Service - update if old version - called when starting MacYTDL +-- +------------------------------------------------------------------------------------------------------------------ +-- Check whether Service is installed and if so, which version - if version is old, update to new - if auto-downloads turned on and user on 10.15+ update NSMenuItem +on update_MacYTDLservice(path_to_MacYTDL, MacYTDL_prefs_file, show_yt_dlp) + set Service_exists_flag to "No" + set user_services_file_posix to (POSIX path of (path to home folder) & "Library/Services/Send-URL-To-MacYTDL.workflow") + set user_services_Folder_nonposix to ((path to home folder as text) & "Library:Services:") + set user_service_file_nonposix to (user_services_Folder_nonposix & "Send-URL-To-MacYTDL.workflow") + set new_Services_Version_file_nonposix to (path_to_MacYTDL & "Contents:Resources:Send-URL-To-MacYTDL.workflow:Contents:Version.txt") + set version_from_Bundled_Service to read file new_Services_Version_file_nonposix as text + set new_Service_file_nonposix_string to (path_to_MacYTDL & "Contents:Resources:Send-URL-To-MacYTDL.workflow") as text + tell application "System Events" + if exists file user_service_file_nonposix then + set Service_exists_flag to "Yes" + end if + end tell + if Service_exists_flag is "Yes" then + set version_from_users_Service to "" + try + set user_service_version_file_nonposix to (user_services_Folder_nonposix & "Send-URL-To-MacYTDL.workflow:Contents:Version.txt") + set version_from_users_Service to read file user_service_version_file_nonposix as text + on error errMsg number errnum + if errnum is -1700 or errnum is -43 then + set version_from_users_Service to "NoVersion" + end if + end try + if (version_from_users_Service is not equal to version_from_Bundled_Service) then + do shell script "rm -R " & quoted form of (user_services_file_posix) + do shell script "cp -R " & (quoted form of (POSIX path of new_Service_file_nonposix_string)) & " " & (quoted form of user_services_file_posix) & ";sleep 1;killall pbs;/System/Library/CoreServices/pbs -flush" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set DL_auto to value of property list item "Auto_Download" + end tell + end tell + -- v1.25 – took out yt-dlp-legacy to isolate Macs in 10.14 and lower + -- if DL_auto is true and (show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy") then + if DL_auto is true and show_yt_dlp is "yt-dlp" then + set new_value to "Download Video Now" + set Service_file_plist_file to ((path to home folder) & "Library:Services:Send-URL-To-MacYTDL.workflow:Contents:info.plist") as text + tell application "System Events" + tell property list file Service_file_plist_file + set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + end tell + end tell + end if + end if + end if +end update_MacYTDLservice + + +--------------------------------------------------- +-- +-- User wants to remove MacYTDL Service +-- +--------------------------------------------------- + +on remove_MacYTDLservice() + set services_Folder to (POSIX path of (path to home folder) & "Library/Services/") + set macYTDL_service_file to services_Folder & "Send-URL-To-MacYTDL.workflow" + tell application "System Events" + if (the file macYTDL_service_file exists) then + tell current application to do shell script "rm -R " & quoted form of (macYTDL_service_file) & ";sleep 1;killall pbs;/System/Library/CoreServices/pbs -flush" + end if + end tell +end remove_MacYTDLservice + + +--------------------------------------------------- +-- +-- Check that settings file is up-to-date +-- +--------------------------------------------------- +-- Check whether Settings file is up to date - call relevant handlers to add missing items - Called my Main and Utilities +on check_settings(MacYTDL_prefs_file, old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version) + tell application "System Events" + try + tell property list file MacYTDL_prefs_file + set test_DL_subtitles to value of property list item "SubTitles" + end tell + -- Old version had string prefs while new version has boolean prefs for 4 items - call set_preferences to delete and recreate if user wishes + -- This is quite old - should try to remove it and replace with something simpler + if test_DL_subtitles is "Yes" or test_DL_subtitles is "No" then + set old_version_prefs to "Yes" + my set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version) + end if + on error + -- Means the plist file exists but there is a problem (eg. it's empty because of an earlier crash) - just delete it, re-create and populate as if replacing the old version + set old_version_prefs to "Yes" + my set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version) + end try + + -- Check on need to add new v1.10 item to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Show_Settings_before_Download") then + my add_v1_10_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.11 item to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "final_Position") then + my add_v1_11_preference(MacYTDL_prefs_file, X_position, Y_position) + end if + end tell + -- Check on need to add new v1.12.1 item to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Subtitles_Language") then + my add_v1_12_1_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.16 write-auto-sub item to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Subtitles_YTAuto") then + my add_v1_16_preference(MacYTDL_prefs_file, theBestLabel) + end if + end tell + -- Check on need to add new v1.17 proxy settings to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Use_Proxy") then + my add_v1_17_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.18 proxy settings to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Use_Cookies") then + my add_v1_18_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.19 yt-dlp settings to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Use_ytdlp") then + my add_v1_19_preference(MacYTDL_prefs_file, show_yt_dlp) + end if + end tell + -- Check on need to add new v1.20 timestamps setting to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Add_TimeStamps") then + my add_v1_20_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.23 Quicktime caompatibility setting to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Make_QuickTime_Compat") then + my add_v1_23_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.24 get formats list setting to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Get_Formats_List") then + my add_v1_24_preference(MacYTDL_prefs_file) + end if + end tell + -- Check on need to add new v1.26 get formats list setting to the prefs file + tell property list file MacYTDL_prefs_file + if not (exists property list item "Discard_URL") then + my add_v1_26_preference(MacYTDL_prefs_file, theBestLabel) + end if + end tell + end tell +end check_settings + +------------------------------------------------------------------------------------------------------------------------------------------------------- +-- +-- Handlers to update format of Preferences file for v1.10, 1.11, 1.12.1, 1.16, 1.17, 1.18, 1.19, 1.20, 1.21, 1.23, v1.24 and v1.26 +-- +------------------------------------------------------------------------------------------------------------------------------------------------------- + +on add_v1_10_preference(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Show_Settings_before_Download", value:true} + end tell + end tell +end add_v1_10_preference + +on add_v1_11_preference(MacYTDL_prefs_file, X_position, Y_position) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:list, name:"final_Position", value:{X_position, Y_position}} + end tell + end tell +end add_v1_11_preference + +on add_v1_12_1_preference(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:string, name:"Subtitles_Language", value:"en"} + end tell + end tell +end add_v1_12_1_preference + +on add_v1_16_preference(MacYTDL_prefs_file, theBestLabel) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Subtitles_YTAuto", value:false} + make new property list item at end with properties {kind:string, name:"Audio_Codec", value:theBestLabel} + make new property list item at end with properties {kind:boolean, name:"Limit_Rate", value:false} + make new property list item at end with properties {kind:real, name:"Limit_Rate_Value", value:0} + end tell + end tell +end add_v1_16_preference + +on add_v1_17_preference(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Use_Proxy", value:false} + make new property list item at end with properties {kind:string, name:"Proxy_URL", value:""} + end tell + end tell +end add_v1_17_preference + +on add_v1_18_preference(MacYTDL_prefs_file) + set theNoCookielabel to localized string "No Cookie File" from table "MacYTDL" + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Use_Cookies", value:false} + make new property list item at end with properties {kind:string, name:"Cookies_Location", value:("/" & theNoCookielabel)} + make new property list item at end with properties {kind:boolean, name:"Use_Custom_Output_Template", value:false} + make new property list item at end with properties {kind:string, name:"Custom_Output_Template", value:""} + end tell + end tell +end add_v1_18_preference + +on add_v1_19_preference(MacYTDL_prefs_file, show_yt_dlp) + -- Need to generalise show_yt_dlp so that only "youtube-dl" or "yt-dlp" is stored in plist + if show_yt_dlp is "yt-dlp-legacy" then + set preferences_show_yt_dlp to "yt-dlp" + else + set preferences_show_yt_dlp to show_yt_dlp + end if + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:string, name:"Use_ytdlp", value:preferences_show_yt_dlp} + end tell + end tell +end add_v1_19_preference + +on add_v1_20_preference(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:string, name:"Add_TimeStamps", value:false} + make new property list item at end with properties {kind:boolean, name:"Use_Custom_Settings", value:false} + make new property list item at end with properties {kind:string, name:"Custom_Settings", value:""} + end tell + end tell +end add_v1_20_preference + +on add_v1_21_preference(MacYTDL_prefs_file, YTDL_version, MacYTDL_preferences_path) + -- Need HFS path to preferences for location of saved settings + set MacYTDL_preferences_path_nonPosix to POSIX file MacYTDL_preferences_path as text + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:string, name:"YTDL_YTDLP_version", value:YTDL_version} + make new property list item at end with properties {kind:boolean, name:"Auto_Download", value:false} + make new property list item at end with properties {kind:string, name:"Saved_Settings_Location", value:MacYTDL_preferences_path_nonPosix} + make new property list item at end with properties {kind:string, name:"Name_Of_Settings_In_Use", value:"MacYTDL"} + end tell + end tell +end add_v1_21_preference + +on add_v1_23_preference(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Make_QuickTime_Compat", value:false} + end tell + end tell +end add_v1_23_preference + +on add_v1_24_preference(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Get_Formats_List", value:false} + end tell + end tell +end add_v1_24_preference + +on add_v1_26_preference(MacYTDL_prefs_file, theBestLabel) + tell application "System Events" + tell property list file MacYTDL_prefs_file + make new property list item at end with properties {kind:boolean, name:"Discard_URL", value:false} + make new property list item at end with properties {kind:string, name:"Resolution_Limit", value:theBestLabel} + make new property list item at end with properties {kind:string, name:"Dont_Use_Parts", value:true} + make new property list item at end with properties {kind:string, name:"Parallel", value:false} + make new property list item at end with properties {kind:string, name:"No_Warnings", value:false} + make new property list item at end with properties {kind:string, name:"Delete_Partial", value:false} + end tell + end tell +end add_v1_26_preference + + +--------------------------------------------------- +-- +-- Check v1.21 settings are in place +-- +--------------------------------------------------- +-- Check on need to add new v1.21 YTDL/YT-DLP version to the prefs file - called on startup and when user restores an old settings file +on check_settings_current(MacYTDL_prefs_file, DL_Use_YTDLP, MacYTDL_preferences_path, youtubedl_file, ytdlp_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + if not (exists property list item "YTDL_YTDLP_version") then + if DL_Use_YTDLP is "youtube-dl" then + set YTDL_version to do shell script youtubedl_file & " --version" + else + set YTDL_version to do shell script ytdlp_file & " --version" + end if + my add_v1_21_preference(MacYTDL_prefs_file, YTDL_version, MacYTDL_preferences_path) + end if + if not (exists property list item "Make_QuickTime_Compat") then + my add_v1_23_preference(MacYTDL_prefs_file) + end if + end tell + end tell +end check_settings_current + + +--------------------------------------------------- +-- +-- Get current preference settings +-- +--------------------------------------------------- + +-- Handler for reading the users' preferences file - called by set_settings, utilities, open_batch_processing and main_dialog +on read_settings(MacYTDL_prefs_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + set DL_Add_Metadata to value of property list item "Add_Metadata" + set DL_TimeStamps to value of property list item "Add_TimeStamps" + set DL_audio_only to value of property list item "Audio_Only" + set DL_audio_codec to value of property list item "Audio_Codec" + set DL_YTDL_auto_check to value of property list item "Auto_Check_YTDL_Update" + set DL_auto to value of property list item "Auto_Download" + set DL_Cookies_Location to value of property list item "Cookies_Location" + set DL_Custom_Template to value of property list item "Custom_Output_Template" + set DL_Custom_Settings to value of property list item "Custom_Settings" + set DL_Delete_Partial to value of property list item "Delete_Partial" + set DL_description to value of property list item "Description" + set DL_discard_URL to value of property list item "Discard_URL" + set downloadsFolder_Path to value of property list item "DownloadFolder" + set DL_format to value of property list item "FileFormat" + set window_Position to value of property list item "final_Position" + set DL_formats_list to value of property list item "Get_Formats_List" + set DL_Remux_original to value of property list item "Keep_Remux_Original" + set DL_Limit_Rate to value of property list item "Limit_Rate" + set DL_Limit_Rate_Value to value of property list item "Limit_Rate_Value" + set DL_QT_Compat to value of property list item "Make_QuickTime_Compat" + set DL_Settings_In_Use to value of property list item "Name_Of_Settings_In_Use" + set DL_No_Warnings to value of property list item "No_Warnings" + set DL_over_writes to value of property list item "Over-writes allowed" + set DL_Proxy_URL to value of property list item "Proxy_URL" + set DL_Remux_format to value of property list item "Remux_Format" + set DL_Parallel to value of property list item "Parallel" + set DL_Resolution_Limit to value of property list item "Resolution_Limit" + set DL_Saved_Settings_Location to value of property list item "Saved_Settings_Location" + set DL_Show_Settings to value of property list item "Show_Settings_before_Download" + set DL_subtitles_format to value of property list item "Subtitles_Format" + set DL_subtitles to value of property list item "SubTitles" + set DL_STEmbed to value of property list item "SubTitles_Embedded" + set DL_YTAutoST to value of property list item "Subtitles_YTAuto" + set DL_STLanguage to value of property list item "Subtitles_Language" + set DL_Thumbnail_Embed to value of property list item "Thumbnail_Embed" + set DL_Thumbnail_Write to value of property list item "Thumbnail_Write" + set DL_Use_Cookies to value of property list item "Use_Cookies" + set DL_Use_Custom_Settings to value of property list item "Use_Custom_Settings" + set DL_Use_Custom_Template to value of property list item "Use_Custom_Output_Template" + set DL_Dont_Use_Parts to value of property list item "Dont_Use_Parts" + set DL_Use_Proxy to value of property list item "Use_Proxy" + set DL_Use_YTDLP to value of property list item "Use_ytdlp" + set DL_verbose to value of property list item "Verbose" + set YTDL_version to value of property list item "YTDL_YTDLP_version" + end tell + end tell +end read_settings + + +--------------------------------------------------------- +-- +-- Create preference settings file with defaults +-- +--------------------------------------------------------- + +-- Handler for creating preferences file and setting default preferences - called by Main if prefs don't exist or are faulty +on set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file) + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of (localized string "Creating MacYTDL preferences." from table "MacYTDL") + do shell script quoted form of (resourcesPath & "alerter") & " -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 7 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + -- Need to generalise show_yt_dlp so that only "youtube-dl" or "yt-dlp" is stored in plist + if show_yt_dlp is "yt-dlp-legacy" then + set preferences_show_yt_dlp to "yt-dlp" + else + set preferences_show_yt_dlp to show_yt_dlp + end if + set downloadsFolder to "Desktop" + set downloadsFolder_Path to (POSIX path of (path to home folder) & downloadsFolder) + if old_version_prefs is "Yes" then + -- Prefs file is old or faulty - warn user it must be replaced for MacYTDL to work + set theInstallMacYTDLPrefsTextLabel to localized string "The MacYTDL Preferences file needs to be replaced. To work, MacYTDL needs the latest version of the Preferences file. Do you wish to continue ?" in bundle file path_to_MacYTDL from table "MacYTDL" + tell me to activate + set ask_update to display dialog theInstallMacYTDLPrefsTextLabel buttons {theButtonNoLabel, theButtonYesLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + set Install_MacYTDL to button returned of ask_update + if Install_MacYTDL is theButtonNoLabel then + error number -128 + end if + tell application "Finder" + delete MacYTDL_prefs_file as POSIX file + end tell + else + -- Set path to default downloads folder and create it + tell application "System Events" + if not (exists folder MacYTDL_preferences_path) then + tell current application to do shell script "mkdir " & MacYTDL_preferences_path + end if + end tell + end if + -- Need HFS path to preferences for locaton of saved settings + set MacYTDL_preferences_path_nonPosix to (POSIX file MacYTDL_preferences_path) as text + -- Create new Preferences file and set the default preferences + set theNoCookielabel to localized string "No Cookie File" from table "MacYTDL" + tell application "System Events" + set thePropertyListFile to make new property list file with properties {name:MacYTDL_prefs_file} + tell property list items of thePropertyListFile + make new property list item at end with properties {kind:string, name:"DownloadFolder", value:downloadsFolder_Path} -- <= Path has no trailing slash + make new property list item at end with properties {kind:string, name:"FileFormat", value:theDefaultLabel} + make new property list item at end with properties {kind:boolean, name:"Audio_Only", value:false} + make new property list item at end with properties {kind:boolean, name:"Auto_Check_YTDL_Update", value:false} + make new property list item at end with properties {kind:boolean, name:"SubTitles", value:false} + make new property list item at end with properties {kind:boolean, name:"SubTitles_Embedded", value:false} + make new property list item at end with properties {kind:string, name:"Subtitles_Format", value:theBestLabel} + make new property list item at end with properties {kind:boolean, name:"Description", value:false} + make new property list item at end with properties {kind:boolean, name:"Over-writes allowed", value:false} + make new property list item at end with properties {kind:string, name:"Remux_Format", value:theNoRemuxLabel} + make new property list item at end with properties {kind:boolean, name:"Keep_Remux_Original", value:false} + make new property list item at end with properties {kind:boolean, name:"Thumbnail_Write", value:false} + make new property list item at end with properties {kind:boolean, name:"Thumbnail_Embed", value:false} + make new property list item at end with properties {kind:boolean, name:"Add_Metadata", value:false} + make new property list item at end with properties {kind:boolean, name:"Verbose", value:false} + make new property list item at end with properties {kind:boolean, name:"Show_Settings_before_Download", value:false} + make new property list item at end with properties {kind:list, name:"final_Position", value:{X_position, Y_position}} + make new property list item at end with properties {kind:string, name:"Subtitles_Language", value:"en"} + make new property list item at end with properties {kind:boolean, name:"Subtitles_YTAuto", value:false} + make new property list item at end with properties {kind:string, name:"Audio_Codec", value:theBestLabel} + make new property list item at end with properties {kind:boolean, name:"Limit_Rate", value:false} + make new property list item at end with properties {kind:real, name:"Limit_Rate_Value", value:0} + make new property list item at end with properties {kind:boolean, name:"Use_Proxy", value:false} + make new property list item at end with properties {kind:string, name:"Proxy_URL", value:""} + make new property list item at end with properties {kind:boolean, name:"Use_Cookies", value:false} + make new property list item at end with properties {kind:string, name:"Cookies_Location", value:("/" & theNoCookielabel)} + make new property list item at end with properties {kind:boolean, name:"Use_Custom_Output_Template", value:false} + make new property list item at end with properties {kind:string, name:"Custom_Output_Template", value:""} + make new property list item at end with properties {kind:string, name:"Use_ytdlp", value:preferences_show_yt_dlp} + make new property list item at end with properties {kind:boolean, name:"Add_TimeStamps", value:false} + make new property list item at end with properties {kind:boolean, name:"Use_Custom_Settings", value:false} + make new property list item at end with properties {kind:string, name:"Custom_Settings", value:""} + make new property list item at end with properties {kind:string, name:"YTDL_YTDLP_version", value:YTDL_version} + make new property list item at end with properties {kind:boolean, name:"Auto_Download", value:false} + make new property list item at end with properties {kind:string, name:"Saved_Settings_Location", value:MacYTDL_preferences_path_nonPosix} + make new property list item at end with properties {kind:string, name:"Name_Of_Settings_In_Use", value:"MacYTDL"} + make new property list item at end with properties {kind:boolean, name:"Make_QuickTime_Compat", value:false} + make new property list item at end with properties {kind:boolean, name:"Get_Formats_List", value:false} + make new property list item at end with properties {kind:boolean, name:"Discard_URL", value:false} + make new property list item at end with properties {kind:string, name:"Resolution_Limit", value:theBestLabel} + make new property list item at end with properties {kind:string, name:"Dont_Use_Parts", value:false} + make new property list item at end with properties {kind:string, name:"Parallel", value:false} + make new property list item at end with properties {kind:string, name:"No_Warnings", value:false} + make new property list item at end with properties {kind:string, name:"Delete_Partial", value:false} + end tell + end tell +end set_preferences + + +--------------------------------------------------- +-- +-- Set Settings +-- +--------------------------------------------------- + +-- Handler for showing dialog to set various MacYTDL and youtube-dl/yt-dlp settings +on set_admin_settings(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file, theButtonCancelLabel, window_Position, theButtonReturnLabel, MacYTDL_custom_icon_file_posix) + -- In case user accidentally deletes the prefs plist file + tell application "System Events" + if exists file MacYTDL_prefs_file then + my read_settings(MacYTDL_prefs_file) + else + my set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file) + set prefs_exists to true + end if + end tell + set DL_format to localized string DL_format from table "MacYTDL" + set DL_subtitles_format to localized string DL_subtitles_format from table "MacYTDL" + set DL_Remux_format to localized string DL_Remux_format from table "MacYTDL" + set DL_audio_codec to localized string DL_audio_codec from table "MacYTDL" + + -- Set variables for the settings dialog + set theAdminDiagPromptLabel to localized string "Admin" from table "MacYTDL" + set admin_diag_prompt to theAdminDiagPromptLabel + set accViewWidth to 450 + set accViewInset to 0 + + -- Set buttons and controls + set theButtonsSaveLabel to localized string "Save" from table "MacYTDL" + set theSettingsButtonLabel to localized string "Settings" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonCancelLabel, theSettingsButtonLabel, theButtonsSaveLabel} button keys {".", "s", ""} default button 3 + --if minWidth > accViewWidth then set accViewWidth to minWidth --<= Not needed as two buttons always narrower than the dialog - keep in case things change + set {theSettingsRule, theTop} to create rule 3 rule width accViewWidth + set theCheckboxNoWarningsLabel to localized string "Suppress warnings from YT-DLP" from table "MacYTDL" + set {settings_theCheckbox_No_Warnings, theTop} to create checkbox theCheckboxNoWarningsLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_No_Warnings + set theCheckboxDeletPartialLabel to localized string "Delete partially downloaded files" from table "MacYTDL" + set {settings_theCheckbox_Delete_Partial, theTop} to create checkbox theCheckboxDeletPartialLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_Delete_Partial + set theCheckboxUsePartsLabel to localized string "Don't use \"part\" file names in download" from table "MacYTDL" + set {settings_theCheckbox_Use_Parts, theTop} to create checkbox theCheckboxUsePartsLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_Dont_Use_Parts + set theCheckboxDiscardURLLabel to localized string "Discard URL after download" from table "MacYTDL" + set {settings_theCheckbox_Discard_URL, theTop} to create checkbox theCheckboxDiscardURLLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_discard_URL + set theCheckboxQTCompatLabel to localized string "QT compatible video" from table "MacYTDL" + set {settings_theCheckbox_QT_Compat, theTop} to create checkbox theCheckboxQTCompatLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_QT_Compat + set theCheckboxParallelLabel to localized string "Download videos in parallel" from table "MacYTDL" + set {settings_theCheckbox_Parallel, theTop} to create checkbox theCheckboxParallelLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_Parallel + set theCheckboxLimitRateLabel to localized string "Limit download speed (MB/sec)" from table "MacYTDL" + set {settings_theCheckbox_Limit_Rate, theTop, RateBoxLeftDist} to create checkbox theCheckboxLimitRateLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_Limit_Rate + set {settings_theField_LimitRateValue, theTop} to create field DL_Limit_Rate_Value left inset (RateBoxLeftDist + 70) bottom (theTop - 20) field width 40 + set theCheckboxAutoDownloadLabel to localized string "Automatic download" from table "MacYTDL" + set {settings_theCheckbox_Auto_Download, theTop} to create checkbox theCheckboxAutoDownloadLabel left inset 70 bottom (theTop + 1) max width 200 initial state DL_auto + set theCheckboxShowSettingsLabel to localized string "Show settings before download" from table "MacYTDL" + set {settings_theCheckbox_Show_Settings, theTop} to create checkbox theCheckboxShowSettingsLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_Show_Settings + -- Hide the legacy version of YT-DLP - too confusing otherwise + if DL_Use_YTDLP is "yt-dlp-legacy" then + set settings_DL_Use_YTDLP to "YT-DLP" + else + set settings_DL_Use_YTDLP to DL_Use_YTDLP + end if + set theCheckboxCheckYTDLOnStartLabel to (localized string "Check" from table "MacYTDL") & " " & settings_DL_Use_YTDLP & " " & (localized string "version on startup" from table "MacYTDL") + set {settings_theCheckbox_Auto_YTDL_Check, theTop} to create checkbox theCheckboxCheckYTDLOnStartLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_YTDL_auto_check + set theCheckboxTimeStampsLabel to localized string "Add timestamps to log" from table "MacYTDL" + set {settings_theCheckbox_TimeStamps, theTop} to create checkbox theCheckboxTimeStampsLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_TimeStamps + set theCheckboxVerboseLabel to localized string "Verbose logging" from table "MacYTDL" + set {settings_theCheckbox_Verbose, theTop} to create checkbox theCheckboxVerboseLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_verbose + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 50 view width 64 view height 64 scale image scale proportionally + set {settings_prompt, theTop} to create label admin_diag_prompt left inset 0 bottom (theTop - 5) max width accViewWidth aligns center aligned with bold type + set settings_allControls to {theSettingsRule, settings_theCheckbox_No_Warnings, settings_theCheckbox_Delete_Partial, settings_theCheckbox_Use_Parts, settings_theCheckbox_Discard_URL, settings_theCheckbox_QT_Compat, settings_theCheckbox_Parallel, settings_theCheckbox_Limit_Rate, settings_theField_LimitRateValue, settings_theCheckbox_Auto_Download, settings_theCheckbox_Show_Settings, settings_theCheckbox_Auto_YTDL_Check, settings_theCheckbox_TimeStamps, settings_theCheckbox_Verbose, MacYTDL_icon, settings_prompt} + + -- Make sure MacYTDL is in front and show dialog - need to make dialog wider in some languages - use width returned from right most control <= activate if necessary + tell me to activate + set calculatedAccViewWidth to accViewWidth + set {settings_button_returned, settings_button_number_returned, settings_controls_results, finalPosition} to display enhanced window diag_Title buttons theButtons acc view width calculatedAccViewWidth acc view height theTop acc view controls settings_allControls initial position window_Position + + -- Has user moved the MacYTDL window - if so, save new position + if finalPosition is not equal to window_Position then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "final_Position" to finalPosition + end tell + end tell + end if + + if settings_button_number_returned is 3 or settings_button_number_returned is 2 then -- Save Settings + -- Get control results from settings dialog - numbered choice variables are not used but help ensure correct values go into prefs file + --set settings_choice_1 to item 1 of settings_controls_results -- <= The ruled line + set settings_No_Warnings_choice to item 2 of settings_controls_results -- <= Suppress warnings + set settings_Delete_Partial_choice to item 3 of settings_controls_results -- <= Delete partial downloads choice + set settings_DontUseParts_choice to item 4 of settings_controls_results -- <= Use parts in DL file names choice + set settings_Discard_URL_choice to item 5 of settings_controls_results -- <= Discard URL on download choice + set settings_QT_Compat_choice to item 6 of settings_controls_results -- <= Make download QT compatible + set settings_parallel_choice to item 7 of settings_controls_results -- <= Download multiple videos in parallel + set settings_limit_rate_choice to item 8 of settings_controls_results -- <= Limit rate choice + set settings_limit_rate_value_choice to item 9 of settings_controls_results -- <= Limit rate value choice + set settings_auto_download_choice to item 10 of settings_controls_results -- <= Automatic download using Service + set settings_show_settings_choice to item 11 of settings_controls_results -- <= Show settings before download choice + set settings_YTDL_auto_choice to item 12 of settings_controls_results -- <= Auto check YTDL version on startup choice + set settings_timestamps_choice to item 13 of settings_controls_results -- <= Add timestamps choice + set settings_verbose_choice to item 14 of settings_controls_results -- <= Verbose choice + + -- Save new settings to preferences file - no error checking needed for these + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "No_Warnings" to settings_No_Warnings_choice + set value of property list item "Delete_Partial" to settings_Delete_Partial_choice + set value of property list item "Discard_URL" to settings_Discard_URL_choice + set value of property list item "Make_QuickTime_Compat" to settings_QT_Compat_choice + set value of property list item "Parallel" to settings_parallel_choice + set value of property list item "Show_Settings_before_Download" to settings_show_settings_choice + set value of property list item "Auto_Check_YTDL_Update" to settings_YTDL_auto_choice + set value of property list item "Add_TimeStamps" to settings_timestamps_choice + set value of property list item "Verbose" to settings_verbose_choice + end tell + end tell + + -- Reverse logic for Dont_Use_parts because using parts is the default + if settings_DontUseParts_choice is true then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Dont_Use_Parts" to true + end tell + end tell + else + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Dont_Use_Parts" to false + end tell + end tell + end if + + -- If user wants auto-downloads, check Service is installed - install Service if user wants - change NSMenuItem of Service to something more useful if user on macOS 10.15+ - show_yt_dlp is proxy for macOS version - Auto download and get formats list together causes a crash or similar + set path_to_home_folder to (path to home folder) + set services_Folder_nonPosix to (path_to_home_folder & "Library:Services:") as text + set macYTDL_service_file_nonPosix to services_Folder_nonPosix & "Send-URL-To-MacYTDL.workflow" + set Service_file_plist to (macYTDL_service_file_nonPosix & ":Contents:info.plist") + set services_Folder to (POSIX path of (path to home folder) & "/Library/Services/") + set macYTDL_service_file to services_Folder & "Send-URL-To-MacYTDL.workflow" + set isServiceInstalled to "Yes" + tell application "System Events" + if not (exists the file macYTDL_service_file) then + set isServiceInstalled to "No" + end if + end tell + + if settings_auto_download_choice is true then + if isServiceInstalled is "Yes" then + set new_value to "Download Video Now" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Auto_Download" to true + end tell + -- if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then -- This do not work properly on macOS earlier than 10.15 - can take some time to be noticeable in Finder + if show_yt_dlp is "yt-dlp" then + try + tell property list file Service_file_plist + set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + end tell + on error errMsg + display dialog "Trying to change Service menu - error: " & errMsg + end try + end if + end tell + end if + if isServiceInstalled is "No" then + set theNeedServiceLabel to localized string "Sorry, to have automatic downloads, you need to install the MacYTDL Service. Discard settings changes and return to Main, install the Service and turn on auto downloads or save all but Auto-download changes" from table "MacYTDL" + set theButtonsInstallLabel to localized string "Install" from table "MacYTDL" + set autoDLNeedService to button returned of (display dialog (theNeedServiceLabel & " ?") with title diag_Title buttons {theButtonReturnLabel, theButtonsInstallLabel, theButtonsSaveLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if autoDLNeedService is theButtonReturnLabel then + set branch_execution to "Main" + return branch_execution + end if + if autoDLNeedService is theButtonsInstallLabel then + my install_MacYTDLservice(path_to_MacYTDL) + set new_value to "Download Video Now" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Auto_Download" to settings_auto_download_choice + end tell + -- if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then -- This does not work properly on macOS earlier than 10.15 + if show_yt_dlp is "yt-dlp" then + try + tell property list file Service_file_plist + set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + end tell + end try + end if + end tell + end if + -- if autoDLNeedService is theButtonsSaveLabel -- processing will just continue and auto-download stay unchanged + end if + -- v1.26 - Don't know why isServiceInstalled is "Yes" test was here - Service will always be installed when Auto-dL is on and no need to test if auto_dl is already false + -- else if settings_auto_download_choice is false and isServiceInstalled is "Yes" then + else if settings_auto_download_choice is false then + set new_value to "Send-URL-To-MacYTDL" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Auto_Download" to false + end tell + -- if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then -- v1.26 + if show_yt_dlp is "yt-dlp" then + try + tell property list file Service_file_plist + set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + end tell + end try + end if + end tell + -- All this code was designed to cope with incompatibility of auto-DL and Get_Formats_list - but, turns out they are not so incompatible - leave in place just in case I'm wrong + -- if DL_formats_list is true then + -- set theChooseListAutoTextLabel to localized string "Sorry, but Automatic dowloads is incompatible with the Formats List. Which would you prefer ?" from table "MacYTDL" + -- set choosel_ListAuto to button returned of (display dialog theChooseListAutoTextLabel buttons {"List", "Auto", "Neither"} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + -- if choosel_ListAuto is "Neither" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to false + -- set value of property list item "Get_Formats_List" to false + -- end tell + -- end tell + -- end if + -- if choosel_ListAuto is "Auto" then + -- if isServiceInstalled is "Yes" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to settings_auto_download_choice + -- end tell + -- -- if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then -- This do not work properly on macOS earlier than 10.15 + -- if show_yt_dlp is "yt-dlp" then + -- set new_value to "Download Video Now" + -- tell property list file Service_file_plist + -- set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + -- end tell + -- end if + -- end tell + -- end if + -- if isServiceInstalled is "No" then + -- set theNeedServiceLabel to localized string "Sorry, to have automatic downloads, you need to install the MacYTDL Service. Discard settings changes and return to Main, install the Service and turn on auto downloads or save all but Auto-download changes" from table "MacYTDL" + -- set theButtonsInstallLabel to localized string "Install" from table "MacYTDL" + -- set autoDLNeedService to button returned of (display dialog (theNeedServiceLabel & " ?") with title diag_Title buttons {theButtonReturnLabel, theButtonsInstallLabel, theButtonsSaveLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + -- if autoDLNeedService is theButtonReturnLabel then + -- set branch_execution to "Main" + -- return branch_execution + -- --main_dialog() + -- end if + -- if autoDLNeedService is theButtonsInstallLabel then + -- my install_MacYTDLservice(path_to_MacYTDL) + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to settings_auto_download_choice + -- end tell + -- -- if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then -- This does not work properly on macOS earlier than 10.15 + -- if show_yt_dlp is "yt-dlp" then + -- set new_value to "Download Video Now" + -- tell property list file Service_file_plist + -- set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + -- end tell + -- end if + -- end tell + -- end if + -- -- if autoDLNeedService is theButtonsSaveLabel -- processing will just continue and auto-download stay unchanged + -- end if + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Get_Formats_List" to false + -- end tell + -- end tell + -- end if + -- if choosel_ListAuto is "List" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to false + -- set value of property list item "Get_Formats_List" to true + -- end tell + -- end tell + -- end if + -- else + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to true + -- end tell + -- end tell + -- end if + -- else if settings_auto_download_choice is false and isServiceInstalled is "Yes" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to false + -- end tell + -- if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then + -- set new_value to "Send-URL-To-MacYTDL" + -- tell property list file Service_file_plist + -- set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + -- end tell + -- end if + -- end tell + end if + + -- Check for valid download limit rate - if limit rate is true then the rate value must be positive real number + try + set settings_limit_rate_value_choice to settings_limit_rate_value_choice as real + on error + set theLimitRateInvalidLabel to localized string "Sorry, you need a positive real number to limit download speed." from table "MacYTDL" + display dialog theLimitRateInvalidLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end try + if settings_limit_rate_choice is true and (settings_limit_rate_value_choice is "" or settings_limit_rate_value_choice is less than or equal to 0) then + set theLimitRateInvalidLabel to localized string "Sorry, you need a positive real number to limit download speed." from table "MacYTDL" + display dialog theLimitRateInvalidLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + -- Now can go ahead and set the download speed settings + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Limit_Rate" to settings_limit_rate_choice + set value of property list item "Limit_Rate_Value" to settings_limit_rate_value_choice + end tell + end tell + + if settings_button_number_returned is 2 then -- Go to Settings + set branch_execution to "Settings" + return branch_execution + end if + end if + + set branch_execution to "Main" + return branch_execution + --main_dialog() + +end set_admin_settings + + +--------------------------------------------------- +-- +-- Parse SBS OnDemand web page +-- +--------------------------------------------------- + +--Handler to parse SBS On Demand "Show" pages so as to get a list of episodes +on Get_SBS_Episodes(URL_user_entered, diag_Title, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL) + -- Can only download from one show page at a time + set AppleScript's text item delimiters to " " + set number_of_URLs to number of text items in URL_user_entered + set AppleScript's text item delimiters to "" + if number_of_URLs is greater than 1 then + set theOnDemandURLProblemLabel to localized string "It looks like you are trying to download from two or more separate SBS show pages at the same time. MacYTDL can't do that at present. Try just one show page URL at a time. There is more info in Help." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theOnDemandURLProblemLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + set branch_execution to "Main" + return branch_execution + end if + -- Something wrong with URL or internet connection + set SBS_show_page to do shell script "curl " & URL_user_entered + if SBS_show_page is "" then + set theOnDemandURLProblemLabel to localized string "There was a problem with the OnDemand URL. Make sure you've copied it correctly." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theOnDemandURLProblemLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + set branch_execution to "Main" + return branch_execution + end if + + -- Get name of the show - using web page to ensure what is shown is same as what user sees - search for: ","name":" and "\",\"url\":\"https://www.sbs.com.au/ondemand/tv-series/" + set start_SBS_show_name to (offset of "\",\"name\":\"" in SBS_show_page) + 10 + set end_SBS_show_name to (offset of "\",\"url\":\"https://www.sbs.com.au/ondemand/tv-series/" in SBS_show_page) - 1 + set SBS_show_name to text start_SBS_show_name thru end_SBS_show_name of SBS_show_page + set length_SBS_show_name to length of SBS_show_name + + -- Get season number + + -- Options for text strings that occur in two kinds of SBS show page found so far immediately before the Season number (usually "Season 1") + -- FROM \">

+ -- TO

" in SBS_show_page) + 86 + -- set end_SBS_seasonnumber to (offset of "

accViewWidth then set accViewWidth to minWidth + -- Need to force showing the last column - because theTop is < screen height * 0.5 + if theTop > first_box then + set accViewInset to accViewInset + set_Width + set accViewWidth to accViewWidth + set_Width + end if + -- Create rest of the dialog + set theCheckBoxAllLabel to localized string "All episodes" in bundle file path_to_MacYTDL from table "MacYTDL" + set {SBS_all_episodes_theCheckbox, theTop} to create checkbox theCheckBoxAllLabel left inset 0 bottom (at_Top + 15) max width 270 + set icon_top to theTop + set {boxes_instruct, theInstructionsTop} to create label instructions_text left inset 75 bottom (theTop + 20) max width accViewWidth - 75 aligns left aligned with multiline + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theInstructionsTop - 64 view width 64 view height 64 scale image scale proportionally + if theInstructionsTop is less than theTop then set theInstructionsTop to theTop + set {boxes_prompt, theTop} to create label diag_prompt left inset 0 bottom (theInstructionsTop + 10) max width accViewWidth aligns center aligned with bold type + set SBS_allControls to {theEpisodesRule, boxes_instruct, boxes_prompt, MacYTDL_icon, SBS_all_episodes_theCheckbox} & SBS_Checkboxes + -- Make sure MacYTDL is in front and show dialog + tell me to activate + set {SBS_button_returned, SBSButtonNumberReturned, SBS_controls_results} to display enhanced window diag_Title buttons theButtons acc view width accViewWidth acc view height theTop acc view controls SBS_allControls + + if SBSButtonNumberReturned is 2 then + -- Get checkbox results from SBS show dialog - process in reverse order - result will become "URL_user_entered" back in main_dialog() + set SBS_choice_1 to item 1 of SBS_controls_results -- <= Missing value [the rule] + set SBS_choice_2 to item 2 of SBS_controls_results -- <= Instructions + set SBS_choice_3 to item 3 of SBS_controls_results -- <= Prompt + set SBS_choice_4 to item 4 of SBS_controls_results -- <= Missing value [the icon] + set SBS_choice_5 to item 5 of SBS_controls_results -- <= All episodes checkbox + set SBS_show_choices to (items 6 thru end of SBS_controls_results) + set SBS_show_choices to reverse of (items 6 thru end of SBS_controls_results) -- <= Reverse choices to get URLs back into correct order + -- Get URLs corresponding to selected shows + set SBS_show_URLs to "" + -- If all episodes selected, set SBS_show_URLs to content of URL_list + if SBS_choice_5 then + set save_delimiters to AppleScript's text item delimiters + set AppleScript's text item delimiters to " " + set SBS_show_URLs to URL_list as text + set AppleScript's text item delimiters to save_delimiters + else + repeat with z from 1 to count of SBS_show_choices + if item z of SBS_show_choices is true then + if z is 1 then + set SBS_show_URLs to item 1 of URL_list + else + set SBS_show_URLs to SBS_show_URLs & " " & item z of URL_list + end if + end if + end repeat + end if + if SBS_show_URLs is "" then + set theCancelSBSLabel to localized string "You didn't select any SBS shows. Do you wish to download an SBS show or just return ?" in bundle file path_to_MacYTDL from table "MacYTDL" + set SBS_cancel_DL to button returned of (display dialog theCancelSBSLabel with title diag_Title buttons {theButtonReturnLabel, theButtonDownloadLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if SBS_cancel_DL is theButtonReturnLabel then + if skip_Main_dialog is true then error number -128 + set branch_execution to "Main" + return branch_execution + else + Get_SBS_Episodes(URL_user_entered, diag_Title, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL) + -- The recursion loops out here if user cancels 2nd instance of the SBS Chooser - cancel means user wants to return to Main Dialog + if skip_Main_dialog is true and ABC_show_URLs is "" then error number -128 + set branch_execution to "Download" + return branch_execution + end if + end if + if SBS_show_URLs is not "" then + if text 1 of SBS_show_URLs is " " then + set SBS_show_URLs to text 2 thru end of SBS_show_URLs + end if + set branch_execution to "Download" + return branch_execution + end if + else + -- User clicked on "Cancel" + if skip_Main_dialog is true then error number -128 + set myNum to 0 -- To make sure myNum doesn't cause SBS processing when not needed + set branch_execution to "Main" + return branch_execution + end if +end Get_SBS_Episodes + + +-------------------------------------------------------- +-- +-- Parse ABC iView web page to get episodes +-- +-------------------------------------------------------- + +-- Handler to parse ABC iView "Show" pages to get and show a list of episodes - ask user which episodes to download +on Get_ABC_Episodes(URL_user_entered, diag_Title, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL) + -- Get the entire web page from user's chosen URL + set ABC_show_page to do shell script "curl " & URL_user_entered + if ABC_show_page is "" then + set theiViewURLProblemLabel to localized string "There was a problem with the iView URLs. It looks like you tried to download from two or more separate show pages at the same time. MacYTDL can't do that at present. Try just one show page URL at a time. There is more info in Help." in bundle file path_to_MacYTDL from table "MacYTDL" + display dialog theiViewURLProblemLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + set branch_execution to "Main" + return branch_execution + return myNum + end if + -- Get name of the show - using web page to ensure what is shown is same as what user sees + set start_show_name to (offset of "\\\"title\\\":\\\"" in ABC_show_page) + 12 + set end_show_name to (offset of "\\\",\\\"displayTitle\\\":\\\"" in ABC_show_page) - 1 + set ABC_show_name to text start_show_name thru end_show_name of ABC_show_page + -- Get name of the show for use in accessing API web page + set start_show_name_api to (offset of "canonicalUrl\":\"https://iview.abc.net.au/show/" in ABC_show_page) + 45 + set end_show_name_api to (offset of "\",\"contentType\"" in ABC_show_page) - 1 + set show_name_api to text start_show_name_api thru end_show_name_api of ABC_show_page + -- Get the list of episodes from iView API and count number of episodes + set iView_API_URL to "https://iview.abc.net.au/api/series/" + set ABC_episodes_list to do shell script "curl " & iView_API_URL & show_name_api + + -- Are there any "Extras" videos ? If so, get text of extras API page and merge with episodes API page + -- NB Does not find extras which are stored under a different show name - which happened with "Employable Me" and "about" + set TID to text item delimiters + set text item delimiters to "Extras" + set are_there_extras to text items of ABC_show_page + if (count are_there_extras) is greater than 0 then + set show_name_api to show_name_api & "-extras" + set ABC_extras_list to do shell script "curl " & iView_API_URL & show_name_api + -- Add the word "Extra - " to title of each extra video + set ABC_extras_list to replace_chars(ABC_extras_list, "\"title\":\"", "\"title\":\"Extra - ") + set ABC_episodes_list to ABC_episodes_list & ABC_extras_list + end if + set text item delimiters to TID + + -- Count the number of occurrences (= number of episodes) - note that if none are found there is still 1 item + set AppleScript's text item delimiters to "\"title\":\"" + set myNum to the (number of text items in ABC_episodes_list) - 1 -- <= Means we know how many loops to do to get all the episode URLs + -- Initiate the three lists: occurrences, names and URLs + set occurrences to {} + set name_list to {} + set URL_list to {} + -- This bit seems to be necessary but I don't yet understand why -- mynum can be zero but causes no error + repeat (myNum) times + set end of occurrences to "" + set end of name_list to "" + set end of URL_list to "" + end repeat + + -- If mynum is 0 (because there are no occurrences of episode title), assume this is a single show page with no separate episodes listed - Means only need to find the URL and then move to downloading - no need for the Choose ABC shows dialog - but, will need to make the file name later + -- If myNum is 1, it's a single episode show page and can be treated in the same way + -- BUT, WE DO HAVE THE SHOW NAME FOR THESE SO, THERE'S NO NEED FOR THE PALAVER + -- Could also put the myNum cases into here too + set ABC_base_URL to "https://iview.abc.net.au/show/" + if myNum is 0 or myNum is 1 then + set AppleScript's text item delimiters to "href\":\"programs\\" + set show_URL_start to text 2 through end of text item 2 of ABC_episodes_list + set AppleScript's text item delimiters to "\",\"" + set ABC_show_URLs_part to ABC_base_URL & text 1 through end of text item 1 of show_URL_start -- Get the URL (one) + set ABC_show_URLs to replace_chars(ABC_show_URLs_part, "\\", "/video") + set AppleScript's text item delimiters to "" + if myNum is 0 then + set YTDL_output_template to " -o '%(title)s.%(ext)s'" + end if + set branch_execution to "Download" + return branch_execution + return myNum + else + -- Populate the lists of names and URLs - Repeat for each occurrence of an episode found in the API call results + repeat with i from 1 to myNum + set item (i) of occurrences to text item (i + 1) of ABC_episodes_list --<= Get text of each occurrence - current delimiter is "\"title\":\"" + set AppleScript's text item delimiters to "\",\"href" + set item (i) of name_list to text 1 through end of text item 1 of item (i) of occurrences --<= Get each episode name from each occurrence + set AppleScript's text item delimiters to "href\":\"programs\\" + set show_URL_start to text 2 through end of text item 2 of item (i) of occurrences --<= Get starting point for each URL + set AppleScript's text item delimiters to "\",\"" + set item (i) of URL_list to ABC_base_URL & replace_chars(text 1 through end of text item 1 of show_URL_start, "\\", "/video") -- Get end of each URL from starting point to end of item + set AppleScript's text item delimiters to "\"title\":\"" --<= Needed to get next occurrence + end repeat + end if + set AppleScript's text item delimiters to "" + + -- Form up the Choose episodes dialog + if myNum is greater than 0 then + -- Reverse name_list as DTP code creates each checkbox strictly in the order processed - reversing the order of items in the list of checkboxes has no effect + -- Note, some ABC show pages have episodes in reverse order anyway + set reverse_name_list to reverse of name_list + + -- Set variables for the ABC episode choice dialog + set theiViewInstructions1Label to localized string "Select which episodes of" in bundle file path_to_MacYTDL from table "MacYTDL" + set theiViewInstructions2Label to localized string "that you wish to download then click on Download or press Return. You can select any combination." in bundle file path_to_MacYTDL from table "MacYTDL" + set instructions_text to theiViewInstructions1Label & " \"" & ABC_show_name & "\" " & theiViewInstructions2Label + set theiViewShowsDiagPromptLabel to localized string "MacYTDL – Choose ABC Shows" in bundle file path_to_MacYTDL from table "MacYTDL" + set diag_prompt to theiViewShowsDiagPromptLabel + set accViewWidth to 0 + set accViewInset to 0 + + -- Set buttons and controls - need to loop through episodes + set {theButtons, minWidth} to create buttons {theButtonCancelLabel, theButtonDownloadLabel} button keys {".", "d"} default button 2 + set {theEpisodesRule, theTop} to create rule 10 rule width 900 + set ABC_Checkboxes to {} + -- Add space between the rule and the first checkbox + set theTop to theTop + 15 + set first_box to theTop + set set_Width to 0 + set number_cols to 1 + + -- Set up factors to vary size of dialog according to screen height + set screen_height to screen_height as integer + if screen_height is less than 900 then set height_conversion_factor to 1.25 + if screen_height is less than 1200 and screen_height is greater than 899 then set height_conversion_factor to 1.1 + if screen_height is less than 1600 and screen_height is greater than 1080 then set height_conversion_factor to 1 + if screen_height is less than 2304 and screen_height is greater than 1440 then set height_conversion_factor to 0.875 + if screen_height is greater than 2303 then set height_conversion_factor to 0.625 + set screen_height_points to screen_height * height_conversion_factor + + -- Show checkboxes for all the episodes on the chosen ABC show page - show boxes down and across the dialog + -- Trim off long episode titles if screen res is small and number of episodes more than 50 + repeat with j from 1 to (myNum) + if X_position is less than 160 and myNum is greater than 50 then + if length of (item j of reverse_name_list) is greater than 30 then + set episode_name_short to text 1 through 30 of (item j of reverse_name_list) + set {aCheckbox, theTop, theWidth} to create checkbox episode_name_short left inset accViewInset bottom (theTop + 2) max width 270 + else + set {aCheckbox, theTop, theWidth} to create checkbox (item j of reverse_name_list) left inset accViewInset bottom (theTop + 2) max width 270 + end if + else + set {aCheckbox, theTop, theWidth} to create checkbox (item j of reverse_name_list) left inset accViewInset bottom (theTop + 2) max width 270 + end if + -- Need to get the width of the widest row in this column - adding up those widths gives the accViewWidth + if set_Width is less than theWidth then + set set_Width to theWidth + end if + -- Build the collection of checkboxes + set end of ABC_Checkboxes to aCheckbox + -- Increment window width and reset vertical and horizontal position of further checkboxes + if theTop is greater than screen_height_points * 0.5 then + set number_cols to number_cols + 1 + set at_Top to theTop + set theTop to first_box + set accViewInset to accViewInset + set_Width + set accViewWidth to accViewWidth + set_Width + set set_Width to 0 + end if + end repeat + -- One column - Need to reset distance to top of theRule to prevent a second blank column but retain distance to top of final checkbox + -- And, make sure accesssory is wide enough to display the instructions + if number_cols = 1 then + set at_Top to theTop + set theTop to first_box + if accViewWidth is less than 260 then set accViewWidth to 300 + end if + -- Dialog too narrow causes instructions to wrap too much + if minWidth > accViewWidth then set accViewWidth to minWidth + -- Need to force showing the last column - tricky + if theTop > first_box then + set accViewInset to accViewInset + set_Width + set accViewWidth to accViewWidth + set_Width + end if + -- Create rest of the dialog + set theCheckBoxAllLabel to localized string "All episodes" in bundle file path_to_MacYTDL from table "MacYTDL" + set {ABC_all_episodes_theCheckbox, theTop} to create checkbox theCheckBoxAllLabel left inset 0 bottom (at_Top + 15) max width 270 + set icon_top to theTop + set {boxes_instruct, theInstructionsTop} to create label instructions_text left inset 75 bottom (theTop + 20) max width accViewWidth - 75 aligns left aligned with multiline + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom icon_top + 20 view width 64 view height 64 scale image scale proportionally + if theInstructionsTop is less than theTop then set theInstructionsTop to theTop + set {boxes_prompt, theTop} to create label diag_prompt left inset 0 bottom (theInstructionsTop + 10) max width accViewWidth aligns center aligned with bold type + set ABC_allControls to {theEpisodesRule, boxes_instruct, boxes_prompt, MacYTDL_icon, ABC_all_episodes_theCheckbox} & ABC_Checkboxes + -- Make sure MacYTDL is in front and show dialog + tell me to activate + set {ABC_button_returned, ABCButtonNumberReturned, ABC_controls_results} to display enhanced window diag_Title buttons theButtons acc view width accViewWidth acc view height theTop acc view controls ABC_allControls + + if ABCButtonNumberReturned is 2 then + -- Get checkbox results from ABC show dialog - process in reverse order - result will become "URL_user_entered" back in main_dialog() + set ABC_choice_1 to item 1 of ABC_controls_results -- <= Missing value [the rule] + set ABC_choice_2 to item 2 of ABC_controls_results -- <= Instructions + set ABC_choice_3 to item 3 of ABC_controls_results -- <= Prompt + set ABC_choice_4 to item 4 of ABC_controls_results -- <= Missing value [the icon] + set ABC_choice_5 to item 5 of ABC_controls_results -- <= All episodes checkbox + set ABC_show_choices to reverse of (items 6 thru end of ABC_controls_results) -- <= Reverse choices to get back into correct order + -- Get URLs corresponding to selected shows + set ABC_show_URLs to "" + -- If all episodes selected, set ABC_show_URLs to content of URL_list + if ABC_choice_5 then + set save_delimiters to AppleScript's text item delimiters + set AppleScript's text item delimiters to " " + set ABC_show_URLs to URL_list as text + set AppleScript's text item delimiters to save_delimiters + else + repeat with z from 1 to count of ABC_show_choices + if item z of ABC_show_choices is true then + if z is 1 then + set ABC_show_URLs to item 1 of URL_list + else + set ABC_show_URLs to ABC_show_URLs & " " & item z of URL_list + end if + end if + end repeat + end if + if ABC_show_URLs is "" then + set theCancelABCLabel to localized string "You didn't select any ABC shows. Do you wish to download an ABC show or just return ?" in bundle file path_to_MacYTDL from table "MacYTDL" + set ABC_cancel_DL to button returned of (display dialog theCancelABCLabel with title diag_Title buttons {theButtonReturnLabel, theButtonDownloadLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if ABC_cancel_DL is theButtonReturnLabel then + if skip_Main_dialog is true then error number -128 + set branch_execution to "Main" + return branch_execution + return myNum + else + Get_ABC_Episodes(URL_user_entered, diag_Title, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL) + -- The recursion loops out here if user cancels 2nd instance of the SBS Chooser - cancel means user wants to return + if skip_Main_dialog is true and ABC_show_URLs is "" then error number -128 + set branch_execution to "Download" + return branch_execution + return myNum + end if + end if + if text 1 of ABC_show_URLs is " " then + set ABC_show_URLs to text 2 thru end of ABC_show_URLs + end if + set branch_execution to "Download" + return branch_execution + return myNum + else + if skip_Main_dialog is true then error number -128 + set myNum to 0 -- To make sure myNum doesn't cause ABC processing when not needed + set branch_execution to "Main" + return branch_execution + return myNum + end if + end if +end Get_ABC_Episodes + + +--------------------------------------------------- +-- +-- Show settings before download +-- +--------------------------------------------------- + +-- Handler to show current settings before commencing download if user has specified that in Settings +on show_settings(YTDL_subtitles, DL_Remux_original, DL_YTDL_auto_check, DL_STEmbed, DL_audio_only, YTDL_description, DL_Limit_Rate, DL_over_writes, DL_Thumbnail_Write, DL_verbose, DL_Thumbnail_Embed, DL_Add_Metadata, DL_Use_Proxy, DL_Use_Cookies, DL_Use_Custom_Template, DL_Use_Custom_Settings, remux_format_choice, DL_TimeStamps, DL_Use_YTDLP, YTDL_version, folder_chosen, theButtonQuitLabel, theButtonCancelLabel, theButtonDownloadLabel, DL_Show_Settings, MacYTDL_prefs_file, MacYTDL_custom_icon_file_posix, diag_Title) + + -- Convert boolean settings to text to enable list of current settings to be shown intelligibly in "Show Settings" dialog + if YTDL_subtitles contains "--write-sub" then + set MDDL_subtitles to "Yes" + else + set MDDL_subtitles to "No" + end if + if YTDL_subtitles contains "--write-auto-sub" then + set MDDL_Auto_subtitles to "Yes" + else + set MDDL_Auto_subtitles to "No" + end if + if DL_Remux_original is true then + set MDDL_Remux_original to "Yes" + else + set MDDL_Remux_original to "No" + end if + if DL_YTDL_auto_check is true then + set MDDL_YTDL_auto_check to "Yes" + else + set MDDL_YTDL_auto_check to "No" + end if + if DL_STEmbed is true then + set MDDL_STEmbed to "Yes" + else + set MDDL_STEmbed to "No" + end if + if DL_audio_only is true then + set MDDL_audio_only to "Yes" + else + set MDDL_audio_only to "No" + end if + if YTDL_description is "--write-description " then + set MDDL_description to "Yes" + else + set MDDL_description to "No" + end if + if DL_Limit_Rate is true then + set MDDL_Limit_Rate to DL_Limit_Rate_Value & " MB/sec" + else + set MDDL_Limit_Rate to "No" + end if + if DL_over_writes is false then + set MDDL_over_writes to "No" + else + set MDDL_over_writes to "Yes" + end if + if DL_Thumbnail_Write is true then + set MDDL_Thumbnail_Write to "Yes " + else + set MDDL_Thumbnail_Write to "No" + end if + if DL_verbose is true then + set MDDL_verbose to "Yes" + else + set MDDL_verbose to "No" + end if + if DL_Thumbnail_Embed is true then + set MDDL_Thumbnail_Embed to "Yes" + else + set MDDL_Thumbnail_Embed to "No" + end if + if DL_Add_Metadata is true then + set MDDL_Add_Metadata to "Yes" + else + set MDDL_Add_Metadata to "No" + end if + if DL_Use_Proxy is true then + set MDDL_Use_Proxy to DL_Proxy_URL + else + set MDDL_Use_Proxy to "No" + end if + if DL_Use_Cookies is true then + set MDDL_Use_Cookies to DL_Cookies_Location + else + set MDDL_Use_Cookies to "No" + end if + if DL_Use_Custom_Template is true then + set MDDL_Use_Template to DL_Custom_Template + else + set MDDL_Use_Template to "No" + end if + if DL_TimeStamps is true then + set MDDL_TimeStamps to "Yes" + else + set MDDL_TimeStamps to "No" + end if + if DL_Use_Custom_Settings is true then + set MDDL_Use_Settings to DL_Custom_Settings + else + set MDDL_Use_Settings to "No" + end if + if DL_formats_list is true then + set MDDL_DL_formats_list to "Yes" + else + set MDDL_DL_formats_list to "No" + end if + if DL_QT_Compat is true then + set MDDL_DL_QT_Compat to "Yes" + else + set MDDL_DL_QT_Compat to "No" + end if + + -- Set contents of optional subtitles embedded status and format - only shows if subtitles are requested + -- Ditto with whether to keep original after remuxing, embedded thumbnails, proxy, cookies and template + set subtitles_embedded_pref to "" + if MDDL_subtitles is "Yes" then + set theShowSettingsPromptTextSTEmbedLabel to localized string "Embedded:" from table "MacYTDL" + set subtitles_embedded_pref to return & theShowSettingsPromptTextSTEmbedLabel & tab & tab & tab & MDDL_STEmbed + end if + set subtitles_format_pref to "" + if DL_subtitles is true and DL_STEmbed is false then + set theShowSettingsPromptTextSTFormatLabel to localized string "Format:" from table "MacYTDL" + set subtitles_format_pref to tab & tab & theShowSettingsPromptTextSTFormatLabel & tab & tab & DL_subtitles_format + end if + set keep_original_pref to "" + if DL_Remux_format is not "No remux" or YTDL_subtitles contains "convert" then + set theShowSettingsPromptTextKeepOrigtLabel to localized string "Keep original file(s):" from table "MacYTDL" + set keep_original_pref to return & theShowSettingsPromptTextKeepOrigtLabel & tab & MDDL_Remux_original + end if + set theShowSettingsPromptTextEmbedThumbLabel to localized string "Embed thumbnails:" from table "MacYTDL" + set thumbnails_embed_pref to theShowSettingsPromptTextEmbedThumbLabel & tab & MDDL_Thumbnail_Embed + + -- Set variables for the Show Settings dialog + set theShowSettingsPromptTextFolderLabel to localized string "Download folder:" from table "MacYTDL" + set theShowSettingsPromptTextYTDLLabel to DL_Use_YTDLP & " " & (localized string "version:" from table "MacYTDL") + set theShowSettingsPromptTextFFmpegLabel to localized string "FFmpeg version:" from table "MacYTDL" + set theShowSettingsPromptTextFormatLabel to localized string "Download file format:" from table "MacYTDL" + set theShowSettingsPromptTextAudioLabel to localized string "Audio only:" from table "MacYTDL" + set theShowSettingsPromptTextDescriptionLabel to localized string "Description:" from table "MacYTDL" + set theShowSettingsPromptTextSTLabel to localized string "Download subtitles:" from table "MacYTDL" + set theShowSettingsPromptTextAutoSTLabel to localized string "Auto subtitles:" from table "MacYTDL" + set theShowSettingsPromptTextRemuxLabel to localized string "Remux download:" from table "MacYTDL" + set theShowSettingsPromptTextThumbsLabel to localized string "Write thumbnails:" from table "MacYTDL" + set theShowSettingsPromptTextVerboseLabel to localized string "Verbose logging:" from table "MacYTDL" + set theShowSettingsPromptTextTimeStampsLabel to localized string "Add timestamps:" from table "MacYTDL" + set theShowSettingsPromptTextMetaDataLabel to localized string "Add metadata:" from table "MacYTDL" + set theShowSettingsPromptTextOverWriteLabel to localized string "Force overwrites:" from table "MacYTDL" + set theShowSettingsPromptTextLimitSpeedLabel to localized string "Limit download speed:" from table "MacYTDL" + set theShowSettingsPromptTextUseProxyLabel to localized string "Use proxy:" from table "MacYTDL" + set theShowSettingsPromptTextUseCookiesLabel to localized string "Use cookies:" from table "MacYTDL" + set theShowSettingsPromptTextUseTemplateLabel to localized string "Custom template:" from table "MacYTDL" + set theShowSettingsPromptTextUseSettingsLabel to localized string "Custom settings:" from table "MacYTDL" + set theShowSettingsPromptTextDLQTLabel to localized string "QT compatible:" from table "MacYTDL" + set theShowSettingsPromptTextGetFormatsLabel to localized string "Get formats list:" from table "MacYTDL" + set diag_prompt_text_1 to theShowSettingsPromptTextFolderLabel & tab & tab & folder_chosen & return & theShowSettingsPromptTextYTDLLabel & tab & tab & YTDL_version & return & theShowSettingsPromptTextFFmpegLabel & tab & tab & ffmpeg_version & return & theShowSettingsPromptTextFormatLabel & tab & DL_format & return & theShowSettingsPromptTextAudioLabel & tab & tab & tab & MDDL_audio_only & return & theShowSettingsPromptTextDescriptionLabel & tab & tab & tab & MDDL_description & return & theShowSettingsPromptTextSTLabel & tab & MDDL_subtitles & subtitles_format_pref & subtitles_embedded_pref & return & theShowSettingsPromptTextAutoSTLabel & tab & tab & MDDL_Auto_subtitles & return & theShowSettingsPromptTextRemuxLabel & tab & tab & remux_format_choice & keep_original_pref & return & theShowSettingsPromptTextThumbsLabel & tab & tab & MDDL_Thumbnail_Write & return & thumbnails_embed_pref & return & theShowSettingsPromptTextVerboseLabel & tab & tab & MDDL_verbose & return & theShowSettingsPromptTextTimeStampsLabel & tab & tab & MDDL_TimeStamps & return & theShowSettingsPromptTextMetaDataLabel & tab & tab & MDDL_Add_Metadata & return & theShowSettingsPromptTextOverWriteLabel & tab & tab & MDDL_over_writes & return & theShowSettingsPromptTextLimitSpeedLabel & tab & MDDL_Limit_Rate & return & theShowSettingsPromptTextDLQTLabel & tab & tab & MDDL_DL_QT_Compat & return & theShowSettingsPromptTextUseProxyLabel & tab & tab & tab & MDDL_Use_Proxy & return & theShowSettingsPromptTextUseCookiesLabel & tab & tab & tab & MDDL_Use_Cookies & return & theShowSettingsPromptTextGetFormatsLabel & tab & tab & MDDL_DL_formats_list & return & theShowSettingsPromptTextUseTemplateLabel & tab & tab & MDDL_Use_Template & return & theShowSettingsPromptTextUseSettingsLabel & tab & tab & MDDL_Use_Settings + set show_settings_diag_promptLabel to localized string "Settings for this download" from table "MacYTDL" + set show_settings_diag_prompt to show_settings_diag_promptLabel + set accViewWidth to 375 + set accViewInset to 70 + + -- Set buttons and controls + set theButtonsShowSettingsEditLabel to localized string "Edit settings" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonQuitLabel, theButtonsShowSettingsEditLabel, theButtonCancelLabel, theButtonDownloadLabel} button keys {"q", "e", ".", "d"} default button 4 + if minWidth > accViewWidth then set accViewWidth to minWidth + set {theShowSettingsRule, theTop} to create rule 10 rule width accViewWidth + set show_settings_theCheckboxLabel to localized string "Show settings before download" from table "MacYTDL" + set {show_settings_theCheckbox, theTop} to create checkbox show_settings_theCheckboxLabel left inset 20 bottom (theTop + 15) max width accViewWidth initial state DL_Show_Settings + set {diag_prompt_1, theTop} to create label diag_prompt_text_1 left inset accViewInset bottom theTop + 15 max width accViewWidth - 75 control size regular size + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 60 view width 64 view height 64 scale image scale proportionally + set {show_settings_prompt, theTop} to create label show_settings_diag_prompt left inset 0 bottom theTop + 5 max width minWidth aligns center aligned with bold type + + set show_settings_allControls to {theShowSettingsRule, show_settings_theCheckbox, diag_prompt_1, MacYTDL_icon, show_settings_prompt} + + -- Make sure MacYTDL is in front and show dialog + tell me to activate + set {show_settings_button_returned, showSettingsButtonNumberReturned, show_settings_controls_results} to display enhanced window diag_Title buttons theButtons acc view width accViewWidth acc view height theTop acc view controls show_settings_allControls + + -- Update show settings setting if user has changed it + set show_settings_choice to item 2 of show_settings_controls_results -- <= User has changed the setting + if show_settings_choice is not equal to DL_Show_Settings then + set DL_Show_Settings to show_settings_choice + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Show_Settings_before_Download" to show_settings_choice + end tell + end tell + end if + set branch_execution to "Download" + if showSettingsButtonNumberReturned is 3 then + set branch_execution to "Main" + else if showSettingsButtonNumberReturned is 2 then + set branch_execution to "Settings" + else if showSettingsButtonNumberReturned is 1 then + set branch_execution to "Quit" + end if + return branch_execution +end show_settings + + +--------------------------------------------------- +-- +-- Find and Replace +-- +--------------------------------------------------- + +-- Handler to find-replace text inside a string +on replace_chars(this_text, search_string, replacement_string) + set AppleScript's text item delimiters to the search_string + set the item_list to every text item of this_text + set AppleScript's text item delimiters to the replacement_string + set this_text to the item_list as text + set AppleScript's text item delimiters to "" + return this_text +end replace_chars + +------------------------------------------------------------- +-- +-- Find offset of last search string in a String +-- +------------------------------------------------------------- + +-- Handler to find offset of last specified character in a string +on last_offset(the_object_string, the_search_string) + try + set astid to AppleScript's text item delimiters + set AppleScript's text item delimiters to the_object_string + set last_occurrence_offset to (count the_search_string) - (count text item -1 of the_search_string) + set AppleScript's text item delimiters to astid + return last_occurrence_offset + on error + return 0 + end try +end last_offset diff --git a/Code/adviser.applescript b/Code/adviser.applescript new file mode 100644 index 0000000..11c3048 --- /dev/null +++ b/Code/adviser.applescript @@ -0,0 +1,241 @@ +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- MacYTDL +-- A GUI for the Python Scripts youtube-dl and yt-dlp. Many thanks to Shane Stanley +-- This is the Adviser - advises user when download complete - give options if download failed +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +-- Include libraries +use AppleScript version "2.4" -- Yosemite (10.10) or later +use scripting additions + +-- This script provides an Adviser for each video file download requested by user in Main Dialog - it is called by monitor.scpt + +on run {monitor_pid, youtubedl_pid, MacYTDL_custom_icon_file_not_posix_monitor, MacYTDL_preferences_path_monitor, YTDL_log_file_monitor, downloadsFolder_Path_monitor, diag_Title_quoted_monitor, DL_description_monitor, is_Livestream_Flag_monitor, download_filename_monitor, download_filename_new_monitor, download_filename_new_monitor_plain, YTDL_simulate_log_monitor} + + -- try + + --********************************************* + -- dialog for checking values passed from Monitor script + -- display dialog "monitor_pid: " & monitor_pid & return & return & "MacYTDL_custom_icon_file_not_posix_monitor: " & MacYTDL_custom_icon_file_not_posix_monitor & return & return & "MacYTDL_preferences_path_monitor: " & MacYTDL_preferences_path_monitor & return & return & "YTDL_log_file_monitor: " & YTDL_log_file_monitor & return & return & "downloadsFolder_Path_monitor: " & downloadsFolder_Path_monitor & return & return & "diag_Title_quoted_monitor: " & diag_Title_quoted_monitor & return & return & "DL_description_monitor: " & DL_description_monitor & return & return & "is_Livestream_Flag_monitor: " & is_Livestream_Flag_monitor & return & return & "download_filename_monitor: \"" & download_filename_monitor & "\"" & return & return & "download_filename_new_monitor: " & download_filename_new_monitor & return & return & "download_filename_new_monitor_plain: " & download_filename_new_monitor_plain & return & return & "YTDL_simulate_log_monitor: \"" & YTDL_simulate_log_monitor & "\"" with title "Adviser" + --********************************************* + + -- display dialog "Sorting out filename variables" & return & "download_filename_monitor: " & download_filename_monitor & return & "download_filename_new_monitor: " & download_filename_new_monitor & return & "download_filename_new_monitor_plain: " & return & download_filename_new_monitor_plain + + -- Set variable to contain path to MacYTDL bundle - to enable localized text and Alerter tool to be found + set pathToBundle to (path to me) as text + set pathToBundleShort to text 1 thru -40 of pathToBundle + set alerterPath to quoted form of (POSIX path of (pathToBundleShort & "Contents:Resources:")) + + -- Set up to enable Adviser to open the log file + set YTDL_log_file_monitor to POSIX file YTDL_log_file_monitor + + -- Some downloads come thru with multiple file names - isolate the first so it can be played when download finished + set num_paragraphs_file_name to count of paragraphs in download_filename_monitor + if num_paragraphs_file_name is greater than 1 then + repeat with find_paragraph in paragraphs of download_filename_monitor + if find_paragraph does not contain "ERROR:" and find_paragraph does not contain "WARNING:" then + set download_filename_play to find_paragraph + exit repeat + end if + end repeat + else + set download_filename_play to download_filename_new_monitor_plain + end if + + -- For a batch need to get download file name from different variable - need to remove quotes - THIS SECTION LOOKS AT WRONG VARIABLE !? + if download_filename_new_monitor is "the saved batch" then + set download_filename_play to download_filename_monitor + end if + + -- Check Monitor process every 2 seconds until it disappears from process list - surrogate for completed download + prevents alert showing at same time as Monitor + -- But, DL can continue after Monitor process ceases so, check on youtubedl_pid also, before posting Adviser + try + repeat + -- does the monitor_pid exist? + do shell script "ps -p" & monitor_pid + delay 2 + end repeat + on error + try + repeat + -- does the PID exist? + do shell script "ps -p" & youtubedl_pid + delay 2 + end repeat + on error + + -- monitor_pid has disappeared - test for download error, advise user accordingly, show Adviser alert, open logs or downloads, or do nothing as desired + -- Change extension of description file(s) to txt if description is requested by user and file exists - using shell has risks but is quick + if DL_description_monitor is "Yes" then + try + do shell script "for file in " & quoted form of downloadsFolder_Path_monitor & "/*.description; do mv \"$file\" \"${file/.description/.txt}\" > /dev/null 2> /dev/null ; done" + end try + end if + + set theAdviserButtonsCloseLabel1 to localized string "Close" in bundle file pathToBundleShort from table "MacYTDL" + set subtitleText to quoted form of ("“" & download_filename_new_monitor_plain & "”") + -- Get log file content into a variable so it can be checked for the 100% - which if not present suggests there was a download error + -- 4/3/23 - Add delay as it seems, sometimes, the log file is not free or is locked + delay 1 + set error39 to false + try + set YTDL_log to read file YTDL_log_file_monitor as «class utf8» + on error errmsg + if errmsg contains "End of file" then + set error39 to true + else + display dialog "Error in Adviser reading log file: " & YTDL_log_file_monitor & return & "The error reported was " & errmsg + end if + end try + if (YTDL_log contains "100%" or is_Livestream_Flag_monitor is "True") and YTDL_log does not contain "ERROR:" then + -- Download completed without errors - if YTDL merged into mkv, update extension in download_filename_play - but not if user has chosen to recode + if (YTDL_log contains "Requested formats are incompatible for merge and will be merged into mkv" or YTDL_log contains "doesn't support embedding a thumbnail, mkv will be used") and YTDL_log does not contain "Converting video from mkv to " then + set start_extension to offset of "." in download_filename_play + set download_filename_play to (text 1 thru start_extension of download_filename_play) & "mkv" + end if + if YTDL_log contains "There are no subtitles for the requested languages" then + set theAdviserTextLabel1 to quoted form of (localized string "Finished - but no subtitles:" in bundle file pathToBundleShort from table "MacYTDL") + else + set theAdviserTextLabel1 to quoted form of (localized string "MacYTDL download finished:" in bundle file pathToBundleShort from table "MacYTDL") + end if + set theAdviserTextLabel2 to quoted form of (localized string "Click to open downloads folder" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserButtonsCloseLabel2 to localized string "Play" in bundle file pathToBundleShort from table "MacYTDL" + set adviser_button to do shell script alerterPath & "/alerter -message " & theAdviserTextLabel2 & " -title " & theAdviserTextLabel1 & " -subtitle " & subtitleText & " -closeLabel " & theAdviserButtonsCloseLabel1 & " -timeout 10 -sender com.apple.script.id.MacYTDL -actions " & theAdviserButtonsCloseLabel2 + + -- User chose to play the finished download - or the first item of a batch, playlist or multiple download + if adviser_button is theAdviserButtonsCloseLabel2 then + -- If download is a recorded live stream, get file name from log file as it can be different to name found in simulation - beware of date-time stamps + -- Look for cases in which downloads are merged + set number_of_log_paras to count of paragraphs in YTDL_log + repeat with x from number_of_log_paras to 1 by -1 + set find_paragraph to paragraph x of YTDL_log + if is_Livestream_Flag_monitor is "True" then + if find_paragraph contains "[download] Destination:" then + set offset_download to offset of "[download] Destination:" in find_paragraph + set download_filename_play to text (offset_download + 24) thru end of find_paragraph + exit repeat + end if + else if find_paragraph contains "; Destination: " then + set offset_download to offset of "; Destination: " in find_paragraph + set download_filename_play to text (offset_download + 15) thru end of find_paragraph + exit repeat + else if find_paragraph contains "[Merger] Merging formats into" then + set offset_download to offset of "[Merger] Merging formats into" in find_paragraph + set length_of_found_paragraph to (count of characters in find_paragraph) - 1 -- Trim off the last double quote + set download_filename_play to text (offset_download + 31) thru length_of_found_paragraph of find_paragraph + exit repeat + end if + if find_paragraph contains " [download] 100% of " then + exit repeat + end if + end repeat + + -- Did user specify download location in custom template - if so, downloadsFolder_Path_monitor can be omitted + if download_filename_play contains "Users" then + set pathToVideoFile to POSIX file (download_filename_play) + else + set pathToVideoFile to POSIX file (downloadsFolder_Path_monitor & "/" & download_filename_play) + end if + tell application "Finder" + -- tell application "System Events" to open file pathToVideoFile -- Decided to switch to Finder + open pathToVideoFile as alias + end tell + -- end if + else if adviser_button is "@CONTENTCLICKED" then + tell application "Finder" + activate + open (downloadsFolder_Path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + end if + -- If batch download completed without error, delete URLs from batch file + if download_filename_new_monitor is "the saved batch" then + set batch_filename to "BatchFile.txt" as string + set batch_file to POSIX file (MacYTDL_preferences_path_monitor & batch_filename) + try + set batch_file_ref to missing value + set batch_file_ref to open for access file batch_file with write permission + set eof batch_file_ref to 0 + close access batch_file_ref + on error batch_errMsg + display dialog "There was an error: " & batch_errMsg & "batch_file: " & batch_file buttons {"OK"} default button {"OK"} + try + close access batch_file_ref + end try + end try + end if + else if YTDL_log contains "ERROR:" or error39 is true then + -- Download had errors + set theAdviserTextLabel1 to quoted form of (localized string "MacYTDL download error with:" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserTextLabel2 to quoted form of (localized string "Click to open downloads or Options" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserButtonsCloseLabel2 to localized string "Options" in bundle file pathToBundleShort from table "MacYTDL" + set theAdviserButtonsCloseLabel3 to quoted form of (localized string "Open Log" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserButtonsCloseLabel4 to quoted form of (localized string "Show Logs" in bundle file pathToBundleShort from table "MacYTDL") + set adviser_button to do shell script alerterPath & "/alerter -message " & theAdviserTextLabel2 & " -title " & theAdviserTextLabel1 & " -subtitle " & subtitleText & " -closeLabel " & theAdviserButtonsCloseLabel1 & " -timeout 20 -sender com.apple.script.id.MacYTDL -actions " & theAdviserButtonsCloseLabel3 & "," & theAdviserButtonsCloseLabel4 & " -dropdownLabel " & theAdviserButtonsCloseLabel2 + if adviser_button is text 2 thru -2 of theAdviserButtonsCloseLabel3 then + -- Substituted ASOC code in a separate handler until Apple fix the bug ! + set theFile to POSIX path of YTDL_log_file_monitor + openFile(theFile) + else if adviser_button is text 2 thru -2 of theAdviserButtonsCloseLabel4 then + tell application "Finder" + activate + open (MacYTDL_preferences_path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + else if adviser_button is "@CONTENTCLICKED" then + tell application "Finder" + activate + open (downloadsFolder_Path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + end if + else if YTDL_log does not contain "ERROR:" and YTDL_log does not contain "100%" and YTDL_log does not contain "has already been downloaded" and is_Livestream_Flag_monitor is "False" then + -- Download not completed but no errors reported + set theAdviserTextLabel1 to quoted form of (localized string "MacYTDL download incomplete:" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserTextLabel2 to quoted form of (localized string "Click \"Options\" to troubleshoot." in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserButtonsCloseLabel2 to localized string "Options" in bundle file pathToBundleShort from table "MacYTDL" + set theAdviserButtonsCloseLabel3 to quoted form of (localized string "Open Log" in bundle file pathToBundleShort from table "MacYTDL") + set theAdviserButtonsCloseLabel4 to quoted form of (localized string "Show Logs" in bundle file pathToBundleShort from table "MacYTDL") + set adviser_button to do shell script alerterPath & "/alerter -message " & theAdviserTextLabel2 & " -title " & theAdviserTextLabel1 & " -subtitle " & subtitleText & " -closeLabel " & theAdviserButtonsCloseLabel1 & " -timeout 20 -sender com.apple.script.id.MacYTDL -actions " & theAdviserButtonsCloseLabel3 & "," & theAdviserButtonsCloseLabel4 & " -dropdownLabel " & theAdviserButtonsCloseLabel2 + if adviser_button is text 2 thru -2 of theAdviserButtonsCloseLabel3 then + -- Substituted ASOC code in a separate handler until Apple fix the bug ! + set theFile to POSIX path of YTDL_log_file_monitor + openFile(theFile) + else if adviser_button is text 2 thru -2 of theAdviserButtonsCloseLabel4 then + tell application "Finder" + activate + open (MacYTDL_preferences_path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + else if adviser_button is "@CONTENTCLICKED" then + tell application "Finder" + activate + open (downloadsFolder_Path_monitor as POSIX file) + set the position of the front Finder window to {100, 100} + end tell + end if + end if + end try + end try + + + + -- on error errmsg + -- display dialog errmsg + -- end try + + +end run + +on openFile(theFile) -- theFile is POSIX path + script theScript + use framework "AppKit" + use framework "Foundation" + on openTheFile(theFile) + set theWorkSpace to current application's NSWorkspace's sharedWorkspace() + set theFile to current application's |NSURL|'s fileURLWithPath:theFile + theWorkSpace's openURL:theFile + end openTheFile + end script + theScript's openTheFile(theFile) +end openFile diff --git a/Code/main.applescript b/Code/main.applescript new file mode 100644 index 0000000..b5192a5 --- /dev/null +++ b/Code/main.applescript @@ -0,0 +1,4407 @@ +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- MacYTDL +-- A GUI for the Python scripts youtube-dl and yt-dlp. Many thanks to Shane Stanley, Adam Albrec, kopurando and Michael Page +-- Trying to bring in useful functions in a pithy GUI with few AppleScript extensions and without AppleScriptObjC +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Include libraries - needed for Shane Staney's Dialog Toolkit +use AppleScript version "2.4" -- Yosemite (10.10) or later +use scripting additions +use script "DialogToolkitMacYTDL" +property parent : AppleScript + + +-- Set variables and default values +-- Variables which need to be controlled across more than one handler +global diag_prompt +global diag_Title +global YTDL_version +global usr_bin_folder +global ffmpeg_version_long +global ffprobe_version +global ffmpeg_version +global alert_text_ytdl +global alert_text_ffmpeg +global path_to_MacYTDL +global shellPath +global downloadsFolder_Path +global Atomic_is_installed +global macYTDL_Atomic_file +global download_filename +global download_filename_new +global YTDL_log_file +global YTDL_simulate_file +global youtubedl_file +global ytdlp_file +global YTDL_exists +global ytdlp_exists +global ffmpeg_exists +global ffprobe_exists +global homebrew_ytdlp_exists +global homebrew_ffmpeg_exists +global homebrew_ffprobe_exists +global show_yt_dlp +global user_system_arch +global user_on_123 +global user_on_old_os +global URL_user_entered +global ABC_show_URLs +global SBS_show_URLs +global ABC_show_name +global SBS_show_name +global playlist_Name +global number_ABC_SBS_episodes +global YTDL_output_template +global YTDL_format_pref +global old_version_prefs +global batch_file +global MacYTDL_prefs_file +global MacYTDL_custom_icon_file +global MacYTDL_custom_icon_file_posix +global macYTDL_service_file +global MacYTDL_preferences_path +global resourcesPath +global YTDL_credentials +global DL_audio_only +global DL_audio_codec +global DL_YTDL_auto_check +global DL_over_writes +global DL_subtitles +global DL_subtitles_format +global DL_YTAutoST +global DL_Thumbnail_Write +global DL_Thumbnail_Embed +global DL_verbose +global DL_description +global DL_format +global DL_STLanguage +global DL_STEmbed +global DL_Remux_format +global DL_Remux_original +global DL_Add_Metadata +global DL_batch_status +global DL_Limit_Rate +global DL_Limit_Rate_Value +global DL_Show_Settings +global DL_Use_Cookies +global DL_Cookies_Location +global DL_Use_Proxy +global DL_Proxy_URL +global DL_Use_Custom_Template +global DL_Custom_Template +global DL_Use_YTDLP +global DL_TimeStamps +global DL_Use_Custom_Settings +global DL_Custom_Settings +global DL_auto +global DL_Saved_Settings_Location +global DL_Settings_In_Use +global DL_QT_Compat +global DL_formats_list +global DL_discard_URL +global DL_Resolution_Limit +global DL_Dont_Use_Parts +global DL_Parallel +global DL_No_Warnings +global DL_Delete_Partial +global MacYTDL_version +global MacYTDL_copyright +global MacYTDL_date +global ffprobe_file +global ffmpeg_file +global DTP_file +global Myriad_file +global Myriad_exists +global called_video_URL +global monitor_dialog_position +global screen_width +global screen_height +global theButtonContinueLabel +global theButtonDownloadLabel +global theButtonOKLabel +global theButtonQuitLabel +global theButtonReturnLabel +global theButtonCancelLabel +global theButtonNoLabel +global theButtonYesLabel +global theBestLabel +global theNoRemuxLabel +global theDefaultLabel +global window_Position +global X_position +global Y_position +global run_Utilities_handlers + + +------------------------------------------------- +-- +-- Set up variables +-- +------------------------------------------------- + +-- Set up a variable which will store URL entered while user goes into other functions: Settings, Help, Utilities, errors. It is reset if user downloads a video. +global URL_user_entered_clean +set URL_user_entered_clean to "" + +-- Accept URL to be downloaded from the MacYTDL Service, assign to a new variable which is available to this script +on called_by_service(video_URL) + tell me to activate + set called_video_URL to video_URL + run +end called_by_service + +-- Variables for this applet's version, date and author +set path_to_MacYTDL to path to me as text +set bundle_file to (path_to_MacYTDL & "contents:Info.plist") as string +tell application "System Events" + set MacYTDL_copyright to value of property list item "NSHumanReadableCopyright" of contents of property list file bundle_file + set MacYTDL_version to value of property list item "CFBundleShortVersionString" of contents of property list file bundle_file +end tell + +set MacYTDL_date_position to (offset of "," in MacYTDL_copyright) + 2 +set MacYTDL_date to text MacYTDL_date_position thru end of MacYTDL_copyright +set MacYTDL_date_day to word 1 of MacYTDL_date +set MacYTDL_date_month to word 2 of MacYTDL_date +set MacYTDL_date_year to word 3 of MacYTDL_date +set thedateLabel to localized string MacYTDL_date_month from table "MacYTDL" +set MacYTDL_date to MacYTDL_date_day & " " & thedateLabel & " " & MacYTDL_date_year + +-- Set variable to contain path to Alerter and ets +set resourcesPath to POSIX path of (path_to_MacYTDL & "Contents:Resources:") +-- Set text for alerts that might be invoked before Main dialog +set alert_text_ytdl to "NotSwitching" + +-- Set variables to contain user's macOS version - for Utilities, Settings, FFmpeg install and yt-dlp install - check if user is on macOS 10.10 to 10.14.6 for YT-DLP legacy install + Utilities dialog - If user on <10.12.1 will have expired certificates preventing FFmpeg dowload - Users on 12.3+ cannot use youtube-dl +set user_sysinfo to system info +set user_os_version to system version of user_sysinfo as string +considering numeric strings + if user_os_version is greater than "10.9.5" and user_os_version is less than "10.15" then + set show_yt_dlp to "yt-dlp-legacy" + else + set show_yt_dlp to "yt-dlp" + end if + if user_os_version is greater than "12.2.1" then + set user_on_123 to true + else + set user_on_123 to false + end if + if user_os_version is less than "10.12.1" then + set user_on_old_os to true + else + set user_on_old_os to false + end if +end considering + +-- Get system architecture – controls whether to download Intel or ARM version of FFmpeg/FFprobe +set user_system_arch to (do shell script "arch") +if user_system_arch is not "arm64" then set user_system_arch to "Intel" + +-- Add shellpath variable because otherwise script can't find youtube-dl/yt-dlp +set shellPath to "PATH=$PATH:/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin:~/opt/bin:~/opt/sbin:/opt/local/bin:/opt/local/sbin:/opt/homebrew/bin:" & quoted form of (POSIX path of (path_to_MacYTDL & "::")) & "; " + +-- Set path and name for custom icon for dialogs +set MacYTDL_custom_icon_file to (path to resource "macytdl.icns") as string +-- Set path and name for custom icon for enhanced window statements +set MacYTDL_custom_icon_file_posix to POSIX path of MacYTDL_custom_icon_file + +-- Set variable for title of dialogs +set theVersionLabel to localized string "Version" from table "MacYTDL" +set diag_Title to "MacYTDL, " & theVersionLabel & " " & MacYTDL_version & ", " & MacYTDL_date + +-- Variables for component installation status - doubling up with version if already installed - changed when components are installed +set YTDL_version to "Not installed" +set ffprobe_version to "Not installed" +set ffmpeg_version to "Not installed" +set Atomic_is_installed to false +set old_version_prefs to "No" + +-- Variables for storing MacYTDL preferences, batch file, youtube-dl/yt-dlp, FFmpeg, FFprobe and DialogToolkitPlus locations +set usr_bin_folder to ("/usr/local/bin/" as text) +set ytdlp_file to ("/usr/local/bin/yt-dlp" as text) +set homebrew_ARM_ytdlp_file to ("/opt/homebrew/bin/yt-dlp" as text) +set homebrew_Intel_ytdlp_file to ("usr:local:bin:yt-dlp" as text) +set macPorts_ytdlp_file to ("/opt/local/bin/yt-dlp" as text) +set youtubedl_file to ("/usr/local/bin/youtube-dl" as text) +set home_folder to (path to home folder) as text +set libraries_folder to home_folder & "Library:Script Libraries" +set DTP_file to libraries_folder & ":DialogToolkitMacYTDL.scptd" +set Myriad_file to libraries_folder & ":Myriad Tables Lib.scptd" +set MacYTDL_preferences_folder to "Library/Preferences/MacYTDL/" +set MacYTDL_preferences_path to (POSIX path of (path to home folder) & MacYTDL_preferences_folder) +set MacYTDL_prefs_file to MacYTDL_preferences_path & "MacYTDL.plist" +set ffmpeg_file to ("/usr/local/bin/ffmpeg" as text) +set ffprobe_file to ("/usr/local/bin/ffprobe" as text) +set homebrew_ARM_ffmpeg_file to ("/opt/homebrew/bin/ffmpeg" as text) +set homebrew_Intel_ffmpeg_file to ("usr:local:bin:ffmpeg" as text) +set homebrew_ARM_ffprobe_file to ("/opt/homebrew/bin/ffprobe" as text) +set homebrew_Intel_ffprobe_file to ("usr:local:bin:ffprobe" as text) +set macPorts_ffmpeg_file to ("/opt/local/bin/ffmpeg" as text) +set macPorts_ffprobe_file to ("/opt/local/bin/ffprobe" as text) + +set batch_filename to "BatchFile.txt" as string +set batch_file to POSIX file (MacYTDL_preferences_path & batch_filename) + + +-- Get size of main screen so dialogs can be positioned +-- Passed to main_dialog via set_preferences when MacYTDL opened for 1st time or if MacYTDL prefs file has been deleted +-- Screen height is used for positioning ABC and SBS choosers and Monitor dialogs +set screen_size to get_screensize() +set X_position to item 1 of screen_size as integer +set Y_position to item 2 of screen_size as integer +set screen_width to item 3 of screen_size as integer +set screen_height to item 4 of screen_size as integer +-- display dialog (screen_width & return & screen_height) as string + +-- Variables for the most common dialog buttons and drop-down boxes - saves a little extra code in all the get_dialogs +set theButtonOKLabel to localized string "OK" from table "MacYTDL" +set theButtonQuitLabel to localized string "Quit" from table "MacYTDL" +set theButtonDownloadLabel to localized string "Download" from table "MacYTDL" +set theButtonReturnLabel to localized string "Return" from table "MacYTDL" +set theButtonContinueLabel to localized string "Continue" from table "MacYTDL" +set theButtonCancelLabel to localized string "Cancel" from table "MacYTDL" +set theButtonNoLabel to localized string "No" from table "MacYTDL" +set theButtonYesLabel to localized string "Yes" from table "MacYTDL" +set theBestLabel to localized string "Best" from table "MacYTDL" +set theDefaultLabel to localized string "Default" from table "MacYTDL" +set theNoRemuxLabel to localized string "No remux" from table "MacYTDL" + +-- Load utilities.scpt so that various handlers can be called +set path_to_Utilities to (path_to_MacYTDL & "Contents:Resources:Scripts:Utilities.scpt") as alias +set run_Utilities_handlers to load script path_to_Utilities + +------------------------------------------------- +-- +-- Make sure components are in place +-- +------------------------------------------------- +-- Check which components are installed - if so, get versions - but, this can be wrong if user has both scripts installed - if yt-dlp is small it is a faulty install +tell application "System Events" + if exists file youtubedl_file then + set YTDL_exists to true + else + set YTDL_exists to false + end if + + -- Note: ytdlp_file can actually be yt-dlp or yt-dlp-legacy but is always named "yt-dlp" in the usr/local/bin folder - only use Homebrew yt-dlp install if there is no MacYTDL install - check for Homebrew install on both Intel and ARM Macs + if exists file ytdlp_file then + set ytdlp_path_alias to POSIX file ytdlp_file as alias + + set its_type to file type of disk item homebrew_Intel_ytdlp_file + + -- Is this a Homebrew install on Intel or MacPorts install ? Homebrew normally adds a symlink to /usr/local/bin/ on Intel Macs - MacPorts adds a symlink to /opt/local/bin/ + if its_type is "slnk" then + set homebrew_ytdlp_exists to true + set ytdlp_exists to false + end if + + -- Is it a complete normal install ? + if size of ytdlp_path_alias is greater than 9000 then + set homebrew_ytdlp_exists to false + set ytdlp_exists to true + end if + + -- Is it a faulty normal install ? Rare case in which MacYTDL install of yt-dlp is faulty and left a stub - Intel Homebrew installs are smaller than 9000 and so are excluded from this test + if size of ytdlp_path_alias is less than 9000 and its_type is not "slnk" then + set homebrew_ytdlp_exists to false + set ytdlp_exists to false + end if + -- Nothing in /usr/local/bin - look for Homebrew on ARM Macs + else if exists file homebrew_ARM_ytdlp_file then + set ytdlp_exists to false + set homebrew_ytdlp_exists to true + set ytdlp_file to ("/opt/homebrew/bin/yt-dlp" as text) + -- Nothing in /opt/homebrew/bin - look for MacPorts - same location for Intel and ARM Macs - use homebrew_ytdlp_exists as proxy for both HomeBrew and MacPorts - simplifies coding everywhere + -- Assume that any file in /opt/local/bin/ is a MacPorts install + else if exists file macPorts_ytdlp_file then + set ytdlp_exists to false + set homebrew_ytdlp_exists to true + set ytdlp_file to ("/opt/local/bin/yt-dlp" as text) + else + set ytdlp_exists to false + set homebrew_ytdlp_exists to false + end if + + if exists file DTP_file then + set DTP_exists to true + else + set DTP_exists to false + end if + + if exists file Myriad_file then + set Myriad_exists to true + else + -- set Myriad_exists to true + set Myriad_exists to false + end if + + if exists file ffmpeg_file then + -- Is this a Homebrew install on Intel ? + set its_type_ffmpeg to file type of disk item homebrew_Intel_ffmpeg_file + if its_type_ffmpeg is "slnk" then + set homebrew_ffmpeg_exists to true + set ffmpeg_exists to false + else + set homebrew_ffmpeg_exists to false + set ffmpeg_exists to true + end if + + -- Nothing in /usr/local/bin - look for Homebrew on ARM Macs + else if exists file homebrew_ARM_ffmpeg_file then + set ffmpeg_exists to false + set homebrew_ffmpeg_exists to true + set ffmpeg_file to ("/opt/homebrew/bin/ffmpeg" as text) + -- Nothing in /opt/homebrew/bin - look for MacPorts install - homebrew_ffmpeg_exists used as proxy for MacPorts install + else if exists file macPorts_ffmpeg_file then + set ffmpeg_exists to false + set homebrew_ffmpeg_exists to true + set ffmpeg_file to ("/opt/local/bin/ffmpeg" as text) + else + set ffmpeg_exists to false + set homebrew_ffmpeg_exists to false + end if + + if exists file ffprobe_file then + -- Is this a Homebrew install on Intel ? + set its_type_ffmprobe to file type of disk item homebrew_Intel_ffprobe_file + if its_type_ffmpeg is "slnk" then + set homebrew_ffprobe_exists to true + set ffprobe_exists to false + else + set homebrew_ffprobe_exists to false + set ffprobe_exists to true + end if + + -- Nothing in /usr/local/bin - look for Homebrew on ARM Macs + else if exists file homebrew_ARM_ffprobe_file then + set ffprobe_exists to false + set homebrew_ffprobe_exists to true + set ffprobe_file to ("/opt/homebrew/bin/ffprobe" as text) + -- Nothing in /opt/homebrew/bin - look for MacPorts install - homebrew_ffprobe_exists used as proxy for MacPorts install + else if exists file macPorts_ffprobe_file then + set ffprobe_exists to false + set homebrew_ffprobe_exists to true + set ffprobe_file to ("/opt/local/bin/ffprobe" as text) + else + set ffprobe_exists to false + set homebrew_ffprobe_exists to false + end if + + if exists file MacYTDL_prefs_file then + set prefs_exists to true + else + set prefs_exists to false + end if +end tell + +if ffmpeg_exists is true or homebrew_ffmpeg_exists is true then + set ffmpeg_version_long to do shell script shellPath & " ffmpeg -version" + set AppleScript's text item delimiters to {"-", " "} + set ffmpeg_version to text item 3 of ffmpeg_version_long + set AppleScript's text item delimiters to "" +end if +if ffprobe_exists is true or homebrew_ffprobe_exists is true then + set ffprobe_version_long to do shell script shellPath & " ffprobe -version" + set AppleScript's text item delimiters to {"-", " "} + set ffprobe_version to text item 3 of ffprobe_version_long + set AppleScript's text item delimiters to "" +end if + +-- If no components are installed, can assume it's the first time MacYTDL has been used - need to do a full installation of all components - include Homebrew test as it can be ARM +if YTDL_exists is false and ytdlp_exists is false and DTP_exists is false and Myriad_exists is false and ffmpeg_exists is false and ffprobe_exists is false and prefs_exists is false and homebrew_ytdlp_exists is false and homebrew_ffmpeg_exists is false and homebrew_ffprobe_exists is false then + set theComponentsNotInstalledtTextLabel1 to localized string "It looks like you have not used MacYTDL before. A number of components must be installed for MacYTDL to run. There is more detail in the Help file. Would you like to install those components now ? Otherwise, Quit." from table "MacYTDL" + set theComponentsNotInstalledtTextLabel2 to localized string "Note: Some components will be downloaded which might take a while and you will need to provide administrator credentials." from table "MacYTDL" + tell me to activate + set components_install_answ to button returned of (display dialog theComponentsNotInstalledtTextLabel1 & return & return & theComponentsNotInstalledtTextLabel2 with title diag_Title buttons {theButtonQuitLabel, theButtonYesLabel} default button 2 cancel button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + if components_install_answ is theButtonYesLabel then + set YTDL_ytdlp_version to run_Utilities_handlers's check_ytdl_installed(usr_bin_folder, diag_Title, youtubedl_file, ytdlp_file, theButtonQuitLabel, theButtonYesLabel, path_to_MacYTDL, theButtonOKLabel, resourcesPath, show_yt_dlp, MacYTDL_custom_icon_file) + set YTDL_version to word 1 of YTDL_ytdlp_version + if word 2 of YTDL_ytdlp_version is "ytdl" then + set YTDL_exists to true + set ytdlp_exists to false + else + set YTDL_exists to false + set ytdlp_exists to true + end if + run_Utilities_handlers's set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file) + set prefs_exists to true + delay 1 + run_Utilities_handlers's install_DTP(DTP_file, path_to_MacYTDL, resourcesPath) + set DTP_exists to true + delay 1 + run_Utilities_handlers's install_Myriad(Myriad_file, path_to_MacYTDL, resourcesPath) + set Myriad_exists to true + delay 1 + run_Utilities_handlers's install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, user_system_arch) + set ffprobe_exists to true + set ffmpeg_exists to true + set ffmpeg_version_long to do shell script ffmpeg_file & " -version" + run_Utilities_handlers's ask_user_install_service(path_to_MacYTDL, theButtonYesLabel, diag_Title, MacYTDL_custom_icon_file) + else + quit_MacYTDL() + end if +end if + +-- If one or more components are installed, indicates user has used MacYTDL before - check and install any missing components + +-- Set up preferences if they don't exist - YTDL_version will contain "not installed" until cleanup below - ugly but a very rare case I hope +if prefs_exists is false then + -- Prefs file doesn't exist - warn user it must be created for MacYTDL to work + set theInstallPrefsTextLabel to localized string "The MacYTDL Preferences file is not present. To work, MacYTDL needs to create a file in your Preferences folder. Do you wish to continue ?" from table "MacYTDL" + set Install_Prefs to button returned of (display dialog theInstallPrefsTextLabel buttons {theButtonNoLabel, theButtonYesLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if Install_Prefs is theButtonYesLabel then + run_Utilities_handlers's set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file) + set prefs_exists to true + else if Install_Prefs is theButtonNoLabel then + error number -128 + end if +end if + +-- If user gets to here can assume Prefs exist so, check whether user has one of the old versions - if so, call set_preferences to fix - continue on if current version - will delete this one day +run_Utilities_handlers's check_settings(MacYTDL_prefs_file, old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version) + +-- Get updated setting for installed downloader +tell application "System Events" + tell property list file MacYTDL_prefs_file + set setting_yt_dlp to value of property list item "Use_ytdlp" + end tell +end tell + +-- 4/3/23 - added test for absence of yt-dlp_macos_legacy - no longer offer to switch to youtube-dl +-- No downloader installed - must install YT-DLP and update settings +-- For some reason user has no downloaders or is missing desired downloader - if youtube-dl is missing force install of YT-DLP - include Homebrew test as it can be ARM +if YTDL_exists is false and ytdlp_exists is false and homebrew_ytdlp_exists is false then + set theYTDLNotInstalledtTextLabel1 to localized string "No downloader is installed. MacYTDL cannot download videos. By default it uses the YT-DLP downloader. Would you like to install YT-DLP now ?" from table "MacYTDL" + set theYTDLNotInstalledtTextLabel2 to localized string "Note: This download can take a while and you will probably need to provide administrator credentials." from table "MacYTDL" + tell me to activate + set yt_install_answ to button returned of (display dialog theYTDLNotInstalledtTextLabel1 & return & return & theYTDLNotInstalledtTextLabel2 with title diag_Title buttons {theButtonQuitLabel, theButtonYesLabel} default button 2 cancel button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + if yt_install_answ is theButtonYesLabel then + set YTDL_ytdlp_version to run_Utilities_handlers's check_ytdl_installed(usr_bin_folder, diag_Title, youtubedl_file, ytdlp_file, theButtonQuitLabel, theButtonYesLabel, path_to_MacYTDL, theButtonOKLabel, resourcesPath, show_yt_dlp, MacYTDL_custom_icon_file) + set YTDL_version to word 1 of YTDL_ytdlp_version + set ytdlp_exists to true + -- Need to generalise show_yt_dlp so that only "youtube-dl" or "yt-dlp" is stored in plist + if show_yt_dlp is "yt-dlp-legacy" then + set ytdlp_install_show_yt_dlp to "yt-dlp" + else + set ytdlp_install_show_yt_dlp to show_yt_dlp + end if + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_ytdlp" to ytdlp_install_show_yt_dlp + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + else + quit_MacYTDL() + end if +end if + +-- YTDL installed contrary to setting - offer switch to YT-DLP - update setting if user chooses not to switch - probably a very rare case +if ytdlp_exists is false and homebrew_ytdlp_exists is false and YTDL_exists is true and (setting_yt_dlp is "yt-dlp" or setting_yt_dlp is "yt-dlp-legacy") then + set switch_to to "yt-dlp" + set theYTDLYTDLPIsInstalledtTextLabel to localized string "You are currently set to download with YT-DLP but, it is not installed. This may have been set according to the version of macOS you are using or because there was a fault in downloading yt-dlp. You do have youtube-dl installed. Would you like to switch to YT-DLP" from table "MacYTDL" + tell me to activate + set yt_install_answ to button returned of (display dialog theYTDLYTDLPIsInstalledtTextLabel & " ?" with title diag_Title buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if yt_install_answ is theButtonYesLabel then + set YTDL_ytdlp_version to run_Utilities_handlers's check_ytdl_installed(usr_bin_folder, diag_Title, youtubedl_file, ytdlp_file, theButtonQuitLabel, theButtonYesLabel, path_to_MacYTDL, theButtonOKLabel, resourcesPath, show_yt_dlp, MacYTDL_custom_icon_file) + set YTDL_version to word 1 of YTDL_ytdlp_version + set ytdlp_exists to true + -- Need to generalise show_yt_dlp so that only "youtube-dl" or "yt-dlp" is stored in plist + if show_yt_dlp is "yt-dlp-legacy" then + set ytdlp_install_show_yt_dlp to "yt-dlp" + else + set ytdlp_install_show_yt_dlp to show_yt_dlp + end if + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_ytdlp" to ytdlp_install_show_yt_dlp + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + else + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_ytdlp" to "youtube-dl" + end tell + end tell + end if +end if + +-- YT-DLP installed contrary to setting - silently update the setting - probably a very rare case +if (ytdlp_exists is true or homebrew_ytdlp_exists is true) and setting_yt_dlp is "youtube-dl" then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_ytdlp" to "yt-dlp" + end tell + end tell +end if + +-- Check if DTP exists - install if not +if DTP_exists is false then + set theInstallDTPTextLabel to localized string "MacYTDL needs a code library installed in your Libraries folder. It cannot function without that library. Do you wish to continue ?" from table "MacYTDL" + set install_DTP to button returned of (display dialog theInstallDTPTextLabel buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if install_DTP is theButtonYesLabel then + run_Utilities_handlers's install_DTP(DTP_file, path_to_MacYTDL, resourcesPath) + set DTP_exists to true + -- else if install_DTP is theButtonNoLabel then + -- error number -128 + end if +end if + +-- v1.26 - Check if Myriad Tables is installed - install if not - save user's choice to stop nagging every time they start MacYTDL +-- Decided to omit this install on startup - user is asked about it if they turn on "Get Formats List" in Settings() +--if Myriad_exists is false then +-- set theInstallMyriadTextLabel to localized string "MacYTDL needs a code library installed in your Libraries folder. It cannot show the \"Formats List\" without that library. Do you wish to install ?" from table "MacYTDL" +-- set install_Myriad to button returned of (display dialog theInstallMyriadTextLabel buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) +-- if install_Myriad is theButtonYesLabel then +-- run_Utilities_handlers's install_Myriad(Myriad_file, path_to_MacYTDL, resourcesPath) +-- set Myriad_exists to true +-- end if +--end if + +-- If user gets to here can assume DTP exists. Check whether DTP name is changed or new version of DTP available +run_Utilities_handlers's check_DTP(DTP_file, path_to_MacYTDL) + +-- Install FFmpeg and FFprobe if either is missing - versions are updated earlier on if they exist +if ffmpeg_exists is false and homebrew_ffmpeg_exists is false then + set theInstallFFmpegTextLabel to localized string "FFmpeg is not installed. Would you like to install it now ? If not, MacYTDL can't run and will have to quit. Note: This download can take a while and you will probably need to provide administrator credentials." from table "MacYTDL" + set Install_FFmpeg to button returned of (display dialog theInstallFFmpegTextLabel buttons {theButtonQuitLabel, theButtonYesLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if Install_FFmpeg is theButtonYesLabel then + run_Utilities_handlers's install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, user_system_arch) + set ffmpeg_exists to true + set ffprobe_exists to true + set ffmpeg_version_long to do shell script ffmpeg_file & " -version" + else if Install_FFmpeg is theButtonNoLabel then + error number -128 + end if +end if +if ffprobe_exists is false and homebrew_ffprobe_exists is false then + set theInstallFFprobeTextLabel to localized string "FFprobe is not installed. Would you like to install it now ? If not, MacYTDL can't run and will have to quit. Note: This download can take a while and you will probably need to provide administrator credentials." from table "MacYTDL" + set Install_FFprobe to button returned of (display dialog theInstallFFprobeTextLabel buttons {theButtonQuitLabel, theButtonYesLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if Install_FFprobe is theButtonYesLabel then + run_Utilities_handlers's install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, user_system_arch) + set ffmpeg_exists to true + set ffprobe_exists to true + set ffmpeg_version_long to do shell script ffmpeg_file & " -version" + else if Install_FFprobe is theButtonNoLabel then + error number -128 + end if +end if + +-- Is Atomic Parsley installed ? [Needed by youtube-dl for embedding thumbnails in mp4 and m4a files] - result is displayed in Utilities dialog +set macYTDL_Atomic_file to ("usr:local:bin:AtomicParsley" as text) +tell application "System Events" + if (exists file macYTDL_Atomic_file) then + set Atomic_is_installed to true + else + set Atomic_is_installed to false + end if +end tell + +-- Set path and name for youtube-dl/yt-dlp simulated log file - a simulated youtube-dl/yt-dlp download puts all its feedback into this file - it's a generic file used for all downloads and so only contains detail on the most recent download - simulation helps find errors and problems before starting the download +--set YTDL_simulate_file to MacYTDL_preferences_path & "youtube-dl_simulate.txt" +set YTDL_simulate_file to MacYTDL_preferences_path & "ytdl_simulate.txt" + +-- Is auto checking of youtube-dl/yt-dlp version on ? DL_Use_YTDLP contains "yt-dlp" or "youtube-dl" +tell application "System Events" + tell property list file MacYTDL_prefs_file + set DL_YTDL_auto_check to value of property list item "Auto_Check_YTDL_Update" + set DL_Use_YTDLP to value of property list item "Use_ytdlp" + end tell +end tell + +-- Check on need to add new v1.21 YTDL/YT-DLP version to the prefs file +run_Utilities_handlers's check_settings_current(MacYTDL_prefs_file, DL_Use_YTDLP, MacYTDL_preferences_path, youtubedl_file, ytdlp_file) + +-- Check version of Service if installed - update if old +run_Utilities_handlers's update_MacYTDLservice(path_to_MacYTDL, MacYTDL_prefs_file, show_yt_dlp) + +-- Check if user is on macOS 12.3+ and using youtube-dl - they need to switch to YT-DLP or quit +if user_on_123 is true and DL_Use_YTDLP is "youtube-dl" then + set warning_YTDL_not_working to localized string "Sorry, \"youtube-dl\" does not work in macOS 12.3 and above. Would you like to switch to \"YT-DLP\" or Quit ?" from table "MacYTDL" + set theButtonSwitchLabel to localized string "Switch" from table "MacYTDL" + set switch_or_quit to button returned of (display dialog warning_YTDL_not_working buttons {theButtonQuitLabel, theButtonSwitchLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if switch_or_quit is theButtonSwitchLabel then + if (ytdlp_exists is false and homebrew_ytdlp_exists is false) then check_ytdl(show_yt_dlp) + set YTDL_version to do shell script ytdlp_file & " --version" + -- Need to generalise show_yt_dlp so that only "youtube-dl" or "yt-dlp" is stored in plist + if show_yt_dlp is "yt-dlp-legacy" then + set switched_show_yt_dlp to "yt-dlp" + else + set switched_show_yt_dlp to show_yt_dlp + end if + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_ytdlp" to switched_show_yt_dlp + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + end if +end if + +-- Do the auto check - but not if user has Homebrew or MacPorts installed - this code might need some more nuance +if DL_YTDL_auto_check is true then + -- Need to set YTDL_version according to current script + if DL_Use_YTDLP is "youtube-dl" then + set YTDL_version to do shell script youtubedl_file & " --version" + else if homebrew_ytdlp_exists is false then + set YTDL_version to do shell script ytdlp_file & " --version" + end if + if length of YTDL_version is greater than 12 then + set alert_text_ytdlLabel to localized string "Do you wish to update your nightly build of YT-DLP" from table "MacYTDL" + set update_nightly_q to button returned of (display dialog (alert_text_ytdlLabel & " ?") with title diag_Title buttons {theButtonNoLabel, theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + set cancel_update_flag to false + if update_nightly_q is theButtonOKLabel then + -- Install nightly build - no need to check version as nightly builds are released almost every 24 hours + try + do shell script shellPath & " yt-dlp --update-to nightly" with administrator privileges + -- trap case where user cancels credentials dialog + on error number -128 + set cancel_update_flag to true + end try + if cancel_update_flag is false then + set YTDL_version to do shell script shellPath & " yt-dlp --version" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + set alert_text_ytdl to "has been updated" + end if + end if + else if homebrew_ytdlp_exists is false and cancel_update_flag is false then + check_ytdl(DL_Use_YTDLP) + else + set alert_text_ytdlLabel to localized string "Sorry, auto update cannot be used for Homebrew/MacPorts installs of YT-DLP." from table "MacYTDL" + display dialog alert_text_ytdlLabel with title diag_Title buttons theButtonOKLabel default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + end if + set alert_text_ytdlLabel to localized string "has been updated" from table "MacYTDL" + if alert_text_ytdl contains alert_text_ytdlLabel then + display dialog DL_Use_YTDLP & " " & (alert_text_ytdl & ".") with title diag_Title buttons theButtonOKLabel default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + end if +end if + +-- Set ABC show name and episode count variables so they exist +set ABC_show_name to "" +set SBS_show_name to "" +set number_ABC_SBS_episodes to 0 + + +main_dialog() + +on main_dialog() + + --***************** This is for testing variables as they come into and back to Main - beware some of these are not defined on all circumstances + -- display dialog "video_URL: " & return & return & "called_video_URL: " & called_video_URL & return & return & "URL_user_entered: " & URL_user_entered & return & return & "URL_user_entered_clean: " & URL_user_entered_clean & return & return & "default_contents_text: " + + -- Read the preferences file to get current settings - if error probably because of missing prefs - error can be caused by user restoring old preferences file + run_Utilities_handlers's read_settings(MacYTDL_prefs_file) + + -- Need to work through why I put this code here - deary me, a lack of documentation + set DL_format to localized string DL_format from table "MacYTDL" + set DL_subtitles_format to localized string DL_subtitles_format from table "MacYTDL" + set DL_Remux_format to localized string DL_Remux_format from table "MacYTDL" + set DL_audio_codec to localized string DL_audio_codec from table "MacYTDL" + + -- In rare cases, the prefs file had to be recreated (above) - need to clean up YTDL_version and YTDL_YTDLP_version + if YTDL_version is "Not installed" then + if DL_Use_YTDLP is "youtube-dl" then + set YTDL_version to do shell script youtubedl_file & " --version" + else + set YTDL_version to do shell script ytdlp_file & " --version" + end if + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + end if + + -- Set batch file status so that it persists while MacYTDL is running + try + if DL_batch_status is true then + set DL_batch_status to true + end if + on error + set DL_batch_status to false + end try + + -- URL is emptied after download started - otherwise it should stay available so that it can be passed to/from Settings and Utilities + -- Test whether app was called by Service - error means not called and so there is no URL to be passed to the Main Dialog + try + -- Test whether URL provided by Service has been reset to blank on a previous pass through - called_video_URL contains URL sent by Service + if called_video_URL is "" then + set default_contents_text to URL_user_entered_clean + else + set default_contents_text to called_video_URL + end if + -- Need to reset the called_video_URL variable so that it doesn't overwrite the URL text box after a later download + set called_video_URL to "" + on error errNum -- Not called from Service, should always be error -2753 (variable not defined) - refill URL so it's shown in dialog - will be blank if user has not pasted a URL + set default_contents_text to URL_user_entered_clean + end try + + set theDiagSettingsTextLabel to localized string "One-time settings: Batches:" from table "MacYTDL" + set accViewWidth to 450 + set accViewInset to 80 + + -- Set buttons and controls + set theButtonsHelpLabel to localized string "Help" from table "MacYTDL" + set theButtonsUtilitiesLabel to localized string "Utilities" from table "MacYTDL" + set theButtonsSettingsLabel to localized string "Settings" from table "MacYTDL" + set theButtonsAdminLabel to localized string "Admin" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonsHelpLabel, theButtonsUtilitiesLabel, theButtonQuitLabel, theButtonsAdminLabel, theButtonsSettingsLabel, theButtonContinueLabel} button keys {"?", "u", "q", "a", "s", ""} default button 6 + if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit + set theFieldLabel to localized string "Paste URL here" from table "MacYTDL" + set {theField, theTop} to create field default_contents_text placeholder text theFieldLabel left inset accViewInset bottom 0 field width accViewWidth - accViewInset extra height 15 + set {theRule, theTop} to create rule theTop + 18 rule width accViewWidth + set theCheckbox_Show_SettingsLabel to localized string "Show settings before download" from table "MacYTDL" + set {theCheckbox_Show_Settings, theTop} to create checkbox theCheckbox_Show_SettingsLabel left inset accViewInset + 50 bottom (theTop + 10) max width 250 initial state DL_Show_Settings + set theCheckbox_SubTitlesLabel to localized string "Subtitles for this download" from table "MacYTDL" + set {theCheckbox_SubTitles, theTop} to create checkbox theCheckbox_SubTitlesLabel left inset accViewInset bottom (theTop + 15) max width 250 initial state DL_subtitles + set theCheckbox_CredentialsLabel to localized string "Credentials for download" from table "MacYTDL" + set {theCheckbox_Credentials, theTop} to create checkbox theCheckbox_CredentialsLabel left inset accViewInset bottom (theTop + 5) max width 200 without initial state + set theCheckbox_DescriptionLabel to localized string "Download description" from table "MacYTDL" + set {theCheckbox_Description, theTop} to create checkbox theCheckbox_DescriptionLabel left inset accViewInset bottom (theTop + 5) max width 175 initial state DL_description + set theLabelledPopUpRemuxFileformat to localized string "Remux format:" from table "MacYTDL" + if DL_Use_YTDLP is "yt-dlp" then + set {main_thePopUp_FileFormat, main_formatlabel, theTop, popupLeft} to create labeled popup {theNoRemuxLabel, "mp4", "mkv", "flv", "webm", "mov", "avi", "ogg"} left inset accViewInset - 5 bottom (theTop + 5) popup width 100 max width 200 label text theLabelledPopUpRemuxFileformat popup left accViewInset - 5 initial choice DL_Remux_format + else + set {main_thePopUp_FileFormat, main_formatlabel, theTop, popupLeft} to create labeled popup {theNoRemuxLabel, "mp4", "mkv", "flv", "webm", "avi", "ogg"} left inset accViewInset - 5 bottom (theTop + 5) popup width 100 max width 200 label text theLabelledPopUpRemuxFileformat popup left accViewInset - 5 initial choice DL_Remux_format + end if + set thePathControlLabel to localized string "Change download folder:" from table "MacYTDL" + set {thePathControl, pathLabel, theTop} to create labeled path control (POSIX path of downloadsFolder_Path) left inset accViewInset bottom (theTop + 5) control width 190 label text thePathControlLabel with pops up + set theCheckbox_OpenBatchLabel to localized string "Open Batch functions" from table "MacYTDL" + set {theCheckbox_OpenBatch, theTop, theBatchLabelWidth} to create checkbox theCheckbox_OpenBatchLabel left inset (accViewInset + 210) bottom (theTop - 40) max width 200 without initial state + -- Increase width when localised text is longer than English + set add_extra_dialog_width to 0 + if theBatchLabelWidth is greater than 158 then + set add_extra_dialog_width to (theBatchLabelWidth - 158) + end if + set theCheckbox_AddToBatchLabel to localized string "Add URL to Batch" from table "MacYTDL" + set {theCheckbox_AddToBatch, theTop} to create checkbox theCheckbox_AddToBatchLabel left inset (accViewInset + 210) bottom (theTop + 5) max width 200 initial state DL_batch_status + set {diag_settings_prompt, theTop} to create label theDiagSettingsTextLabel left inset accViewInset bottom theTop + 8 max width accViewWidth control size regular size with bold type + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 60 view width 64 view height 64 scale image scale proportionally + + -- Display the dialog + tell me to activate + set {button_label_returned, button_number_returned, controls_results, finalPosition} to display enhanced window diag_Title acc view width (accViewWidth + add_extra_dialog_width) acc view height theTop acc view controls {theField, theCheckbox_Show_Settings, theCheckbox_SubTitles, theCheckbox_Credentials, theCheckbox_Description, main_thePopUp_FileFormat, main_formatlabel, thePathControl, theCheckbox_AddToBatch, theCheckbox_OpenBatch, pathLabel, diag_settings_prompt, theRule, MacYTDL_icon} buttons theButtons active field theField initial position window_Position + + if button_number_returned is 3 then -- Quit + quit_MacYTDL() + end if + + -- Get control results from Main dialog + set openBatch_chosen to item 10 of controls_results + set DL_batch_status to item 9 of controls_results + set folder_chosen to item 8 of controls_results + set remux_format_choice to item 6 of controls_results + set description_choice to item 5 of controls_results + set credentials_choice to item 4 of controls_results + set subtitles_choice to item 3 of controls_results + set show_settings_choice to item 2 of controls_results + set URL_user_entered_clean to item 1 of controls_results -- Needed to refill the URL box on return from Settings, Help etc. + + -- Trim any trailing spaces from URL entered by user - reduces errors later on + if URL_user_entered_clean is not "" and URL_user_entered_clean is not " " then + if text item -1 of URL_user_entered_clean is " " then set URL_user_entered_clean to text 1 thru -2 of URL_user_entered_clean + end if + set URL_user_entered to quoted form of URL_user_entered_clean -- Quoted form needed in case the URL contains ampersands etc - but really need to get quoted form of each URL when more than one + + -- Does user wish to see settings before download - save choice - the setting will be queried before download starts + if show_settings_choice is not equal to DL_Show_Settings then + set DL_Show_Settings to show_settings_choice + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Show_Settings_before_Download" to show_settings_choice + end tell + end tell + end if + + -- Has user moved the MacYTDL window - if so, save new position + if finalPosition is not equal to window_Position then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "final_Position" to finalPosition + end tell + end tell + end if + + if button_number_returned is 5 then -- Show Settings + set_settings() + else if button_number_returned is 4 then + set branch_execution to run_Utilities_handlers's set_admin_settings(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file, theButtonCancelLabel, window_Position, theButtonReturnLabel, MacYTDL_custom_icon_file_posix) + if branch_execution is "Main" then main_dialog() + if branch_execution is "Settings" then set_settings() + else if button_number_returned is 2 then -- Show Utilities + utilities() + else if button_number_returned is 1 then -- Show Help + set path_to_MacYTDL_alias to path_to_MacYTDL as alias + set MacYTDL_help_file to (path to resource "Help.pdf" in bundle path_to_MacYTDL_alias) as string + set MacYTDL_help_file_posix to POSIX path of MacYTDL_help_file + tell application "System Events" to open file MacYTDL_help_file_posix + main_dialog() + end if + + -- Convert settings to format that can be used as youtube-dl/yt-dlp parameters + define variables + if description_choice is true then + set YTDL_description to "--write-description " + else + set YTDL_description to "" + end if + set YTDL_audio_only to "" + set YTDL_audio_codec to "" + if DL_over_writes is true and DL_Use_YTDLP is "yt-dlp" then + set YTDL_over_writes to "--force-overwrites " + else + set YTDL_over_writes to "" + end if + + set YTDL_subtitles to "" + + if DL_STEmbed is true then + set YTDL_STEmbed to "--embed-subs " + else + set YTDL_STEmbed to "" + end if + + -- Prepare User's download settings - using current settings - yt-dlp prefers to have name of post processor + if remux_format_choice is not theNoRemuxLabel then + if DL_Use_YTDLP is "yt-dlp" then + set YTDL_remux_format to "--recode-video " & remux_format_choice & " " & "--postprocessor-args \"ffmpeg:-codec copy\" " + else + set YTDL_remux_format to "--recode-video " & remux_format_choice & " " & "--postprocessor-args \"-codec copy\" " + end if + else + set YTDL_remux_format to "" + end if + if DL_Remux_original is true then + set YTDL_Remux_original to "--keep-video " + else + set YTDL_Remux_original to "" + end if + -- Set YTDL format parameter desired format + set separate YTDL_format_pref variable for use in simulate stage + if DL_format is not theDefaultLabel then + set YTDL_format to "-f bestvideo[ext=" & DL_format & "]+bestaudio/best[ext=" & DL_format & "]/best " + set YTDL_format_pref to "-f " & DL_format & " " + else + set YTDL_format_pref to "" + set YTDL_format to "" + end if + -- Set format sort parameter to desired maximum - not used in Simulate + if DL_Resolution_Limit is "Best" then + set YTDL_Resolution_Limit to "" + else if DL_audio_only is true then + set YTDL_Resolution_Limit to "" + else + set YTDL_Resolution_Limit to "-S \"res:" & DL_Resolution_Limit & "\" " + end if + if DL_Thumbnail_Embed is true then + set YTDL_Thumbnail_Embed to "--embed-thumbnail " + else + set YTDL_Thumbnail_Embed to "" + end if + if DL_Thumbnail_Write is true then + set YTDL_Thumbnail_Write to "--write-thumbnail " + else + set YTDL_Thumbnail_Write to "" + end if + if DL_verbose is true then + set YTDL_verbose to "--verbose " + else + set YTDL_verbose to "" + end if + if DL_TimeStamps is true then + set YTDL_TimeStamps to resourcesPath & "ets" + else + set YTDL_TimeStamps to "" + end if + set YTDL_credentials to "" + if credentials_choice is true then + get_YTDL_credentials() + end if + if DL_Limit_Rate is true then + set YTDL_limit_rate_value to ("--limit-rate " & DL_Limit_Rate_Value & "m ") + else + set YTDL_limit_rate_value to "" + end if + if DL_Add_Metadata is true then + set YTDL_metadata to "--add-metadata " + else + set YTDL_metadata to "" + end if + if DL_Use_Proxy is true then + set YTDL_Use_Proxy to ("--proxy " & DL_Proxy_URL & " ") + else + set YTDL_Use_Proxy to "" + end if + if DL_Use_Cookies is true then + set YTDL_Use_Cookies to ("--cookies " & DL_Cookies_Location & " ") + else + set YTDL_Use_Cookies to "" + end if + if DL_No_Warnings is true then + set YTDL_No_Warnings to "--no-warnings " + else + set YTDL_No_Warnings to "" + end if + if DL_Dont_Use_Parts is true then + set YTDL_Use_Parts to "--no-part " + else + set YTDL_Use_Parts to "" + end if + if DL_Use_Custom_Settings is true then + set YTDL_Custom_Settings to (DL_Custom_Settings & " ") + else + set YTDL_Custom_Settings to "" + end if + if DL_Use_Custom_Template is true then + set YTDL_Custom_Template to DL_Custom_Template + else + set YTDL_Custom_Template to "" + end if + -- If user wants QT compatibility, must turn off remux + if DL_QT_Compat is true then + set YTDL_QT_Compat to "--recode-video \"mp4\" --ppa \"VideoConvertor:-vcodec libx264 -acodec aac\" " + set YTDL_remux_format to "" + else + set YTDL_QT_Compat to "" + end if + + set YTDL_no_part to "" + + -- Set settings to enable audio only download - gets a format list - use post-processing if necessary - need to ignore all errors here which are usually due to missing videos etc. - only check first item of a playlist + if DL_audio_only is true then + set one_playlist_item to "" + if URL_user_entered_clean contains "playlist" or (URL_user_entered_clean contains "watch?" and URL_user_entered_clean contains "&list=") or (URL_user_entered_clean contains "?list=") then + set one_playlist_item to "--playlist-items 1 " + end if + try + set YTDL_get_formats to do shell script shellPath & DL_Use_YTDLP & " --list-formats --ignore-errors " & one_playlist_item & URL_user_entered & " 2>&1" + on error errStr + set YTDL_get_formats to errStr + end try + -- To get a straight audio-only download - rely on YTDL to get best available audio only file - if user also requests remux, container will contain audio in best format + if YTDL_get_formats contains "audio only" and DL_audio_codec is theBestLabel then + set YTDL_audio_only to "--format bestaudio " + set YTDL_format to "" + else + -- If audio only file not available and/or user wants specific format, extract audio only file in desired format from best container and, if needed, convert in post-processing to desired format + set YTDL_audio_codec to "--extract-audio --audio-format " & DL_audio_codec & " --audio-quality 0 " + end if + end if + + -- Tell download_video handler that it should return to main_dialog when finished - auto_download tells download_video to skip main and just close + set skip_Main_dialog to false + + check_download_folder(folder_chosen, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, diag_Title, MacYTDL_custom_icon_file, skip_Main_dialog) + if DL_Use_Cookies is true then check_cookies_file(DL_Cookies_Location) + + -- Set variable to contain download folder path - value comes from runtime settings which gets initial value from preferences but which user can then change + -- But first, if user has set download path to a file, use parent folder for downloads + tell application "System Events" to set test_DL_folder to (get class of item (folder_chosen as text)) as text + if test_DL_folder is "file" then + -- Trim last part of path name + set offset_to_file_name to last_offset(folder_chosen as text, "/") + set folder_chosen to text 1 thru offset_to_file_name of folder_chosen + end if + + -- Need to set up a dummy variable to take the URL when it is sent by Utilities/auto_download(). This is so that the old behaviour in which main_dialog reopens with a blank URL box after a download can be retained yet the URL is retained if user goes from Main to Settings/Utilities and back to Main + set URL_user_entered_from_auto_download to "" + + set downloadsFolder_Path to folder_chosen + + if button_number_returned is 6 then -- Continue to download + if openBatch_chosen is true then + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + else + download_video(shellPath, path_to_MacYTDL, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, screen_width, screen_height, YTDL_simulate_file, URL_user_entered, URL_user_entered_from_auto_download, folder_chosen, diag_Title, DL_batch_status, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format_pref, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, skip_Main_dialog, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, theButtonReturnLabel, theButtonQuitLabel, theButtonContinueLabel, YTDL_QT_Compat, DL_Use_YTDLP, theBestLabel, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + end if + end if +end main_dialog + + +--------------------------------------------------------------------------------------------- +-- +-- Download videos - called by Main dialog - calls monitor.scpt +-- +--------------------------------------------------------------------------------------------- +on download_video(shellPath, path_to_MacYTDL, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, screen_width, screen_height, YTDL_simulate_file, URL_user_entered, URL_user_entered_from_auto_download, folder_chosen, diag_Title, DL_batch_status, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format_pref, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, skip_Main_dialog, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, theButtonReturnLabel, theButtonQuitLabel, theButtonContinueLabel, YTDL_QT_Compat, DL_Use_YTDLP, theBestLabel, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + + if URL_user_entered_from_auto_download is not "" then + set URL_user_entered_clean to URL_user_entered_from_auto_download + end if + + set number_ABC_SBS_episodes to 0 + + -- Remove any trailing slash in the URL - causes syntax error with code to follow + if text -2 of URL_user_entered is "/" then + set URL_user_entered to quoted form of (text 2 thru -3 of URL_user_entered) -- Why not just remove the trailing slash ?? + end if + + -- Do error checking on pasted URL + -- First, is pasted URL blank ? + if URL_user_entered is "" or URL_user_entered is "''" then + tell me to activate + set theURLBlankLabel to localized string "You need to paste a URL before selecting Download. Quit or OK to try again." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theURLBlankLabel buttons {theButtonQuitLabel, theButtonOKLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonOKLabel then + main_dialog() + end if + end if + + -- Second was pasted URL > 4 characters long but did not begin with "http" + if length of URL_user_entered is greater than 4 then + set test_URL to text 2 thru 5 of URL_user_entered + if not test_URL is "http" then + set theURLNothttpLabel1 to localized string "The URL" from table "MacYTDL" + set theURLNothttpLabel2 to localized string "is not valid. It should begin with the letters http. You need to paste a valid URL before selecting Download. Quit or OK to try again." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theURLNothttpLabel1 & " \"" & URL_user_entered & "\" " & theURLNothttpLabel2 buttons {theButtonQuitLabel, theButtonOKLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonOKLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + end if + + -- Third, is length of pasted URL /dev/null 2> /dev/null & echo $!" + try + set playlist_Simulate to do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; " & DL_Use_YTDLP & " --flat-playlist " & DL_Playlist_Items_Spec & YTDL_Use_Cookies & URL_user_entered_clean_quoted + try + do shell script "kill " & alerterPiD + end try + on error error_Message + try + do shell script "kill " & alerterPiD + end try + set theErrorWithPlaylistLabel1 to "There was an error with the playlist. The error was: \"" + if DL_Use_Cookies is true and error_Message contains "playlist does not exist" then + set theErrorWithPlaylistLabel2 to "This may have been caused by a faulty cookies file. Check the file and try again." + else + set theErrorWithPlaylistLabel2 to "Check the URL and try again." + end if + display dialog theErrorWithPlaylistLabel1 & error_Message & "\" " & theErrorWithPlaylistLabel2 buttons {theButtonReturnLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end try + -- set AppleScript's text item delimiters to {"[download] Downloading playlist: ", return & "[youtube:tab] Playlist "} -- v1.26 - updated for change to format of data returned by "--flat-playlist" + set AppleScript's text item delimiters to {"[download] Finished downloading playlist: "} + set playlist_Name to text item 2 of playlist_Simulate + if playlist_Name contains "/" then + set playlist_Name to run_Utilities_handlers's replace_chars(playlist_Name, "/", "_") + end if + + -- Get number of items in playlist - find paragraph containing number - warn user if more than 20 items + -- For some reason, YTDL duplicates a line in the log to --flat-playlist for playlists that point to an item (including the youtu.be URLs), but not mixes or ordinary playlists – yt-dlp does not do that + if DL_Use_YTDLP is "youtube-dl" then + set AppleScript's text item delimiters to {": Downloading ", " videos"} + if (URL_user_entered_clean contains "list=PL" or URL_user_entered_clean contains "list=OL") and (URL_user_entered_clean contains "watch?" or URL_user_entered_clean contains "//youtu.be/") then + set playlist_Number_Items to text item 4 of playlist_Simulate as integer + else + set playlist_Number_Items to text item 3 of playlist_Simulate as integer + end if + set AppleScript's text item delimiters to {""} + end if + if DL_Use_YTDLP is "yt-dlp" then + repeat with x from 1 to count paragraphs of playlist_Simulate + if contents of paragraph x of playlist_Simulate begins with "[youtube:tab] Playlist" then + set PL_simulate_Paragraph to paragraph (x) of playlist_Simulate + exit repeat + end if + end repeat + --set AppleScript's text item delimiters to {": Downloading", " videos"} -- <== This code changed on 16/1/23 + set AppleScript's text item delimiters to {": Downloading ", " items "} + set playlist_Number_Items to text item 2 of PL_simulate_Paragraph as integer + set AppleScript's text item delimiters to {""} + end if + if playlist_Number_Items is greater than 20 then + try + if alerterPiD is not "" then do shell script "kill " & alerterPiD + end try + set theManyPlaylistItemsLabel1 to localized string "There are " from table "MacYTDL" + set theManyPlaylistItemsLabel2 to localized string " items in playlist " from table "MacYTDL" + set theManyPlaylistItemsLabel3 to localized string "It will take a long time to download. Do you wish to continue or return to the Main dialog ?" from table "MacYTDL" + set quit_or_return to button returned of (display dialog theManyPlaylistItemsLabel1 & playlist_Number_Items & theManyPlaylistItemsLabel2 & "\"" & playlist_Name & "\". " & theManyPlaylistItemsLabel3 buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + end if + else if DL_Parallel is true then + set parallel_playlist to true + set playlist_Name to "Parallel playlist" + -- User wants to download playlist in parallel - do a simulate but get different data back using --print to get playlist name, item URLs and item names - send output to file - show an alert first + set playListAlertActionLabel to quoted form of "_" + set playListAlertTitle to quoted form of (localized string "MacYTDL" from table "MacYTDL") + set playListAlertMessage to quoted form of (localized string " Please wait." from table "MacYTDL") + set playListAlertSubtitle to quoted form of (localized string "Now checking detail of playlist. " from table "MacYTDL") + set alerterPiD to do shell script quoted form of (resourcesPath & "alerter") & " -message " & playListAlertMessage & " -title " & playListAlertTitle & " -subtitle " & playListAlertSubtitle & " -sender com.apple.script.id.MacYTDL -actions " & playListAlertActionLabel & " -timeout 20 > /dev/null 2> /dev/null & echo $!" + try + do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --print '%(playlist_title)s##%(webpage_url)s##%(title)s.%(ext)s' " & DL_Playlist_Items_Spec & YTDL_Use_Cookies & URL_user_entered_clean_quoted & " 2>&1 &>" & YTDL_simulate_file & " ; exit 0" + try + do shell script "kill " & alerterPiD + end try + on error error_Message + try + do shell script "kill " & alerterPiD + end try + set theErrorWithPlaylistLabel1 to "There was an error with the playlist. The error was: \"" + if DL_Use_Cookies is true and error_Message contains "playlist does not exist" then + set theErrorWithPlaylistLabel2 to "This may have been caused by a faulty cookies file. Check the file and try again." + else + set theErrorWithPlaylistLabel2 to "Check the URL and try again." + end if + display dialog theErrorWithPlaylistLabel1 & error_Message & "\" " & theErrorWithPlaylistLabel2 buttons {theButtonReturnLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end try + end if + set AppleScript's text item delimiters to "" + end if + + set alerterPiD to "" + -- Does the URL point to an entire channel - might be entire channel or a "tab" - either way must check for number of videos - warn if "playlist" or "featured" tab + -- URL_user_entered_clean does not end with "streams" + if playlist_Name is "" and DL_Use_YTDLP is "yt-dlp" and is_channel is true then + set playListAlertActionLabel to quoted form of "_" + set playListAlertTitle to quoted form of (localized string "MacYTDL" from table "MacYTDL") + set playListAlertMessage to quoted form of (localized string " Please wait." from table "MacYTDL") + set playListAlertSubtitle to quoted form of (localized string "Now checking detail of channel. " from table "MacYTDL") + set alerterPiD to do shell script quoted form of (resourcesPath & "alerter") & " -message " & playListAlertMessage & " -title " & playListAlertTitle & " -subtitle " & playListAlertSubtitle & " -sender com.apple.script.id.MacYTDL -actions " & playListAlertActionLabel & " -timeout 10 > /dev/null 2> /dev/null & echo $!" + try + set playlist_Simulate to do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; " & DL_Use_YTDLP & " --flat-playlist " & DL_Playlist_Items_Spec & YTDL_Use_Cookies & URL_user_entered_clean_quoted + on error error_Message + try + do shell script "kill " & alerterPiD + end try + set theErrorWithPlaylistLabel1 to "There was an error with the channel. The error was: \"" + if DL_Use_Cookies is true and error_Message contains "channel does not exist" then + set theErrorWithPlaylistLabel2 to "This may have been caused by a faulty cookies file. Check the file and try again." + else + set theErrorWithPlaylistLabel2 to "Check the URL and try again." + end if + display dialog theErrorWithPlaylistLabel1 & error_Message & "\" " & theErrorWithPlaylistLabel2 buttons {theButtonReturnLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end try + -- Parse channel simulate log for channel name and number of videos - most logs will have "Videos: " once but some will have "Topic: " once - so far, none have both - assume number of videos is at end of same paragraph + -- Have to repeat through paragraphs in playlist_Simulate because layout varies and there are multiple occurrences of most delimiters - luckily only need the first found paragraph + repeat with x from 1 to count paragraphs of playlist_Simulate + if (contents of paragraph x of playlist_Simulate contains " - Videos: Downloading ") or (contents of paragraph x of playlist_Simulate contains " - Topic: Downloading ") then + set playlist_details to paragraph (x) of playlist_Simulate + exit repeat + end if + end repeat + set AppleScript's text item delimiters to {"[youtube:tab] Playlist ", " - Videos: Downloading ", " - Topic: Downloading "} + set playlist_Name to text item 2 of playlist_details + set AppleScript's text item delimiters to {" "} + set playlist_Number_Items to last text item of playlist_details as integer + set AppleScript's text item delimiters to {""} + if playlist_Name contains "/" then + set playlist_Name to run_Utilities_handlers's replace_chars(playlist_Name, "/", "_") + end if + if playlist_Number_Items is greater than 20 then + try + if alerterPiD is not "" then do shell script "kill " & alerterPiD + end try + set theManyPlaylistItemsLabel1 to localized string "There are " from table "MacYTDL" + set theManyPlaylistItemsLabel2 to localized string " items in channel " from table "MacYTDL" + set theManyPlaylistItemsLabel3 to localized string "It will take a long time to download. Do you wish to continue or return to the Main dialog ?" from table "MacYTDL" + set quit_or_return to button returned of (display dialog theManyPlaylistItemsLabel1 & playlist_Number_Items & theManyPlaylistItemsLabel2 & "\"" & playlist_Name & "\". " & theManyPlaylistItemsLabel3 buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + end if + end if + + -- Error checking DL_formats_list before the simulate (which takes time) + if number_of_URLs is greater than 1 and DL_formats_list is true then + set theTooManyUELsLabel to localized string "Sorry, but MacYTDL cannot list formats for more than one URL. Would you like to cancel the download and return to the main dialog or skip the formats list and continue to download ?" from table "MacYTDL" + set skip_or_return to button returned of (display dialog theTooManyUELsLabel buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if skip_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + set DL_formats_list to false + end if + if playlist_Name is not "" and DL_formats_list is true then + set thePlaylistAndListLabel to localized string "Sorry, but MacYTDL cannot list formats for playlists. Would you like to cancel the download and return to the main dialog or skip the formats list and continue to download ?" from table "MacYTDL" + set skip_or_return to button returned of (display dialog thePlaylistAndListLabel buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if skip_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + set DL_formats_list to false + end if + if is_channel is true and DL_formats_list is true then + set thePlaylistAndListLabel to localized string "Sorry, but MacYTDL cannot list formats for channels. Would you like to cancel the download and return to the main dialog or skip the formats list and continue to download ?" from table "MacYTDL" + set skip_or_return to button returned of (display dialog thePlaylistAndListLabel buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if skip_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + set DL_formats_list to false + end if + + -- Do a simulation to get back file names, get is_live status and disclose any errors or warnings + -- URLs to iView and OnDemand show pages causes error => takes processing to Get_ABC_Episodes or Get_SBS_Episodes handlers + -- If desired file format not available, advise user and ask what to do + -- Other kinds of errors are reported to user asking what to do + -- Takes a long time when simulating channels and playlists - users are warned earlier + -- Exclude playlists when user has request parallel downloads - simulate file already contains required data + set simulate_YTDL_output_template to run_Utilities_handlers's replace_chars(YTDL_output_template, " -o '%", " -o '%(is_live)s#%") + if parallel_playlist is false then + do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & YTDL_format_pref & DL_Playlist_Items_Spec & YTDL_credentials & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & simulate_YTDL_output_template & " " & URL_user_entered_clean_quoted & " 2>&1 &>" & YTDL_simulate_file & " ; exit 0" + -- Added delay as one user gets end of file errors which might be due to simulate file not being ready + end if + delay 1 + try + set YTDL_simulate_log to read POSIX file YTDL_simulate_file as «class utf8» + on error errMSG + display dialog "Error in reading simulate file: " & YTDL_simulate_file & return & "The error reported was " & errMSG + end try + + -- Check whether URL points to a live stream - add "no-part" so that file is playable - exclude playlists as by definition they can't be live streams - then strip out is_live response + -- v1.26: force --no-part ignoring user's setting - so that saved file is immediately playable + set is_Livestream_Flag to "False" + if playlist_Name is "" then + if YTDL_simulate_log contains "True#" then + set is_Livestream_Flag to "True" + set YTDL_no_part to "--no-part " + end if + end if + + -- Why is this here ? Very odd - maybe a crude way of dismissing an alert which otherwise doesn't close + try + if alerterPiD is not "" then do shell script "kill " & alerterPiD + end try + + -- If file name is too long, remove user's custom output template or truncate to 190 characters then redo simulation - exclude playlists & multiple downloads + -- Not sure if the "195" figure allows for warnings and remux settings which are also in the simulate log + if (length of YTDL_simulate_log is greater than 195) and ((count of paragraphs in YTDL_simulate_log) is less than 3) then + if YTDL_Custom_Template is not "" then + set theFileNameTooLongLabel to localized string "With your custom file name output template, the total length of the log file name is too long. Would you like to exclude your custom template then continue or return to Main ?" from table "MacYTDL" + set quit_or_return to button returned of (display dialog theFileNameTooLongLabel buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + set YTDL_Custom_Template to "" + set YTDL_output_template to " -o '%(is_live)s#%(title)s.%(ext)s'" + end if + do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & YTDL_no_playlist & DL_Playlist_Items_Spec & YTDL_format_pref & YTDL_credentials & YTDL_Use_Proxy & YTDL_Use_Cookies & simulate_YTDL_output_template & " " & URL_user_entered_clean_quoted & " 2>&1 &>" & YTDL_simulate_file & " ; exit 0" + -- Added delay as one user gets end of file errors which might be due to simulate file not being ready + delay 1 + try + set YTDL_simulate_log to read POSIX file YTDL_simulate_file as «class utf8» + on error errMSG + display dialog "Error in reading simulate file: " & YTDL_simulate_file & return & "The error reported was " & errMSG + end try + end if + + -- Fix output template and file names used in Monitor and Adviser for cases where there is no series - e.g. ABC Radio doesn't have series detail + if YTDL_simulate_log contains "#NA-" and (URL_user_entered contains "ABC" or URL_user_entered contains "ITV" or URL_user_entered contains "7Plus") then + set YTDL_simulate_log to run_Utilities_handlers's replace_chars(YTDL_simulate_log, "NA-", "") -- Removes placeholder when there is no series name - put there by output template for ABC, ITV & 7Plus + set YTDL_output_template to " -o '%(title)s.%(ext)s'" + end if + + if YTDL_simulate_log contains "Unsupported URL: https://7Plus.com.au" then + set theURLWarning7PlusLabel to localized string "This is a 7Plus movie or a show page from which MacYTDL cannot download videos. If it's a show page, try an individual episode." from table "MacYTDL" + display dialog theURLWarning7PlusLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + if YTDL_simulate_log contains "Unsupported URL: https://www.9now.com.au" then + set theURLWarning9NowLabel to localized string "This is a 9Now Show page from which MacYTDL cannot download videos. Try an individual episode." from table "MacYTDL" + display dialog theURLWarning9NowLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + if YTDL_simulate_log contains "Unsupported URL: https://10play.com.au" then + set theURLWarning10playLabel to localized string "This is a 10Play Show page from which MacYTDL cannot download videos. Try an individual episode." from table "MacYTDL" + display dialog theURLWarning10playLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + if YTDL_simulate_log contains "requested format not available" then + set theFormatNotAvailLabel1 to localized string "Your preferred file format is not available. Would you like to cancel download and return, have your download remuxed into your preferred format or just download the best format available ?" from table "MacYTDL" + set theFormatNotAvailLabel2 to localized string "{Note: 3gp format is not available - a request for 3gp will be remuxed into mp4.}" from table "MacYTDL" + set theFormatNotAvailButtonRemuxLabel to localized string "Remux" from table "MacYTDL" + set quit_or_return to button returned of (display dialog theFormatNotAvailLabel1 & return & theFormatNotAvailLabel2 buttons {theButtonReturnLabel, theFormatNotAvailButtonRemuxLabel, theButtonDownloadLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + main_dialog() + else if quit_or_return is theButtonDownloadLabel then + -- User wants to download the best format available so, set desired format to null - simulate again to get file name into simulate file + do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename " & YTDL_no_playlist & DL_Playlist_Items_Spec & YTDL_credentials & URL_user_entered_clean_quoted & " " & simulate_YTDL_output_template & " > /dev/null" & " &> " & YTDL_simulate_file + set YTDL_format to "" + -- Added delay as one user gets end of file errors which might be due to simulate file not being ready + delay 1 + try + set YTDL_simulate_log to read POSIX file YTDL_simulate_file as «class utf8» + on error errMSG + display dialog "Error in reading simulate file: " & YTDL_simulate_file & return & "The error reported was " & errMSG + end try + else if quit_or_return is "Remux" then + -- User wants download remuxed to preferred format - simulate again to get file name into similate file - set desired format to null so that YTDL automatically downloads best available and set remux parameters + do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename " & YTDL_no_playlist & DL_Playlist_Items_Spec & YTDL_credentials & URL_user_entered_clean_quoted & " " & simulate_YTDL_output_template & " > /dev/null" & " &> " & YTDL_simulate_file + set YTDL_format to "" + set remux_format_choice to DL_format + if YTDL_format_pref is "3gp" then + set remux_format_choice to "mp4" + end if + set YTDL_remux_format to "--recode-video " & remux_format_choice & " " & "--postprocessor-args \"-codec copy\" " + delay 1 + try + set YTDL_simulate_log to read POSIX file YTDL_simulate_file as «class utf8» + on error errMSG + display dialog "Error in reading simulate file: " & YTDL_simulate_file & return & "The error reported was " & errMSG + end try + end if + end if + + -- Remove the is_live status from the simulate log - crude but effective - hopefully, there are no valid cases where file name includes "NA-" + set YTDL_simulate_log to run_Utilities_handlers's replace_chars(YTDL_simulate_log, "True#", "") + set YTDL_simulate_log to run_Utilities_handlers's replace_chars(YTDL_simulate_log, "False#", "") + set YTDL_simulate_log to run_Utilities_handlers's replace_chars(YTDL_simulate_log, "NA#", "") -- Removes placeholder when there is no is_live returned by simulate + + -- ******************************************************************************************************************************************************* + -- v1.24: trap errors caused by SBS OnDemand problem - v1.25: yt-dlp is fixed but, leaving in place in case fix is undone by SBS - v1.26: comment out + -- set is_SBS_bug_page to false + -- ******************************************************************************************************************************************************* + -- Try to exclude errors caused by iView URL that bang an error but need to be processed anyway - advise user of other errors + if YTDL_simulate_log contains "ERROR:" and YTDL_simulate_log does not contain "Unsupported URL: https://www.sbs.com.au/ondemand" and YTDL_simulate_log does not contain "Unsupported URL: https://iview.abc.net.au/show" then + -- Extractor error cases are skipped – because that error is a bug in YT-DLP + if URL_user_entered_clean contains "https://iview.abc.net.au/show" and YTDL_simulate_log contains "An extractor error has occurred" then + -- Do nothing + -- ******************************************************************************************************************************************************* + -- else if URL_user_entered_clean contains "https://www.sbs.com.au/ondemand/" and YTDL_simulate_log contains "HTTP Error 403: Forbidden" then + -- set is_SBS_bug_page to true + -- ******************************************************************************************************************************************************* + else + if playlist_Name is not "" then + set theURLErrorTextLabelString to localized string "for the playlist" from table "MacYTDL" + set theURLErrorTextLabel4 to localized string theURLErrorTextLabelString & " " & "'" & playlist_Name & "':" + else + set theURLErrorTextLabel4 to ":" + end if + set theURLErrorTextLabel1 to localized string "There was an error with the URL you entered" from table "MacYTDL" + set theURLErrorTextLabel2 to localized string "The error message was: " from table "MacYTDL" + if skip_Main_dialog is true then + set theURLErrorTextLabel3 to localized string "OK to give up or Download to try anyway." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theURLErrorTextLabel1 & " " & theURLErrorTextLabel4 & return & return & URL_user_entered & return & return & theURLErrorTextLabel2 & return & return & YTDL_simulate_log & return & theURLErrorTextLabel3 buttons {theButtonOKLabel, theButtonDownloadLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonOKLabel then + return + else if quit_or_return is theButtonDownloadLabel then + -- User wants to try to download ! Processing just continues from here down + end if + else + set theURLErrorTextLabel3 to localized string "Quit, OK to return or Download to try anyway." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theURLErrorTextLabel1 & theURLErrorTextLabel4 & return & return & URL_user_entered & return & return & theURLErrorTextLabel2 & return & return & YTDL_simulate_log & return & theURLErrorTextLabel3 buttons {theButtonQuitLabel, theButtonOKLabel, theButtonDownloadLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonOKLabel then + main_dialog() + else if quit_or_return is theButtonDownloadLabel then + -- User wants to try to download ! Processing just continues from here down + end if + end if + end if + end if + if YTDL_simulate_log contains "IOError: CRC check failed" then + set theURLErrorTextLabel1 to localized string "There was an error with the URL you entered. The video might be DRM protected or it could be a network, VPN or macOS install issue. If the URL is correct, you may need to look more deeply into your network settings and macOS install." from table "MacYTDL" + display dialog theURLErrorTextLabel1 buttons {theButtonOKLabel} with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + end if + + -- ***************************************************************************** + -- Setting ABC and SBS show page variables here for now - might change if this handler moves to utilities + -- ***************************************************************************** + -- Set ABC show name and episode count variables so they exist - Initialise indicators which will show whether URL is for an ABC or SBS show page - needed for overwriting code below + set ABC_show_name to "" + set SBS_show_name to "" + set ABC_show_indicator to "No" + set SBS_show_indicator to "No" + + -- Is the URL from an ABC or SBS Show Page ? - If so, get the user to choose which episodes to download - Warn user if URL is an Oz commercial FTA show page + if URL_user_entered_clean contains "iview.abc.net.au/show/" then + -- Add a "/" to end of iView URLs so that they are treated correctly both by code to follow and YT-DLP - This might change if YT-DLP changes + if last character of URL_user_entered_clean is not "/" then + set URL_user_entered_clean to (URL_user_entered_clean & "/") + end if + set branch_execution to run_Utilities_handlers's Get_ABC_Episodes(URL_user_entered, diag_Title, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL) + if branch_execution is "Main" then main_dialog() + set ABC_show_indicator to "Yes" + set URL_user_entered to ABC_show_URLs + -- Bang a warning if user specifies needing a format list and selects more than one ABC episode + set AppleScript's text item delimiters to " " + set number_ABC_SBS_episodes to number of text items in ABC_show_URLs + set AppleScript's text item delimiters to "" + if number_ABC_SBS_episodes is greater than 1 and DL_formats_list is true then + set theTooManyUELsLabel to localized string "Sorry, but MacYTDL cannot list formats for more than one ABC show. Would you like to cancel the download and return to the main dialog or skip the formats list and continue to download ?" from table "MacYTDL" + set skip_or_return to button returned of (display dialog theTooManyUELsLabel buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if skip_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + else if skip_or_return is theButtonContinueLabel then + set DL_formats_list to false + end if + end if + end if + + -- ******************************************************************************************************************************************************* + -- v1.24 - Added workaround for SBS bug in YT-DLP - v1.26: removed test on is_SBS_bug_page + -- if YTDL_simulate_log contains "Unsupported URL: https://www.sbs.com.au/ondemand" or is_SBS_bug_page is true then + if YTDL_simulate_log contains "Unsupported URL: https://www.sbs.com.au/ondemand" then + -- If user uses URL from 'Featured' episode on a SBS Show page, trim trailing text of URL and treat like a Show page - NB Some featured videos are supported by youtube-dl/yt-dlp + if URL_user_entered contains "?action=play" then + set URL_user_entered to (text 1 thru -14 of URL_user_entered & "'") + end if + -- youtube-dl/yt-dlp cannot download from some SBS show links - mostly on the OnDemand home and search pages + if YTDL_simulate_log contains "?play=" or URL_user_entered contains "ondemand/search" then + set theOnDemandURLProblemLabel to localized string "MacYTDL cannot download video from an SBS OnDemand \"Play\" or Search links. Navigate to a \"Show\" page and try again." from table "MacYTDL" + display dialog theOnDemandURLProblemLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + else + set check_URL_ID to last word of URL_user_entered + set length_check_URL_ID to length of check_URL_ID + try + set check_URL_number to check_URL_ID as number + set is_ID to true + on error errText number errNum + set is_ID to false + end try + + -- ******************************************************************************************************************************************************* + -- v1.26: commented out + -- Form up URL and get file name - single URL for a particular video + -- if is_SBS_bug_page is true then + -- set URL_user_entered to ("https://www.sbs.com.au/api/v3/video_smil?id=" & check_URL_ID) + -- set SBS_show_name to "This is a bug URL" + -- set number_ABC_SBS_episodes to 1 + -- set SBS_workaround_page to do shell script "curl " & URL_user_entered + -- if SBS_workaround_page contains "abstract" then + -- set AppleScript's text item delimiters to {"title=\"", "\" abstract="} + -- set download_filename to (text item 2 of SBS_workaround_page) & ".mp4" + -- else + -- set AppleScript's text item delimiters to {"title=\"", "\" copyright="} + -- set download_filename to (text item 2 of SBS_workaround_page) & ".mp4" + -- end if + -- set AppleScript's text item delimiters to "" + -- set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + -- set download_date_time to get_Date_Time() + -- set YTDL_log_file to MacYTDL_preferences_path & "youtube-dl_log-" & download_filename_new & "-" & download_date_time & ".txt" + -- if YTDL_remux_format contains "recode" then set YTDL_remux_format to "" + -- set YTDL_output_template to "-o '" & download_filename_new & ".%(ext)s'" + -- -- If URL ends in a video ID and is not a "watch" URL, then user copied URL from an SBS "play" button - form into a watch URL and process without calling SBS chooser + -- else if is_ID is true and length_check_URL_ID is greater than 7 and URL_user_entered does not contain "watch" then + if is_ID is true and length_check_URL_ID is greater than 7 and URL_user_entered does not contain "watch" then + set URL_user_entered to ("https://www.sbs.com.au/ondemand/watch/" & check_URL_ID) + set SBS_show_name to "This is a watcher URL" + set number_ABC_SBS_episodes to 1 + else + -- The URL from an SBS Show Page - get the user to choose which episodes to download + set branch_execution to run_Utilities_handlers's Get_SBS_Episodes(URL_user_entered, diag_Title, theButtonOKLabel, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL) + if branch_execution is "Main" then main_dialog() + set SBS_show_indicator to "Yes" + set URL_user_entered to SBS_show_URLs + -- Bang a warning if user specifies needing a format list and selects more than one SBS episode + set AppleScript's text item delimiters to " " + set number_ABC_SBS_episodes to number of text items in SBS_show_URLs + set AppleScript's text item delimiters to "" + if number_ABC_SBS_episodes is greater than 1 and DL_formats_list is true then + set theTooManyUELsLabel to localized string "Sorry, but MacYTDL cannot list formats for more than one SBS show. Would you like to cancel the download and return to the main dialog or skip the formats list and continue to download ?" from table "MacYTDL" + set skip_or_return to button returned of (display dialog theTooManyUELsLabel buttons {theButtonReturnLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if skip_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + else if skip_or_return is theButtonContinueLabel then + set DL_formats_list to false + end if + end if + end if + end if + end if + + -- Seventh, look for any more warnings in simulate file. Get filename from the simulate log file + -- Don't show warning to user if it's just the fallback to generic extractor - that happens too often to be useful - same with the "Futurewarning" and non-available subtitles + -- Because extension can be different, exclude that from file name + -- Currently testing method for doing that (getting download_filename) - might not work if file extension is not 3 characters (eg. ts) + -- Might remove the extraneous dot characters in file names if they prove a problem + + set simulate_warnings to "" + repeat with aPara in (paragraphs of YTDL_simulate_log) + -- if aPara contains "WARNING:" then -- <= Used for testing + if aPara contains "WARNING:" and aPara does not contain "Falling back on generic information" and aPara does not contain "Incomplete data received" and aPara does not contain "Ignoring subtitle tracks found in the HLS manifest" and aPara does not contain "FutureWarning:" then + if simulate_warnings is "" then + set simulate_warnings to aPara + else + set simulate_warnings to simulate_warnings & return & aPara + end if + end if + end repeat + -- ******************************************************************************************************************************************************* + -- v1.24 - Exclude SBS workaround URLs from warning advices and from set_File_Names() - BUT, exiting from SBS Chooser doesn't flag workaround - v1.26: commented out + -- if is_SBS_bug_page is false then + -- ******************************************************************************************************************************************************* + if simulate_warnings is not "" then + set theURLWarningTextLabel1 to DL_Use_YTDLP & (localized string " has given a warning on the URL you entered:" from table "MacYTDL") + set theURLWarningTextLabel2 to localized string "The warning message(s) was: " from table "MacYTDL" + set theURLWarningTextLabel3 to (localized string "You can return to the main dialog or continue to see what happens." from table "MacYTDL") + set theWarningButtonsMainLabel to localized string "Main" from table "MacYTDL" + set warning_quit_or_continue to button returned of (display dialog theURLWarningTextLabel1 & return & return & URL_user_entered & return & return & theURLWarningTextLabel2 & return & return & simulate_warnings & return & return & theURLWarningTextLabel3 buttons {theWarningButtonsMainLabel, theButtonContinueLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if warning_quit_or_continue is theButtonContinueLabel then -- <= Ignore warning - try DL - get filename from last paragraph of simulate file + set_File_Names(shellPath, YTDL_simulate_log, URL_user_entered, ABC_show_name, SBS_show_name, DL_Use_YTDLP, parallel_playlist) + else if warning_quit_or_continue is theWarningButtonsMainLabel then -- <= Stop and return to Main dialog + if skip_Main_dialog is true then + error number -128 + end if + main_dialog() + end if + else + -- This is a non-warning download + -- v1.24 add "set URL_user_entered to" because for some reason the URL_user_entered variable going forward in this handler is the old value instead of the value set in set_File_Names - affected SBS chooser cases which are workarounds + set URL_user_entered to set_File_Names(shellPath, YTDL_simulate_log, URL_user_entered, ABC_show_name, SBS_show_name, DL_Use_YTDLP, parallel_playlist) + end if + -- end if + + -- If user asked for subtitles, get ytdl/yt-dlp to check whether they are available - if not, warn user - if available, check against format requested - convert if different + -- v1.21.2, added URL_user_entered to variables specifically passed - fixes SBS OnDemand subtitles error - don't know why + if subtitles_choice is true or DL_YTAutoST is true then + set YTDL_subtitles to check_subtitles_download_available(shellPath, diag_Title, subtitles_choice, URL_user_entered, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, MacYTDL_custom_icon_file, DL_Use_YTDLP, theBestLabel) + end if + + -- Call the formats chooser if in settings and no conflict with other settings - chosen_formats_list is returned containing the format ids to be requested and whether merged or not + -- Currently just return a string but, maybe it would be better to return a list - although this handler would still need the try block for separating items + -- If branch_execution is "Skip", download will proceed without formats specified + -- v1.26 - Decided to put get_formats_list() into separate script file - because it is only script that requires Myriad Tables Lib + set YTDL_formats_to_download to "" + if DL_formats_list is true then + set download_filename_formats to quoted form of download_filename + set chosen_formats_list to "" + set formats_reported to "" + -- Need to get path to get_formats_list script file then run get_formats_list() + set path_to_Formats_Chooser to (path_to_MacYTDL & "Contents:Resources:Scripts:Formats.scpt") as alias + set run_Formats_Chooser_Handler to load script path_to_Formats_Chooser + set chosen_formats_list to run_Formats_Chooser_Handler's formats_Chooser(URL_user_entered, diag_Title, theButtonCancelLabel, theButtonDownloadLabel, X_position, screen_height, MacYTDL_custom_icon_file, MacYTDL_custom_icon_file_posix, theButtonReturnLabel, skip_Main_dialog, path_to_MacYTDL, DL_Use_YTDLP, shellPath, download_filename_formats, YTDL_credentials, window_Position, formats_reported, is_Livestream_Flag) + -- Parse data returned from get_formats_list to separate out the formats list in the format "nnn+nnn" or "nnn,nnn %(format_id)s" + set AppleScript's text item delimiters to " " + set branch_execution to text item 1 of chosen_formats_list + set format_id_output_template to "" + if branch_execution is "Main" then + main_dialog() + else if branch_execution is "Skip" then + set YTDL_formats_to_download to "" + else if branch_execution is "Download" then + try + set YTDL_formats_to_download to " --format " & text item 2 of chosen_formats_list + end try + if YTDL_formats_to_download contains "," then + set format_id_output_template to text item 3 of chosen_formats_list -- Contains "%(format_id)s" if user has asked to not merge but to download and retain each format + end if + end if + set AppleScript's text item delimiters to "" + if format_id_output_template is not "" then + set YTDL_output_template to run_Utilities_handlers's replace_chars(YTDL_output_template, ".%(ext)s", "." & format_id_output_template & ".%(ext)s") + end if + end if + + -- Set the YTDL settings into one variable - makes it easier to maintain - ensure spaces are where needed - quoted to enable passing to Monitor script + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_over_writes & YTDL_Thumbnail_Write & YTDL_Thumbnail_Embed & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + + -- Does user want to be able to delete existing files – by default YTDL/YT-DLP refuse to delete existing + continue partially completed downloads + -- Beware ! This section doesn't cope with part download files which are left to klag YTDL - they should be automatically deleted but, anything can happen + -- THIS HAS BUGS - SOMETIMES DOESN'T FIND EXISTING FILES + if DL_over_writes is true then + set downloadsFolder_Path_posix to (POSIX file downloadsFolder_Path) + set downloadsFolder_Path_alias to downloadsFolder_Path_posix as alias + + -- Look for file of same name in downloads folder - use file names saved in the simulate file - there can be one or a number + -- But, first check whether it's an ABC show page - because the simulate result for those comes from the set_File_Names handler - same for SBS + set search_for_download to {} + + if ABC_show_indicator is "Yes" then + set download_filename_new_plain to run_Utilities_handlers's replace_chars(download_filename_new, "_", " ") + repeat with each_filename in (get paragraphs of download_filename_new_plain) + set each_filename to each_filename as text + if each_filename contains "/" then + set offset_to_file_name to last_offset(each_filename, "/") + 2 + set each_filename to text offset_to_file_name thru end of each_filename + end if + set length_each_filename to count words of each_filename + if length_each_filename is not 0 then + try + tell application "Finder" + set search_for_download to (name of files in downloadsFolder_Path_alias where name contains each_filename) + end tell + end try + if search_for_download is not {} then + set theABCShowExistsLabel1 to localized string "A file for the ABC show" from table "MacYTDL" + set theABCShowExistsLabel2 to localized string "already exists." from table "MacYTDL" + set theABCShowExistsLabel3 to localized string "Do you want to continue anyway, download with a different name or stop and return to the main dialog ?" from table "MacYTDL" + set theABCShowExistsButtonOverwriteLabel to localized string "Overwrite" from table "MacYTDL" + set theABCShowExistsButtonNewnameLabel to localized string "New name" from table "MacYTDL" + set overwrite_continue_choice to button returned of (display dialog theABCShowExistsLabel1 & " \"" & each_filename & "\" " & theABCShowExistsLabel2 & return & return & theABCShowExistsLabel3 buttons {theABCShowExistsButtonOverwriteLabel, theABCShowExistsButtonNewnameLabel, theButtonReturnLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if overwrite_continue_choice is theABCShowExistsButtonOverwriteLabel then + -- Have to manually remove existing file because YTDL always refuses to overwrite + set search_for_download to search_for_download as text + set file_to_delete to quoted form of (POSIX path of (downloadsFolder_Path & "/" & search_for_download)) + do shell script "mv " & file_to_delete & " ~/.trash/" + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + else if overwrite_continue_choice is theABCShowExistsButtonNewnameLabel then + set YTDL_output_template_new to run_Utilities_handlers's replace_chars(YTDL_output_template, ".%(ext)s", "-2.%(ext)s") + set set_new_download_filename to text 1 thru -5 of download_filename_new + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, set_new_download_filename, set_new_download_filename & "-2") + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_over_writes & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template_new & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + else if overwrite_continue_choice is theButtonReturnLabel then + if DL_auto is false then + my main_dialog() + else + error number -128 + end if + end if + end if + end if + end repeat + -- Need to revert download_filename_new to just show_name to be passed for the Monitor and Adviser dialogs - but only for the multiple downloads !!! + if (count of paragraphs of download_filename_new_plain) is greater than 1 then + set download_filename_new to ABC_show_name + end if + else if SBS_show_indicator is "Yes" then + set download_filename_new_plain to run_Utilities_handlers's replace_chars(download_filename_new, "_", " ") + repeat with each_filename in (get paragraphs of download_filename_new_plain) + set each_filename to each_filename as text + if each_filename contains "/" then + set offset_to_file_name to last_offset(each_filename, "/") + 2 + set each_filename to text offset_to_file_name thru end of each_filename + end if + set length_each_filename to count words of each_filename + if length_each_filename is not 0 then + try + tell application "Finder" + set search_for_download to (name of files in downloadsFolder_Path_alias where name contains each_filename) + end tell + end try + if search_for_download is not {} then + set theShowExistsLabel1 to localized string "A file for the SBS show" from table "MacYTDL" + set theShowExistsLabel2 to localized string "already exists." from table "MacYTDL" + set theShowExistsLabel3 to localized string "Do you want to continue anyway, download with a different name or stop and return to the main dialog ?" from table "MacYTDL" + set theShowExistsButtonOverwriteLabel to localized string "Overwrite" from table "MacYTDL" + set theShowExistsButtonNewnameLabel to localized string "New name" from table "MacYTDL" + set overwrite_continue_choice to button returned of (display dialog theShowExistsLabel1 & " \"" & each_filename & "\" " & theShowExistsLabel2 & return & return & theShowExistsLabel3 buttons {theShowExistsButtonOverwriteLabel, theShowExistsButtonNewnameLabel, theButtonReturnLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if overwrite_continue_choice is theShowExistsButtonOverwriteLabel then + -- Have to manually remove existing file because YTDL always refuses to overwrite + set search_for_download to search_for_download as text + set file_to_delete to quoted form of (POSIX path of (downloadsFolder_Path & "/" & search_for_download)) + do shell script "mv " & file_to_delete & " ~/.trash/" + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + else if overwrite_continue_choice is theShowExistsButtonNewnameLabel then + set YTDL_output_template_new to run_Utilities_handlers's replace_chars(YTDL_output_template, ".%(ext)s", "-2.%(ext)s") + set set_new_download_filename to text 1 thru -5 of download_filename_new + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, set_new_download_filename, set_new_download_filename & "-2") + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_over_writes & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template_new & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + else if overwrite_continue_choice is theButtonReturnLabel then + if DL_auto is false then + my main_dialog() + else + error number -128 + end if + end if + end if + end if + end repeat + -- Need to revert download_filename_new to just show_name to be passed for the Monitor and Adviser dialogs - but only for the multiple downloads !!! + if (count of paragraphs of download_filename_new_plain) is greater than 1 then + set download_filename_new to SBS_show_name + end if + else + repeat with each_filename in (get paragraphs of YTDL_simulate_log) + set each_filename to each_filename as text + if each_filename contains "/" then + set offset_to_file_name to last_offset(each_filename, "/") + 2 + set each_filename to text offset_to_file_name thru end of each_filename + end if + set length_each_filename to count words of each_filename + if length_each_filename is not 0 then + try + tell application "Finder" + set search_for_download to (name of files in downloadsFolder_Path_alias where name contains each_filename) + end tell + end try + if search_for_download is not {} then + set theShowExistsWarningTextLabel1 to localized string "The file" from table "MacYTDL" + set theShowExistsWarningTextLabel2 to localized string "already exists." from table "MacYTDL" + set theShowExistsWarningTextLabel3 to localized string "Do you want to continue anyway, download with a different name or stop and return to the main dialog ?" from table "MacYTDL" + set theShowExistsButtonOverwriteLabel to localized string "Overwrite" from table "MacYTDL" + set theShowExistsButtonNewnameLabel to localized string "New name" from table "MacYTDL" + set overwrite_continue_choice to button returned of (display dialog theShowExistsWarningTextLabel1 & " \"" & each_filename & "\" " & theShowExistsWarningTextLabel2 & return & return & theShowExistsWarningTextLabel3 buttons {theShowExistsButtonOverwriteLabel, theShowExistsButtonNewnameLabel, theButtonReturnLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if overwrite_continue_choice is theShowExistsButtonOverwriteLabel then + -- Have to manually remove existing file because YTDL always refuses to overwrite + set search_for_download to search_for_download as text + set file_to_delete to quoted form of (POSIX path of (downloadsFolder_Path & "/" & search_for_download)) + do shell script "mv " & file_to_delete & " ~/.trash/" + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + else if overwrite_continue_choice is theShowExistsButtonNewnameLabel then + set YTDL_output_template_new to run_Utilities_handlers's replace_chars(YTDL_output_template, ".%(ext)s", "-2.%(ext)s") + set set_new_download_filename to text 1 thru -5 of download_filename_new + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, set_new_download_filename, set_new_download_filename & "-2") + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_over_writes & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template_new & " " & YTDL_QT_Compat & " " & YTDL_formats_to_download & " ") + else if overwrite_continue_choice is theButtonReturnLabel then + if DL_auto is false then + my main_dialog() + else + error number -128 + end if + end if + end if + end if + end repeat + end if + end if + + -- Need to revert download_filename_new to just show_name to be passed for the Monitor and Adviser dialogs - but only for the multiple downloads !!! + -- Added in v1.24 - don't know why I didn't notice a problem with Monitor as this was needed for years ! + -- v1.26 - Add parallel download flag to download_filename_new - Monitor does all heavy lifting to initiate parallel downloads from iView + set download_filename_new_plain to run_Utilities_handlers's replace_chars(download_filename_new, "_", " ") + if ABC_show_indicator is "Yes" then + if (count of paragraphs of download_filename_new_plain) is greater than 1 then + set download_filename_new to ABC_show_name + if DL_Parallel is true then + set download_filename_new to download_filename_new & "$$" + end if + end if + end if + if SBS_show_indicator is "Yes" then + if (count of paragraphs of download_filename_new_plain) is greater than 1 then + set download_filename_new to SBS_show_name + if DL_Parallel is true then + set download_filename_new to download_filename_new & "$$" + end if + end if + end if + + -- Add the URL and file name to the batch file if requested + if DL_batch_status is true then + add_To_Batch(URL_user_entered, download_filename, download_filename_new, YTDL_remux_format) + -- add_To_Batch(URL_user_entered, download_filename) -- Changed on 10/2/23 + -- add_To_Batch(URL_user_entered, download_filename_new, YTDL_remux_format) - v1.26 - need download_filname for multiple URL cases + end if + + -- Prepare to call on the download Monitor - first get Monitor script location -- Monitor-bundle.scptd + set myMonitorScriptAsString to quoted form of ((POSIX path of path_to_MacYTDL) & "Contents/Resources/Scripts/Monitor.scpt") + + -- Get number of current downloads underway - each download spawns 2 osascript processes - send to monitor.scpt for positioning monitor dialogs + try -- In a try block to catch error of nil pids returned + set monitor_dialogs_list to do shell script "pgrep -f osascript" + set monitor_dialog_position to ((count of paragraphs in monitor_dialogs_list) / 2) + 1 + on error + set monitor_dialog_position to 1 + end try + + -- Pull together all the parameters to be sent to the Monitor script + -- Set URL to quoted form so that Monitor will parse myParams correctly when URLs come from the Get_ABC_Episodes and Get_SBS_Episodes handlers - but not for single episode iView show pages + if ABC_show_name is not "" or SBS_show_name is not "" then + set URL_user_entered to quoted form of URL_user_entered + end if + + -- Put diag title, file and path names into quotes as they are not passed to Monitor correctly when they contain apostrophes or spaces + set download_filename to quoted form of download_filename + set download_filename_new to quoted form of download_filename_new + set YTDL_log_file to quoted form of YTDL_log_file + set YTDL_simulate_log to text 1 thru -2 of YTDL_simulate_log + set YTDL_simulate_log to quoted form of YTDL_simulate_log + set diag_Title_quoted to quoted form of diag_Title + set YTDL_TimeStamps_quoted to quoted form of YTDL_TimeStamps + + -- Form up parameters for the following do shell script + set my_params to quoted form of downloadsFolder_Path & " " & quoted form of MacYTDL_preferences_path & " " & YTDL_TimeStamps_quoted & " " & ytdl_settings & " " & URL_user_entered & " " & YTDL_log_file & " " & download_filename & " " & download_filename_new & " " & quoted form of MacYTDL_custom_icon_file_posix & " " & monitor_dialog_position & " " & YTDL_simulate_log & " " & diag_Title_quoted & " " & is_Livestream_Flag & " " & screen_width & " " & screen_height & " " & DL_Use_YTDLP & " " & quoted form of path_to_MacYTDL & " " & DL_Delete_Partial + + ---- Show current download settings if user has specified that in Settings + if DL_Show_Settings is true then + set branch_execution to run_Utilities_handlers's show_settings(YTDL_subtitles, DL_Remux_original, DL_YTDL_auto_check, DL_STEmbed, DL_audio_only, YTDL_description, DL_Limit_Rate, DL_over_writes, DL_Thumbnail_Write, DL_verbose, DL_Thumbnail_Embed, DL_Add_Metadata, DL_Use_Proxy, DL_Use_Cookies, DL_Use_Custom_Template, DL_Use_Custom_Settings, remux_format_choice, DL_TimeStamps, DL_Use_YTDLP, YTDL_version, folder_chosen, theButtonQuitLabel, theButtonCancelLabel, theButtonDownloadLabel, DL_Show_Settings, MacYTDL_prefs_file, MacYTDL_custom_icon_file_posix, diag_Title) + if branch_execution is "Main" then main_dialog() + if branch_execution is "Settings" then set_settings() + if branch_execution is "Quit" then quit_MacYTDL() + end if + + + -- PRODUCTION CALL - Call the download Monitor script which will run as a separate process and return so Main Dialog can be re-displayed - thus user can start any number of downloads + do shell script "osascript -s s " & myMonitorScriptAsString & " " & my_params & " " & " > /dev/null 2> /dev/null &" + + -- try + -- -- -- TESTING CALL - Call the download Monitor script for testing - this formulation gets any errors back from Monitor, but holds execution until Monitor dialog is dismissed + -- do shell script "osascript -s s " & myMonitorScriptAsString & " " & my_params & " 2>&1" + -- on error errMSG + -- display dialog "errMSG: " & errMSG + -- end try + + + -- After download, reset ABC & SBS URLs, show name and number_ABC_SBS_episodes so that correct file name is used for next download + -- v1.26 - Decided to change behaviour - retain/discard URL after a download + if DL_discard_URL is true then + set URL_user_entered to "" + set URL_user_entered_clean to "" + end if + set ABC_show_name to "" + set SBS_show_name to "" + set SBS_show_URLs to "" + set ABC_show_URLs to "" + set number_ABC_SBS_episodes to 0 + -- set the clipboard to "" + + -- This is needed so using Service doesn't invoke the Main Dialog + if skip_Main_dialog is false then + main_dialog() + end if + +end download_video + + +---------------------------------------------------------------------------------------------------- +-- +-- Check cookies - called by main_dialog and utilities - if user turns on use_cookies +-- +---------------------------------------------------------------------------------------------------- +-- Check cookies file is available - in case user has not mounted an external volume or has moved/renamed the file/folder +on check_cookies_file(DL_Cookies_Location) + set cookies_Path_posix to (POSIX file DL_Cookies_Location) + try + set cookies_Path_alias to cookies_Path_posix as alias + on error + set theCookiesFileMissingLabel to localized string "Your cookies file is not available. You can make it available then click on Continue, return to set a new cookies location or quit." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theCookiesFileMissingLabel buttons {theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + main_dialog() + else if quit_or_return is theButtonQuitLabel then + quit_MacYTDL() + end if + end try + -- If user clicks "Continue" processing returns to after call to this handler and download process commences +end check_cookies_file + + +---------------------------------------------------------------------------------------------------- +-- +-- Check downloads folder - called by main_dialog and utilities +-- +---------------------------------------------------------------------------------------------------- +-- Check that download folder is available - in case user has not mounted an external volume or has moved/renamed the folder - user must cancel or make folder available +on check_download_folder(folder_chosen, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, diag_Title, MacYTDL_custom_icon_file, skip_Main_dialog) + if folder_chosen = downloadsFolder_Path then + set downloadsFolder_Path_posix to (POSIX file downloadsFolder_Path) + try + set downloadsFolder_Path_alias to downloadsFolder_Path_posix as alias + on error + set theDownloadFolderMissingLabel to localized string "Your download folder is not available. You can make it available then click on Continue, return to set a new download folder or quit." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theDownloadFolderMissingLabel buttons {theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + if skip_Main_dialog is true then + error number -128 + else + main_dialog() + end if + else if quit_or_return is theButtonQuitLabel then + quit_MacYTDL() + end if + check_download_folder(folder_chosen, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, diag_Title, MacYTDL_custom_icon_file, skip_Main_dialog) + end try + end if + -- If user clicks "Continue" processing returns to after call to this handler and download process commences +end check_download_folder + + +------------------------------------------------------------ +-- +-- Try to get correct file names for use elsewhere +-- +------------------------------------------------------------ +on set_File_Names(shellPath, YTDL_simulate_log, URL_user_entered, ABC_show_name, SBS_show_name, DL_Use_YTDLP, parallel_playlist) + + -- Set download_filename_new which is used to show a name in the Monitor dialog and forms basis for log file name + -- Set download_filename which is used by Adviser to open downloaded file (called download_filename_monitor) + -- Reformat file name and add to name of log files - converting spaces to underscores to reduce need for quoting throughout code + + set num_paragraphs_log to count of paragraphs of YTDL_simulate_log + set AppleScript's text item delimiters to " " + set number_of_URLs to number of text items in URL_user_entered + set AppleScript's text item delimiters to "" + + -- Get date and time so it can be added to log file name + set download_date_time to get_Date_Time() + + -- First, look for non-iView show pages (but iView non-error single downloads are included) + -- Trim extension off download filename that is in the simulate file - not implemented as it involves lots of changes to the following code + --set download_filename_no_ext to text 1 thru ((YTDL_simulate_log's length) - (offset of "." in (the reverse of every character of YTDL_simulate_log) as text)) of YTDL_simulate_log + if ABC_show_name is "" and SBS_show_name is "" then -- not an ABC or SBS show page + if number_of_URLs is 1 and parallel_playlist is false then -- Single file download or playlist to be downloaded serially + set download_filename to YTDL_simulate_log + if YTDL_simulate_log does not contain "WARNING:" and YTDL_simulate_log does not contain "ERROR:" then --<= A single file or playlist download non-error and non-warning (iView and non-iView) + if num_paragraphs_log is 2 then --<= A single file download (iView and non-iView) - need to trim ".mp4" from end of file (which is a single line containing one file name) + if YTDL_simulate_log contains "/" then + set offsetOfLastSlash to last_offset(YTDL_simulate_log, "/") + 2 + set download_filename_only to text offsetOfLastSlash thru -2 of YTDL_simulate_log + set download_filename_trimmed to text offsetOfLastSlash thru ((YTDL_simulate_log's length) - (offset of "." in (the reverse of every character of YTDL_simulate_log) as text)) of YTDL_simulate_log + else + set download_filename_only to text 1 thru -2 of YTDL_simulate_log + set download_filename_trimmed to text 1 thru ((YTDL_simulate_log's length) - (offset of "." in (the reverse of every character of YTDL_simulate_log) as text)) of YTDL_simulate_log + end if + set download_filename_trimmed to run_Utilities_handlers's replace_chars(download_filename_trimmed, " ", "_") + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_only, " ", "_") + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + else --<= Probably a Youtube playlist - but beware as there can be playlists on other sites + if playlist_Name is not "" then + set download_filename_new to playlist_Name + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, " ", "_") + else + set download_filename_new to "the-playlist" + end if + set download_filename to YTDL_simulate_log + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_new & "-" & download_date_time & ".txt" + end if + else if YTDL_simulate_log contains "WARNING:" and YTDL_simulate_log does not contain "ERROR:" then --<= Single file download or playlist but simulate.txt contains WARNING(S) (iView and non-iView) - need to trim warning paras and ".mp4" from end of simulate log - but Futurewarning warnings have reverse layout in simulate log + if YTDL_simulate_log contains "FutureWarning:" then + set YTDL_simulate_log to paragraph 1 of YTDL_simulate_log + else + set numParas to count paragraphs in YTDL_simulate_log + -- Assumes that 1st para is a warning and there are no others + set YTDL_simulate_log to paragraph (numParas - 1) of YTDL_simulate_log + end if + set download_filename to YTDL_simulate_log + if text -1 thru -6 of YTDL_simulate_log contains "." then + set download_filename_trimmed to text 1 thru ((YTDL_simulate_log's length) - (offset of "." in (the reverse of every character of YTDL_simulate_log) as text)) of YTDL_simulate_log + else + set download_filename_trimmed to download_filename + end if + -- If it's a playlist, put playlist_name into download_filename_new which is passed to Monitor and into YTDL_log_file which is the name of the log file + if playlist_Name is not "" then + set download_filename_new to playlist_Name + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, " ", "_") + set download_filename_trimmed to download_filename_new + else + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + set download_filename_trimmed to run_Utilities_handlers's replace_chars(download_filename_trimmed, " ", "_") + end if + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + else if YTDL_simulate_log contains "ERROR:" then --<= Single file download or playlist but simulate.txt contains ERROR (iView and non-iView) - need a generic file name for non-playlists + if playlist_Name is not "" then + set download_filename_new to playlist_Name + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, " ", "_") + else + set download_filename_new to "the-error-download" + end if + set download_filename to YTDL_simulate_log + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_new & "-" & download_date_time & ".txt" + end if + + + + else --<= This is a multiple file (iView and non-iView) download - don't distinguish between iView and others - covers warning and non-warning cases also parallel downloads + + + -- ******************************************************************************************************************************************************* + -- v1.26 - Building details needed for parallel downloads - form up records for download_filename_new variable which will contain everything needed for parallel downloads + -- DL_parallel is set using user's preference + -- Playlists probably have 1 URL and so need a separate if/end if block - anyway, simulate created above already has data needed for parallel downloads + -- ******************************************************************************************************************************************************* + if DL_Parallel is true and parallel_playlist is false then + set download_filename to YTDL_simulate_log + set URL_user_entered_for_parallel_multiple to text 2 thru -2 of URL_user_entered -- Need to remove single quotes around URLs + set download_filename_new to "" + set URL_counter to 1 + -- Need to remove warning paragraphs from simulate log while forming up file names with URLs - warnings can be anywhere but usually before the name of the related video + set number_paragraphs to ((count of paragraphs of YTDL_simulate_log) - 1) + repeat with x from 1 to number_paragraphs + if paragraph x of YTDL_simulate_log does not contain "WARNING:" then + set download_filename_full to (paragraph x of YTDL_simulate_log) + -- Trying to remove colons and spaces from file names as it might cause macOS trouble - although it hasn't up till now - the strange small colon DOES cause issues + -- Not sure whether this would make a mess of some URLs + set download_filename_full to run_Utilities_handlers's replace_chars(download_filename_full, " ", "_") + set download_filename_full to run_Utilities_handlers's replace_chars(download_filename_full, ":", "_-") -- Not sure whether this would make a mess of URLs + set download_filename_full to run_Utilities_handlers's replace_chars(download_filename_full, ":", "_-") + -- Need to trim off ".[extension]" from file name before adding to name of log file + set download_filename_trimmed to text 1 thru ((download_filename_full's length) - (offset of "." in (the reverse of every character of download_filename_full) as text)) of download_filename_full + set AppleScript's text item delimiters to {" "} -- There are spaces between the URLs in URL_user_entered_for_parallel_multiple + set URL_user_entered_for_parallel to (text item URL_counter of URL_user_entered_for_parallel_multiple) + set AppleScript's text item delimiters to {""} -- This is needed to prevent "reverse of" adding a space between each character as it's a list being coerced to text + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + set download_filename_new to download_filename_new & download_filename_full & "##" & URL_user_entered_for_parallel & "##" & YTDL_log_file & return + set URL_counter to URL_counter + 1 -- Unlike "x", URL_counter has to be manually incremented + end if + end repeat + + --display dialog "download_filename_full: " & download_filename_full & return & return & "URL_user_entered_for_parallel_multiple: " & URL_user_entered_for_parallel_multiple & return & return & "download_filename_new: " & download_filename_new + + -- This is code is used if user doesn't want parallel downloads i.e. serial + else if DL_Parallel is false then + set download_filename to YTDL_simulate_log + set download_filename_new to "the multiple videos" + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-Multiple_download_on-" & download_date_time & ".txt" + end if + end if + -- User wants parallel download of a playlist - download_filename_new needs to contain playlist name as well as URL, file name and log file name - YTDL_simulate_log has all the data needed + if parallel_playlist is true then + set download_filename to "Parallel downloads" + set download_filename_new to "" + -- Need to exclude warning paragraphs in simulate log while forming up file names with URLs - warnings are usually at the beginning of the simulate log + set number_paragraphs to ((count of paragraphs of YTDL_simulate_log) - 1) + repeat with x from 1 to number_paragraphs + if paragraph x of YTDL_simulate_log does not contain "WARNING:" then + set download_filename_full to (paragraph x of YTDL_simulate_log) + -- Parse out components needed to send to Monitor + set AppleScript's text item delimiters to {"##"} + set playlist_Name to text item 1 of download_filename_full + set URL_user_entered_for_parallel to text item 2 of download_filename_full + set parallel_download_filename to text item 3 of download_filename_full + set AppleScript's text item delimiters to {""} + + -- Trying to remove colons and spaces from file names as it might cause macOS trouble = the strange small colon and the double // DO cause issues + set parallel_download_filename to run_Utilities_handlers's replace_chars(parallel_download_filename, " ", "_") + set parallel_download_filename to run_Utilities_handlers's replace_chars(parallel_download_filename, ":", "_") -- Not sure whether this would make a mess of URLs + set parallel_download_filename to run_Utilities_handlers's replace_chars(parallel_download_filename, ":", "_") + set parallel_download_filename to run_Utilities_handlers's replace_chars(parallel_download_filename, "//", "-") + + -- Need to trim off ".[extension]" from file name before adding to name of log file + set download_filename_trimmed to text 1 thru ((parallel_download_filename's length) - (offset of "." in (the reverse of every character of parallel_download_filename) as text)) of parallel_download_filename + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + + -- Add a unique delimiter to signify this is a playlist parallel download - used by Monitor + set download_filename_new to download_filename_new & playlist_Name & "#$" & parallel_download_filename & "##" & URL_user_entered_for_parallel & "##" & YTDL_log_file & return + end if + end repeat + + --display dialog "download_filename_full: " & download_filename_full & return & return & "URL_user_entered_for_parallel_multiple: " & URL_user_entered_for_parallel_multiple & return & return & "download_filename_new: " & download_filename_new + end if + -- ******************************************************************************************************************************************************* + + + + + else if ABC_show_name is not "" then + -- Second, look for iView show page downloads (which are all ERROR: cases) + if number_ABC_SBS_episodes is 0 then + -- Look for iView single show page downloads - no episodes are shown on these pages - so, have to simulate to get file name - there is usually no separate series name available as the show is also the series + set download_filename to last paragraph of (do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & URL_user_entered & " " & YTDL_output_template) + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + set download_filename_trimmed to text 1 thru ((download_filename's length) - (offset of "." in (the reverse of every character of download_filename) as text)) of download_filename + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + else if number_ABC_SBS_episodes is 1 then + -- Look for iView single episode page downloads - just one episode is shown on these pages - so, have to simulate to get file name + set download_filename to text 1 thru -1 of (do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & URL_user_entered & " " & YTDL_output_template) + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + -- The following line is odd as the simulate log contains lots of rubbish - don't understand how this passed testing + -- set download_filename_trimmed to text 1 thru ((YTDL_simulate_log's length) - (offset of "." in (the reverse of every character of YTDL_simulate_log) as text)) of YTDL_simulate_log + set download_filename_trimmed to text 1 thru ((download_filename_new's length) - (offset of "." in (the reverse of every character of download_filename_new) as text)) of download_filename_new + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + else + -- Look for iView episode show page downloads - two or more episodes are shown on web page and so ABC_show_name is populated in Get_ABC_episodes handler + set download_filename to text 1 thru -1 of (do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & ABC_show_URLs & " " & YTDL_output_template) + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + set ABC_show_name_underscore to run_Utilities_handlers's replace_chars(ABC_show_name, " ", "_") + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & ABC_show_name_underscore & "-" & download_date_time & ".txt" + end if + else if SBS_show_name is not "" then + -- Second, look for SBS show page downloads (which are all ERROR: cases) + if number_ABC_SBS_episodes is 1 then + -- Look for SBS single episode page downloads - just one episode is shown on these pages - so, have to simulate to get file name + -- ******************************************************************************************************************************************************* + -- v1.24 - added try block as SBS changes can cause a crash - can use same workaround code as above for a single file download + try + set download_filename to text 1 thru -1 of (do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & URL_user_entered & " " & YTDL_output_template) + on error errMSG + if errMSG contains "ERROR: [ThePlatform]" or errMSG contains "HTTP Error 403: Forbidden" then + set check_URL_ID to last word of URL_user_entered + set URL_user_entered to ("https://www.sbs.com.au/api/v3/video_smil?id=" & check_URL_ID) + set SBS_show_name to "This is a bug URL" + set number_ABC_SBS_episodes to 1 + set SBS_workaround_page to do shell script "curl " & URL_user_entered + if SBS_workaround_page contains "abstract" then + set AppleScript's text item delimiters to {"title=\"", "\" abstract="} + set download_filename to (text item 2 of SBS_workaround_page) & ".mp4" + else + set AppleScript's text item delimiters to {"title=\"", "\" copyright="} + set download_filename to (text item 2 of SBS_workaround_page) & ".mp4" + end if + set AppleScript's text item delimiters to "" + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + set download_date_time to get_Date_Time() + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_new & "-" & download_date_time & ".txt" + -- if YTDL_remux_format contains "recode" then set YTDL_remux_format to "" -- Poinless as YTDL_remux_format is not sent to this handler and is not global + set YTDL_output_template to "-o '" & download_filename_new & ".%(ext)s'" + else + set theSBSsimulateFailedLabel to localized string "Something went wrong trying to download from SBS. The error was: " from table "MacYTDL" + display dialog (theSBSsimulateFailedLabel & return & return & errMSG) buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + end if + end try + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + -- ******************************************************************************************************************************************************* + -- v1.24 - Cases where a single episode comes from SBS Chooser need to have the log file name formed differently + if YTDL_simulate_log contains "ERROR: Unsupported URL: https://www.sbs.com.au/ondemand" then + set download_filename_trimmed to download_filename_new + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + else + set download_filename_trimmed to text 1 thru ((YTDL_simulate_log's length) - (offset of "." in (the reverse of every character of YTDL_simulate_log) as text)) of YTDL_simulate_log + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + end if + else + + -- ******************************************************************************************************************************************************* + -- v1.24 - added try block as SBS changes can cause a crash - can't use multiple file names in output template - use autonumber instead + try + set download_filename to text 1 thru -1 of (do shell script shellPath & "cd " & quoted form of downloadsFolder_Path & " ; export LC_CTYPE=UTF-8 ; " & DL_Use_YTDLP & " --get-filename --ignore-errors " & SBS_show_URLs & " " & YTDL_output_template) + on error errMSG + if errMSG contains "ERROR: [ThePlatform]" or errMSG contains "HTTP Error 403: Forbidden" then + set URL_user_entered to run_Utilities_handlers's replace_chars(URL_user_entered, "https://www.sbs.com.au/ondemand/watch/", "https://www.sbs.com.au/api/v3/video_smil?id=") + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & SBS_show_name & "-" & download_date_time & ".txt" + -- if YTDL_remux_format contains "recode" then set YTDL_remux_format to "" + set YTDL_output_template to "-o '" & SBS_show_name & "-%(autonumber)s.%(ext)s'" + else + set theSBSsimulateFailedLabel to localized string "Something went wrong trying to download from SBS. The error was: " from table "MacYTDL" + display dialog (theSBSsimulateFailedLabel & return & return & errMSG) buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + end if + end try + + -- Setting download_filename_new and download_filename to SBS_show_name as can't do a simulate to get file name - why do a simulate if it's not used ? + -- v1.26 => Decided to treat SBS same as iView + -- set download_filename_new to run_Utilities_handlers's replace_chars(SBS_show_name, " ", "_") + -- set download_filename to SBS_show_name + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename, " ", "_") + set SBS_show_name_underscore to run_Utilities_handlers's replace_chars(SBS_show_name, " ", "_") + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-" & SBS_show_name_underscore & "-" & download_date_time & ".txt" + end if + -- ******************************************************************************************************************************************************* + end if + + -- Make sure there are no colons in the file name - can happen with iView and maybe others - ytdl converts colons into "_-" so, this must also + -- 1.26 - commented out because of conflict with parallel processing code + -- set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, ":", "_-") + + -- **************** Dialog to show variable values set by this handler - set up for iView URLs + -- display dialog "num_paragraphs_log: " & num_paragraphs_log & return & return & "number_of_URLs: " & number_of_URLs & return & return & "URL_user_entered: " & URL_user_entered & return & return & "ABC_show_name: " & ABC_show_name & return & return & "number_ABC_SBS_episodes: " & number_ABC_SBS_episodes & return & return & "download_filename_new: " & download_filename_new & return & return & "YTDL_log_file: " & YTDL_log_file + -- ***************** + + -- 1.24 – Added this return statement as for some reason the value in URL_user_entered set in this handler was being ignored in download_video() for SBS Chooser workaround cases + -- Might be able to remove this soon as SBS workaround no longer in use + return URL_user_entered + +end set_File_Names + + +----------------------------------------------------------------------- +-- +-- Check subtitles are available and in desired language +-- +----------------------------------------------------------------------- +-- Handler to check that requested subtitles are available and apply conversion if not - called by download_video() when user requests subtitles or auto-subtitles +-- Might not need the duplication in this handler - leave till a later release - Handles ABC, SBS show URL and multiple URLs somewhat +on check_subtitles_download_available(shellPath, diag_Title, subtitles_choice, URL_user_entered, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, MacYTDL_custom_icon_file, DL_Use_YTDLP, theBestLabel) + -- Initialise the subtitles parameter - will go into the YTDL call - will merging settings for author and auto generated STs - Initialise local vars for use in this handler leaving user's settings unchanged + set YTDL_subtitles to "" + set author_gen to subtitles_choice + set auto_gen to DL_YTAutoST + -- Need to use different URL variable for ABC and SBS shows - different treatment of quotes + if ABC_show_name is "" and SBS_show_name is "" then + set URL_for_subtitles_test to URL_user_entered_clean + else + set URL_for_subtitles_test to URL_user_entered + end if + -- If user asked only for auto generated subtitles, warn if URL is not YouTube + if auto_gen is true and author_gen is false and URL_for_subtitles_test does not contain "YouTube" and URL_for_subtitles_test does not contain "YouTu.be" then + set theAutoSTWillNotWorkLabel to localized string "You have specified auto-generated subtitles but not from Youtube. It will not work. Do you want to try author generated subtitles, continue without subtitles or cancel this download and return to the Main dialog ?" from table "MacYTDL" + set theButtonContinueGoAuthorLabel to localized string "Try author" from table "MacYTDL" + set auto_subtitles_stop_or_continue to button returned of (display dialog theAutoSTWillNotWorkLabel buttons {theButtonContinueGoAuthorLabel, theButtonContinueLabel, theButtonReturnLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if auto_subtitles_stop_or_continue is theButtonReturnLabel then + main_dialog() + else if auto_subtitles_stop_or_continue is theButtonContinueGoAuthorLabel then + set author_gen to true + set auto_gen to false + else if auto_subtitles_stop_or_continue is theButtonContinueLabel then + set auto_gen to false + return YTDL_subtitles + end if + end if + + -- If user asked for subtitles, get ytdl to check whether they are available - if not, warn user if so, test for kind and language + set check_subtitles_available to do shell script shellPath & DL_Use_YTDLP & " --list-subs --ignore-errors " & URL_for_subtitles_test + if check_subtitles_available does not contain "Language formats" and check_subtitles_available does not contain "Language formats" and check_subtitles_available does not contain "Language Name" then + set theSTNotAvailableLabel1 to localized string "There is no subtitle file available for your video (although it might be embedded)." from table "MacYTDL" + set theSTNotAvailableLabel2 to localized string "You can quit, stop and return or download anyway." from table "MacYTDL" + set subtitles_quit_or_continue to button returned of (display dialog theSTNotAvailableLabel1 & return & return & theSTNotAvailableLabel2 buttons {theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if subtitles_quit_or_continue is theButtonQuitLabel then + quit_MacYTDL() + else if subtitles_quit_or_continue is theButtonReturnLabel then + main_dialog() + else + return YTDL_subtitles + end if + else if check_subtitles_available contains "Language formats" or check_subtitles_available contains "Language formats" or check_subtitles_available contains "Language Name" then + -- Subtitles are available - check what kind and consider w.r.t settings + -- Auto-gen requested but only author-gen available - what to do ? + if auto_gen is true and author_gen is false and check_subtitles_available does not contain "Available automatic captions for" and check_subtitles_available contains "Available subtitles for" then + set theNoAutoYesAuthorLabel to localized string "You have specified auto-generated subtitles but only author generated are available. Do you want author generated subtitles, continue without subtitles or cancel this download and return to the Main dialog ?" from table "MacYTDL" + set theButtonContinueGoAuthorLabel to localized string "Get author" from table "MacYTDL" + set auto_subtitles_stop_or_continue to button returned of (display dialog theAutoSTWillNotWorkLabel buttons {theButtonContinueGoAuthorLabel, theButtonContinueLabel, theButtonReturnLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if auto_subtitles_stop_or_continue is theButtonReturnLabel then + main_dialog() + else if auto_subtitles_stop_or_continue is theButtonContinueGoAuthorLabel then + set author_gen to true + set auto_gen to false + else if auto_subtitles_stop_or_continue is theButtonContinueLabel then + set auto_gen to false + return YTDL_subtitles + end if + -- Or, author-gen requested but only auto-gen available - what to do ? + else if auto_gen is false and author_gen is true and check_subtitles_available contains "Available automatic captions for" and check_subtitles_available does not contain "Available subtitles for" then + set theNoAutoYesAuthorLabel to localized string "You have specified author-generated subtitles but only auto-generated are available. Do you want auto-generated subtitles, continue without subtitles or cancel this download and return to the Main dialog ?" from table "MacYTDL" + set theButtonContinueGoAutoLabel to localized string "Get auto" from table "MacYTDL" + set auto_subtitles_stop_or_continue to button returned of (display dialog theNoAutoYesAuthorLabel buttons {theButtonContinueGoAutoLabel, theButtonContinueLabel, theButtonReturnLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if auto_subtitles_stop_or_continue is theButtonReturnLabel then + main_dialog() + else if auto_subtitles_stop_or_continue is theButtonContinueGoAutoLabel then + set author_gen to false + set auto_gen to true + else if auto_subtitles_stop_or_continue is theButtonContinueLabel then + set author_gen to false + return YTDL_subtitles + end if + end if + + -- Check against language and format requested - convert if different - there can be more than one format available - warn user if desired language not available + -- Parse check_subtitles_available to get list of languages and formats that are available + set subtitles_info to "" + set log_ST_paragraphs to paragraphs of check_subtitles_available + set show_languages_avail to "" + set AppleScript's text item delimiters to " " + repeat with log_subtitle_paragraph in log_ST_paragraphs + -- Loop thru all paragraphs - collect those which contain subtitle info - look @ all paragraphs because can have >1 download - collate languages avail into one variable + if log_subtitle_paragraph contains " " or character 3 of log_subtitle_paragraph is "-" then + set subtitles_info to subtitles_info & log_subtitle_paragraph & return + set lang_code to text item 1 of log_subtitle_paragraph + set show_languages_avail to show_languages_avail & lang_code & ", " + end if + end repeat + set AppleScript's text item delimiters to "" + + -- Isolate case when both author-gen and auto-gen are available but user requests wrong one due to language non-availability + if subtitles_info does not contain (DL_STLanguage & " ") then + set theSTLangNotAvailableLabel1 to localized string "There is no subtitle file in your preferred language " from table "MacYTDL" + set theSTLangNotAvailableLabel2 to localized string "These languages are available: " from table "MacYTDL" + set theSTLangNotAvailableLabel3 to localized string "You can quit, cancel your download (then go to Settings to change language) or download anyway." from table "MacYTDL" + set subtitles_quit_or_continue to button returned of (display dialog theSTLangNotAvailableLabel1 & "\"" & DL_STLanguage & "\". " & theSTLangNotAvailableLabel2 & return & return & show_languages_avail & return & return & theSTLangNotAvailableLabel3 buttons {theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if subtitles_quit_or_continue is theButtonQuitLabel then + quit_MacYTDL() + else if subtitles_quit_or_continue is theButtonReturnLabel then + main_dialog() + end if + else + set AppleScript's text item delimiters to {"Available automatic captions for", "Available subtitles for"} + if (count of text items in check_subtitles_available) is 3 then + -- YTDL always reports auto-gen availability before author-gen + set alt_lang_avail to "N" + set auto_gen_subtitles to text item 2 of check_subtitles_available + set author_gen_subtitles to text item 3 of check_subtitles_available + if author_gen_subtitles contains (DL_STLanguage & " ") and auto_gen_subtitles does not contain (DL_STLanguage & " ") and author_gen is false then + set dialog_1_text to "auto-generated " + set dialog_2_text to "author-generated " + set dialog_3_text to author_gen_subtitles + set theButtonContinueGoLabel to localized string "Get author" from table "MacYTDL" + set alt_lang_avail to "Y" + end if + if author_gen_subtitles does not contain (DL_STLanguage & " ") and auto_gen_subtitles contains (DL_STLanguage & " ") and auto_gen is false then + set dialog_1_text to "author-generated " + set dialog_2_text to "auto-generated " + set dialog_3_text to auto_gen_subtitles + set theButtonContinueGoLabel to localized string "Get auto" from table "MacYTDL" + set alt_lang_avail to "Y" + end if + if alt_lang_avail is "Y" then + set theSTLangNotAvailableLabel1a to localized string "There is no" from table "MacYTDL" + set theSTLangNotAvailableLabel1b to localized string "subtitle file in your preferred language" from table "MacYTDL" + set theSTLangNotAvailableLabel1 to localized string theSTLangNotAvailableLabel1a & " " & dialog_1_text & theSTLangNotAvailableLabel1b & " " + set theSTLangNotAvailableLabel2a to localized string "But" from table "MacYTDL" + set theSTLangNotAvailableLabel2b to localized string "subtitles are available." from table "MacYTDL" + set theSTLangNotAvailableLabel2 to localized string theSTLangNotAvailableLabel2a & " " & dialog_2_text & theSTLangNotAvailableLabel2b + set theSTLangNotAvailableLabel3a to localized string "You cancel your download, download " from table "MacYTDL" + set theSTLangNotAvailableLabel3b to localized string "subtitles or download without subtitles." from table "MacYTDL" + set theSTLangNotAvailableLabel3 to theSTLangNotAvailableLabel3a & dialog_2_text & theSTLangNotAvailableLabel3b + set subtitles_quit_or_continue to button returned of (display dialog theSTLangNotAvailableLabel1 & "\"" & DL_STLanguage & "\". " & theSTLangNotAvailableLabel2 & return & return & theSTLangNotAvailableLabel3 buttons {theButtonReturnLabel, theButtonContinueGoLabel, theButtonContinueLabel} default button 3 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if subtitles_quit_or_continue is theButtonContinueGoLabel then + if dialog_2_text is "author-generated " then + set author_gen to true + set auto_gen to false + else if dialog_2_text is "auto-generated " then + set author_gen to false + set auto_gen to true + end if + else if subtitles_quit_or_continue is theButtonReturnLabel then + main_dialog() + else if subtitles_quit_or_continue is theButtonContinueLabel then + return YTDL_subtitles + end if + end if + end if + set AppleScript's text item delimiters to "" + end if + + -- If desired language is available or user choose to continue anyway, processing continues here - YTDL returns a warning if lang not available but continues to download + -- Is desired format available - if so continue - if not convert - conversion can currently handle only srt, ass, lrc and vtt - passing best, dfxp or ttml uses YTDL's own choice + -- For author generated STs + if author_gen is true and auto_gen is false then + if subtitles_info does not contain DL_subtitles_format and DL_subtitles_format is not theBestLabel and DL_subtitles_format is not "ttml" and DL_subtitles_format is not "dfxp" then + set YTDL_subtitles to "--write-sub --convert-subs " & DL_subtitles_format & " " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is theBestLabel then + set YTDL_subtitles to "--write-sub --sub-format best " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is "dfxp" then + set YTDL_subtitles to "--write-sub --sub-format dfxp " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is "ttml" then + set YTDL_subtitles to "--write-sub --sub-format ttml " & "--sub-lang " & DL_STLanguage & " " + else + -- Site does provide format user wants + set YTDL_subtitles to "--write-sub --sub-format " & DL_subtitles_format & " " & "--sub-lang " & DL_STLanguage & " " + end if + end if + -- For auto-generated STs + if author_gen is false and auto_gen is true then + if subtitles_info does not contain DL_subtitles_format and DL_subtitles_format is not theBestLabel and DL_subtitles_format is not "ttml" and DL_subtitles_format is not "dfxp" then + set YTDL_subtitles to "--write-auto-sub --convert-subs " & DL_subtitles_format & " " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is theBestLabel then + set YTDL_subtitles to "--write-auto-sub --sub-format best " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is "dfxp" then + set YTDL_subtitles to "--write-auto-sub --sub-format dfxp " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is "ttml" then + set YTDL_subtitles to "--write-auto-sub --sub-format ttml " & "--sub-lang " & DL_STLanguage & " " + else + -- Site does provide format user wants + set YTDL_subtitles to "--write-auto-sub --sub-format " & DL_subtitles_format & " --sub-lang " & DL_STLanguage & " " + end if + end if + -- Ask for both kinds of STs + if author_gen is true and auto_gen is true then + if subtitles_info does not contain DL_subtitles_format and DL_subtitles_format is not theBestLabel and DL_subtitles_format is not "ttml" and DL_subtitles_format is not "dfxp" then + set YTDL_subtitles to "--write-auto-sub --write-sub --convert-subs " & DL_subtitles_format & " " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is theBestLabel then + set YTDL_subtitles to "--write-auto-sub --write-sub --sub-format best " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is "dfxp" then + set YTDL_subtitles to "--write-auto-sub --write-sub --sub-format dfxp " & "--sub-lang " & DL_STLanguage & " " + else if DL_subtitles_format is "ttml" then + set YTDL_subtitles to "--write-auto-sub --write-sub --sub-format ttml " & "--sub-lang " & DL_STLanguage & " " + else + -- Site does provide format user wants + set YTDL_subtitles to "--write-auto-sub --write-sub --sub-format " & DL_subtitles_format & " --sub-lang " & DL_STLanguage & " " + end if + end if + return YTDL_subtitles + end if +end check_subtitles_download_available + + +--------------------------------------------------- +-- +-- Date and time +-- +--------------------------------------------------- + +-- Handler to get and format current date-time - needs all special characters replaced with underscores +on get_Date_Time() + set download_date_time to (current date) as string + set AppleScript's text item delimiters to {", ", " ", ":", ","} + set the item_list to every text item of download_date_time + set AppleScript's text item delimiters to "_" + set download_date_time to the item_list as string + set AppleScript's text item delimiters to "" + return download_date_time +end get_Date_Time + + +--------------------------------------------------- +-- +-- Set Settings +-- +--------------------------------------------------- + +-- Handler for showing dialog to set various MacYTDL and youtube-dl/yt-dlp settings +on set_settings() + -- In case user accidentally deletes the prefs plist file + tell application "System Events" + if exists file MacYTDL_prefs_file then + run_Utilities_handlers's read_settings(MacYTDL_prefs_file) + else + run_Utilities_handlers's set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file) + set prefs_exists to true + end if + end tell + set DL_format to localized string DL_format from table "MacYTDL" + set DL_subtitles_format to localized string DL_subtitles_format from table "MacYTDL" + set DL_Remux_format to localized string DL_Remux_format from table "MacYTDL" + set DL_audio_codec to localized string DL_audio_codec from table "MacYTDL" + + -- Set variables for the settings dialog + set theSettingsDiagPromptLabel to localized string "Settings" from table "MacYTDL" + set theSettingsBUttonAdminLabel to localized string "Admin" from table "MacYTDL" + set settings_diag_prompt to theSettingsDiagPromptLabel + set accViewWidth to 450 + set accViewInset to 0 + + -- Set buttons and controls + set theButtonsSaveLabel to localized string "Save Settings" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonCancelLabel, theSettingsBUttonAdminLabel, theButtonsSaveLabel} button keys {".", "a", ""} default button 3 + --if minWidth > accViewWidth then set accViewWidth to minWidth --<= Not needed as two buttons always narrower than the dialog - keep in case things change + set {theSettingsRule, theTop} to create rule 3 rule width accViewWidth + -- set theCheckboxQTCompatLabel to localized string "QT compatible video" from table "MacYTDL" + -- set {settings_theCheckbox_QT_Compat, theTop} to create checkbox theCheckboxQTCompatLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_QT_Compat + set theCheckBoxUseCustomSettingsLabel to localized string "Use custom settings" from table "MacYTDL" + set {settings_theCheckbox_Use_CustomSettings, theTop, BoxCustSetLeftDist} to create checkbox theCheckBoxUseCustomSettingsLabel left inset 70 bottom (theTop + 3) max width 150 initial state DL_Use_Custom_Settings + set theFieldCustomSettingsLabel to localized string "Custom settings" from table "MacYTDL" + set {settings_theField_Custom_Settings, theTop} to create field DL_Custom_Settings left inset (BoxCustSetLeftDist + 70) bottom (theTop - 20) field width 200 placeholder text theFieldCustomSettingsLabel + set theCheckBoxUseCustomTemplateLabel to localized string "Use custom template" from table "MacYTDL" + set {settings_theCheckbox_Use_CustomTemplate, theTop, CustTempPopLeftDist} to create checkbox theCheckBoxUseCustomTemplateLabel left inset 70 bottom (theTop + 3) max width 150 initial state DL_Use_Custom_Template + set theFieldCustomTemplateLabel to localized string "Custom file name template" from table "MacYTDL" + set {settings_theField_Custom_Template, theTop} to create field DL_Custom_Template left inset (CustTempPopLeftDist + 70) bottom (theTop - 20) field width 200 placeholder text theFieldCustomTemplateLabel + set {settings_theCookiesLocationPathControl, theTop} to create path control (POSIX path of DL_Cookies_Location) left inset 205 bottom (theTop + 1) control width 225 with pops up + set theCheckboxUseCookiesLabel to localized string "Use cookies" from table "MacYTDL" + set {settings_theCheckBox_Use_Cookies, theTop} to create checkbox theCheckboxUseCookiesLabel left inset 70 bottom (theTop - 25) max width 150 initial state DL_Use_Cookies + set theCheckboxUseProxyLabel to localized string "Use proxy" from table "MacYTDL" + set {settings_theCheckBox_Use_Proxy, theTop, ProxyCheckBoxWidth} to create checkbox theCheckboxUseProxyLabel left inset 70 bottom (theTop + 3) max width 100 initial state DL_Use_Proxy + set theFieldProxyURLPlaceholderLabel to localized string "No URL set" from table "MacYTDL" + set {settings_theField_ProxyURL, theTop} to create field DL_Proxy_URL left inset (ProxyCheckBoxWidth + 70) bottom (theTop - 20) field width 250 placeholder text theFieldProxyURLPlaceholderLabel + set theCheckboxForceOWLabel to localized string "Force overwrites" from table "MacYTDL" + set {settings_theCheckbox_OverWrites, theTop} to create checkbox theCheckboxForceOWLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_over_writes + set theCheckboxGetFormatsListLabel to localized string "Get formats list" from table "MacYTDL" + set {settings_theCheckbox_Formats, theTop} to create checkbox theCheckboxGetFormatsListLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_formats_list + set theCheckboxKeepOriginalLabel to localized string "Keep original video and/or subtitles file" from table "MacYTDL" + set {settings_theCheckbox_Original, theTop} to create checkbox theCheckboxKeepOriginalLabel left inset 70 bottom (theTop + 3) max width 200 initial state DL_Remux_original + set theLabeledPopupRemuxFormatLabel to localized string "Remux format:" from table "MacYTDL" + if DL_Use_YTDLP is "yt-dlp" then + set {settings_thePopUp_RemuxFormat, settings_remuxlabel, theTop} to create labeled popup {theNoRemuxLabel, "avi", "flv", "gif", "mkv", "mov", "mp4", "webm"} left inset 70 bottom (theTop + 3) popup width 100 max width 200 label text theLabeledPopupRemuxFormatLabel popup left 70 initial choice DL_Remux_format + else + set {settings_thePopUp_RemuxFormat, settings_remuxlabel, theTop} to create labeled popup {theNoRemuxLabel, "mp4", "mkv", "flv", "webm", "avi", "ogg"} left inset 70 bottom (theTop + 3) popup width 100 max width 200 label text theLabeledPopupRemuxFormatLabel popup left 70 initial choice DL_Remux_format + end if + set theCheckboxMetadataLabel to localized string "Add metadata" from table "MacYTDL" + set {settings_theCheckbox_Metadata, theTop} to create checkbox theCheckboxMetadataLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_Add_Metadata + set theCheckboxEmbedThumbsLabel to localized string "Embed thumbnails" from table "MacYTDL" + set {settings_theCheckbox_ThumbEmbed, theTop} to create checkbox theCheckboxEmbedThumbsLabel left inset 280 bottom (theTop + 1) max width 250 initial state DL_Thumbnail_Embed + set theCheckboxWriteThumbsLabel to localized string "Write thumbnails" from table "MacYTDL" + set {settings_theCheckbox_ThumbWrite, theTop} to create checkbox theCheckboxWriteThumbsLabel left inset 70 bottom (theTop - 18) max width 250 initial state DL_Thumbnail_Write + set theLabeledPopupCodecLabel to localized string "Audio format:" from table "MacYTDL" + set {settings_thePopup_AudioCodec, settingsCodecLabel, theTop} to create labeled popup {theBestLabel, "aac", "flac", "mp3", "m4a", "opus", "vorbis", "wav"} left inset 220 bottom (theTop - 2) popup width 90 max width 200 label text theLabeledPopupCodecLabel popup left 220 initial choice DL_audio_codec + set theCheckboxAudioOnlyLabel to localized string "Audio only" from table "MacYTDL" + set {settings_theCheckbox_AudioOnly, theTop} to create checkbox theCheckboxAudioOnlyLabel left inset 70 bottom (theTop - 21) max width 250 initial state DL_audio_only + set settings_theCheckbox_DescriptionLabel to localized string "Download description" from table "MacYTDL" + set {settings_theCheckbox_Description, theTop} to create checkbox settings_theCheckbox_DescriptionLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_description + set {theSettingsAdminRule, theTop} to create rule (theTop + 1) left inset 70 rule width (accViewWidth - 70) + set theCheckboxDLAutoSTsLabel to localized string "Auto-generated subtitles" from table "MacYTDL" + set {settings_theCheckbox_AutoSubTitles, theTop} to create checkbox theCheckboxDLAutoSTsLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_YTAutoST + set theCheckboxEmbedSTsLabel to localized string "Embed subtitles" from table "MacYTDL" + set {settings_theCheckbox_STEmbed, theTop} to create checkbox theCheckboxEmbedSTsLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_STEmbed + set theLabeledFieldSTsLangLabel to localized string "Subtitles language:" from table "MacYTDL" + set {settings_theField_STLanguage, settings_language_label, theTop, fieldSTLangLeft} to create side labeled field DL_STLanguage left inset 70 bottom (theTop + 3) total width 200 label text theLabeledFieldSTsLangLabel field left 0 + set theCheckboxDLSTsLabel to localized string "Download subtitles" from table "MacYTDL" + set {settings_theCheckbox_SubTitles, theTop, STCheckBoxWidth} to create checkbox theCheckboxDLSTsLabel left inset 70 bottom (theTop + 3) max width 250 initial state DL_subtitles + set theLabeledPopUpSTsFormatLabel to localized string "Subtitles format:" from table "MacYTDL" + set {settings_thePopUp_SubTitlesFormat, settings_STFormatlabel, theTop, popupSTFormatLeftDist} to create labeled popup {theBestLabel, "srt", "vtt", "ass", "lrc", "ttml", "dfxp", "srv3"} left inset (STCheckBoxWidth + 77) bottom (theTop - 23) popup width 65 max width 250 label text theLabeledPopUpSTsFormatLabel popup left (STCheckBoxWidth + 77) initial choice DL_subtitles_format + set {theSettingsSTEndRule, theTop} to create rule (theTop + 1) left inset 70 rule width (accViewWidth - 70) + set theLabeledPopUpResolutionLimitLabel to localized string "Maximum resolution:" from table "MacYTDL" + set {settings_thePopUp_Resolution_Limit, settings_resolutionlabel, theTop, popupLeft} to create labeled popup {theBestLabel, "2560", "1920", "1080", "720", "480"} left inset 70 bottom (theTop + 3) popup width 75 max width 400 label text theLabeledPopUpResolutionLimitLabel popup left 70 initial choice DL_Resolution_Limit + set theLabeledPopUpFileFormatLabel to localized string "File format:" from table "MacYTDL" + set {settings_thePopUp_FileFormat, settings_formatlabel, theTop, popupLeft} to create labeled popup {theDefaultLabel, "mp4", "webm", "ogg", "3gp", "flv"} left inset 70 bottom (theTop + 3) popup width 90 max width 400 label text theLabeledPopUpFileFormatLabel popup left 70 initial choice DL_format + set theLabelPathChangeDLFolderLabel to localized string "Change download folder:" from table "MacYTDL" + set {settings_thePathControl, settings_pathLabel, theTop} to create labeled path control (POSIX path of downloadsFolder_Path) left inset 70 bottom (theTop + 8) control width 150 label text theLabelPathChangeDLFolderLabel with pops up + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 50 view width 64 view height 64 scale image scale proportionally + set {settings_prompt, theTop} to create label settings_diag_prompt left inset 0 bottom (theTop - 5) max width accViewWidth aligns center aligned with bold type + set settings_allControls to {theSettingsRule, settings_theCheckbox_Use_CustomSettings, settings_theField_Custom_Settings, settings_theCheckbox_Use_CustomTemplate, settings_theField_Custom_Template, settings_theCheckBox_Use_Cookies, settings_theCookiesLocationPathControl, settings_theCheckBox_Use_Proxy, settings_theField_ProxyURL, settings_theCheckbox_Original, settings_thePopUp_RemuxFormat, settings_remuxlabel, settings_theCheckbox_Formats, settings_theCheckbox_Metadata, settings_theCheckbox_ThumbEmbed, settings_theCheckbox_ThumbWrite, settings_theCheckbox_AutoSubTitles, settings_thePopUp_SubTitlesFormat, settings_STFormatlabel, settings_theField_STLanguage, settings_language_label, settings_theCheckbox_STEmbed, settings_theCheckbox_SubTitles, settings_theCheckbox_AudioOnly, settings_theCheckbox_OverWrites, settings_thePopup_AudioCodec, settingsCodecLabel, settings_theCheckbox_Description, theSettingsAdminRule, settings_thePopUp_Resolution_Limit, settings_resolutionlabel, settings_thePopUp_FileFormat, settings_formatlabel, settings_thePathControl, settings_pathLabel, MacYTDL_icon, settings_prompt, theSettingsSTEndRule} + + -- Make sure MacYTDL is in front and show dialog - need to make dialog wider in some languages - use width returned from right most control + tell me to activate + if (popupSTFormatLeftDist + 50) is greater than accViewWidth then + set calculatedAccViewWidth to (popupSTFormatLeftDist + 60) + else + set calculatedAccViewWidth to accViewWidth + end if + if (BoxCustSetLeftDist + 250) is greater than calculatedAccViewWidth then + set calculatedAccViewWidth to (BoxCustSetLeftDist + 250) + end if + set {settings_button_returned, settings_button_number_returned, settings_controls_results, finalPosition} to display enhanced window diag_Title buttons theButtons acc view width calculatedAccViewWidth acc view height theTop acc view controls settings_allControls initial position window_Position + + -- Has user moved the MacYTDL window - if so, save new position + if finalPosition is not equal to window_Position then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "final_Position" to finalPosition + end tell + end tell + end if + + if settings_button_number_returned is 3 or settings_button_number_returned is 2 then -- Save Settings and return to Main or Admin + -- Get control results from settings dialog - numbered choice variables are not used but help ensure correct values go into prefs file + -- set settings_choice_1 to item 1 of settings_controls_results -- <= The ruled line + set settings_use_custom_settings_choice to item 2 of settings_controls_results -- <= Use custom settings choice + set settings_custom_settings_choice to item 3 of settings_controls_results -- <= The custom settings to use + set settings_use_custom_template_choice to item 4 of settings_controls_results -- <= Use custom template choice + set settings_custom_template_choice to item 5 of settings_controls_results -- <= The custom template to use + set settings_use_cookies_choice to item 6 of settings_controls_results -- <= Use proxy choice + set settings_cookies_location_choice to item 7 of settings_controls_results -- <= The proxy URL + set settings_use_proxy_choice to item 8 of settings_controls_results -- <= Use proxy choice + set settings_proxy_URL_choice to item 9 of settings_controls_results -- <= The proxy URL + set settings_original_choice to item 10 of settings_controls_results -- <= Keep original after remux choice + set settings_remux_format_choice to item 11 of settings_controls_results -- <= Remux format choice + -- set settings_choice_12 to item 12 of settings_controls_results -- <= The Remux format popup label + set settings_formats_list_choice to item 13 of settings_controls_results -- <= Get formats list choice + set settings_metadata_choice to item 14 of settings_controls_results -- <= Add metadata choice + set settings_thumb_embed_choice to item 15 of settings_controls_results -- <= Embed Thumbnails choice + set settings_thumb_write_choice to item 16 of settings_controls_results -- <= Write Thumbnails choice + set settings_autoST_choice to item 17 of settings_controls_results -- <= Auto-gen subtitles choice + set settings_subtitlesformat_choice to item 18 of settings_controls_results -- <= Subtitles format choice + -- set settings_STFormatlabel_choice to item 19 of settings_controls_results -- <= Subtitles format popup label + set settings_subtitleslanguage_choice to item 20 of settings_controls_results -- <= Subtitles language choice + -- set settings_subtitleslanguage_21 to item 21 of settings_controls_results -- <= Subtitles language field label + set settings_stembed_choice to item 22 of settings_controls_results -- <= Embed subtitles choice + set settings_subtitles_choice to item 23 of settings_controls_results -- <= Subtitles choice + set settings_audio_only_choice to item 24 of settings_controls_results -- <= Audio only choice + set settings_forceOW_choice to item 25 of settings_controls_results -- <= Force overwrites choice + set settings_audio_codec_choice to item 26 of settings_controls_results -- <= Audio codec choice + -- set settings_audiocodec_27 to item 27 of settings_controls_results -- <= Audio codec field label + set settings_description_choice to item 28 of settings_controls_results -- <= Description choice + -- set settings_choice_29 to item 29 of settings_controls_results -- <= The Admin rule + set settings_resolution_choice to item 30 of settings_controls_results -- <= Maximum resolution choice + -- set settings_choice_31 to item 31 of settings_controls_results -- <= The Format popup label + set settings_format_choice to item 32 of settings_controls_results -- <= File format choice + -- set settings_choice_33 to item 33 of settings_controls_results -- <= The Format popup label + set settings_folder_choice to item 34 of settings_controls_results -- <= The download path choice + -- set settings_choice_35 to item 35 of settings_controls_results -- <= The Path label + -- set settings_choice_36 to item 36 of settings_controls_results -- <= The MacYTDL icon + -- set settings_choice_37 to item 37 of settings_controls_results -- <= The Settings label + -- set settings_choice_38 to item 38 of settings_controls_results -- <= The Subtitles end rule + + -- Save new settings to preferences file - no error checking needed for these + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Add_Metadata" to settings_metadata_choice + set value of property list item "Audio_Only" to settings_audio_only_choice + set value of property list item "Audio_Codec" to settings_audio_codec_choice + set value of property list item "Description" to settings_description_choice + set value of property list item "FileFormat" to settings_format_choice + set value of property list item "Keep_Remux_Original" to settings_original_choice + set value of property list item "Over-writes allowed" to settings_forceOW_choice + set value of property list item "Remux_Format" to settings_remux_format_choice + set value of property list item "Resolution_Limit" to settings_resolution_choice + set value of property list item "SubTitles" to settings_subtitles_choice + set value of property list item "Subtitles_Format" to settings_subtitlesformat_choice + set value of property list item "Subtitles_Language" to settings_subtitleslanguage_choice + set value of property list item "Subtitles_YTAuto" to settings_autoST_choice + set value of property list item "Thumbnail_Write" to settings_thumb_write_choice + set value of property list item "SubTitles_Embedded" to settings_stembed_choice + end tell + end tell + + -- User wants a formats list - check that Myriad Tables Lib is installed - if user switches off formats list toggle the saved setting - formats list and auto download seem to be compatible after all + if settings_formats_list_choice is true then + if Myriad_exists is false then + set theInstallMyriadTextLabel to localized string "MacYTDL needs a code library installed in your Libraries folder. It cannot show the \"Formats List\" without that library. Do you wish to install ?" from table "MacYTDL" + set install_Myriad to button returned of (display dialog theInstallMyriadTextLabel buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if install_Myriad is theButtonYesLabel then + run_Utilities_handlers's install_Myriad(Myriad_file, path_to_MacYTDL, resourcesPath) + set Myriad_exists to true + -- Now can go ahead and set the formats list setting + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Get_Formats_List" to true + end tell + end tell + end if + -- else if DL_auto is true then + -- set theChooseListAutoTextLabel to localized string "Sorry, but the Formats List is incompatible with Automatic dowloads. Which would you prefer ?" from table "MacYTDL" + -- set choosel_ListAuto to button returned of (display dialog theChooseListAutoTextLabel buttons {"List", "Auto", "Neither"} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + -- if choosel_ListAuto is "Neither" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to false + -- set value of property list item "Get_Formats_List" to false + -- end tell + -- end tell + -- else if choosel_ListAuto is "List" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to false + -- set value of property list item "Get_Formats_List" to true + -- end tell + -- end tell + -- else if choosel_ListAuto is "Auto" then + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "Auto_Download" to true + -- set value of property list item "Get_Formats_List" to false + -- end tell + -- end tell + -- end if + else + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Get_Formats_List" to true + end tell + end tell + end if + end if + if settings_formats_list_choice is false and DL_formats_list is true then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Get_Formats_List" to false + end tell + end tell + end if + + -- Check proxy URL starts with a valid protocol + if settings_proxy_URL_choice is not "" then + set protocol_chosen to text 1 thru 5 of settings_proxy_URL_choice + if protocol_chosen is not "http:" and protocol_chosen is not "https" and protocol_chosen is not "socks" then + set theNeedValidProtocolLabel to localized string "Sorry, you need a valid protocol for a proxy URL (http, https or socks)." from table "MacYTDL" + display dialog theNeedValidProtocolLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + end if + -- Check that user has a valid proxy URL if Use Proxy is on + if settings_use_proxy_choice is true and settings_proxy_URL_choice is "" then + set theMustProvideProxyURLLabel to localized string "Sorry, you need a proxy URL to use a proxy for downloads." from table "MacYTDL" + display dialog theMustProvideProxyURLLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + -- Now can go ahead and set the proxy settings + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Proxy_URL" to settings_proxy_URL_choice + set value of property list item "Use_Proxy" to settings_use_proxy_choice + end tell + end tell + + -- Check that user has supplied cookies location if use cookies is on + set theNoCookieFileLabel to localized string "No Cookie File" from table "MacYTDL" + if settings_use_cookies_choice is true and settings_cookies_location_choice is ("/" & theNoCookieFileLabel) then + set theMustProvideCookiesLocationLabel to localized string "Sorry, you need to give the location of your cookies file." from table "MacYTDL" + display dialog theMustProvideCookiesLocationLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + -- Ask if user wants to blank out the cookies location + if settings_use_cookies_choice is false and DL_Use_Cookies is true then + set theAskBlankCookiesLocationLabel to localized string "You have turned off \"Use cookies\". Do you wish to remove the current cookies location ?" from table "MacYTDL" + set blankCookiesLocation to button returned of (display dialog theAskBlankCookiesLocationLabel with title diag_Title buttons {theButtonNoLabel, theButtonYesLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + if blankCookiesLocation is theButtonYesLabel then set settings_cookies_location_choice to ("/" & theNoCookieFileLabel) + end if + -- Now can go ahead and set the cookies settings + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_Cookies" to settings_use_cookies_choice + set value of property list item "Cookies_Location" to settings_cookies_location_choice + end tell + end tell + + -- Check that user has supplied custom template - add .%(ext)s if necessary + if settings_use_custom_template_choice is true and (settings_custom_template_choice is "" or settings_custom_template_choice is " ") then + set theMustProvideCustomTemplateLabel to localized string "Sorry, you have not provided a custom file name template." from table "MacYTDL" + display dialog theMustProvideCustomTemplateLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + if settings_custom_template_choice is not equal to "" and settings_custom_template_choice does not end with ".%(ext)s" then + set settings_custom_template_choice to settings_custom_template_choice & ".%(ext)s" + end if + -- Now can go ahead and set the custom output template settings + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_Custom_Output_Template" to settings_use_custom_template_choice + set value of property list item "Custom_Output_Template" to settings_custom_template_choice + end tell + end tell + + -- Check that user has supplied custom settings + if settings_use_custom_settings_choice is true and settings_custom_settings_choice is "" then + set theMustProvideCustomSettingsLabel to localized string "Sorry, you have not provided custom settings." from table "MacYTDL" + display dialog theMustProvideCustomSettingsLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + -- Now can go ahead and set the custom settings settings + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_Custom_Settings" to settings_use_custom_settings_choice + set value of property list item "Custom_Settings" to settings_custom_settings_choice + end tell + end tell + + -- User must make DL folder available - If download path is to a file, use parent folder for downloads + set test_DL_folder to "" + repeat until test_DL_folder is "file" or test_DL_folder is "folder" or test_DL_folder is "disk" or test_DL_folder is "«class cfol»" or test_DL_folder is "alias" + try + tell application "System Events" to set test_DL_folder to (get class of item (settings_folder_choice as text)) as text + on error + set theDownloadFolderMissingLabel to localized string "Your download folder is not available. You can make it available then click on Continue, return to set a new download folder or quit." from table "MacYTDL" + set quit_or_return to button returned of (display dialog theDownloadFolderMissingLabel buttons {theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel} default button 2 cancel button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if quit_or_return is theButtonReturnLabel then + set_settings() + else if quit_or_return is theButtonQuitLabel then + quit_MacYTDL() + end if + end try + end repeat + if test_DL_folder is "file" then + -- Trim last part of path name and use parent for downloads + set offset_to_file_name to last_offset(settings_folder_choice as text, "/") + set settings_folder_choice to text 1 thru offset_to_file_name of settings_folder_choice + end if + -- Now can go ahead and set the download folder setting + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "DownloadFolder" to settings_folder_choice + end tell + end tell + + -- Check for invalid choice of subtitles and embedding and if OK, save to preferences file -- v1.26 - Found no need to write subtitles + -- if settings_subtitles_choice is false and settings_autoST_choice is false and settings_stembed_choice is true then + -- set theSTsEmbeddedTogetherLabel to localized string "Sorry, you need to turn on subtitles if you want them embedded." from table "MacYTDL" + -- display dialog theSTsEmbeddedTogetherLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + -- set_settings() + -- end if + + -- Check for invalid choice of subtitles embedding and file format - v1.26 - Specific file format or remux not necessary for embedding subtitles + -- if settings_stembed_choice is true and (settings_format_choice is not "mp4" and settings_format_choice is not "mkv" and settings_format_choice is not "webm" and settings_remux_format_choice is not "webm" and settings_remux_format_choice is not "mkv" and settings_remux_format_choice is not "mp4") then + -- set theSTsEmbeddedFileformatLabel to localized string "Sorry, File format or Remux format must be mp4, mkv or webm for subtitles to be embedded." from table "MacYTDL" + -- display dialog theSTsEmbeddedFileformatLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + -- set_settings() + -- end if + -- -- Now can go ahead and set the subtitles embedding settings + -- tell application "System Events" + -- tell property list file MacYTDL_prefs_file + -- set value of property list item "SubTitles_Embedded" to settings_stembed_choice + -- end tell + -- end tell + + -- Can set embed thumbnail to true if user is using yt-dlp or (user is using youtube-dl, Atomic is installed and audio format is mp3 or m4a) + if settings_thumb_embed_choice is true and ((DL_Use_YTDLP is "yt-dlp") or (DL_Use_YTDLP is "youtube-dl" and Atomic_is_installed is true and settings_audio_only_choice is true and (settings_audio_codec_choice is "mp3" or settings_audio_codec_choice is "m4a"))) then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Thumbnail_Embed" to true + end tell + end tell + -- If Atomic is not installed, cannot set embed thumbnails + else if settings_thumb_embed_choice is true and Atomic_is_installed is false and DL_Use_YTDLP is "youtube-dl" then + set theSTsEmbedFormatLabel to localized string "Sorry, to embed thumbnails, you need to install Atomic Parsley. You can do that in Utilities." from table "MacYTDL" + display dialog theSTsEmbedFormatLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + else if settings_thumb_embed_choice is true and DL_Use_YTDLP is "youtube-dl" and (settings_audio_only_choice is false or (settings_audio_codec_choice is not "mp3" and settings_audio_codec_choice is not "m4a")) then + set theSTsEmbedFormatLabel to localized string "Sorry, to embed thumbnails, you need to specify audio only and use mp3 or m4a audio format." from table "MacYTDL" + display dialog theSTsEmbedFormatLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + set_settings() + end if + -- User wants Embedding off - set settings and return to Main + if settings_thumb_embed_choice is false then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Thumbnail_Embed" to false + end tell + end tell + end if + if settings_button_number_returned is 2 then -- Go to Admin + set branch_execution to run_Utilities_handlers's set_admin_settings(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file, theButtonCancelLabel, window_Position, theButtonReturnLabel, MacYTDL_custom_icon_file_posix) + if branch_execution is "Main" then main_dialog() + if branch_execution is "Settings" then set_settings() + end if + end if + + main_dialog() + +end set_settings + + +--------------------------------------------------- +-- +-- Check for youtube-dl/yt-dlp updates +-- +--------------------------------------------------- + +-- Handler to check and update yt-dlp if user wishes - called by Utilities dialog to update script and switch to YT-DLP, the auto check on startup and the Warning dialog +-- v1.24 – Added code to enable switch from Homebrew to MacYTDL YT-DLP install +on check_ytdl(show_yt_dlp) + -- Get version of yt-dlp available from GitHub - which has a different name to what is used by MacYTDL - get legacy version for users on 10.9-10.15 - Not called if user has Homebrew + -- v1.24 - no longer offer to update youtube-dl + set YTDL_site_URL to "https://github.com/yt-dlp/yt-dlp/releases" + if show_yt_dlp is "yt-dlp" then + set name_of_executable to "yt-dlp_macos" + else if show_yt_dlp is "yt-dlp-legacy" then + set name_of_executable to "yt-dlp_macos_legacy" + end if + try + set YTDL_releases_page to do shell script "curl " & YTDL_site_URL & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + on error errMSG + set theYTDLCurlErrorLabel1 to localized string "There was an error with looking for the " from table "MacYTDL" + set theYTDLCurlErrorLabel2 to localized string " web page. The error was: " from table "MacYTDL" + set theYTDLCurlErrorLabel3 to localized string ", and the URL that produced the error was: " from table "MacYTDL" + set theYTDLCurlErrorLabel4 to localized string "Try again later and/or send a message to macytdl@gmail.com with the details." from table "MacYTDL" + set theYTDLCurlErrorLabel to theYTDLCurlErrorLabel1 & show_yt_dlp & theYTDLCurlErrorLabel2 & errMSG & theYTDLCurlErrorLabel3 & YTDL_site_URL & ". " & theYTDLCurlErrorLabel4 + display dialog theYTDLCurlErrorLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + end try + + -- The plist file normally has the correct version number of the installed YTDL_version - but, because settings are on a user basis, on multi-user Macs this can be out-of-date + if DL_Use_YTDLP is "yt-dlp" or DL_Use_YTDLP is "yt-dlp-legacy" then + set installedYTDL_version to do shell script ytdlp_file & " --version" + else + set installedYTDL_version to do shell script youtubedl_file & " --version" + end if + if installedYTDL_version is not YTDL_version then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "YTDL_YTDLP_version" to installedYTDL_version + end tell + end tell + set YTDL_version to installedYTDL_version -- Added on 9/6/23 - seems like a good idea + end if + + set theYTDLUpToDateLabela to localized string " is up to date. Your current version is " from table "MacYTDL" + set theYTDLUpToDateLabel to show_yt_dlp & theYTDLUpToDateLabela + set switch_flag to false + if alert_text_ytdl is "Switching" then set switch_flag to true + set alert_text_ytdl to theYTDLUpToDateLabel & installedYTDL_version + -- Trap case in which user is offline or some other problem in reaching YT-DLP + if YTDL_releases_page is "" then + set theYTDLPageErrorLabel1 to localized string "There was a problem with looking for " from table "MacYTDL" + set theYTDLPageErrorLabel2 to localized string "Perhaps you are not connected to the internet or GitHub is currently not available." from table "MacYTDL" + set theYTDLPageErrorLabel to theYTDLPageErrorLabel1 & show_yt_dlp & ". " & theYTDLPageErrorLabel2 + display dialog theYTDLPageErrorLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + else + set AppleScript's text item delimiters to "Latest" + set YTDL_releases_text to text item 1 of YTDL_releases_page + set numParas to count paragraphs in YTDL_releases_text + set version_para to paragraph (numParas) of YTDL_releases_text + set AppleScript's text item delimiters to " " + set YTDL_version_check to text item 2 of version_para + set AppleScript's text item delimiters to "" + if YTDL_version_check is not equal to installedYTDL_version or homebrew_ytdlp_exists is true then + if switch_flag is true then + set YTDL_update_text to "To switch to " & show_yt_dlp & " it will need to be installed. Would you like to install it now ?" + else + set YTDL_update_text to "A new version of " & show_yt_dlp & " is available. You have version " & installedYTDL_version & ". The current version is " & YTDL_version_check & return & return & "Would you like to install it now ?" + end if + tell me to activate + set YTDL_install_answ to button returned of (display dialog YTDL_update_text buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if YTDL_install_answ is theButtonYesLabel then + set installAlertActionLabel to quoted form of "_" + set installAlertTitle to quoted form of (localized string "MacYTDL installation:" from table "MacYTDL") + set installAlertMessage to quoted form of (localized string "started. Please wait." from table "MacYTDL") + set installAlertSubtitle to quoted form of ((localized string "Download and install of " from table "MacYTDL") & show_yt_dlp) + do shell script resourcesPath & "alerter -message " & installAlertMessage & " -title " & installAlertTitle & " -subtitle " & installAlertSubtitle & " -timeout 5 -sender com.apple.script.id.MacYTDL -actions " & installAlertActionLabel & " > /dev/null 2> /dev/null & " + try + if homebrew_ytdlp_exists is true then + do shell script "rm /usr/local/bin/yt-dlp" with administrator privileges + end if + do shell script "curl -L " & YTDL_site_URL & "/download/" & YTDL_version_check & "/" & name_of_executable & " -o /usr/local/bin/yt-dlp" with administrator privileges + on error errMSG + if errMSG does not contain "User canceled" then + display dialog "There was an error in downloading the YT-DLP update. The error reported was " & errMSG + end if + main_dialog() + end try + do shell script "chmod a+x /usr/local/bin/yt-dlp" with administrator privileges + if show_yt_dlp is "yt-dlp" or show_yt_dlp is "yt-dlp-legacy" then + set ytdlp_exists to true + else + set YTDL_exists to true + end if + set YTDL_version to YTDL_version_check + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + set theYTDLUpDatedLabel to localized string " has been updated. Your new version is " from table "MacYTDL" + set alert_text_ytdl to show_yt_dlp & theYTDLUpDatedLabel & YTDL_version + else + set theYTDLOutOfDateLabel to localized string " installed has not been changed. Your current version is " from table "MacYTDL" + set alert_text_ytdl to show_yt_dlp & theYTDLOutOfDateLabel & YTDL_version + end if + end if + end if +end check_ytdl + + +-------------------------------------------------------------------------- +-- +-- Are FFMpeg/FFprobe up-to-date - fork to relevant handler +-- +-------------------------------------------------------------------------- + +-- Handler for forking FFmpeg & FFprobe version checks to ARM or Intel handlers - called by "Check for FFmpeg update" in Utilities Dialog +on check_ffmpeg() + if user_system_arch is "Intel" then + check_ffmpeg_intel() + else + check_ffmpeg_arm() + end if +end check_ffmpeg + +-------------------------------------------------------------------------- +-- +-- Are FFMpeg/FFprobe up-to-date - Intel +-- +-------------------------------------------------------------------------- + +-- Handler for updating FFmpeg & FFprobe - called by "Check for FFmpeg update" in Utilities Dialog - assumes always have same version of both tools +on check_ffmpeg_intel() + -- Get version of FFmpeg currently installed + set ffmpeg_version_long to do shell script ffmpeg_file & " -version" + set ffprobe_version_long to do shell script ffprobe_file & " -version" + set AppleScript's text item delimiters to {"-", " "} + set ffmpeg_version to text item 3 of ffmpeg_version_long + set ffprobe_version to text item 3 of ffprobe_version_long + set AppleScript's text item delimiters to "" + set theFFmpegAlertUpToDateLabel to localized string "FFmpeg and FFprobe are up to date. Your current version is " from table "MacYTDL" + set alert_text_ffmpeg to theFFmpegAlertUpToDateLabel & ffmpeg_version + -- Get version of FFmpeg available from web site - is also proxy for FFprobe version + set ffmpeg_site to "https://evermeet.cx/pub/ffmpeg/" + try + set FFmpeg_page to do shell script "curl " & ffmpeg_site & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + on error errMSG + set theFFmpegCurlErrorLabel to localized string "There was an error with looking for the FFmpeg web page. The error was: " & errMSG & ", and the URL that produced the error was: " & ffmpeg_site & ". Try again later and/or send a message to macytdl@gmail.com with the details." from table "MacYTDL" + display dialog theFFmpegCurlErrorLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + end try + -- Trap case in which user is offline + if FFmpeg_page is "" then + set theFFmpegDownloadProblemLabel to localized string "There was a problem with accessing FFmpeg. Perhaps you are not connected to the internet or the server is currently not available. Try again later." from table "MacYTDL" + display dialog theFFmpegDownloadProblemLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + else + set ffmpeg_version_start to (offset of "version" in FFmpeg_page) + 8 + set ffmpeg_version_end to (offset of "-tessus" in FFmpeg_page) - 1 + set ffmpeg_version_check to text ffmpeg_version_start thru ffmpeg_version_end of FFmpeg_page + if ffmpeg_version_check is not equal to ffmpeg_version or ffmpeg_version_check is not equal to ffprobe_version then + set theFFmpegOutDatedTextLabel1 to localized string "FFmpeg is out of date. You have version " from table "MacYTDL" + set theFFmpegOutDatedTextLabel2 to localized string "The current version is " from table "MacYTDL" + set theFFmpegOutDatedTextLabel3 to localized string "Would you like to update it now ? If yes, this will also update FFprobe. Note: You may need to provide administrator credentials." from table "MacYTDL" + set ffmpeg_install_text to theFFmpegOutDatedTextLabel1 & ffmpeg_version & ". " & theFFmpegOutDatedTextLabel2 & ffmpeg_version_check & return & return & theFFmpegOutDatedTextLabel3 + tell me to activate + set ffmpeg_install_answ to button returned of (display dialog ffmpeg_install_text buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if ffmpeg_install_answ is theButtonYesLabel then + run_Utilities_handlers's install_ffmpeg_ffprobe_intel(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os) + set theFFmpegProbeAlertUpDatedLabel to localized string "FFmpeg and FFprobe have been updated. Your new version is " from table "MacYTDL" + set alert_text_ffmpeg to theFFmpegProbeAlertUpDatedLabel & ffmpeg_version + else + set theFFmpegProbeAlertOutOfDateLabel to localized string "FFmpeg is out of date. Your current version is " from table "MacYTDL" + set alert_text_ffmpeg to "" & ffmpeg_version + end if + end if + end if +end check_ffmpeg_intel + + +-------------------------------------------------------------------------- +-- +-- Are FFMpeg/FFprobe up-to-date - ARM +-- +-------------------------------------------------------------------------- + +-- Handler for updating FFmpeg & FFprobe - called by "Check for FFmpeg update" in Utilities Dialog - assumes always have same version of both tools +on check_ffmpeg_arm() + -- Get version of FFmpeg currently installed + set ffmpeg_version_long to do shell script ffmpeg_file & " -version" + set ffprobe_version_long to do shell script ffprobe_file & " -version" + set AppleScript's text item delimiters to {"-", " "} + set ffmpeg_version to text item 3 of ffmpeg_version_long + set ffprobe_version to text item 3 of ffprobe_version_long + set AppleScript's text item delimiters to "" + set theFFmpegAlertUpToDateLabel to localized string "FFmpeg and FFprobe are up to date. Your current version is " from table "MacYTDL" + set alert_text_ffmpeg to theFFmpegAlertUpToDateLabel & ffmpeg_version + -- Get version of FFmpeg available from web site - is also proxy for FFprobe version + set ffmpeg_site to "https://ffmpeg.martin-riedl.de" + try + set FFmpeg_page to do shell script "curl " & ffmpeg_site & " | textutil -stdin -stdout -format html -convert txt -encoding UTF-8 " + on error errMSG + set theFFmpegCurlErrorLabel to localized string "There was an error with looking for the FFmpeg web page. The error was: " & errMSG & ", and the URL that produced the error was: " & ffmpeg_site & ". Try again later and/or send a message to macytdl@gmail.com with the details." from table "MacYTDL" + display dialog theFFmpegCurlErrorLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + end try + -- Trap case in which user is offline + if FFmpeg_page is "" then + set theFFmpegDownloadProblemLabel to localized string "There was a problem with accessing FFmpeg. Perhaps you are not connected to the internet or the server is currently not available. Try again later." from table "MacYTDL" + display dialog theFFmpegDownloadProblemLabel buttons {theButtonOKLabel} default button 1 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600 + main_dialog() + else + set AppleScript's text item delimiters to {"macOS (Apple Silicon/arm64)"} + set release_build_text_FFmpeg to paragraph 2 of text item 3 of FFmpeg_page + set AppleScript's text item delimiters to {" "} + set release_build_version_FFmpeg to text item 2 of release_build_text_FFmpeg + set AppleScript's text item delimiters to {""} + if release_build_version_FFmpeg is not equal to ffmpeg_version or release_build_version_FFmpeg is not equal to ffprobe_version then + set theFFmpegOutDatedTextLabel1 to localized string "FFmpeg is out of date. You have version " from table "MacYTDL" + set theFFmpegOutDatedTextLabel2 to localized string "The current version is " from table "MacYTDL" + set theFFmpegOutDatedTextLabel3 to localized string "Would you like to update it now ? If yes, this will also update FFprobe. Note: You may need to provide administrator credentials." from table "MacYTDL" + set ffmpeg_install_text to theFFmpegOutDatedTextLabel1 & ffmpeg_version & ". " & theFFmpegOutDatedTextLabel2 & release_build_version_FFmpeg & return & return & theFFmpegOutDatedTextLabel3 + tell me to activate + set ffmpeg_install_answ to button returned of (display dialog ffmpeg_install_text buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if ffmpeg_install_answ is theButtonYesLabel then + run_Utilities_handlers's install_ffmpeg_ffprobe_arm(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os) + set theFFmpegProbeAlertUpDatedLabel to localized string "FFmpeg and FFprobe have been updated. Your new version is " from table "MacYTDL" + set alert_text_ffmpeg to theFFmpegProbeAlertUpDatedLabel & ffmpeg_version + else + set theFFmpegProbeAlertOutOfDateLabel to localized string "FFmpeg is out of date. Your current version is " from table "MacYTDL" + set alert_text_ffmpeg to "" & ffmpeg_version + end if + end if + end if +end check_ffmpeg_arm + + +--------------------------------------------------- +-- +-- Perform various utilities +-- +--------------------------------------------------- + +-- Handler for MacYTDL utility operations called by the Utilities button on Main dialog +on utilities() + + run_Utilities_handlers's read_settings(MacYTDL_prefs_file) + set DL_format to localized string DL_format from table "MacYTDL" + set DL_subtitles_format to localized string DL_subtitles_format from table "MacYTDL" + set DL_Remux_format to localized string DL_Remux_format from table "MacYTDL" + set DL_audio_codec to localized string DL_audio_codec from table "MacYTDL" + + -- Test for Service and Atomic installs + set isServiceInstalled to "Yes" + set path_to_home_folder to (path to home folder) + set services_Folder_nonPosix to (path_to_home_folder & "Library:Services:") as text + set macYTDL_service_file_nonPosix to services_Folder_nonPosix & "Send-URL-To-MacYTDL.workflow" + set services_Folder to (POSIX path of (path to home folder) & "/Library/Services/") + set macYTDL_service_file to services_Folder & "Send-URL-To-MacYTDL.workflow" + tell application "System Events" + if not (exists the file macYTDL_service_file) then + set isServiceInstalled to "No" + end if + end tell + set macYTDL_Atomic_file to ("usr:local:bin:AtomicParsley" as text) + tell application "System Events" + if (exists file macYTDL_Atomic_file) then + set Atomic_is_installed to true + else + set Atomic_is_installed to false + end if + end tell + + -- Set youtube-dl/yt-dlp and FFmpeg version installed text - to show in Utilities dialog - use number of items to set nightly/stable build flag + set AppleScript's text item delimiters to "." + set version_Kind_Check to count of text items in YTDL_version + set AppleScript's text item delimiters to "" + set ytdlp_kind to "stable" + if version_Kind_Check is 4 then set ytdlp_kind to "nightly" + set theVersionInstalledLabel to localized string "Installed:" from table "MacYTDL" + set theYTDLVersionInstalledlabel to theVersionInstalledLabel & " v" & YTDL_version + set FFMpeg_version_installed to theVersionInstalledLabel & " v" & ffmpeg_version + set theCurrentInstalledLabel to localized string "Current:" from table "MacYTDL" + set current_settings_installed to "(" & theCurrentInstalledLabel & " " & DL_Settings_In_Use & ")" + + -- Set variables for the Utilities dialog + set theInstructionsTextLabel to localized string "Choose the utility(ies) you would like to run then click 'Start'" from table "MacYTDL" + set instructions_text to theInstructionsTextLabel + set theDiagPromptLabel to localized string "Utilities" from table "MacYTDL" + set utilities_diag_prompt to theDiagPromptLabel + set accViewWidth to 600 + set accViewInset to 75 + + -- Set buttons and controls + set theButtonsDeleteLogsLabel to localized string "Delete logs" from table "MacYTDL" + set theButtonsUninstallLabel to localized string "Uninstall" from table "MacYTDL" + set theButtonsAboutLabel to localized string "About MacYTDL" from table "MacYTDL" + set theButtonsStartLabel to localized string "Start" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonsDeleteLogsLabel, theButtonsUninstallLabel, theButtonsAboutLabel, theButtonCancelLabel, theButtonsStartLabel} button keys {"d", "U", "a", ".", ""} default button 5 + if minWidth > accViewWidth then set accViewWidth to minWidth + set {theUtilitiesRule, theTop} to create rule 10 rule width accViewWidth + -- Set up alternatives for Service and AtomicParsley + if isServiceInstalled is "Yes" then + set theCheckBoxRemoveServiceLabel to localized string "Remove Service" from table "MacYTDL" + set {utilities_theCheckbox_Service_Install, theTop} to create checkbox theCheckBoxRemoveServiceLabel left inset accViewInset bottom (theTop + 5) max width 250 + else + set theCheckBoxInstallServiceLabel to localized string "Install Service" from table "MacYTDL" + set {utilities_theCheckbox_Service_Install, theTop} to create checkbox theCheckBoxInstallServiceLabel left inset accViewInset bottom (theTop + 5) max width 250 + end if + if Atomic_is_installed is true then + set theCheckBoxRemoveAtomicLabel to localized string "Remove Atomic Parsley" from table "MacYTDL" + set {utilities_theCheckbox_Atomic_Install, theTop} to create checkbox theCheckBoxRemoveAtomicLabel left inset accViewInset bottom (theTop + 5) max width 250 + else + set theCheckBoxInstallAtomicLabel to localized string "Install Atomic Parsley" from table "MacYTDL" + set {utilities_theCheckbox_Atomic_Install, theTop} to create checkbox theCheckBoxInstallAtomicLabel left inset accViewInset bottom (theTop + 5) max width 250 + end if + + set AppleScript's text item delimiters to {"-", " "} + set ffmpeg_version_arch to text item 4 of ffmpeg_version_long + set AppleScript's text item delimiters to "" + set switch_FFmpeg to "No" + -- v1.22 - show FFmpeg arch switcher if user on Apple Silicon + set installed_FFmpeg_arch to "ARM" + if ffmpeg_version_arch is "tessus" then + set installed_FFmpeg_arch to "Intel" + set new_FFmpeg_arch to "ARM" + else + set new_FFmpeg_arch to "Intel" + end if + + -- v1.24 - disable FFmpeg items if Homebrew installs are in place + if user_system_arch is "arm64" and homebrew_ffmpeg_exists is false then + set theCheckBoxSwitchFFmpegLabel2 to localized string "Switch FFmpeg to" from table "MacYTDL" + set theCheckBoxSwitchFFmpegLabel to theCheckBoxSwitchFFmpegLabel2 & " " & new_FFmpeg_arch + set {utilities_theCheckbox_SwitchFFmpeg, theTop} to create checkbox theCheckBoxSwitchFFmpegLabel left inset accViewInset bottom (theTop + 5) max width 200 + else + set {utilities_theCheckbox_SwitchFFmpeg, theTop} to create label " " left inset accViewInset + 5 bottom (theTop - 17) max width minWidth - 100 aligns left aligned + end if + if homebrew_ffmpeg_exists is false then + set theCheckBoxCheckFFmpegLabel to localized string "Check for FFmpeg update" from table "MacYTDL" + set theCheckBoxCheckFFmpegversion to theCheckBoxCheckFFmpegLabel & " " & "(" & FFMpeg_version_installed & ")" + set {utilities_theCheckbox_FFmpeg_Check, theTop} to create checkbox theCheckBoxCheckFFmpegversion left inset accViewInset bottom (theTop + 5) max width 250 + else + set {utilities_theCheckbox_FFmpeg_Check, theTop} to create label " " left inset accViewInset + 5 bottom (theTop - 17) max width minWidth - 100 aligns left aligned + end if + set theCheckBoxCheckMacYTDLLabel to localized string "Check for MacYTDL update" from table "MacYTDL" + set {utilities_theCheckbox_MacYTDL_Check, theTop} to create checkbox theCheckBoxCheckMacYTDLLabel left inset accViewInset bottom (theTop + 5) max width 200 + set theCheckBoxReturnDefaultsLabel to localized string "Return to default settings" from table "MacYTDL" + set {utilities_theCheckbox_Return_Defaults, theTop} to create checkbox theCheckBoxReturnDefaultsLabel left inset accViewInset bottom (theTop + 5) max width 250 + set theCheckBoxRestoreSettingsLabel to localized string "Restore settings" from table "MacYTDL" + set {utilities_theCheckbox_Restore_Settings, theTop} to create checkbox theCheckBoxRestoreSettingsLabel & " " & current_settings_installed left inset accViewInset bottom (theTop + 5) max width 200 + set theCheckBoxSaveSettingsLabel to localized string "Save current settings" from table "MacYTDL" + set {utilities_theCheckbox_Save_Settings, theTop} to create checkbox theCheckBoxSaveSettingsLabel left inset accViewInset bottom (theTop + 5) max width 250 + + -- v1.24 - Show YT-DLP switcher if user currently using youtube-dl + if DL_Use_YTDLP is "youtube-dl" then + set theCheckBoxSwitchScriptsLabel to localized string "Switch to yt-dlp" from table "MacYTDL" + set {utilities_theCheckbox_Switch_Scripts, theTop} to create checkbox theCheckBoxSwitchScriptsLabel left inset accViewInset bottom (theTop + 5) max width 250 + set utilities_DL_Use_YTDLP to "youtube-dl" + else + set {utilities_theCheckbox_Switch_Scripts, theTop} to create label " " left inset accViewInset + 5 bottom (theTop - 17) max width minWidth - 100 aligns left aligned with multiline + set utilities_DL_Use_YTDLP to "yt-dlp" + end if + + set theCheckBoxOpenYTDLLabel to (localized string "Open" from table "MacYTDL") & " " & utilities_DL_Use_YTDLP & " " & (localized string "web page" from table "MacYTDL") + set {utilities_theCheckbox_YTDL_release, theTop} to create checkbox theCheckBoxOpenYTDLLabel left inset accViewInset bottom (theTop + 5) max width 200 + + -- v1.24 - Hide YT-DLP updater if user currently using Homebrew or youtube-dl + -- v1.25 - Provide for yt-dlp nightly builds + if ytdlp_exists is true and (DL_Use_YTDLP is "yt-dlp" or DL_Use_YTDLP is "yt-dlp-legacy") then + if ytdlp_kind is "stable" then + set theCheckBoxCheckYTDLNightlyLabel to (localized string "Install" from table "MacYTDL") & " " & utilities_DL_Use_YTDLP & " " & (localized string "nightly build" from table "MacYTDL") + set theCheckBoxCheckYTDLNightlyVersion to theCheckBoxCheckYTDLNightlyLabel + set theCheckBoxCheckYTDLLabel to (localized string "Update" from table "MacYTDL") & " " & utilities_DL_Use_YTDLP & " " & (localized string "stable build" from table "MacYTDL") + set theCheckBoxCheckYTDLversion to theCheckBoxCheckYTDLLabel & " " & "(" & theYTDLVersionInstalledlabel & ")" + set minWidth to 465 + end if + if ytdlp_kind is "nightly" then + set theCheckBoxCheckYTDLNightlyLabel to (localized string "Update" from table "MacYTDL") & " " & utilities_DL_Use_YTDLP & " " & (localized string "nightly build" from table "MacYTDL") + set theCheckBoxCheckYTDLNightlyVersion to theCheckBoxCheckYTDLNightlyLabel & " " & "(" & theYTDLVersionInstalledlabel & ")" + set theCheckBoxCheckYTDLLabel to (localized string "Install" from table "MacYTDL") & " " & utilities_DL_Use_YTDLP & " " & (localized string "stable build" from table "MacYTDL") + set theCheckBoxCheckYTDLversion to theCheckBoxCheckYTDLLabel + set minWidth to 500 + end if + set theCheckBoxDoNotUpdateYTDLLabel to localized string "Do not update YT-DLP" from table "MacYTDL" + set theCheckBoxDoNotUpdateYTDLTextLabel to localized string "Update" from table "MacYTDL" + set {utilities_theMatrix_YTDL_Check, theMatrixLabel, theTop, theMatrixWidth} to create labeled matrix {theCheckBoxDoNotUpdateYTDLLabel, theCheckBoxCheckYTDLversion, theCheckBoxCheckYTDLNightlyVersion} initial choice 1 bottom (theTop + 5) label text (theCheckBoxDoNotUpdateYTDLTextLabel & " YT-DLP") matrix left 110 max width 600 + else + set {utilities_theCheckbox_YTDL_Check, theTop} to create label " " left inset accViewInset + 5 bottom (theTop - 17) max width minWidth - 100 aligns left aligned with multiline + set {theMatrixLabel, theTop} to create label " " left inset accViewInset + 5 bottom (theTop - 17) max width minWidth - 100 aligns left aligned with multiline + set {utilities_theMatrix_YTDL_Check, theTop} to create label " " left inset accViewInset + 5 bottom (theTop - 17) max width minWidth - 100 aligns left aligned with multiline + end if + set theCheckBoxOpenDLFolderLabel to localized string "Open download folder" from table "MacYTDL" + set {utilities_theCheckbox_DL_Open, theTop} to create checkbox theCheckBoxOpenDLFolderLabel left inset accViewInset bottom (theTop + 5) max width 250 + set theCheckBoxOpenLogFolderLabel to localized string "Open log folder" from table "MacYTDL" + set {utilities_theCheckbox_Logs_Open, theTop} to create checkbox theCheckBoxOpenLogFolderLabel left inset accViewInset bottom (theTop + 5) max width 250 + set {utilities_instruct, theTop} to create label instructions_text left inset accViewInset + 5 bottom (theTop + 10) max width minWidth - 100 aligns left aligned with multiline + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 50 view width 64 view height 64 scale image scale proportionally + set {utilities_prompt, theTop} to create label utilities_diag_prompt left inset 0 bottom (theTop) max width minWidth aligns center aligned with bold type + set utilities_allControls to {theUtilitiesRule, utilities_theCheckbox_Service_Install, utilities_theCheckbox_Atomic_Install, utilities_theCheckbox_SwitchFFmpeg, utilities_theCheckbox_FFmpeg_Check, utilities_theCheckbox_MacYTDL_Check, utilities_theCheckbox_Return_Defaults, utilities_theCheckbox_Restore_Settings, utilities_theCheckbox_Save_Settings, utilities_theCheckbox_Switch_Scripts, utilities_theCheckbox_YTDL_release, theMatrixLabel, utilities_theMatrix_YTDL_Check, utilities_theCheckbox_DL_Open, utilities_theCheckbox_Logs_Open, MacYTDL_icon, utilities_instruct, utilities_prompt} + + -- Make sure MacYTDL is in front and show dialog with correct width + tell me to activate + set {utilities_button_returned, utilities_button_number_returned, utilities_controls_results, finalPosition} to display enhanced window diag_Title buttons theButtons acc view width minWidth acc view height theTop acc view controls utilities_allControls initial position window_Position + + -- Has user moved the MacYTDL window - if so, save new position + if finalPosition is not equal to window_Position then + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "final_Position" to finalPosition + end tell + end tell + end if + + if utilities_button_number_returned is 5 then -- Start + -- Get control results from utilities dialog - numbered choice variables are not used but help ensure correct utilities are run + -- set utilities_choice_1 to item 1 of utilities_controls_results -- <= Missing value [the rule] + set utilities_Service_choice to item 2 of utilities_controls_results -- <= Install Service choice + set utilities_Atomic_choice to item 3 of utilities_controls_results -- <= Install Atomic Parsley choice + set utilities_FFmpeg_switch_choice to item 4 of utilities_controls_results -- <= Switch FFmpeg architecture + set utilities_FFmpeg_check_choice to item 5 of utilities_controls_results -- <= Check FFmpeg version choice + set utilities_MacYTDL_check_choice to item 6 of utilities_controls_results -- <= Check MacYTDL version choice + set utilities_Return_Defaults_choice to item 7 of utilities_controls_results -- <= Return to default settings choice + set utilities_Restore_Settings_choice to item 8 of utilities_controls_results -- <= Restore saved settings choice + set utilities_Save_Settings_choice to item 9 of utilities_controls_results -- <= Save current settings choice + set utilities_Switch_choice to item 10 of utilities_controls_results -- <= Switch downloaders choice + set utilities_YTDL_webpage_choice to item 11 of utilities_controls_results -- <= Show YTDL/yt-dlp web page choice + --set utilities_choice_12 to item 12 of utilities_controls_results -- <= Contains matrix label text + set utilities_YTDL_check_choice to item 13 of utilities_controls_results -- <= Check/Install yt-dlp stable/nightly build + set utilities_DL_folder_choice to item 14 of utilities_controls_results -- <= Open download folder choice + set utilities_log_folder_choice to item 15 of utilities_controls_results -- <= Open log folder choice + --set utilities_choice_16 to item 16 of utilities_controls_results -- <= Missing value [the icon] + --set utilities_choice_17 to item 17 of utilities_controls_results -- <= Contains the "Instructions" text + --set utilities_choice_18 to item 18 of utilities_controls_results -- <= Contains the "Utilities" heading + + -- Open log folder + if utilities_log_folder_choice is true then + -- Open the log folder in a Finder window positioned away from the MacYTDL main dialog which will re-appear + tell application "Finder" + activate + open (MacYTDL_preferences_path as POSIX file) + set the position of the front Finder window to {200, 200} + end tell + end if + + -- Open downloads folder - make sure it's available + if utilities_DL_folder_choice is true then + -- Tell utilities handler that it should return to main_dialog when finished - auto_download tells utilities to skip main and just close + set skip_Main_dialog to false + check_download_folder(downloadsFolder_Path, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, diag_Title, MacYTDL_custom_icon_file, skip_Main_dialog) + -- Open the downloads folder in a Finder window positioned away from the MacYTDL main dialog which will re-appear - Assistive Access not needed as Finder windows have position properties + tell application "Finder" + activate + open (downloadsFolder_Path as POSIX file) -- <= Had to read prefs again to get this working - something to do with this path in Main Dialog + set the position of the front Finder window to {100, 100} -- <= This DOES work but is ugly - it opens the window then moves it to a location which should not overlap Main Dialog + end tell + end if + + -- Do selected combination of YT-DLP and FFmpeg version checks - Provide for each possible combination of choices + -- Need to show the version checked dialog before returning to Main dialog + -- v.25 - This section redesigned to handle installation/update of YT-DLP nightly builds + if utilities_YTDL_check_choice contains "build" and utilities_FFmpeg_check_choice is true then + set alert_text_ytdl to "NotSwitching" + if utilities_YTDL_check_choice contains "stable" then + check_ytdl(DL_Use_YTDLP) + else if utilities_YTDL_check_choice contains "nightly" then + -- Install nightly build - no need to check version as nightly builds are released almost every 24 hours + try + do shell script shellPath & " yt-dlp --update-to nightly" with administrator privileges + -- trap case where user cancels credentials dialog + on error number -128 + main_dialog() + end try + set YTDL_version to do shell script shellPath & " yt-dlp --version" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + set theYTDLUpDatedLabel to localized string "has been updated to the most recent nightly build. Your new version is " from table "MacYTDL" + set alert_text_ytdl to "yt-dlp " & theYTDLUpDatedLabel & YTDL_version + end if + if ffmpeg_version is "Not installed" then + run_Utilities_handlers's install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, user_system_arch) + set theFFmpegProbeInstalledAlertLabel to localized string "FFmpeg and FFprobe have been installed." from table "MacYTDL" + set alert_text_ffmpeg to theFFmpegProbeInstalledAlertLabel + else + check_ffmpeg() + end if + tell me to activate + display dialog alert_text_ytdl & return & alert_text_ffmpeg with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + else if utilities_FFmpeg_check_choice is true and utilities_YTDL_check_choice contains "Do not update" then + if ffmpeg_version is "Not installed" then + run_Utilities_handlers's install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, user_system_arch) + set theFFmpegProbeInstalledAlertLabel to localized string "FFmpeg and FFprobe have been installed." from table "MacYTDL" + set alert_text_ffmpeg to theFFmpegProbeInstalledAlertLabel + else + check_ffmpeg() + end if + tell me to activate + display dialog alert_text_ffmpeg & return & return with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + -- else if (utilities_YTDL_check_choice contains "Update yt-dlp stable" and utilities_FFmpeg_check_choice is not true then + else if utilities_YTDL_check_choice contains "build" and utilities_FFmpeg_check_choice is not true then + set alert_text_ytdl to "NotSwitching" + if utilities_YTDL_check_choice contains "stable" then + check_ytdl(DL_Use_YTDLP) + else if utilities_YTDL_check_choice contains "nightly" then + -- Install nightly build + try + do shell script shellPath & " yt-dlp --update-to nightly" with administrator privileges + -- trap case where user cancels credentials dialog + on error number -128 + main_dialog() + end try + set YTDL_version to do shell script shellPath & " yt-dlp --version" + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + set theYTDLUpDatedLabel to localized string "has been updated to the most recent nightly build. Your new version is " from table "MacYTDL" + set alert_text_ytdl to "yt-dlp " & theYTDLUpDatedLabel & YTDL_version + end if + tell me to activate + display dialog alert_text_ytdl & return with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + end if + + -- Added in v1.22 + -- Switch FFmpeg architecture + if utilities_FFmpeg_switch_choice is true then + set theFFmpegSwitchLabel to localized string "Switch FFmpeg and FFprobe from" from table "MacYTDL" + set theFFmpegToLabel to localized string " to " from table "MacYTDL" + -- set theFFmpegSwitchLabel to localized string "Switch FFmpeg and FFprobe from " & installed_FFmpeg_arch & " to " & new_FFmpeg_arch & "?" from table "MacYTDL" + set switch_FFmpeg to button returned of (display dialog (theFFmpegSwitchLabel & " " & installed_FFmpeg_arch & theFFmpegToLabel & new_FFmpeg_arch & " ?") buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with title diag_Title with icon file MacYTDL_custom_icon_file giving up after 600) + if switch_FFmpeg is theButtonYesLabel then + run_Utilities_handlers's install_ffmpeg_ffprobe(theButtonOKLabel, diag_Title, path_to_MacYTDL, usr_bin_folder, resourcesPath, MacYTDL_custom_icon_file, user_on_old_os, new_FFmpeg_arch) + set ffmpeg_version_long to do shell script ffmpeg_file & " -version" + set AppleScript's text item delimiters to {"-", " "} + set ffmpeg_version to text item 3 of ffmpeg_version_long + set AppleScript's text item delimiters to "" + end if + end if + + -- Open youtube-dl/yt-dlp web page (in default web browser) + if utilities_YTDL_webpage_choice is true then + if DL_Use_YTDLP is "youtube-dl" then + open location "https://github.com/ytdl-org/youtube-dl" + else + open location "https://github.com/yt-dlp/yt-dlp" + end if + end if + + -- Switch from youtube-dl to yt-dlp - only available if YTDL is installed (checked before Main) and is the current setting - if Homebrew yt-dlp installed, silently switch from YTDL to the Homebrew-YT-DLP install (rare case I expect) + -- v1.24 - No longer offer to switch to youtube-dl + if utilities_Switch_choice is true then + set alert_text_ytdl to "Switching" + set user_wants_switch to "yt-dlp" + + -- User currently using YTDL and has no form of yt-dlp + if ytdlp_exists is false and homebrew_ytdlp_exists is false then + check_ytdl(show_yt_dlp) + end if + + -- User currently using YTDL but has Homebrew install of yt-dlp - silently switch to the Homebrew install - use PATH to find both Intel and ARM Homebrew installs - hopefully a rare case + if ytdlp_exists is false and homebrew_ytdlp_exists is true then + set thePreferMainOrBrewYTDLPInstallTextLabel to localized string "You currently have a Homebrew install of YT-DLP. Do you wish to switch to a MacYTDL install ?" from table "MacYTDL" + set choiceMainOrBrewYTDL to button returned of (display dialog thePreferMainOrBrewYTDLPInstallTextLabel with title diag_Title buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if choiceMainOrBrewYTDL is theButtonYesLabel then + check_ytdl(show_yt_dlp) + end if + end if + + -- Update Use_ytdlp setting if user switches to YT-DLP - use show_yt_dlp as source of which YT-DLP was installed + if alert_text_ytdl does not contain "is out of date" then + set YTDL_version to do shell script ytdlp_file & " --version" + -- Need to generalise show_yt_dlp so that only "youtube-dl" or "yt-dlp" is stored in plist + if show_yt_dlp is "yt-dlp-legacy" then + set switched_show_yt_dlp to "yt-dlp" + else + set switched_show_yt_dlp to show_yt_dlp + end if + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Use_ytdlp" to switched_show_yt_dlp + set value of property list item "YTDL_YTDLP_version" to YTDL_version + end tell + end tell + end if + end if + + -- Save current settings to file - retain saved settings location and name - might need to remove any weird extension chosen by user but leave for now + if utilities_Save_Settings_choice is true then + set DL_Saved_Settings_Location_Alias to DL_Saved_Settings_Location as alias + try + set save_settings_file_name to (choose file name with prompt "Save MacYTDL Settings" & return & "Enter a file name and choose a location" default location DL_Saved_Settings_Location_Alias default name "Name for your saved settings") + on error number -128 -- If user cancels, go back to Main dialog + main_dialog() + end try + set save_settings_file_name_text to save_settings_file_name as text + if text -5 thru -1 of save_settings_file_name_text is not "plist" then + set save_settings_file_name_posix to quoted form of ((POSIX path of save_settings_file_name) & ".plist") -- Need quoted posix form to pass to do shell script + else + set save_settings_file_name_posix to quoted form of (POSIX path of save_settings_file_name) + end if + do shell script "cp -a " & MacYTDL_prefs_file & " " & save_settings_file_name_posix + delay 1 + set last_colon_in_path to last_offset(save_settings_file_name_text, ":") + set path_to_saved_settings_location to text 1 thru last_colon_in_path of save_settings_file_name_text + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Saved_Settings_Location" to path_to_saved_settings_location + end tell + end tell + end if + + -- Restore settings from file - store restored settings name - is a literal OK for type ? - Keep current save settings location instead of what might be in restored settings file + if utilities_Restore_Settings_choice is true then + set DL_Saved_Settings_Location_Alias to DL_Saved_Settings_Location as alias + -- v1.22 - Added repeat loop to prevent error on cp + repeat + try + set restore_settings_file_name to choose file with prompt "Choose a settings file to restore:" default location DL_Saved_Settings_Location_Alias of type "plist" + on error number -128 -- If user cancels, go back to Main dialog + main_dialog() + exit repeat + end try + set restore_settings_file_name_text to restore_settings_file_name as text + set restore_settings_file_name_posix to quoted form of (POSIX path of restore_settings_file_name) -- Need quoted posix form to pass to do shell script + if restore_settings_file_name_posix = quoted form of MacYTDL_prefs_file then + set theCannotRestoreLabel to localized string "Sorry, can't restore settings file to itself. Try again ?" from table "MacYTDL" + set restore_or_giveup to button returned of (display dialog theCannotRestoreLabel with title diag_Title buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if restore_or_giveup is theButtonNoLabel then + main_dialog() + exit repeat + end if + else + exit repeat + end if + end repeat + + set last_colon_in_path to last_offset(restore_settings_file_name_text, ":") + set last_stop_in_path to last_offset(restore_settings_file_name_text, ".") + set restored_settings_name to text (last_colon_in_path + 2) thru last_stop_in_path of restore_settings_file_name_text + do shell script "cp -a " & restore_settings_file_name_posix & " " & MacYTDL_prefs_file + run_Utilities_handlers's check_settings(MacYTDL_prefs_file, old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version) + -- Need to ensure restored settings are compatible with v1.21 and newer + run_Utilities_handlers's check_settings_current(MacYTDL_prefs_file, DL_Use_YTDLP, MacYTDL_preferences_path, youtubedl_file, ytdlp_file) + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Name_Of_Settings_In_Use" to restored_settings_name + set value of property list item "Saved_Settings_Location" to DL_Saved_Settings_Location + end tell + end tell + end if + + -- Return to default settings - Delete current settings file and rebuild default settings + if utilities_Return_Defaults_choice is true then + set theReturnSettingsLabel to localized string "Do you really want to return to the default settings ?" from table "MacYTDL" + set Really_Return_To_Defaults to button returned of (display dialog theReturnSettingsLabel with title diag_Title buttons {theButtonNoLabel, theButtonYesLabel} default button 2 with icon file MacYTDL_custom_icon_file giving up after 600) + if Really_Return_To_Defaults is theButtonYesLabel then + run_Utilities_handlers's set_preferences(old_version_prefs, diag_Title, theButtonNoLabel, theButtonYesLabel, MacYTDL_prefs_file, MacYTDL_version, MacYTDL_date, MacYTDL_preferences_path, path_to_MacYTDL, X_position, Y_position, theBestLabel, theDefaultLabel, theNoRemuxLabel, resourcesPath, show_yt_dlp, YTDL_version, MacYTDL_custom_icon_file) + end if + end if + + -- Check for MacYTDL update + if utilities_MacYTDL_check_choice is true then + -- Tell utilities handler that it should return to main_dialog when finished - auto_download tells utilities to skip main and just close + set skip_Main_dialog to false + check_download_folder(downloadsFolder_Path, theButtonQuitLabel, theButtonReturnLabel, theButtonContinueLabel, diag_Title, MacYTDL_custom_icon_file, skip_Main_dialog) + run_Utilities_handlers's check_MacYTDL(downloadsFolder_Path, diag_Title, theButtonOKLabel, theButtonNoLabel, theButtonYesLabel, MacYTDL_version, MacYTDL_custom_icon_file) + end if + + -- Install/Remove Atomic Parsely + if utilities_Atomic_choice is true then + if Atomic_is_installed is false then + if DL_Use_YTDLP is "yt-dlp" then + set theDontNeedAPTextLabel to localized string "You are currently using yt-dlp and so there is no need for Atomic Parsley. Do you still wish to install Atomic Parsley ?" from table "MacYTDL" + set reallyWantsAP to button returned of (display dialog theDontNeedAPTextLabel with title diag_Title buttons {theButtonNoLabel, theButtonYesLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + if reallyWantsAP is theButtonNoLabel then main_dialog() + end if + run_Utilities_handlers's install_MacYTDLatomic(diag_Title, theButtonOKLabel, path_to_MacYTDL, usr_bin_folder) + set Atomic_is_installed to true + tell me to activate + else if Atomic_is_installed is true then + run_Utilities_handlers's remove_MacYTDLatomic(path_to_MacYTDL, theButtonOKLabel, diag_Title, MacYTDL_custom_icon_file) + set Atomic_is_installed to false + tell application "System Events" + tell property list file MacYTDL_prefs_file + set value of property list item "Thumbnail_Embed" to false + end tell + end tell + tell me to activate + end if + end if + + -- Install/Remove Service + if utilities_Service_choice is true then + if isServiceInstalled is "No" then + -- Service is not installed - user wants to install it + run_Utilities_handlers's install_MacYTDLservice(path_to_MacYTDL) + tell me to activate + set theServiceInstalledLabel to localized string "The MacYTDL Service is installed." from table "MacYTDL" + display dialog theServiceInstalledLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + else if isServiceInstalled is "Yes" then + -- Service is installed - user wants to remove it - but warn user if auto_download setting must be off before removing Service + if DL_auto is true then + set theButtonRemoveLabel to localized string "Remove" from table "MacYTDL" + set theAutoDLisOnLabel to localized string "You have the Auto downloads setting on. You can cancel and return to Main dialog or remove the Service and turn off auto downloads." from table "MacYTDL" + set reallyWantsAPRemoved to button returned of (display dialog theAutoDLisOnLabel with title diag_Title buttons {theButtonReturnLabel, theButtonRemoveLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600) + if reallyWantsAPRemoved is theButtonReturnLabel then main_dialog() + set Service_file_plist to (macYTDL_service_file_nonPosix & ":Contents:info.plist") + tell application "System Events" + set new_value to "Send-URL-To-MacYTDL" + tell property list file Service_file_plist + set value of property list item "default" of property list item "NSMenuItem" of property list item 1 of property list items of contents to new_value + end tell + tell property list file MacYTDL_prefs_file + set value of property list item "Auto_Download" to false + end tell + end tell + end if + run_Utilities_handlers's remove_MacYTDLservice() + tell me to activate + set theServiceRemovedLabel to localized string "The MacYTDL Service has been removed." from table "MacYTDL" + display dialog theServiceRemovedLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + end if + end if + + -- Move all log files to Trash - split moves because mv fails "too many args" if there are too many files - try loop in case one of mv commands fails to find any files + else if utilities_button_number_returned is 1 then -- Delete logs + try + do shell script "mv " & POSIX path of MacYTDL_preferences_path & "ytdl_log-[ABCDEabcde]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "ytdl_log-[FGHIJKLMNfghijklmn]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "ytdl_log-[OPQRSTUVWXYZopqrstuvwxyz]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "ytdl_log-[1234567890#~!@$%^]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "ytdl_log-*" & " ~/.trash/" + end try + try + do shell script "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_log-[ABCDEabcde]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_log-[FGHIJKLMNfghijklmn]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_log-[OPQRSTUVWXYZopqrstuvwxyz]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_log-[1234567890#~!@$%^]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_log-*" & " ~/.trash/" + end try + try + do shell script "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_response-[ABCDEabcde]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_response-[FGHIJKLMNfghijklmn]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_response-[OPQRSTUVWXYZopqrstuvwxyz]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_response-[1234567890#~!@$%^]*" & " ~/.trash/" & " ; " & "mv " & POSIX path of MacYTDL_preferences_path & "youtube-dl_response-*" & " ~/.trash/" + end try + set theUtilitiesDeleteLogsLabel to localized string "All MacYTDL log files are now in the Trash." from table "MacYTDL" + display dialog theUtilitiesDeleteLogsLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 100 + + -- Uninstall all MacYTDL files - move files to Trash + else if utilities_button_number_returned is 2 then + set theUtilitiesUninstallLabel to localized string "Do you really want to remove MacYTDL ? Everything will be moved to the Trash." from table "MacYTDL" + set really_remove_MacYTDL to display dialog theUtilitiesUninstallLabel buttons {theButtonYesLabel, theButtonNoLabel} with title diag_Title default button 2 with icon file MacYTDL_custom_icon_file giving up after 600 + set remove_answ to button returned of really_remove_MacYTDL + if remove_answ is theButtonNoLabel then + main_dialog() + end if + try + -- If it exists, move AtomicParsley to Trash + if Atomic_is_installed is true then + do shell script "mv /usr/local/bin/AtomicParsley" & " ~/.trash/AtomicParsley" with administrator privileges + end if + if YTDL_exists is true then + do shell script "mv " & POSIX path of youtubedl_file & " ~/.trash/youtube-dl" with administrator privileges + end if + if ytdlp_exists is true then + do shell script "mv " & POSIX path of ytdlp_file & " ~/.trash/yt-dlp" with administrator privileges + end if + if ffprobe_exists is true then + do shell script "mv " & POSIX path of ffprobe_file & " ~/.trash/ffprobe" with administrator privileges + end if + if ffmpeg_exists is true then + do shell script "mv " & POSIX path of ffmpeg_file & " ~/.trash/ffmpeg" with administrator privileges + end if + if Myriad_exists is true then + do shell script "mv " & quoted form of (POSIX path of Myriad_file) & " ~/.trash/MyriadTablesLib.scptd" with administrator privileges -- Quoted form because of space in "Script Libraries" folder name + end if + set path_to_macytdl_file to quoted form of (POSIX path of path_to_MacYTDL) + do shell script "mv " & path_to_macytdl_file & " ~/.trash/MacYTDL.app" with administrator privileges + -- trap case where user cancels credentials dialog + on error number -128 + main_dialog() + end try + do shell script "mv " & POSIX path of MacYTDL_preferences_path & " ~/.trash/MacYTDL" + do shell script "mv " & quoted form of (POSIX path of DTP_file) & " ~/.trash/DialogToolkitMacYTDL.scptd" -- Quoted form because of space in "Script Libraries" folder name + -- If it exists, move the MacYTDL Service to Trash - Ditto the Defaults plist file + set User_defaults_path to "Library/Preferences/com.apple.script.id.MacYTDL.plist" + set macYTDL_defaults_preferences_file to (POSIX path of (path to home folder) & User_defaults_path) + if isServiceInstalled is "Yes" then + do shell script "mv " & quoted form of (macYTDL_service_file) & " ~/.trash/Send-URL-To-MacYTDL.workflow" + end if + tell application "System Events" + if (the file macYTDL_defaults_preferences_file exists) then + tell current application to do shell script "mv " & quoted form of (macYTDL_defaults_preferences_file) & " ~/.trash/com.apple.script.id.MacYTDL.plist" + end if + end tell + set theUtilitiesMYTDLUninstalledLabel to localized string "MacYTDL is uninstalled. All components are in the Trash which you can empty when you wish. Cheers." from table "MacYTDL" + set theUtilitiesMYTDLUninstalledByeLabel to localized string "Goodbye" from table "MacYTDL" + set MacYTDL_custom_icon_file_Trash to (path_to_home_folder & ".Trash:MacYTDL.app:Contents:Resources:MacYTDL.icns") as string + display dialog theUtilitiesMYTDLUninstalledLabel buttons {theUtilitiesMYTDLUninstalledByeLabel} default button 1 with icon file MacYTDL_custom_icon_file_Trash giving up after 600 + error number -128 + + -- Show the About MacYTDL dialog + else if utilities_button_number_returned is 3 then -- About + my show_about() + end if + + main_dialog() + +end utilities + + +--------------------------------------------------------------------- +-- +-- Display About dialog - invoked in Utilities dialog +-- +--------------------------------------------------------------------- + +-- Show user the About MacYTDL dialog +on show_about() + -- Set variables for the settings dialog + set theButtonsAbout1Label to (localized string "MacYTDL is a simple AppleScript program for downloading videos from various web sites. It uses the" from table "MacYTDL") & " " & DL_Use_YTDLP & " " & (localized string "Python script as the download engine." from table "MacYTDL") + set about_text_1 to theButtonsAbout1Label + set theButtonsAbout2Label to localized string "Please post any questions or suggestions to github.com/section83/MacYTDL/issues" from table "MacYTDL" + set theButtonsAbout3Label to localized string "Written by © Vincentius, " from table "MacYTDL" + set theButtonsAbout4Label to localized string "With thanks to Shane Stanley, Adam Albrec, kopurando, Michael Page, Tombs and all MacYTDL users." from table "MacYTDL" + set about_text_2 to theButtonsAbout2Label & return & return & theButtonsAbout3Label & MacYTDL_date & ". " & theButtonsAbout4Label + set theButtonsAboutDiagLabel to localized string "About MacYTDL" from table "MacYTDL" + set about_diag_prompt to theButtonsAboutDiagLabel + set accViewWidth to 300 + set accViewInset to 0 + + -- Set buttons and controls + set theButtonsVisitLabel to localized string "Visit Site" from table "MacYTDL" + set theButtonsEmailLabel to localized string "Send E-Mail" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonsVisitLabel, theButtonsEmailLabel, theButtonOKLabel} button keys {"v", "e", ""} default button 3 + if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit + set {about_Rule, theTop} to create rule 10 rule width accViewWidth + set {about_instruct_2, theTop} to create label about_text_2 left inset 5 bottom (theTop + 10) max width accViewWidth aligns left aligned with multiline + set {about_instruct_1, theTop} to create label about_text_1 left inset 75 bottom (theTop + 10) max width accViewWidth - 75 aligns left aligned with multiline + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 60 view width 64 view height 64 scale image scale proportionally + set {about_prompt, theTop} to create label about_diag_prompt left inset 0 bottom (theTop) max width minWidth aligns center aligned with bold type + set about_allControls to {about_Rule, MacYTDL_icon, about_instruct_1, about_instruct_2, about_prompt} + + -- Make sure MacYTDL is in front and show dialog + tell me to activate + set {about_button_returned, about_button_number_returned, about_controls_results} to display enhanced window diag_Title buttons theButtons acc view width accViewWidth acc view height theTop acc view controls about_allControls + if about_button_number_returned is 3 then -- OK + main_dialog() + end if + -- Open MacYTDL release page (in default web browser) to manually check version + if about_button_number_returned is 1 then -- Visit Site + open location "https://github.com/section83/MacYTDL/" + end if + -- Open email message to author + if about_button_number_returned is 2 then -- Send Email + open location "mailto:macytdl@gmail.com?subject=MacYTDL%20Feedback%2FQuestion" + end if +end show_about + + +--------------------------------------------------- +-- +-- Get user's credentials +-- +--------------------------------------------------- + +-- User ticked the runtime settings to include credentials for next download +on get_YTDL_credentials() + -- Set variables for the get credentials dialog + set theCredentialsInstructionsLabel to localized string "Enter your user name and password in the boxes below for the next download, skip credentials and continue to download or return to the Main dialog." from table "MacYTDL" + set theCredentialsDiagPromptLabel to localized string "Credentials for next download" from table "MacYTDL" + set instructions_text to theCredentialsInstructionsLabel + set credentials_diag_prompt to theCredentialsDiagPromptLabel + set accViewWidth to 275 + set accViewInset to 0 + + -- Set buttons and controls + set theButtonsCredSkipLabel to localized string "Skip" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonReturnLabel, theButtonsCredSkipLabel, theButtonOKLabel} button keys {"r", "s", ""} default button 3 + set theButtonsCredPasswordLabel to localized string "Password" from table "MacYTDL" + set {theField_password, theTop} to create field "" placeholder text theButtonsCredPasswordLabel left inset accViewInset bottom 5 field width accViewWidth + set theButtonsCredNameLabel to localized string "User name" from table "MacYTDL" + set {theField_username, theTop} to create field "" placeholder text theButtonsCredNameLabel left inset accViewInset bottom (theTop + 20) field width accViewWidth + set {utilities_instruct, theTop} to create label instructions_text left inset 75 bottom (theTop + 15) max width (accViewWidth - 75) aligns left aligned with multiline + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 60 view width 64 view height 64 scale image scale proportionally + set {utilities_prompt, theTop} to create label credentials_diag_prompt left inset 0 bottom (theTop + 10) max width accViewWidth aligns center aligned with bold type + set credentials_allControls to {theField_username, theField_password, MacYTDL_icon, utilities_instruct, utilities_prompt} + + -- Make sure MacYTDL is in front and show dialog + tell me to activate + set {credentials_button_returned, credentialsButtonNumberReturned, credentials_results} to display enhanced window diag_Title buttons theButtons acc view width accViewWidth acc view height theTop acc view controls credentials_allControls + + if credentialsButtonNumberReturned is 3 then + -- Get control results from credentials dialog + set theField_username_choice to item 1 of credentials_results -- <= User name + set theField_password_choice to item 2 of credentials_results -- <= Password + set YTDL_credentials to "--username " & theField_username_choice & " --password " & theField_password_choice & " " + return YTDL_credentials + else if credentialsButtonNumberReturned is 2 then + -- Continue download without credentials + set YTDL_credentials to "" + return YTDL_credentials + else + main_dialog() + end if +end get_YTDL_credentials + + +--------------------------------------------------- +-- +-- Write current URL(s) to batch file +-- +--------------------------------------------------- +-- Handler to write the user's pasted URL to the batch file for later download - called from download_video() - returns to main_dialog() +-- Creates file if need, adds URL, file name and remux format and a return each time +on add_To_Batch(URL_user_entered, download_filename, download_filename_new, YTDL_remux_format) + -- Remove any quotes from around URL_user_entered - so it can be written out to the batch file + if character 1 of URL_user_entered is "'" then + set URL_user_entered_lines to text 2 thru -2 of URL_user_entered + else + set URL_user_entered_lines to URL_user_entered + end if + -- Change spaces to returns when URL_user_entered has more than one URL - then add file name and remux format setting as comment - used by Adviser to play 1st file + set URL_user_entered_lines to text 1 thru end of (run_Utilities_handlers's replace_chars(URL_user_entered_lines, " ", return)) + set count_of_URLs to count of paragraphs in URL_user_entered_lines + -- Need to change file name extension if remux is required + if YTDL_remux_format contains "--recode-video" then + -- Get new extension - always follows the word recode -- v1.26 - Why do a loop when a simple "does it contain" would do ? + set all_words to words in YTDL_remux_format + repeat with i from 1 to the length of all_words + if item i of all_words is "recode" then exit repeat + end repeat + set new_extension to item (i + 2) in all_words + -- Get old extension - with multiple downloads and playlists, only need to find the first as the Adviser only plays the first file -- BUT ONLY HAS "THE MULTIPLE VIDEOS" IF MORE THAN ONE URL ! + if count_of_URLs is greater than 1 then + set the_first_file_name to first paragraph of download_filename + else + set the_first_file_name to first paragraph of download_filename_new + end if + set AppleScript's text item delimiters to {"."} + set old_extension to last text item of the_first_file_name + set AppleScript's text item delimiters to {""} + if old_extension is not equal to new_extension then + if count_of_URLs is greater than 1 then + -- v1.26 - add replace_chars for multiple URLs case - download_filename has multiple file names if more than one URL + set download_filename to run_Utilities_handlers's replace_chars(download_filename, old_extension, new_extension) + else + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, old_extension, new_extension) + end if + end if + end if + set download_filename_new to run_Utilities_handlers's replace_chars(download_filename_new, "_", " ") + if count_of_URLs is greater than 1 then + set URL_user_entered_forming to "" + repeat with i from 1 to count_of_URLs + set URL_user_entered_forming to URL_user_entered_forming & paragraph i of URL_user_entered_lines & "#" & paragraph i of download_filename & "$" & YTDL_remux_format & return + end repeat + else + set download_filename_new to text 1 thru -1 of download_filename_new + set URL_user_entered_forming to URL_user_entered_lines & "#" & download_filename_new & "$" & YTDL_remux_format & return + end if + set batch_filename to "BatchFile.txt" as string + set batch_file to POSIX file (MacYTDL_preferences_path & batch_filename) as «class furl» + try + set batch_refNum to missing value + set batch_refNum to open for access batch_file with write permission + write URL_user_entered_forming to batch_refNum starting at eof as «class utf8» + close access batch_refNum + on error batch_errMsg + set theBatchErrorLabel to localized string "There was an error: " from table "MacYTDL" + display dialog theBatchErrorLabel & batch_errMsg + close access batch_refNum + main_dialog() + end try + set theAddedToBatchLabel to localized string "The URL has been added to batch file." from table "MacYTDL" + display dialog theAddedToBatchLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + -- After adding to batch, reset ABC & SBS show name and number_ABC_SBS_episodes so that correct file name is used for next download + -- v1.26 - Decided to change behaviour - retain/discard URL after adding to batch + if DL_discard_URL is true then + set URL_user_entered to "" + set URL_user_entered_clean to "" + end if + set ABC_show_name to "" + set SBS_show_name to "" + set SBS_show_URLs to "" + set ABC_show_URLs to "" + set number_ABC_SBS_episodes to 0 + -- set the clipboard to "" + + main_dialog() +end add_To_Batch + + +--------------------------------------------------------- +-- +-- Open batch processing dialog - called by Main +-- +--------------------------------------------------------- +-- Handler to open batch file processing dialog - called by Main dialog +on open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + + run_Utilities_handlers's read_settings(MacYTDL_prefs_file) + set DL_format to localized string DL_format from table "MacYTDL" + set DL_subtitles_format to localized string DL_subtitles_format from table "MacYTDL" + set DL_Remux_format to localized string DL_Remux_format from table "MacYTDL" + set DL_audio_codec to localized string DL_audio_codec from table "MacYTDL" + + -- Start by calculating tally of URLs currently saved in the batch file + set batch_tally_number to tally_batch() + + -- Set variables for the Batch functions dialog + set theBatchFunctionsInstructionLabel to localized string "Choose to download list of URLs in batch file, clear the batch list, edit the batch list, remove last addition to the batch or return to Main dialog." from table "MacYTDL" + set theBatchFunctionsDiagPromptLabel to localized string "Batch Functions" from table "MacYTDL" + set instructions_text to theBatchFunctionsInstructionLabel + set batch_diag_prompt to theBatchFunctionsDiagPromptLabel + set accViewWidth to 500 + set accViewInset to 0 + + -- Set buttons and controls + set theButtonsEditLabel to localized string "Edit" from table "MacYTDL" + set theButtonsClearLabel to localized string "Clear" from table "MacYTDL" + set theButtonsRemoveLabel to localized string "Remove last item" from table "MacYTDL" + set {theButtons, minWidth} to create buttons {theButtonReturnLabel, theButtonsEditLabel, theButtonsClearLabel, theButtonsRemoveLabel, theButtonDownloadLabel} button keys {"r", "e", "c", "U", "d"} default button 5 + if minWidth > accViewWidth then set accViewWidth to minWidth + set {theBatchRule, theTop} to create rule 10 rule width accViewWidth + set theNumberVideosLabel to localized string "Number of videos in batch: " from table "MacYTDL" + set {batch_tally, theTop} to create label theNumberVideosLabel & batch_tally_number left inset 25 bottom (theTop + 15) max width 225 aligns left aligned + set {batch_instruct, theTop} to create label instructions_text left inset 75 bottom (theTop + 30) max width minWidth - 75 aligns left aligned with multiline + set {MacYTDL_icon, theTop} to create image view MacYTDL_custom_icon_file_posix left inset 0 bottom theTop - 60 view width 64 view height 64 scale image scale proportionally + set {batch_prompt, theTop} to create label batch_diag_prompt left inset 0 bottom (theTop) max width minWidth aligns center aligned with bold type + set batch_allControls to {theBatchRule, batch_tally, MacYTDL_icon, batch_instruct, batch_prompt} + + -- Make sure MacYTDL is in front and show dialog + tell me to activate + set {batch_button_returned, batchButtonNumberReturned, batch_controls_results} to display enhanced window diag_Title buttons theButtons acc view width minWidth acc view height theTop acc view controls batch_allControls initial position window_Position + + if batchButtonNumberReturned is 5 then + -- Eventually, will have code here which will read the batch file and present user with list to choose from + download_batch(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + else if batchButtonNumberReturned is 2 then + -- Check that there is a batch file + tell application "System Events" + set batch_file_test to batch_file as string + if not (exists file batch_file_test) then + set theNoBatchFileLabel to localized string "Sorry, there is no batch file." from table "MacYTDL" + display dialog theNoBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + my main_dialog() + end if + end tell + set batch_file_posix to POSIX path of batch_file + tell application "System Events" to open file batch_file_posix + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + else if (batchButtonNumberReturned is 3) or ((batchButtonNumberReturned is 4) and (batch_tally_number is 1)) then + clear_batch(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + else if batchButtonNumberReturned is 4 then + remove_last_from_batch(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + end if + + main_dialog() + +end open_batch_processing + + +--------------------------------------------------- +-- +-- Calculate tally of URLs saved in batch file +-- +--------------------------------------------------- +-- Handler to calculate tally of URLs saved in Batch file - called by Batch dialog and maybe Main too +on tally_batch() + tell application "System Events" + set batch_file_test to batch_file as string + if not (exists file batch_file_test) then + set number_of_URLs to 0 + return number_of_URLs + end if + end tell + if (get eof file batch_file) is 0 then + set number_of_URLs to 0 + return number_of_URLs + end if + try + set batch_file_ref to missing value + set batch_file_ref to open for access file batch_file + set batch_URLs to read batch_file_ref from 1 as «class utf8» + set number_of_URLs to (count of paragraphs in batch_URLs) - 1 + close access batch_file_ref + on error batch_errMsg + set theBatchErrorLabel to localized string "There was an error: " from table "MacYTDL" + display dialog theBatchErrorLabel & batch_errMsg & "batch_file: " & batch_file with title "Tally_batch handler" buttons {theButtonOKLabel} default button 1 + close access batch_file_ref + main_dialog() + end try + return number_of_URLs +end tally_batch + + +----------------------------------------------------------------------------- +-- +-- Download videos in Batch file - called by open_batch_processing +-- +----------------------------------------------------------------------------- +-- Handler to download selection of URLs in Batch file - forms and calls youtube-dl/yt-dlp separately from the download_video handler +on download_batch(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + + -- Check that there is a batch file containing some URLs + set no_batch_file to false + set batch_file_test to batch_file as string + tell application "System Events" + if not (exists file batch_file_test) then set no_batch_file to true + end tell + if no_batch_file is true then + set theNoBatchFileLabel to localized string "Sorry, there is no batch file." from table "MacYTDL" + display dialog theNoBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + my open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + end if + if (get eof file batch_file) is 0 then + set theEmptyBatchFileLabel to localized string "Sorry, the batch file is empty." from table "MacYTDL" + display dialog theEmptyBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + end if + + -- Get date and time so it can be added to log file name + set download_date_time to get_Date_Time() + + -- Always set is_Livestream_Flag to false for batch downloads + set is_Livestream_Flag to "False" + + -- Set name to be used for log file and monitor dialog - name is in comment section of each URL line + set YTDL_log_file to MacYTDL_preferences_path & "ytdl_log-Batch_download_on-" & download_date_time & ".txt" + set batch_file_ref to missing value + set batch_file_ref to open for access file batch_file + set batch_file_contents to read batch_file_ref as «class utf8» + + -- Look for manual edits of the batch file that made a muck of it + set bad_Batch_file_edits to "No" + set AppleScript's text item delimiters to {"#", "$", return} + repeat with aPara in (paragraphs of batch_file_contents) + if length of aPara is greater than 2 then + if aPara does not contain "#" then + set bad_Batch_file_edits to "Yes" + else + set num_sections to number of text items in aPara + if num_sections is not equal to 3 then + set bad_Batch_file_edits to "Yes" + end if + end if + end if + if bad_Batch_file_edits is "Yes" then + set theBadBatchFileEditsLabel to localized string "Sorry, it seems the batch file has been edited with the wrong format. Check the Help manual for advice on how to edit the batch file." from table "MacYTDL" + display dialog theBadBatchFileEditsLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + close access batch_file_ref + return + end if + end repeat + + -- Get first file name to pass to Adviser - trim off the trailing return character + set download_filename to text item 2 of batch_file_contents + set YTDL_remux_format to text item 3 of batch_file_contents + set download_filename to text 1 thru -1 of download_filename -- Probably not needed but, is a safety measure + if length of YTDL_remux_format is greater than 5 then + set YTDL_remux_format to text 1 thru -2 of YTDL_remux_format + else + set YTDL_remux_format to "" + end if + set AppleScript's text item delimiters to "" + close access batch_file_ref + + -- v1.25.1 - added rough logic to get subtitles - previously never passed subtitles settings to the download + -- If user wants for subtitles, pass current settings to download without checking - it is checked during add_To_batch() + if subtitles_choice is true and DL_YTAutoST is false then + set YTDL_subtitles to "--write-sub --sub-format " & DL_subtitles_format & " --sub-lang " & DL_STLanguage & " " + end if + if DL_YTAutoST is true and subtitles_choice is false then + set YTDL_subtitles to "--write-auto-sub --sub-format " & DL_subtitles_format & " --sub-lang " & DL_STLanguage & " " + end if + if DL_YTAutoST is true and subtitles_choice is true then + set YTDL_subtitles to "--write-auto-sub --write-sub --sub-format " & DL_subtitles_format & " --sub-lang " & DL_STLanguage & " " + end if + + set YTDL_batch_file to quoted form of POSIX path of batch_file + set YTDL_no_playlist to "" + + -- Set up download_filename_new to hold data required for parallel download - need to get URL, file name and log file pathname - it's delimited, not a list - repeat through content of batchfile.txt + if DL_Parallel is true then + set download_filename_new to "" + set number_paragraphs to ((count of paragraphs of batch_file_contents) - 1) -- Always has a blank last paragraph + repeat with x from 1 to number_paragraphs + set AppleScript's text item delimiters to {"#", "$"} + set download_batch_details to (paragraph x of batch_file_contents) + set URL_user_entered_for_parallel to text item 1 of download_batch_details + set download_filename_full to text item 2 of download_batch_details + -- Trying to remove colons and spaces from file names as it might cause macOS trouble - the strange small colon DOES cause issues + set download_filename_full to run_Utilities_handlers's replace_chars(download_filename_full, " ", "_") + -- set download_filename_full to run_Utilities_handlers's replace_chars(download_filename_full, ":", "_-") -- Not sure whether this would make a mess of URLs + set download_filename_full to run_Utilities_handlers's replace_chars(download_filename_full, ":", "_-") + -- Need to trim off ".[extension]" from file name before adding to name of log file + set download_filename_trimmed to text 1 thru ((download_filename_full's length) - (offset of "." in (the reverse of every character of download_filename_full) as text)) of download_filename_full + set YTDL_batch_item_log_file to MacYTDL_preferences_path & "ytdl_log-" & download_filename_trimmed & "-" & download_date_time & ".txt" + set download_filename_new to download_filename_new & download_filename_full & "##" & URL_user_entered_for_parallel & "##" & YTDL_batch_item_log_file & return + set AppleScript's text item delimiters to "" + end repeat + set download_batch_parallel_serial to "" + else + set download_filename_new to "the saved batch" + set download_batch_parallel_serial to ("--batch-file " & YTDL_batch_file) + end if + + -- Change underscores to spaces in download_filname + put diag title, file and path names into quotes as they are not passed correctly when they contain apostrophes or spaces + set diag_Title_quoted to quoted form of diag_Title + set download_filename to run_Utilities_handlers's replace_chars(download_filename, "_", " ") + set download_filename to quoted form of download_filename + set download_filename_new to quoted form of download_filename_new + set YTDL_log_file to quoted form of YTDL_log_file + set YTDL_TimeStamps_quoted to quoted form of YTDL_TimeStamps + + -- Set remaining variables needed by Monitor.scpt + set YTDL_simulate_log to "Null" + set URL_user_entered to "Null" -- URL is read from the file by YT-DLP + if YTDL_Custom_Template is not "" then + set YTDL_output_template to " -o '" & YTDL_Custom_Template & "'" + else + set YTDL_output_template to " -o '%(title)s.%(ext)s'" + end if + + -- Increment the monitor dialog position number - used by monitor.scpt for positioning monitor dialogs + try -- In a try block to catch error of nil pids returned + set monitor_dialogs_list to do shell script "pgrep -f osascript" + set monitor_dialog_position to ((count of paragraphs in monitor_dialogs_list) / 2) + 1 + on error + set monitor_dialog_position to 1 + end try + + -- Form up parameters to send to monitor.scpt - collect YTDL settings then merge with MacYTDL variables + -- v1.26 - Copy ytdl_settings from download_video() + -- set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_remux_format & " " & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_over_writes & YTDL_Thumbnail_Write & YTDL_Thumbnail_Embed & YTDL_metadata & YTDL_limit_rate_value & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template & " " & YTDL_QT_Compat & download_batch_parallel_serial) + + set ytdl_settings to quoted form of (" --ignore-errors --newline " & YTDL_subtitles & YTDL_STEmbed & YTDL_credentials & YTDL_format & YTDL_Resolution_Limit & YTDL_Use_Parts & YTDL_No_Warnings & YTDL_remux_format & YTDL_Remux_original & YTDL_description & YTDL_audio_only & YTDL_audio_codec & YTDL_over_writes & YTDL_Thumbnail_Write & YTDL_Thumbnail_Embed & YTDL_metadata & YTDL_limit_rate_value & " " & YTDL_verbose & YTDL_Use_Proxy & YTDL_Use_Cookies & YTDL_no_playlist & YTDL_no_part & YTDL_Custom_Settings & YTDL_output_template & " " & YTDL_QT_Compat & " " & download_batch_parallel_serial) + + set my_params to quoted form of folder_chosen & " " & quoted form of MacYTDL_preferences_path & " " & YTDL_TimeStamps_quoted & " " & ytdl_settings & " " & URL_user_entered & " " & YTDL_log_file & " " & download_filename & " " & download_filename_new & " " & quoted form of MacYTDL_custom_icon_file_posix & " " & monitor_dialog_position & " " & YTDL_simulate_log & " " & diag_Title_quoted & " " & is_Livestream_Flag & " " & screen_width & " " & screen_height & " " & DL_Use_YTDLP & " " & quoted form of path_to_MacYTDL & " " & DL_Delete_Partial + + ---- Show current download settings if user has specified that in Settings + if DL_Show_Settings is true then + set branch_execution to run_Utilities_handlers's show_settings(YTDL_subtitles, DL_Remux_original, DL_YTDL_auto_check, DL_STEmbed, DL_audio_only, YTDL_description, DL_Limit_Rate, DL_over_writes, DL_Thumbnail_Write, DL_verbose, DL_Thumbnail_Embed, DL_Add_Metadata, DL_Use_Proxy, DL_Use_Cookies, DL_Use_Custom_Template, DL_Use_Custom_Settings, remux_format_choice, DL_TimeStamps, DL_Use_YTDLP, YTDL_version, folder_chosen, theButtonQuitLabel, theButtonCancelLabel, theButtonDownloadLabel, DL_Show_Settings, MacYTDL_prefs_file, MacYTDL_custom_icon_file_posix, diag_Title) + if branch_execution is "Main" then main_dialog() + if branch_execution is "Settings" then set_settings() + if branch_execution is "Quit" then quit_MacYTDL() + end if + + -- Prepare to call on the download Monitor - first get Monitor script location -- Monitor-bundle.scptd + set myMonitorScriptAsString to quoted form of ((POSIX path of path_to_MacYTDL) & "Contents/Resources/Scripts/Monitor.scpt") + + -- PRODUCTION CALL - Call the download Monitor script which will run as a separate process and return so Main Dialog can be re-displayed - thus user can start any number of downloads + do shell script "osascript -s s " & myMonitorScriptAsString & " " & my_params & " " & " > /dev/null 2> /dev/null &" + + -- TESTING CALL - Call the download Monitor script for testing - this formulation gets any errors back from Monitor, but holds execution until Monitor dialog is dismissed + --do shell script "osascript -s s " & myMonitorScriptAsString & " " & my_params + + main_dialog() + +end download_batch + + +------------------------------------------------------------- +-- +-- Clear batch file - called by open_batch_processing +-- +------------------------------------------------------------- +-- Handler to clear all URLs from batch file - empties the file but does not delete it +on clear_batch(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + -- Check that there is a batch file + tell application "System Events" + set batch_file_test to batch_file as string + if not (exists file batch_file_test) then + set theNoBatchFileLabel to localized string "Sorry, there is no batch file." from table "MacYTDL" + display dialog theNoBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + return + end if + end tell + if (get eof file batch_file) is 0 then + set theEmptyBatchFileLabel to localized string "Sorry, the batch file is empty." from table "MacYTDL" + display dialog theEmptyBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + end if + try + set batch_file_ref to missing value + set batch_file_ref to open for access file batch_file with write permission + set eof batch_file_ref to 0 + close access batch_file_ref + on error batch_errMsg + set theBatchErrorLabel to localized string "There was an error: " from table "MacYTDL" + display dialog theBatchErrorLabel & batch_errMsg & "batch_file: " & batch_file buttons {theButtonOKLabel} default button 1 + try + close access batch_file_ref + on error + main_dialog() + end try + main_dialog() + end try + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) +end clear_batch + + +-------------------------------------------------------------------------- +-- +-- Remove last batch addition - called by open_batch_processing +-- +-------------------------------------------------------------------------- +-- Handler to remove the most recent addition to batch file +on remove_last_from_batch(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + -- Check that there is a batch file + tell application "System Events" + set batch_file_test to batch_file as string + if not (exists file batch_file_test) then + set theNoBatchFileLabel to localized string "Sorry, there is no batch file." from table "MacYTDL" + display dialog theNoBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + return + end if + end tell + if (get eof file batch_file) is 0 then + set theEmptyBatchFileLabel to localized string "Sorry, the batch file is empty." from table "MacYTDL" + display dialog theEmptyBatchFileLabel with title diag_Title buttons {theButtonOKLabel} default button 1 with icon file MacYTDL_custom_icon_file giving up after 600 + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) + end if + try + set batch_file_ref to missing value + set batch_file_ref to open for access file batch_file with write permission + set batch_URLs to read batch_file_ref from 1 as «class utf8» + set batch_URLs to text 1 thru -4 of batch_URLs --<= remove last few characters to remove last return + set last_URL_offset to last item of allOffset(batch_URLs, return) --<= Get last in list of offsets of returns + set new_batch_contents to text 1 thru (last_URL_offset - 1) of batch_URLs --<= Trim off last URL + set eof batch_file_ref to 0 --<= Empty the batch file + write new_batch_contents & return to batch_file_ref as «class utf8» --<= Write out all URLs except the last + close access batch_file_ref + on error batch_errMsg number errorNumber + set theBatchErrorLabel to localized string "There was an error: number " from table "MacYTDL" + display dialog theBatchErrorLabel & errorNumber & " - " & batch_errMsg & " batch_file: " & batch_file buttons {theButtonOKLabel} default button 1 + close access batch_file_ref + main_dialog() + end try + open_batch_processing(folder_chosen, remux_format_choice, subtitles_choice, YTDL_credentials, YTDL_subtitles, YTDL_STEmbed, YTDL_format, YTDL_remux_format, YTDL_Remux_original, YTDL_description, YTDL_audio_only, YTDL_audio_codec, YTDL_over_writes, YTDL_Thumbnail_Write, YTDL_Thumbnail_Embed, YTDL_metadata, YTDL_limit_rate_value, YTDL_verbose, YTDL_TimeStamps, YTDL_Use_Proxy, YTDL_Use_Cookies, YTDL_Custom_Settings, YTDL_Custom_Template, YTDL_no_part, YTDL_QT_Compat, DL_Use_YTDLP, YTDL_Resolution_Limit, YTDL_Use_Parts, YTDL_No_Warnings) +end remove_last_from_batch + + +---------------------------------------------------------------------------------------------------------------------------- +-- +-- Get screen height and width - using AppKit - called in preliminaries - also used in Monitor.scpt +-- Only loading AppKit when needed - simplifies changes to rest of code +-- Using NSScreen's mainScreen frame as does the Dialog Toolkit +---------------------------------------------------------------------------------------------------------------------------- +on get_screensize() + script theScript + property parent : a reference to current application + use framework "AppKit" + on get_screensize() + try + set mainScreenFrame to current application's NSScreen's mainScreen()'s frame() + set screen_width to current application's NSWidth(mainScreenFrame) + set screen_height to current application's NSHeight(mainScreenFrame) + set X_position to (screen_width / 10) + on error errText + display dialog "There was an error: " & errText + set X_position to 50 + end try + set Y_position to 50 + return X_position & Y_position & screen_width & screen_height + end get_screensize + end script + return theScript's get_screensize() +end get_screensize + + +--------------------------------------------------- +-- +-- Find All Offsets in String +-- +--------------------------------------------------- + +-- Handler to find offsets items in a string +on allOffset(theString, thechar) + set theString to theString as text + set reverse_offsetList to {} + repeat with i from 1 to length of theString + if item i of theString is thechar then + set end of reverse_offsetList to i + end if + end repeat + return reverse_offsetList +end allOffset + + +------------------------------------------------------------- +-- +-- Find offset of last search string in a String +-- +------------------------------------------------------------- + +-- Handler to find offset of last specified character in a string +on last_offset(the_object_string, the_search_string) + try + set len to count of the_object_string + set reverses to reverse of characters of the_search_string as string + set reversed to reverse of characters of the_object_string as string + set last_occurrence_offset to len - (offset of reverses in reversed) + if last_occurrence_offset > len then + return 0 + end if + on error + return 0 + end try + return last_occurrence_offset +end last_offset + + +--------------------------------------------------- +-- +-- Empty these variables on Quit +-- +--------------------------------------------------- + +-- Found that contents of these these variables persisted - so, empty them to stop them affecting a later instance of MacYTDL +-- This doesn't seem to need a Continue statement to properly quit - perhaps because this is NOT a "Stay Open" app and does not use a "on quit" handler +on quit_MacYTDL() + set called_video_URL to "" + set default_contents_text to "" + set YTDL_version to "" + set monitor_dialog_position to "" + set old_version_prefs to "No" + set DL_batch_status to false + --quit -- doesn't seem to add anything - might be relevant for enhanced applets in an "on quit" + error number -128 +end quit_MacYTDL