Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions archinstall/applications/audio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from typing import TYPE_CHECKING

from archinstall.lib.hardware import SysInfo
from archinstall.lib.models.application import Audio, AudioConfiguration
from archinstall.lib.models.users import User
from archinstall.lib.output import debug

if TYPE_CHECKING:
from archinstall.lib.installer import Installer


class AudioApp:
@property
def pulseaudio_packages(self) -> list[str]:
return [
'pulseaudio',
]

@property
def pipewire_packages(self) -> list[str]:
return [
'pipewire',
'pipewire-alsa',
'pipewire-jack',
'pipewire-pulse',
'gst-plugin-pipewire',
'libpulse',
'wireplumber',
]

def _enable_pipewire(
self,
install_session: 'Installer',
users: list['User'] | None = None,
) -> None:
if users is None:
return

for user in users:
# Create the full path for enabling the pipewire systemd items
service_dir = install_session.target / 'home' / user.username / '.config' / 'systemd' / 'user' / 'default.target.wants'
service_dir.mkdir(parents=True, exist_ok=True)

# Set ownership of the entire user catalogue
install_session.arch_chroot(f'chown -R {user.username}:{user.username} /home/{user.username}')

# symlink in the correct pipewire systemd items
install_session.arch_chroot(
f'ln -sf /usr/lib/systemd/user/pipewire-pulse.service /home/{user.username}/.config/systemd/user/default.target.wants/pipewire-pulse.service',
run_as=user.username,
)
install_session.arch_chroot(
f'ln -sf /usr/lib/systemd/user/pipewire-pulse.socket /home/{user.username}/.config/systemd/user/default.target.wants/pipewire-pulse.socket',
run_as=user.username,
)

def install(
self,
install_session: 'Installer',
audio_config: AudioConfiguration,
users: list[User] | None = None,
) -> None:
debug(f'Installing audio server: {audio_config.audio.value}')

if audio_config.audio == Audio.NO_AUDIO:
debug('No audio server selected, skipping installation.')
return

if SysInfo.requires_sof_fw():
install_session.add_additional_packages('sof-firmware')

if SysInfo.requires_alsa_fw():
install_session.add_additional_packages('alsa-firmware')

match audio_config.audio:
case Audio.PIPEWIRE:
install_session.add_additional_packages(self.pipewire_packages)
self._enable_pipewire(install_session, users)
case Audio.PULSEAUDIO:
install_session.add_additional_packages(self.pulseaudio_packages)
2 changes: 1 addition & 1 deletion archinstall/applications/bluetooth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from archinstall.lib.installer import Installer


class Bluetooth:
class BluetoothApp:
@property
def packages(self) -> list[str]:
return [
Expand Down
Empty file.
57 changes: 0 additions & 57 deletions archinstall/default_profiles/applications/pipewire.py

This file was deleted.

19 changes: 12 additions & 7 deletions archinstall/lib/applications/application_handler.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from typing import TYPE_CHECKING

from archinstall.applications.bluetooth import Bluetooth
from archinstall.applications.audio import AudioApp
from archinstall.applications.bluetooth import BluetoothApp
from archinstall.lib.models.application import ApplicationConfiguration
from archinstall.lib.models.users import User

if TYPE_CHECKING:
from archinstall.lib.installer import Installer
Expand All @@ -11,13 +13,16 @@ class ApplicationHandler:
def __init__(self) -> None:
pass

def install_applications(
self,
install_session: 'Installer',
app_config: ApplicationConfiguration,
) -> None:
def install_applications(self, install_session: 'Installer', app_config: ApplicationConfiguration, users: list['User'] | None = None) -> None:
if app_config.bluetooth_config:
Bluetooth().install(install_session)
BluetoothApp().install(install_session)

if app_config.audio_config:
AudioApp().install(
install_session,
app_config.audio_config,
users,
)


application_handler = ApplicationHandler()
40 changes: 38 additions & 2 deletions archinstall/lib/applications/application_menu.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import override

from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.models.application import ApplicationConfiguration, BluetoothConfiguration
from archinstall.lib.models.application import ApplicationConfiguration, Audio, AudioConfiguration, BluetoothConfiguration
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.types import Alignment, Orientation
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties, Orientation


class ApplicationMenu(AbstractSubMenu[ApplicationConfiguration]):
Expand Down Expand Up @@ -41,6 +42,12 @@ def _define_menu_options(self) -> list[MenuItem]:
preview_action=self._prev_bluetooth,
key='bluetooth_config',
),
MenuItem(
text=tr('Audio'),
action=select_audio,
preview_action=self._prev_audio,
key='audio_config',
),
]

def _prev_bluetooth(self, item: MenuItem) -> str | None:
Expand All @@ -52,6 +59,12 @@ def _prev_bluetooth(self, item: MenuItem) -> str | None:
return output
return None

def _prev_audio(self, item: MenuItem) -> str | None:
if item.value is not None:
config: AudioConfiguration = item.value
return f'{tr("Audio")}: {config.audio.value}'
return None


def select_bluetooth(preset: BluetoothConfiguration | None) -> BluetoothConfiguration | None:
group = MenuItemGroup.yes_no()
Expand All @@ -74,3 +87,26 @@ def select_bluetooth(preset: BluetoothConfiguration | None) -> BluetoothConfigur
enabled = result.item() == MenuItem.yes()

return BluetoothConfiguration(enabled)


def select_audio(preset: AudioConfiguration | None = None) -> AudioConfiguration | None:
items = [MenuItem(a.value, value=a) for a in Audio]
group = MenuItemGroup(items)

if preset:
group.set_focus_by_value(preset.audio)

result = SelectMenu[Audio](
group,
allow_skip=True,
alignment=Alignment.CENTER,
frame=FrameProperties.min(tr('Audio')),
).run()

match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return AudioConfiguration(audio=result.get_value())
case ResultType.Reset:
raise ValueError('Unhandled result type')
16 changes: 7 additions & 9 deletions archinstall/lib/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

from archinstall.lib.crypt import decrypt
from archinstall.lib.models.application import ApplicationConfiguration
from archinstall.lib.models.audio_configuration import AudioConfiguration
from archinstall.lib.models.bootloader import Bootloader
from archinstall.lib.models.device_model import DiskEncryption, DiskLayoutConfiguration
from archinstall.lib.models.locale import LocaleConfiguration
Expand Down Expand Up @@ -63,8 +62,7 @@ class ArchConfig:
network_config: NetworkConfiguration | None = None
bootloader: Bootloader = field(default=Bootloader.get_default())
uki: bool = False
audio_config: AudioConfiguration | None = None
application_config: ApplicationConfiguration | None = None
app_config: ApplicationConfiguration | None = None
hostname: str = 'archlinux'
kernels: list[str] = field(default_factory=lambda: ['linux'])
ntp: bool = True
Expand Down Expand Up @@ -106,8 +104,7 @@ def safe_json(self) -> dict[str, Any]:
'services': self.services,
'custom_commands': self.custom_commands,
'bootloader': self.bootloader.json(),
'audio_config': self.audio_config.json() if self.audio_config else None,
'app_config': self.application_config.json() if self.application_config else None,
'app_config': self.app_config.json() if self.app_config else None,
}

if self.locale_config:
Expand Down Expand Up @@ -184,11 +181,12 @@ def from_config(cls, args_config: dict[str, Any]) -> 'ArchConfig':
if args_config.get('uki') and not arch_config.bootloader.has_uki_support():
arch_config.uki = False

if audio_config := args_config.get('audio_config', None):
arch_config.audio_config = AudioConfiguration.parse_arg(audio_config)
# deprecated: backwards compatibility
audio_config_args = args_config.get('audio_config', None)
app_config_args = args_config.get('app_config', None)

if app_config := args_config.get('app_config', None):
arch_config.application_config = ApplicationConfiguration.parse_arg(app_config)
if audio_config_args is not None or app_config_args is not None:
arch_config.app_config = ApplicationConfiguration.parse_arg(app_config_args, audio_config_args)

if hostname := args_config.get('hostname', ''):
arch_config.hostname = hostname
Expand Down
22 changes: 7 additions & 15 deletions archinstall/lib/global_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
add_number_of_parallel_downloads,
ask_additional_packages_to_install,
ask_for_a_timezone,
ask_for_audio_selection,
ask_hostname,
ask_ntp,
)
Expand All @@ -26,7 +25,6 @@
from .locale.locale_menu import LocaleMenu
from .menu.abstract_menu import CONFIG_KEY, AbstractMenu
from .mirrors import MirrorMenu
from .models.audio_configuration import AudioConfiguration
from .models.bootloader import Bootloader
from .models.locale import LocaleConfiguration
from .models.mirrors import MirrorConfiguration
Expand Down Expand Up @@ -128,12 +126,6 @@ def _get_menu_options(self) -> list[MenuItem]:
preview_action=self._prev_profile,
key='profile_config',
),
MenuItem(
text=tr('Audio'),
action=ask_for_audio_selection,
preview_action=self._prev_audio,
key='audio_config',
),
MenuItem(
text=tr('Applications'),
action=self._select_applications,
Expand Down Expand Up @@ -311,7 +303,13 @@ def _prev_applications(self, item: MenuItem) -> str | None:

if app_config.bluetooth_config:
output += f'{tr("Bluetooth")}: '
output += tr('Enabled') if app_config.bluetooth_config.enabled else tr('Disabled') + '\n'
output += tr('Enabled') if app_config.bluetooth_config.enabled else tr('Disabled')
output += '\n'

if app_config.audio_config:
audio_config = app_config.audio_config
output += f'{tr("Audio")}: {audio_config.audio.value}'
output += '\n'

return output

Expand Down Expand Up @@ -378,12 +376,6 @@ def _prev_root_pwd(self, item: MenuItem) -> str | None:
return f'{tr("Root password")}: {password.hidden()}'
return None

def _prev_audio(self, item: MenuItem) -> str | None:
if item.value is not None:
config: AudioConfiguration = item.value
return f'{tr("Audio")}: {config.audio.value}'
return None

def _prev_parallel_dw(self, item: MenuItem) -> str | None:
if item.value is not None:
return f'{tr("Parallel Downloads")}: {item.value}'
Expand Down
2 changes: 0 additions & 2 deletions archinstall/lib/interactions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
add_number_of_parallel_downloads,
ask_additional_packages_to_install,
ask_for_a_timezone,
ask_for_audio_selection,
ask_hostname,
ask_ntp,
select_archinstall_language,
Expand All @@ -26,7 +25,6 @@
'ask_additional_packages_to_install',
'ask_for_a_timezone',
'ask_for_additional_users',
'ask_for_audio_selection',
'ask_for_bootloader',
'ask_for_swap',
'ask_for_uki',
Expand Down
Loading