Py2Exe: https://github.com/pyinstaller/pyinstaller
*python-help


Poweramp adb Control
-----------------------------

import subprocess
import tkinter as tk
from pynput import keyboard

def send_adb_command(command):
    ip_address = ip_entry.get()
    port = port_entry.get()
    adb_shell_command = f"adb -s {ip_address}:{port} shell am broadcast 'intent:#Intent;action=com.maxmpz.audioplayer.API_COMMAND;package=com.maxmpz.audioplayer;i.cmd={command};end'"
    subprocess.run(adb_shell_command, shell=True)

def restart():
    ip_address = ip_entry.get()
    port = port_entry.get()
    command = f'adb kill-server && adb start-server && adb connect {ip_address}:{port}'
    subprocess.Popen(['cmd.exe', '/c', 'start', 'cmd.exe', '/k', command])

def handle_key_press(key):
    if key == keyboard.Key.media_play_pause:
        send_adb_command(1)  # Play/Pause
    elif key == keyboard.Key.media_next:
        send_adb_command(4)  # Next Track
    elif key == keyboard.Key.media_previous:
        send_adb_command(5)  # Previous Track

# Create the main window
window = tk.Tk()
window.title("ADB Audio Player Control")

# Create IP address label and text entry
ip_label = tk.Label(window, text="IP Address:")
ip_label.pack()
ip_entry = tk.Entry(window)
ip_entry.insert(0, "192.168.0.101")  # Pre-fill with IP address
ip_entry.pack()

# Create port label and text entry
port_label = tk.Label(window, text="Port:")
port_label.pack()
port_entry = tk.Entry(window)
port_entry.insert(0, "5555")  # Pre-fill with port
port_entry.pack()

# Create previous track button
prev_button = tk.Button(window, text="Previous Track", command=lambda: send_adb_command(5))
prev_button.pack()

# Create play/pause button
play_pause_button = tk.Button(window, text="Play/Pause", command=lambda: send_adb_command(1))
play_pause_button.pack()

# Create next track button
next_button = tk.Button(window, text="Next Track", command=lambda: send_adb_command(4))
next_button.pack()

# Create restart button
restart_button = tk.Button(window, text="Restart", command=restart)
restart_button.pack()

# Bind key presses to button actions
def on_key_press(event):
    key = event.keysym.lower()
    if key == 'xf86audioplay':
        send_adb_command(1)  # Play/Pause
    elif key == 'xf86audionext':
        send_adb_command(4)  # Next Track
    elif key == 'xf86audioprev':
        send_adb_command(5)  # Previous Track

window.bind("<KeyPress>", on_key_press)

# Start the tkinter event loop
window.mainloop()




__________________

Video Converter GUI (ffmpeg)
-------------------------------

import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
import subprocess
from tqdm import tqdm
import configparser
import os
settings_file = "videoconverter_settings.ini"
settings = configparser.ConfigParser()
if os.path.exists(settings_file):
    settings.read(settings_file)
# Create the settings.ini file if it doesn't exist
if not os.path.exists(settings_file):
    settings.add_section("General")
    settings.set("General", "OutputPath", "")
    with open(settings_file, "w") as configfile:
        settings.write(configfile)
def calculate_bitrate(width, height, mode):
    if mode == 'CBR':
        if width <= 640 and height <= 480:
            return 500
        elif width <= 1280 and height <= 720:
            return 1000
        elif width <= 1920 and height <= 1080:
            return 2000
        else:
            return 4000
def open_folder_picker():
    folder_path = filedialog.askdirectory()
    output_path_var.set(folder_path)
    settings.set("General", "OutputPath", folder_path)
    with open(settings_file, "w") as configfile:
        settings.write(configfile)
def convert_videos():
    filetypes = (("Video files", "*.mp4 *.avi"), ("All files", "*.*"))
    filenames = filedialog.askopenfilenames(filetypes=filetypes)
    resolution = resolution_var.get()
    bitrate_mode = bitrate_var.get()
    output_path = output_path_var.get()
    if not output_path:
        output_path = filedialog.askdirectory()
        settings.set("General", "OutputPath", output_path)
        with open(settings_file, "w") as configfile:
            settings.write(configfile)
    for filename in filenames:
        output_filename = os.path.join(output_path, filename.split('/')[-1])
        command = ['ffmpeg', '-i', filename]
        command += ['-vf', f"scale={resolution}"]
        width, height = map(int, resolution.split('x'))
        bitrate = calculate_bitrate(width, height, bitrate_mode)
        command += ['-b:v', f"{bitrate}k"]
        command.append(output_filename)
        with tqdm(total=100, ncols=80, bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt}') as pbar:
            process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            for line in process.stderr:
                line = line.decode().strip()
                if line.startswith('frame='):
                    frame = int(line.split('frame=')[1].split()[0])
                    pbar.update(frame - pbar.n)
                    progress_var.set(pbar.n)
                    progress_text.insert(tk.END, line + '\n')
                    progress_text.see(tk.END)
        print(f"Converted {filename} to {output_filename}")
root = tk.Tk()
root.title("Video Converter")
resolution_frame = tk.Frame(root)
resolution_frame.pack(pady=10)
resolution_label = tk.Label(resolution_frame, text="Resolution:")
resolution_label.pack(side=tk.LEFT)
# Dropdown menu with video resolutions
resolution_var = tk.StringVar(value="640x480")
resolution_dropdown = tk.OptionMenu(resolution_frame, resolution_var, "640x480", "1280x720", "1920x1080")
resolution_dropdown.pack(side=tk.LEFT)
bitrate_frame = tk.Frame(root)
bitrate_frame.pack(pady=10)
bitrate_label = tk.Label(bitrate_frame, text="Bitrate Mode:")
bitrate_label.pack(side=tk.LEFT)
bitrate_var = tk.StringVar(value="CBR")
bitrate_cbr_radio = tk.Radiobutton(bitrate_frame, text="CBR", variable=bitrate_var, value="CBR")
bitrate_cbr_radio.pack(side=tk.LEFT)
bitrate_vbr_radio = tk.Radiobutton(bitrate_frame, text="VBR", variable=bitrate_var, value="VBR")
bitrate_vbr_radio.pack(side=tk.LEFT)
output_path_frame = tk.Frame(root)
output_path_frame.pack(pady=10)
output_path_label = tk.Label(output_path_frame, text="Output Path:")
output_path_label.pack(side=tk.LEFT)
output_path_var = tk.StringVar(value=settings.get("General", "OutputPath", fallback=""))
output_path_entry = tk.Entry(output_path_frame, textvariable=output_path_var, state="readonly")
output_path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
folder_picker_button = tk.Button(output_path_frame, text="Select Folder", command=open_folder_picker)
folder_picker_button.pack(side=tk.LEFT)
progress_text = tk.Text(root, height=10, width=50)
progress_text.pack(pady=10)
progress_var = tk.DoubleVar(value=0.0)
progress_bar = ttk.Progressbar(root, variable=progress_var, maximum=100)
progress_bar.pack(pady=10)
convert_button = tk.Button(root, text="Convert", command=convert_videos)
convert_button.pack(pady=10)
root.mainloop()




________________________________

Youtube Downloader:
-------------------

import tkinter as tk
from pytube import YouTube
from tkinter import ttk
import os

def download():
    # Get the URL from the text box
    url = url_textbox.get()

    # Create a YouTube object
    yt = YouTube(url)

    # Get the video format from the radio buttons
    if mp4_radio_button.get():
        video_format = "mp4"
        extension = ".mp4"
        res = res_textbox.get()
        stream = yt.streams.filter(res=res).first()
    else:
        video_format = "mp3"
        extension = ".mp3"
        streams = yt.streams.filter(only_audio=True).all()

        # Create a new window to display the available audio streams
        stream_window = tk.Toplevel(root)
        stream_window.title("Select Audio Stream")

        # Display the available audio streams in a listbox
        stream_listbox = tk.Listbox(stream_window)
        for stream in streams:
            stream_listbox.insert(tk.END, f"{stream.abr} ({stream.mime_type})")
        stream_listbox.pack(padx=10, pady=10)

        def select_stream():
            # Get the selected stream
            selected_stream_index = stream_listbox.curselection()[0]
            selected_stream = streams[selected_stream_index]

            # Destroy the stream window
            stream_window.destroy()

            # Set up the progress bar
            progress_bar["maximum"] = selected_stream.filesize
            progress_bar["value"] = 0

            # Set up the title label
            title_label.config(text=f"Downloading: {yt.title}")

            # Download the audio
            filename = yt.title.encode('utf-8') + extension
            selected_stream.download(output_path="downloads", filename=filename)

            # Reset the progress bar and title label
            progress_bar["value"] = 0
            title_label.config(text="")

        # Create a select button to download the selected audio stream
        select_button = tk.Button(stream_window, text="Select", command=select_stream)
        select_button.pack(padx=10, pady=10)

        # Wait for the user to select a stream
        stream_window.wait_window()

    # Download the video or audio
    filename = yt.title + extension
    stream.download(output_path="downloads", filename=filename)

    # Reset the progress bar and title label
    progress_bar["value"] = 0
    title_label.config(text="")

def open_download_folder():
    # Open the download folder
    os.startfile(os.path.abspath("downloads"))

def check_url(*args):
    # Get the URL from the text box
    url = url_textbox.get()

    # Replace https://m.youtube. with https://www.youtube.
    url = url.replace("https://m.youtube.", "https://www.youtube.")

    # Check if the URL is valid
    if not url.startswith("https://www.youtube.com/watch?v="):
        return

    # Create a YouTube object
    yt = YouTube(url)

    # Get the available audio streams
    streams = yt.streams.filter(only_audio=True).all()

    # Create a new window to display the available audio streams
    stream_window = tk.Toplevel(root)
    stream_window.title("Select Audio Stream")

    # Display the available audio streams in a listbox
    stream_listbox = tk.Listbox(stream_window)
    for stream in streams:
        stream_listbox.insert(tk.END, f"{stream.abr} ({stream.mime_type})")
    stream_listbox.pack(padx=10, pady=10)

    def select_stream():
        # Get the selected stream
        selected_stream_index = stream_listbox.curselection()[0]
        selected_stream = streams[selected_stream_index]

        # Destroy the stream window
        stream_window.destroy()

        # Set up the progress bar
        progress_bar["maximum"] = selected_stream.filesize
        progress_bar["value"] = 0

        # Set up the title label
        title_label.config(text=f"Downloading: {yt.title}")

        # Download the audio
        filename = yt.title + ".mp3"
        selected_stream.download(output_path="downloads", filename=filename)

        # Reset the progress bar and title label
        progress_bar["value"] = 0
        title_label.config(text="")

    # Create a select button to download the selected audio stream
    select_button = tk.Button(stream_window, text="Select", command=select_stream)
    select_button.pack(padx=10, pady=10)

    # Wait for the user to select a stream
    stream_window.wait_window()

# Create the GUI
root = tk.Tk()
root.title("YouTube Downloader")

# Create the text box for the video resolution
res_textbox = tk.Entry(root, width=10)
res_textbox.pack()
res_textbox.insert(0, "360p")

# Create the text box for the URL
url_textbox =tk.Entry(root, width=50)
url_textbox.pack(padx=10, pady=10)
url_textbox.bind("<Return>", check_url)

# Create the radio buttons to choose the download format
mp4_radio_button = tk.BooleanVar(value=True)
mp4_radio = ttk.Radiobutton(root, text="MP4", variable=mp4_radio_button, value=True)
mp4_radio.pack()
mp3_radio = ttk.Radiobutton(root, text="MP3", variable=mp4_radio_button, value=False)
mp3_radio.pack()

# Create the download button
download_button = tk.Button(root, text="Download", command=download)
download_button.pack(padx=10, pady=10)

# Create the progress bar
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode="determinate")
progress_bar.pack(padx=10, pady=10)

# Create the title label
title_label = tk.Label(root, text="")
title_label.pack(padx=10, pady=10)

# Create the button to open the download folder
open_folder_button = tk.Button(root, text="Open Download Folder", command=open_download_folder)
open_folder_button.pack(padx=10, pady=10)

# Start the GUI
root.mainloop()



_________________________________________________________________________


MeteoCtrl Lister (with date search, keyword search and hyperlink support):
------------------------------------------------------------------------

import os
import sys
import tkinter as tk
from datetime import datetime, timezone, timedelta


directory = r'C:\Konfi-Data\Export\json'

german_tz = timezone(timedelta(hours=1), 'CET')

def display_files(file_list):
    for file in file_list:
        file_path = os.path.join(directory, file)
        file_time = os.path.getmtime(file_path)
        dt = datetime.fromtimestamp(file_time, tz=timezone.utc)
        german_time = dt.astimezone(german_tz)
        file_timestamp = f'{file} - {german_time.strftime("%d/%m/%Y %I:%M:%S %p")} ({german_tz.tzname(None)})'
        file_label = tk.Label(root, text=file_timestamp, anchor='w', justify='left', fg='blue', cursor='hand2')
        file_label.pack(fill='x')
        file_label.bind('<Button-1>', lambda event, file_path=file_path: open_file(file_path))

def open_file(file_path):
    try:
        with open(file_path, 'r') as f:
            file_content = f.read()
            text_editor = tk.Toplevel(root)
            text_editor.title(file_path)
            text_editor_text = tk.Text(text_editor)
            text_editor_text.pack(fill='both', expand=True)
            text_editor_text.insert('1.0', file_content)
    except Exception as e:
        tk.messagebox.showerror('Error', str(e))

def get_file_date(file):
    # Get the last modification time of the file
    last_modified_time = os.path.getmtime(os.path.join(directory, file))
    # Convert the last modification time to a datetime object
    last_modified_datetime = datetime.fromtimestamp(last_modified_time, tz=german_tz)
    # Extract the date from the datetime object
    return last_modified_datetime.date()

def search_files(keyword, date_str):
    # Clear the previous search results
    for widget in root.winfo_children():
        if isinstance(widget, tk.Label) or isinstance(widget, tk.Button):
            widget.destroy()
    if keyword or date_str:
        count = 0
        for file in file_list:
            file_date = get_file_date(file)
            if (not keyword or keyword.lower() in file.lower()) and (not date_str or file_date == datetime.strptime(date_str, "%d/%m/%Y").date()):
                count += 1
                file_path = os.path.join(directory, file)
                file_time = os.path.getmtime(file_path)
                dt = datetime.fromtimestamp(file_time, tz=timezone.utc)
                german_time = dt.astimezone(german_tz)
                file_timestamp = f'{file} - {german_time.strftime("%d/%m/%Y %I:%M:%S %p")} ({german_tz.tzname(None)})'
                file_label = tk.Label(root, text=file_timestamp, anchor='w', justify='left', fg='blue', cursor='hand2')
                file_label.pack(fill='x')
                file_label.bind('<Button-1>', lambda event, file_path=file_path: open_file(file_path))
                if keyword:
                    with open(file_path, 'r') as f:
                        for line in f:
                            if keyword.lower() in line.lower():
                                line_label = tk.Label(root, text=line.strip(), anchor='w', justify='left')
                                line_label.pack(fill='x')
        total_count.set(f'Occurrences: {count}')
    else:
        display_files(file_list_sorted)
        total_count.set('Occurrences: 0')

def reload_program():
    python = sys.executable
    args = [os.path.abspath(__file__)]
    os.execl(python, python, *args)

    # Close the current instance of the program
    root.destroy()

    
file_list = os.listdir(directory)
file_info_list = [(file, os.path.getmtime(os.path.join(directory, file))) for file in file_list]
file_info_list_sorted = sorted(file_info_list, key=lambda x: x[1], reverse=True)[:100]
file_list_sorted = [file_info[0] for file_info in file_info_list_sorted]

root = tk.Tk()
root.title('Newest 100 Files')

search_entry = tk.Entry(root)
search_entry.pack()

filter_frame = tk.Frame(root)
filter_frame.pack(side='top', fill='x')

date_label = tk.Label(filter_frame, text='Date (dd/mm/yyyy) [t-todays date:]', font='Helvetica 12', anchor='w', justify='left')
date_label.pack(side='left')

date_entry = tk.Entry(filter_frame)
date_entry.pack(side='left', padx=5)

total_count = tk.StringVar()
total_count.set('Occurrences: 0')
count_label = tk.Label(filter_frame, textvariable=total_count, font='Helvetica 12', anchor='e', justify='right')
count_label.pack(side='right', fill='x', expand=True)

# Create the "RELOAD" button
reload_button = tk.Button(root, text='RELOAD / F5', command=reload_program)
reload_button.pack(side='top', pady=10)
root.bind('<F5>', lambda event: reload_program())

display_files(file_list_sorted)

root.after_id = None

def on_search_entry_change(event):
    # Cancel any existing call to the search function
    if root.after_id is not None:
        root.after_cancel(root.after_id)
    # Schedule a new call to the search function in 1 second
    root.after_id = root.after(1500, search_files, search_entry.get(), date_entry.get())
    # Check if "t" is entered in the date entry
    if event.widget == date_entry and event.char.lower() == "t":
        # Replace "t" with the current date in the format "dd/mm/yyyy"
        today = datetime.now(german_tz).strftime("%d/%m/%Y")
        date_entry.delete(0, tk.END)
        date_entry.insert(0, today)



search_entry.bind('<KeyRelease>', on_search_entry_change)
date_entry.bind('<KeyRelease>', on_search_entry_change)

root.mainloop()


( Source: https://poe.com/Pythonmachine )


=============================
===PythonHelp=================



Start .py without visible cmd (save as *.vbs)
-----------------------------------------------

Set objShell = CreateObject("WScript.Shell")
objShell.Run "C:\adb\PowerampCtrl.py", 0, True
Set objShell = Nothing

________________________________

Start py with minimized cmd:
---------------------------------------------

cmd /c start /min "C:\adb\PowerampCtrl.py"
_________________________

Figure out url from pip installer:
----------------------------------
pip install PyQt5 --log log.txt

________________________________________

Install py for specific version:
--------------------------------

C:\Users\User\AppData\Local\Programs\Python\Python310\Scripts\pip install torch-2.0.1+cu118-cp310-cp310-win_amd64.whl

________________________________________

Install whl:
------------

pip install *.whl
