Skip to content
Open
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
16 changes: 16 additions & 0 deletions archinstall/applications/camera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import TYPE_CHECKING

from archinstall.lib.output import debug

if TYPE_CHECKING:
from archinstall.lib.installer import Installer


class CameraApp:
@property
def packages(self) -> list[str]:
return ['libcamera', 'libcamera-ipa', 'libcamera-tools', 'gst-plugin-libcamera', 'pipewire-libcamera']

def install(self, install_session: 'Installer') -> None:
debug('Installing libcamera')
install_session.add_additional_packages(self.packages)
3 changes: 3 additions & 0 deletions archinstall/lib/applications/application_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from archinstall.applications.audio import AudioApp
from archinstall.applications.bluetooth import BluetoothApp
from archinstall.applications.camera import CameraApp
from archinstall.applications.firewall import FirewallApp
from archinstall.applications.power_management import PowerManagementApp
from archinstall.applications.print_service import PrintServiceApp
Expand Down Expand Up @@ -43,5 +44,7 @@ def install_applications(self, install_session: 'Installer', app_config: Applica
app_config.firewall_config,
)

if app_config.camera_config and app_config.camera_config.enabled:
CameraApp().install(install_session)

application_handler = ApplicationHandler()
43 changes: 43 additions & 0 deletions archinstall/lib/applications/application_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
ApplicationConfiguration,
Audio,
AudioConfiguration,
CameraConfiguration,
BluetoothConfiguration,
Firewall,
FirewallConfiguration,
Expand Down Expand Up @@ -78,6 +79,12 @@ def _define_menu_options(self) -> list[MenuItem]:
preview_action=self._prev_firewall,
key='firewall_config',
),
MenuItem(
text=tr('Camera'),
action=select_camera,
preview_action=self._prev_camera,
key='camera_config',
),
]

def _prev_power_management(self, item: MenuItem) -> str | None:
Expand Down Expand Up @@ -116,6 +123,15 @@ def _prev_firewall(self, item: MenuItem) -> str | None:
return f'{tr("Firewall")}: {config.firewall.value}'
return None

def _prev_camera(self, item: MenuItem) -> str | None:
if item.value is not None:
camera_config: CameraConfiguration = item.value

output = f'{tr("Camera")}: '
output += tr('Enabled') if camera_config.enabled else tr('Disabled')
return output
return None


def select_power_management(preset: PowerManagementConfiguration | None = None) -> PowerManagementConfiguration | None:
group = MenuItemGroup.from_enum(PowerManagement)
Expand Down Expand Up @@ -240,3 +256,30 @@ def select_firewall(preset: FirewallConfiguration | None = None) -> FirewallConf
return FirewallConfiguration(firewall=result.get_value())
case ResultType.Reset:
return None

def select_camera(preset: CameraConfiguration | None) -> CameraConfiguration | None:
group = MenuItemGroup.yes_no()
group.focus_item = MenuItem.no()

if preset is not None:
group.set_selected_by_value(preset.enabled)

header = tr('Would you like to install libcamera?') + '\n'

result = SelectMenu[bool](
group,
header=header,
alignment=Alignment.CENTER,
columns=2,
orientation=Orientation.HORIZONTAL,
allow_skip=True,
).run()

match result.type_:
case ResultType.Selection:
enabled = result.item() == MenuItem.yes()
return CameraConfiguration(enabled)
case ResultType.Skip:
return preset
case _:
raise ValueError('Unhandled result type')
5 changes: 5 additions & 0 deletions archinstall/lib/global_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ def _prev_applications(self, item: MenuItem) -> str | None:
output += f'{tr("Firewall")}: {firewall_config.firewall.value}'
output += '\n'

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

return output

return None
Expand Down
3 changes: 2 additions & 1 deletion archinstall/lib/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .application import ApplicationConfiguration, Audio, AudioConfiguration, BluetoothConfiguration, PrintServiceConfiguration
from .application import ApplicationConfiguration, Audio, AudioConfiguration, BluetoothConfiguration, CameraConfiguration, PrintServiceConfiguration
from .bootloader import Bootloader
from .device import (
BDevice,
Expand Down Expand Up @@ -41,6 +41,7 @@
'BDevice',
'BluetoothConfiguration',
'Bootloader',
'CameraConfiguration',
'CustomRepository',
'DeviceGeometry',
'DeviceModification',
Expand Down
22 changes: 21 additions & 1 deletion archinstall/lib/models/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Firewall(StrEnum):
class FirewallConfigSerialization(TypedDict):
firewall: str

class CameraConfigSerialization(TypedDict):
enabled: bool

class ZramAlgorithm(StrEnum):
ZSTD = 'zstd'
Expand All @@ -53,7 +55,7 @@ class ApplicationSerialization(TypedDict):
power_management_config: NotRequired[PowerManagementConfigSerialization]
print_service_config: NotRequired[PrintServiceConfigSerialization]
firewall_config: NotRequired[FirewallConfigSerialization]

camera_config: NotRequired[CameraConfigSerialization]

@dataclass
class AudioConfiguration:
Expand Down Expand Up @@ -141,6 +143,16 @@ def parse_arg(cls, arg: bool | dict[str, Any]) -> Self:
algo = arg.get('algorithm', arg.get('algo', ZramAlgorithm.ZSTD.value))
return cls(enabled=enabled, algorithm=ZramAlgorithm(algo))

@dataclass
class CameraConfiguration:
enabled: bool

def json(self) -> CameraConfigSerialization:
return {'enabled': self.enabled}

@classmethod
def parse_arg(cls, arg: CameraConfigSerialization) -> Self:
return cls(arg['enabled'])

@dataclass
class ApplicationConfiguration:
Expand All @@ -149,6 +161,7 @@ class ApplicationConfiguration:
power_management_config: PowerManagementConfiguration | None = None
print_service_config: PrintServiceConfiguration | None = None
firewall_config: FirewallConfiguration | None = None
camera_config: CameraConfiguration | None = None

@classmethod
def parse_arg(
Expand Down Expand Up @@ -177,6 +190,10 @@ def parse_arg(
if args and (firewall_config := args.get('firewall_config')) is not None:
app_config.firewall_config = FirewallConfiguration.parse_arg(firewall_config)

if args and (camera_config := args.get('camera_config')) is not None:
app_config.camera_config = CameraConfiguration.parse_arg(camera_config)


return app_config

def json(self) -> ApplicationSerialization:
Expand All @@ -197,4 +214,7 @@ def json(self) -> ApplicationSerialization:
if self.firewall_config:
config['firewall_config'] = self.firewall_config.json()

if self.camera_config:
config['camera_config'] = self.camera_config.json()

return config
6 changes: 6 additions & 0 deletions archinstall/locales/base.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,12 @@ msgstr ""
msgid "Would you like to configure the print service?"
msgstr ""

msgid "Camera"
msgstr ""

msgid "Would you like to install libcamera?"
msgstr ""

msgid "Power management"
msgstr ""

Expand Down
3 changes: 3 additions & 0 deletions tests/data/test_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
},
"print_service_config": {
"enabled": true
},
"camera_config": {
"enabled": true
}
},
"auth_config": {
Expand Down
2 changes: 2 additions & 0 deletions tests/test_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Audio,
AudioConfiguration,
BluetoothConfiguration,
CameraConfiguration,
PrintServiceConfiguration,
ZramConfiguration,
)
Expand Down Expand Up @@ -140,6 +141,7 @@ def test_config_file_parsing(
bluetooth_config=BluetoothConfiguration(enabled=True),
audio_config=AudioConfiguration(audio=Audio.PIPEWIRE),
print_service_config=PrintServiceConfiguration(enabled=True),
camera_config=CameraConfiguration(enabled=True),
),
auth_config=AuthenticationConfiguration(
root_enc_password=Password(enc_password='password_hash'),
Expand Down