diff --git a/.github/workflows/build_appimage_bundle.yml b/.github/workflows/build_appimage_bundle.yml new file mode 100644 index 00000000..b1dca3fc --- /dev/null +++ b/.github/workflows/build_appimage_bundle.yml @@ -0,0 +1,117 @@ +name: Build and Release APPIMAGE Installer +on: [push] + +jobs: + build-and-release: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Electron Builder + working-directory: gui + run: | + npm i + npm run build + + - name: LIST ALL FILES + run: ls -R + + - name: Install Linux dependencies + run: | + sudo apt install -y portaudio19-dev libhamlib-dev libhamlib-utils build-essential cmake python3-libhamlib2 patchelf + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Build binaries + working-directory: modem + run: | + python3 -m nuitka --remove-output --assume-yes-for-downloads --follow-imports --include-data-dir=lib=lib --include-data-files=lib/codec2/*=lib/codec2/ --include-data-files=config.ini.example=config.ini --standalone server.py --output-filename=freedata-server + + - name: Prepare AppImage folder + run: | + mkdir -p $HOME/freedata-appimage + + - name: Copy GUI + run: | + cp -r gui/release/linux-unpacked/* $HOME/freedata-appimage/gui + + + - name: Copy server + run: | + cp -r modem/server.dist/* $HOME/freedata-appimage/server + + - name: Copy Icon + run: | + cp gui/build/icon.png $HOME/freedata-appimage/icon.png + + - name: Create Desktop shortcut + run: | + echo ' + # Create desktop file + echo "[Desktop Entry] + Type=Application + Name=FreeDATA + Icon=icon + Exec=AppRun + Categories=Utility ' > $HOME/freedata-appimage/FreeDATA.desktop + + - name: Create AppImage build script + run: | + echo '#!/bin/bash + # Navigate to the AppDir root; this ensures relative paths work as expected + cd "$(dirname "$(readlink -f "${0}")")" + + # check if config exists in ~/.config/FreeDATA/config.ini else create it + SERVER_CONFIG_FILE=~/.config/FreeDATA/config.ini + if test -f "$SERVER_CONFIG_FILE"; then + echo "$SERVER_CONFIG_FILE exists." + else + echo "$SERVER_CONFIG_FILE does not exist. Copying the default one" + mkdir ~/.config/FreeDATA + cp server.dist/config.ini $SERVER_CONFIG_FILE + fi + + export FREEDATA_CONFIG=$SERVER_CONFIG_FILE + + # Launch the main application executable from the linux-unpacked directory + ./linux-unpacked/freedata + + ' > $HOME/AppRun + chmod +x $HOME/freedata-appimage/AppRun + + - name: Download AppImage + run: | + wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage -O appimagetool-x86_64.AppImage + chmod +x appimagetool-x86_64.AppImage + + - name: Execute AppImage + run: | + ./appimagetool-x86_64.AppImage freedata-appimage/ + + - name: LIST ALL FILES + run: ls -R + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: 'FreeDATA-x86_64.AppImage' + path: ./$HOME/FreeDATA-x86_64.AppImage + + - name: Upload Installer to Release + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/v') + with: + draft: true + files: ./$HOME/FreeDATA-x86_64.AppImage + tag_name: ${{ github.ref_name }} + name: 'FreeDATA-x86_64.AppImage' diff --git a/.github/workflows/pip_package.yml b/.github/workflows/pip_package.yml new file mode 100644 index 00000000..2cae2991 --- /dev/null +++ b/.github/workflows/pip_package.yml @@ -0,0 +1,38 @@ +name: Deploy Python Package +on: + push: + tags: + - '*' + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install Linux dependencies + run: | + sudo apt install -y portaudio19-dev libhamlib-dev libhamlib-utils build-essential cmake python3-libhamlib2 patchelf + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install wheel + + - name: Build package + run: | + python setup.py sdist bdist_wheel + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@v1.4.2 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/gui/electron/main/index.ts b/gui/electron/main/index.ts index 112cca9b..0b6005f6 100644 --- a/gui/electron/main/index.ts +++ b/gui/electron/main/index.ts @@ -111,11 +111,12 @@ app.whenReady().then(() => { //serverProcess = spawn(serverPath, [], { detached: true }); //serverProcess.unref(); // Allow the server process to continue running independently of the parent process // break; - //case "linux": - //serverPath = join(basePath, "freedata-server", "freedata-server.exe"); - //serverProcess = spawn(serverPath, [], { detached: true }); - //serverProcess.unref(); // Allow the server process to continue running independently of the parent process - // break; + case "linux": + serverPath = join(basePath, "server.dist", "freedata-server"); + console.log(`Starting server with path: ${serverPath}`); + serverProcess = spawn(serverPath, [], { detached: true }); + serverProcess.unref(); // Allow the server process to continue running independently of the parent process + break; case "win32": serverPath = join(basePath, "freedata-server", "freedata-server.exe"); console.log(`Starting server with path: ${serverPath}`); diff --git a/modem/__init__.py b/modem/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/modem/codec2.py b/modem/codec2.py index b6fe0981..c65f0bf0 100644 --- a/modem/codec2.py +++ b/modem/codec2.py @@ -82,14 +82,14 @@ def freedv_get_mode_name_by_value(mode: int) -> str: """ return FREEDV_MODE(mode).name - # Get the directory of the current script file script_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.append(script_dir) + # Use script_dir to construct the paths for file search if sys.platform == "linux": files = glob.glob(os.path.join(script_dir, "**/*libcodec2*"), recursive=True) - files.append(os.path.join(script_dir, "libcodec2.so")) + #files.append(os.path.join(script_dir, "libcodec2.so")) elif sys.platform == "darwin": if hasattr(sys, "_MEIPASS"): files = glob.glob(os.path.join(getattr(sys, "_MEIPASS"), '**/*libcodec2*'), recursive=True) @@ -100,6 +100,8 @@ elif sys.platform in ["win32", "win64"]: else: files = [] api = None + +print(files) for file in files: try: api = ctypes.CDLL(file) diff --git a/modem/message_system_db_manager.py b/modem/message_system_db_manager.py index ce76b08a..5bd3cf58 100644 --- a/modem/message_system_db_manager.py +++ b/modem/message_system_db_manager.py @@ -13,6 +13,8 @@ class DatabaseManager: def __init__(self, event_manger, db_file=None): self.event_manager = event_manger if not db_file: + print(os.environ) + script_dir = os.path.dirname(os.path.abspath(__file__)) db_path = os.path.join(script_dir, 'freedata-messages.db') db_file = 'sqlite:///' + db_path diff --git a/modem/server.py b/modem/server.py index c0d8ff2a..4d2e1bd4 100644 --- a/modem/server.py +++ b/modem/server.py @@ -1,10 +1,13 @@ -import time +import sys +import os +script_directory = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(script_directory) + +import time from flask import Flask, request, jsonify, make_response, abort, Response from flask_sock import Sock from flask_cors import CORS -import os -import sys import serial_ports from config import CONFIG import audio @@ -33,7 +36,7 @@ from schedule_manager import ScheduleManager app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) sock = Sock(app) -MODEM_VERSION = "0.15.2-alpha" +MODEM_VERSION = "0.15.3-alpha" # set config file to use def set_config(): @@ -343,7 +346,7 @@ def stop_server(): print('Server shutdown...') print("------------------------------------------") -if __name__ == "__main__": +def main(): app.config['SOCK_SERVER_OPTIONS'] = {'ping_interval': 10} # define global MODEM_VERSION app.MODEM_VERSION = MODEM_VERSION @@ -382,3 +385,5 @@ if __name__ == "__main__": app.run(modemaddress, modemport) +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..182200e3 --- /dev/null +++ b/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup, find_packages + +# Reading requirements.txt for dependencies +with open('requirements.txt') as f: + required = f.read().splitlines() + +with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + +setup( + name='freedata-server', + version='0.15.3', + packages=find_packages(where='.'), + package_dir={'': '.'}, + install_requires=required, + python_requires='>=3.9', + author='DJ2LS', + author_email='dj2ls@proton.me', + description='A free, open-source, multi-platform application for sending files and messages, using the codec2 HF modems.', + long_description=long_description, + long_description_content_type="text/markdown", + url='https://freedata.app', + license='GPL3.0', + entry_points={ + 'console_scripts': [ + 'freedata-server=modem.server:main', # Points to the main() function in server.py + ], + }, + include_package_data=True, # Ensure non-python files are included if specified + package_data={ + # Include all files under any directory within the 'modem' package + 'modem': ['lib/**/*'], # Recursive include for all files in 'lib' and its subdirectories + }, +) diff --git a/tools/cleanup.sh b/tools/cleanup.sh index 07572dcb..6b22b596 100644 --- a/tools/cleanup.sh +++ b/tools/cleanup.sh @@ -1,3 +1,3 @@ -#autopep8 --in-place --select W291,W293,W391,E231 --ignore E501 ../modem.py ../deprecated_data_handler.py ../deprecated_main.py ../deprecated_sock.py ../deprecated_static.py ../helpers.py +#autopep8 --in-place --select W291,W293,W391,E231 --ignore E501 ../encoder_decoder.py ../deprecated_data_handler.py ../deprecated_main.py ../deprecated_sock.py ../deprecated_static.py ../helpers.py autopep8 --in-place --ignore E501 ../modem.py ../data_handler.py ../main.py ../sock.py ../static.py ../helpers.py