#!/usr/bin/env bash

DEST=${1:-/etc/skel}
PIPEWIRE_HOME=${DEST}/.config/pipewire
WIREPLUMBER_HOME=${DEST}/.config/wireplumber

mkdir -p ${DEST}/.config/pipewire,wireplumber

# https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/home
#
# with-alsa:
# https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-ALSA

sudo apt -y install \
  libfdk-aac2 \
  libldacbt-{abr,enc}2 \
  libopenaptx0

sudo apt -y install \
  gstreamer1.0-pipewire \
  libpipewire-0.3-{0,dev,modules} \
  libspa-0.2-{bluetooth,dev,jack,libcamera,modules} \
  pipewire \
  pipewire-{alsa,jack,v4l2,libcamera}

sudo apt install \
  pipewire-audio-client-libraries \
  pipewire \
  pipewire-alsa \
  pipewire-audio \
  pipewire-jack

## For WirePlumber - pipewire session manager
sudo apt-get install wireplumber{,-doc}

## Other management tools
sudo apt-get install qpwgraph vlc-plugin-pipewire

# Copy conffiles to /etc
sudo cp -vRa /usr/share/pipewire /etc/
sudo mkdir -p ${PIPEWIRE_HOME}/pipewire.conf.d

# Wireplumber now expects configuration files in /usr/share and no more lua.
# sudo cp -vRa /usr/share/wireplumber /etc/
# sudo mkdir -p ${WIREPLUMER_HOME}/wireplumber.conf.d

# WirePlumber has profile auto-switching enabled by default. It can
# automatically switch between HSP/HFP and A2DP profiles whenever an
# input stream is detected. You can disable it with:
conf_print_wireplumber_bt_autoswitch() {
  cat <<-EOF
		wireplumber.settings = {                          
		  bluetooth.autoswitch-to-headset-profile = false 
		}
	EOF
}
# conf_print_wireplumber_bt_autoswitch | sudo tee ${WIREPLUMBER_HOME}/wireplumber.conf.d/11-bluetooth-policy.conf
# conf_print_wireplumber_bt_autoswitch | sudo tee ${WIREPLUMBER_HOME}/wireplumber/wireplumber.conf.d/11-bluetooth-policy.conf

sudo touch ${PIPEWIRE_HOME}/media-session.d/with-alsa

sudo cp /usr/share/doc/pipewire/examples/ld.so.conf.d/pipewire-jack-x86_64-linux-gnu.conf /etc/ld.so.conf.d/

sudo ldconfig

# sudo cp /usr/share/doc/pipewire/examples/alsa.conf.d/99-pipewire-default.conf /etc/alsa/conf.d/
sudo ln -s /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf /etc/alsa/conf.d/99-pipewire-default.conf
#conf_print_pipewire_default() {
#cat <<-EOF
#pcm.!default {
#    type pipewire
#    playback_node "-1"
#    capture_node  "-1"
#    hint {
#        show on
#        description "Default ALSA Output (currently PipeWire Media Server)"
#    }
#}
#
#ctl.!default {
#    type pipewire
#}
#EOF
#}
# conf_print_pipewire_default | sudo tee /etc/alsa/conf.d/99-pipewire-default.conf

conf_print_pipewire_desktop() {
  cat <<-EOF
		[Desktop Entry]
		Version=1.0
		Name=PipeWire Media System
		Comment=Start the PipeWire Media System
		Exec=/usr/bin/pipewire
		Terminal=false
		Type=Application
		X-GNOME-Autostart-Phase=Initialization
		X-KDE-autostart-phase=1
	EOF
}
conf_print_pipewire_desktop | sudo tee /etc/xdg/autostart/pipewire.desktop
￼
conf_print_wireplumber_desktop() {
  cat <<-EOF
		[Desktop Entry]
		Version=1.0
		Name=WirePlumber PipeWire Media System
		Comment=Start the WirePlumber
		Exec=/usr/bin/wireplumber
		Terminal=false
		Type=Application
		X-GNOME-Autostart-Phase=Initialization
		X-KDE-autostart-phase=1
	EOF
}
conf_print_wireplumber_desktop | sudo tee /etc/xdg/autostart/wireplumber.desktop

# don't use this we make incremental changes to conf.d/<file>.conf
#
# conf_print_pipewire_conf() {
#	cat <<-EOF
#		# PipeWire ALSA configuration
#		context.properties = {
#		 # ALSA settings
#		 alsa.jack.device = "hw:0"
#		 alsa.jack.autoconnect = true
#		 alsa.jack.autoconnect-ports = true
#		 alsa.jack.latency = 100000
#		}
#	EOF
#}
# conf_print_pipewire_conf | sudo tee /etc/pipewire/pipewire.conf

# https://davejansen.com/disable-wireplumber-pipewire-suspend-on-idle-pops-delays-noise/
conf_print_alsa_conf_suspend-timeout() {
  cat <<-EOF
		alsa_monitor.enabled = true

		alsa_monitor.properties = {
		 -- Your existing properties configuration
		}

		alsa_monitor.rules = {
		 {
		    matches = {
		      {
		        -- This matches all cards.
		        { "device.name", "matches", "alsa_card.*" },
		      },
		    },
		    apply_properties = {
		      -- Your existing apply_properties configuration
		      ["session.suspend-timeout-seconds"] = 0, -- Add this line
		    },
		 },
		 {
		    matches = {
		      {
		        -- Matches all sources.
		        { "node.name", "matches", "alsa_input.*" },
		      },
		      {
		        -- Matches all sinks.
		        { "node.name", "matches", "alsa_output.*" },
		      },
		    },
		    apply_properties = {
		      -- Your existing apply_properties configuration
		      ["session.suspend-timeout-seconds"] = 0, -- Add this line
		    },
		 },
		}
	EOF
}
# no more lua for wireplumber
# conf_print_alsa_conf_suspend-timeout | sudo tee ${WIREPLUMBER_HOME}/main.lua.d/60-alsa_suspend-timeout.conf

# improved crackling in fullscreen
conf_print_pipewire_quantum() {
  cat <<-EOF
		conf_print_pipewire_quantum() {
		default.clock.quantum = "32"
		default.clock.min-quantum = "64"
		default.clock.max-quantum = "768"
	EOF
}
conf_print_pipewire_quantum | sudo tee ${PIPEWIRE_HOME}/pipewire.conf.d/clock_quantum.conf

#  default.clock.allowed-rates = [ 44100 48000 96000 192000 ]
conf_print_pipewire_quantum() {
  cat <<-EOF
		      default.clock.rate = 44100
				  default.clock.allowed-rates = 44100
				  default.clock.quantum = 512
				  default.clock.min-quantum = 16
				  default.clock.max-quantum = 2048
				  default.clock.quantum-limit = 512
				  settings.check-quantum = false
				  settings.check-rate = false
	EOF
}
conf_print_pipewire_quantum | sudo tee ${PIPEWIRE_HOME}/pipewire.conf.d/clock_quantum.conf

conf_print_pipewire_alsa-api() {
  cat <<-EOF
		    # See: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-ALSA#alsa-buffer-properties
				api.alsa.headroom = 1024
				api.alsa.period-size = 256
	EOF
}
conf_print_pipewire_alsa-api | sudo tee ${PIPEWIRE_HOME}/pipewire.conf.d/alsa-api.conf

conf_print_pipewire_clock-rate() {
  cat <<-EOF
		context.properties = {
		   default.clock.rate  =   [ 44100 48000 ]
		}
	EOF
}
conf_print_pipewire_clock-rate | sudo tee ${PIPEWIRE_HOME}/pipewire.conf.d/alsa-dmix.conf

conf_print_pipewire_alsa-dmix() {
  cat <<EOF

EOF
}
conf_print_pipewire_alsa-dmix | sudo tee ${PIPEWIRE_HOME}/pipewire.conf.d/alsa-dmix.conf

## with-jack: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-JACK:
# sudo apt -y install libspa-0.2-jack
#
#sudo touch /etc/pipewire/media-session.d/with-jack
#
## Either run JACK clients using the pw-jack wrapper, or copy:
# cp /usr/share/doc/pipewire/examples/ld.so.conf.d/pipewire-jack-*.conf /etc/ld.so.conf.d/

# ldconfig

# /usr/share/pipewire/client-rt.conf /etc/pipewire/client-rt.conf.d/
mkdir -p ${PIPEWIRE_HOME}/client-rt.conf.d/

# Real-time Client config file for PipeWire version "1.0.3" #
#
# Copy and edit this file in /etc/pipewire for system-wide changes
# or in ~/.config/pipewire for local changes.
#
# It is also possible to place a file with an updated section in
# /etc/pipewire/client-rt.conf.d/ for system-wide changes or in
# ~/.config/pipewire/client-rt.conf.d/ for local changes.
#

conf_print_client-rt_context_property() {
  cat <<-EOF
		context.properties = {
		    ## Configure properties in the system.
		    #mem.warn-mlock  = false
		    #mem.allow-mlock = true
		    #mem.mlock-all   = false
		    log.level        = 0

		    #default.clock.quantum-limit = 8192
		}
	EOF
}
conf_print_client-rt_context_property | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_context_property.conf >/dev/null

conf_print_client-rt_context_spa-libs() {
  cat <<-EOF
		context.spa-libs = {
		    #<factory-name regex> = <library-name>
		    #
		    # Used to find spa factory names. It maps an spa factory name
		    # regular expression to a library name that should contain
		    # that factory.
		    #
		    audio.convert.* = audioconvert/libspa-audioconvert
		    support.*       = support/libspa-support
		}
	EOF
}
conf_print_client-rt_context_spa-libs | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_context_spa-libs.conf >/dev/null

conf_print_client-rt_context_modules() {
  cat <<-EOF
		context.modules = [
		    #{ name = <module-name>
		    #    ( args  = { <key> = <value> ... } )
		    #    ( flags = [ ( ifexists ) ( nofail ) ] )
		    #    ( condition = [ { <key> = <value> ... } ... ] )
		    #}
		    #
		    # Loads a module with the given parameters.
		    # If ifexists is given, the module is ignored when it is not found.
		    # If nofail is given, module initialization failures are ignored.
		    #
		    # Uses realtime scheduling to boost the audio thread priorities
		    { name = libpipewire-module-rt
		        args = {
		            #rt.prio      = 88
		            #rt.time.soft = -1
		            #rt.time.hard = -1
		        }
		        flags = [ ifexists nofail ]
		    }

		    # The native communication protocol.
		    { name = libpipewire-module-protocol-native }

		    # Allows creating nodes that run in the context of the
		    # client. Is used by all clients that want to provide
		    # data to PipeWire.
		    { name = libpipewire-module-client-node }

		    # Allows creating devices that run in the context of the
		    # client. Is used by the session manager.
		    { name = libpipewire-module-client-device }

		    # Makes a factory for wrapping nodes in an adapter with a
		    # converter and resampler.
		    { name = libpipewire-module-adapter }

		    # Allows applications to create metadata objects. It creates
		    # a factory for Metadata objects.
		    { name = libpipewire-module-metadata }

		    # Provides factories to make session manager objects.
		    { name = libpipewire-module-session-manager }
		]
	EOF
}
conf_print_client-rt_context_modules | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_context_modules.conf >/dev/null

conf_print_client-rt_filter_properties() {
  cat <<-EOF
		filter.properties = {
		    #node.latency = 1024/48000
		}
	EOF
}
conf_print_client-rt_filter_properties | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_filter_properties.conf >/dev/null

conf_print_client-rt_stream_properties() {
  cat <<-EOF
		stream.properties = {
		    #node.latency          = 1024/48000
		    #node.autoconnect      = true
		    #resample.quality      = 4
		    #channelmix.normalize  = false
		    #channelmix.mix-lfe    = true
		    #channelmix.upmix      = true
		    #channelmix.upmix-method = psd  # none, simple
		    #channelmix.lfe-cutoff = 150
		    #channelmix.fc-cutoff  = 12000
		    #channelmix.rear-delay = 12.0
		    #channelmix.stereo-widen = 0.0
		    #channelmix.hilbert-taps = 0
		    #dither.noise = 0
		}
	EOF
}
conf_print_client-rt_stream_properties | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_stream_properties.conf >/dev/null

conf_print_client-rt_stream_rules() {
  cat <<-EOF
		stream.rules = [
		    {   matches = [
		            {
		                # all keys must match the value. ! negates. ~ starts regex.
		                #application.name       = "pw-cat"
		                #node.name   = "~Google Chrome$"
		            }
		        ]
		        actions = {
		            update-props = {
		                #node.latency = 512/48000
		            }
		        }
		    }
		]
	EOF
}
conf_print_client-rt_stream_rules | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_stream_rules.conf >/dev/null

conf_print_client-rt_alsa_properties() {
  cat <<-EOF
		alsa.properties = {
		    #alsa.deny = false
		    # ALSA params take a single value, an array [] of values
		    # or a range { min=.. max=... }
		    #alsa.access = [ MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED ]
		    #alsa.format = [ FLOAT S32 S24 S24_3 S16 U8 ]
		    #alsa.rate = { min=1 max=384000 }  # or [ 44100 48000 .. ]
		    #alsa.channels = { min=1 max=64 }  # or [ 2 4 6 .. ]
		    #alsa.period-bytes = { min=128 max=2097152 } # or [ 128 256 1024 .. ]
		    #alsa.buffer-bytes = { min=256 max=4194304 } # or [ 256 512 4096 .. ]

		    #alsa.volume-method = cubic   # linear, cubic
		}
	EOF
}
conf_print_client-rt_alsa_properties | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_alsa_properties.conf >/dev/null

conf_print_client-rt_alsa_rules() {
  cat <<-EOF
		# client specific properties
		alsa.rules = [
		    {   matches = [ { application.process.binary = "resolve" } ]
		        actions = {
		            update-props = {
				alsa.buffer-bytes = 131072
		            }
		        }
		    }
		]
	EOF
}
conf_print_client-rt_alsa_rules | sudo tee ${PIPEWIRE_HOME}/client-rt.conf.d/client-rt_alsa_rules.conf >/dev/null
