Misc ns-usbloader MacOS Application

TheStonedModder

Developer
Developer
Joined
Dec 25, 2022
Messages
2,701
Reaction score
4,012
Trophies
2
Age
29
XP
8,392
Country
United States
Java programs are annoying to use on mac, so I bundled it and a python script into a standalone .app file so that it can be installed and launched directly from the command center like a normal application. (assuming you have python3, and java installed already)


image (1).png

If anyone wants to update or improve it here is the script that I used.

This will bundle an "ns-usbloader.jar" and run.py script in root into a .app file
Code:
import os
import shutil
import subprocess
import sys

def create_mac_app():
    # Define paths
    app_name = "ns-usbloader"
    app_bundle = f"{app_name}.app"
    contents_dir = os.path.join(app_bundle, "Contents")
    macos_dir = os.path.join(contents_dir, "MacOS")
    resources_dir = os.path.join(contents_dir, "Resources")
    python_script = "run.py"

    # Step 1: Create the macOS application bundle structure
    print("Creating macOS application bundle structure...")
    os.makedirs(macos_dir, exist_ok=True)
    os.makedirs(resources_dir, exist_ok=True)

    # Step 2: Copy the Python script, JAR files, and icon into the bundle
    print("Copying Python script, JAR files, and icon...")
    shutil.copy(python_script, resources_dir)
    for file in os.listdir():
        if file.endswith(".jar") and "ns-usbloader" in file:
            shutil.copy(file, resources_dir)
  
    # Copy the .icns file if it exists
    if os.path.exists("AppIcon.icns"):
        shutil.copy("AppIcon.icns", resources_dir)
    else:
        print("Warning: AppIcon.icns not found. The app will use a default icon.")

    # Step 3: Create a shell script to run the Python script
    print("Creating shell script...")
    shell_script_content = f"""#!/bin/bash
DIR="$( cd "$( dirname "${{BASH_SOURCE[0]}}" )" && pwd )"
cd "$DIR/../Resources"
export PYTHONPATH="$PYTHONPATH:$(pwd)"
/usr/bin/env python3 {python_script}
"""
    with open(os.path.join(macos_dir, "run_app"), "w") as shell_script:
        shell_script.write(shell_script_content)
    os.chmod(os.path.join(macos_dir, "run_app"), 0o755)

    # Step 4: Create the Info.plist file
    print("Creating Info.plist...")
    info_plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>run_app</string>
    <key>CFBundleIdentifier</key>
    <string>com.yourcompany.{app_name}</string>
    <key>CFBundleName</key>
    <string>{app_name}</string>
    <key>CFBundleVersion</key>
    <string>1.0</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleIconFile</key>
    <string>AppIcon.icns</string>
    <key>NSHighResolutionCapable</key>
    <true/>
    <key>LSMinimumSystemVersion</key>
    <string>10.9</string>
</dict>
</plist>
"""
    with open(os.path.join(contents_dir, "Info.plist"), "w") as plist_file:
        plist_file.write(info_plist_content)

    print(f"{app_name}.app has been created successfully.")

if __name__ == "__main__":
    create_mac_app()

If you want the application to have an icon. Just put a png file next to this script, and run it. It should spit out the proper icns file. You can than just drag the icsn file next to the scripts above, and run the make script again to give it an icon
Code:
import os
import subprocess
from PIL import Image
import shutil

def create_iconset(png_path, iconset_path):
    # Define the sizes for the iconset
    sizes = [16, 32, 64, 128, 256, 512, 1024]

    # Create the iconset directory
    os.makedirs(iconset_path, exist_ok=True)

    # Generate images for each size
    for size in sizes:
        img = Image.open(png_path)
        img = img.resize((size, size), Image.LANCZOS)  # Use LANCZOS instead of ANTIALIAS
        img.save(os.path.join(iconset_path, f"icon_{size}x{size}.png"))

        # Save @2x images for Retina displays
        img_2x = img.resize((size * 2, size * 2), Image.LANCZOS)  # Use LANCZOS instead of ANTIALIAS
        img_2x.save(os.path.join(iconset_path, f"icon_{size}x{size}@2x.png"))

def convert_to_icns(iconset_path, icns_path):
    # Use iconutil to convert the iconset to an icns file
    subprocess.run(['iconutil', '-c', 'icns', iconset_path, '-o', icns_path], check=True)

def main():
    png_path = "icon.png"
    iconset_path = "AppIcon.iconset"
    icns_path = "AppIcon.icns"

    if not os.path.exists(png_path):
        print(f"{png_path} not found.")
        return

    print("Creating iconset...")
    create_iconset(png_path, iconset_path)

    print("Converting iconset to icns...")
    convert_to_icns(iconset_path, icns_path)

    print(f"{icns_path} has been created successfully.")

    # Clean up the iconset directory
    shutil.rmtree(iconset_path)

if __name__ == "__main__":
    main()

Download: https://gbatemp.net/download/ns-usbloader-macos-app-v7-1.38845/
 
Last edited by TheStonedModder,
Thanks very much!

What is that run.py script in python_script = "run.py"?
Maybe I didn't install Python3 correctly or maybe some path hasn't been set up correctly.
 
Thanks very much!

What is that run.py script in python_script = "run.py"?
Maybe I didn't install Python3 correctly or maybe some path hasn't been set up correctly.
I don’t quite understand. Do you have a screenshot?

This is the first time I made something like this so it’s very possible I forgot something when uploading
 
I don’t quite understand.
Code:
Traceback (most recent call last):
  File "/Users/user/Downloads/ns-usbloader/maketheapp.py", line 76, in <module>
    create_mac_app()
    ~~~~~~~~~~~~~~^^
  File "/Users/user/Downloads/ns-usbloader/maketheapp.py", line 22, in create_mac_app
    shutil.copy(python_script, resources_dir)
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/shutil.py", line 428, in copy
    copyfile(src, dst, follow_symlinks=follow_symlinks)
    ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/shutil.py", line 260, in copyfile
    with open(src, 'rb') as fsrc:
         ~~~~^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'run.py'

I think this is what they meant
 

Site & Scene News

Popular threads in this forum