diff --git a/.gitignore b/.gitignore index 2668eede..1b84bcee 100644 --- a/.gitignore +++ b/.gitignore @@ -19,11 +19,12 @@ windows/ASIOSDK2 windows/VC_redist.x64.exe windows/vc_redist.x86.exe debug/ +release/ +build/ +deploy/ jamulus.sln jamulus.vcxproj jamulus.vcxproj.filters -release/ -deploy/ Jamulus.app/ .DS_Store distributions/opus* diff --git a/Jamulus.pro b/Jamulus.pro index a125acee..5f854b15 100755 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -70,6 +70,8 @@ win32 { SOURCES += mac/sound.cpp RC_FILE = mac/mainicon.icns CONFIG += x86 + QMAKE_INFO_PLIST = mac/Info.plist + QMAKE_TARGET_BUNDLE_PREFIX = net.sourceforge.llcon LIBS += -framework CoreFoundation \ -framework CoreServices \ diff --git a/mac/Info.plist b/mac/Info.plist new file mode 100644 index 00000000..9f750fad --- /dev/null +++ b/mac/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleName + @EXECUTABLE@ + CFBundleDisplayName + @EXECUTABLE@ + CFBundleIdentifier + @BUNDLEIDENTIFIER@ + CFBundlePackageType + APPL + CFBundleVersion + @FULL_VERSION@ + CFBundleExecutable + @EXECUTABLE@ + CFBundleDevelopmentRegion + en + CFBundleIconFile + mainicon.icns + CFBundleGetInfoString + Created by Qt/QMake + + NSPrincipalClass + NSApplication + NSMicrophoneUsageDescription + Jamulus needs access to the microphone to record and stream your music to other musicians + + NSRequiresAquaSystemAppearance + true + + diff --git a/mac/deploy_mac.sh b/mac/deploy_mac.sh index ef841dde..e494dd02 100755 --- a/mac/deploy_mac.sh +++ b/mac/deploy_mac.sh @@ -1,31 +1,57 @@ -#!/bin/sh -cd .. +#!/bin/bash +set -e +APP_NAME="Jamulus" +SERVER_NAME="${APP_NAME}Server" +INSTALLER_NAME="${APP_NAME}-installer" +ROOT_PATH="$(pwd)" +MAC_PATH="${ROOT_PATH}/mac" +RES_PATH="${ROOT_PATH}/src/res" +BUILD_PATH="${ROOT_PATH}/build" +DEPLOY_PATH="${ROOT_PATH}/deploy" +JOB_COUNT=$(sysctl -n hw.ncpu) -# TODO add tag to CVS with current version number -# cvs -n update 2>null | grep -i "M " # error if any file is locally modified!!! -> TODO +function build_app { + # Build Jamulus + qmake "${ROOT_PATH}/${APP_NAME}.pro" -o "${BUILD_PATH}/Makefile" \ + "CONFIG+=release" "TARGET=$1" "QMAKE_APPLICATION_BUNDLE_NAME=$1" ${@:2} + make -f "${BUILD_PATH}/Makefile" -C "${BUILD_PATH}" -j${JOB_COUNT} -# call qmake -qmake Jamulus.pro + # Deploy Jamulus + macdeployqt "${BUILD_PATH}/$1.app" -verbose=2 -always-overwrite + mv "${BUILD_PATH}/$1.app" "${DEPLOY_PATH}" + make -f "${BUILD_PATH}/Makefile" -C "${BUILD_PATH}" distclean +} -# first clean up -rm -rf Jamulus.app -make clean +# Check we are running from the correct location +if [ ! -f "${ROOT_PATH}/${APP_NAME}.pro" ]; then + echo Please run this script from the ${APP_NAME} Qt project directory. + echo Usage: mac/$(basename $0) + exit 1 +fi -# make everything -make -j2 +# Install dmgbuild (for the current user), this is required to build the installer image +python -m ensurepip --user --default-pip +python -m pip install --user dmgbuild +DMGBUILD_BIN="$(python -c 'import site; print(site.USER_BASE)')/bin/dmgbuild" -# call qt mac deploy tool -macdeployqt Jamulus.app -dmg +# Get Jamulus version +APP_VERSION=$(cat "${ROOT_PATH}/${APP_NAME}.pro" | sed -nE 's/^VERSION *= *(.*)$/\1/p') -# create zip file including COPYING file -zip Jamulus-version-mac.zip Jamulus.dmg COPYING +# Clean up previous deployments +rm -rf "${BUILD_PATH}" +rm -rf "${DEPLOY_PATH}" +mkdir -p "${BUILD_PATH}" +mkdir -p "${DEPLOY_PATH}" -# move new file in deploy directory -mkdir -p deploy -mv Jamulus-version-mac.zip deploy/Jamulus-version-mac.zip +# Build Jamulus client +build_app "${APP_NAME}" -# cleanup and go back to original directory -rm Jamulus.dmg -cd mac +# Build Jamulus server +build_app "${SERVER_NAME}" "DEFINES+=SERVER_BUNDLE" + +# Build installer image +"${DMGBUILD_BIN}" -s "${MAC_PATH}/deployment_settings.py" -D background="${RES_PATH}/installerbackground.png" \ + -D app_path="${DEPLOY_PATH}/${APP_NAME}.app" -D server_path="${DEPLOY_PATH}/${SERVER_NAME}.app" \ + -D license="${ROOT_PATH}/COPYING" "${INSTALLER_NAME}" "${DEPLOY_PATH}/${INSTALLER_NAME}-${APP_VERSION}-mac.dmg" diff --git a/mac/deployment_settings.py b/mac/deployment_settings.py new file mode 100644 index 00000000..b552eebf --- /dev/null +++ b/mac/deployment_settings.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +import biplist +import os.path + + +def icon_from_app(app_path): + plist_path = os.path.join(app_path, "Contents", "Info.plist") + plist = biplist.readPlist(plist_path) + icon_name = plist["CFBundleIconFile"] + icon_root, icon_ext = os.path.splitext(icon_name) + icon_name = icon_root + (icon_ext or ".icns") + + return os.path.join(app_path, "Contents", "Resources", icon_name) + + +def validate_key_path(key, example): + value = defines.get(key, None) + + if value is None: + raise ValueError("The " + key + " key must be specified.\n" + "Example: dmgbuild -D " + key + "=" + example + " ...") + + if not os.path.exists(value): + raise ValueError("The " + key + " key must be a valid path.") + + return value + + +# Path of the applications to deploy +app_path = validate_key_path("app_path", "Jamulus.app") +server_path = validate_key_path("server_path", "JamulusServer.app") + +# Name of the applications to deploy +app_name = os.path.basename(app_path) +server_name = os.path.basename(server_path) + +# Volume format (see hdiutil create -help) +format = defines.get("format", "UDBZ") + +# Volume size +size = defines.get('size', None) + +# Files to include +files = [ + app_path, + server_path +] + +# Symlinks to create +symlinks = { 'Applications': '/Applications' } + +# Background +background = validate_key_path("background", "picture.png") + +# Volume icon +badge_icon = icon_from_app(app_path) + +# Select the default view +default_view = "icon-view" + +# Set these to True to force inclusion of icon/list view settings +include_icon_view_settings = False +include_list_view_settings = False + +# Where to put the icons +icon_locations = { + app_name: (630, 210), + server_name: (530, 210), + "Applications": (820, 210) +} + +# View/Window element configuration +show_status_bar = False +show_tab_view = False +show_toolbar = False +show_pathbar = False +show_sidebar = False +show_icon_preview = False + +# Window position in ((x, y), (w, h)) format +window_rect = ((200, 400), (900, 320)) + +# Icon view configuration +arrange_by = None +grid_offset = (0, 0) +grid_spacing = 72 +scroll_position = (0, 0) +label_pos = "bottom" +icon_size = 72 +text_size = 12 + +# License configuration +license = { + "default-language": "en_US", + "licenses": { "en_US": validate_key_path("license", "COPYING") } +} diff --git a/src/main.cpp b/src/main.cpp index c9fd4c10..bfd05295 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,14 @@ int main ( int argc, char** argv ) // initialize all flags and string which might be changed by command line // arguments + +#if defined( SERVER_BUNDLE ) && ( defined( __APPLE__ ) || defined( __MACOSX ) ) + // if we are on MacOS and we are building a server bundle, starts Jamulus in server mode + bool bIsClient = false; +#else bool bIsClient = true; +#endif + bool bUseGUI = true; bool bStartMinimized = false; bool bShowComplRegConnList = false; @@ -447,7 +454,6 @@ int main ( int argc, char** argv ) #endif } - // Dependencies ------------------------------------------------------------ // per definition: if we are in "GUI" server mode and no central server // address is given, we use the default central server address diff --git a/src/res/installerbackground.png b/src/res/installerbackground.png new file mode 100644 index 00000000..230d2fb6 Binary files /dev/null and b/src/res/installerbackground.png differ diff --git a/src/res/installerbackground.xcf b/src/res/installerbackground.xcf new file mode 100644 index 00000000..a5776467 Binary files /dev/null and b/src/res/installerbackground.xcf differ