Skip to content

Commit

Permalink
Add initial drafts of camera and disk drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseTG committed Apr 9, 2024
1 parent 7d1be1b commit fece657
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 12 deletions.
22 changes: 15 additions & 7 deletions src/libretro/api/camera.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
from ctypes import CFUNCTYPE, POINTER, c_bool, c_uint, c_size_t, c_uint32, c_float, Structure, c_uint64, \
c_int
from ctypes import CFUNCTYPE, POINTER, c_bool, c_uint, c_size_t, c_uint32, c_float, Structure, c_uint64, c_int
from dataclasses import dataclass
from enum import IntEnum
from enum import IntEnum, IntFlag

from libretro.api._utils import FieldsFromTypeHints


retro_camera_buffer = c_int
RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0
RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER = (RETRO_CAMERA_BUFFER_OPENGL_TEXTURE + 1)
RETRO_CAMERA_BUFFER_DUMMY = 0x7fffffff
RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER = RETRO_CAMERA_BUFFER_OPENGL_TEXTURE + 1
RETRO_CAMERA_BUFFER_DUMMY = 0x7FFFFFFF


retro_camera_start_t = CFUNCTYPE(c_bool)
Expand All @@ -19,10 +18,18 @@
retro_camera_frame_opengl_texture_t = CFUNCTYPE(None, c_uint, c_uint, POINTER(c_float))


class CameraBufferType(IntEnum):
class CameraCapabilities(IntEnum):
OPENGL_TEXTURE = RETRO_CAMERA_BUFFER_OPENGL_TEXTURE
RAW_FRAMEBUFFER = RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER

def flag(self) -> int:
return 1 << self.value


class CameraCapabilityFlags(IntFlag):
OPENGL_TEXTURE = 1 << CameraCapabilities.OPENGL_TEXTURE
RAW_FRAMEBUFFER = 1 << CameraCapabilities.RAW_FRAMEBUFFER


@dataclass(init=False)
class retro_camera_callback(Structure, metaclass=FieldsFromTypeHints):
Expand Down Expand Up @@ -57,6 +64,7 @@ def __deepcopy__(self, _):
'retro_camera_frame_raw_framebuffer_t',
'retro_camera_frame_opengl_texture_t',
'retro_camera_callback',
'CameraBufferType',
'CameraCapabilities',
'CameraCapabilityFlags',
'retro_camera_buffer',
]
1 change: 1 addition & 0 deletions src/libretro/driver/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .audio import *
from .camera import *
from .content import *
from .disk import *
from .environment import *
from .input import *
from .led import *
Expand Down
1 change: 1 addition & 0 deletions src/libretro/driver/camera/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .driver import *
from .generator import *
84 changes: 81 additions & 3 deletions src/libretro/driver/camera/driver.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,88 @@
from abc import abstractmethod
from typing import Protocol, runtime_checkable
from libretro.api.camera import *

from libretro.api.camera import (
retro_camera_callback,
retro_camera_start_t,
retro_camera_stop_t,
retro_camera_lifetime_status_t,
retro_camera_frame_raw_framebuffer_t,
retro_camera_frame_opengl_texture_t, CameraCapabilityFlags,
)


@runtime_checkable
class CameraDriver(Protocol):
pass
@abstractmethod
def __init__(self):
self._as_parameter_: retro_camera_callback = retro_camera_callback()
self._as_parameter_.start = retro_camera_start_t(self.start)
self._as_parameter_.stop = retro_camera_stop_t(self.stop)

@property
@abstractmethod
def caps(self) -> CameraCapabilityFlags: ...

@caps.setter
@abstractmethod
def caps(self, value: CameraCapabilityFlags) -> None: ...

@abstractmethod
def start(self) -> bool: ...

@abstractmethod
def stop(self) -> None: ...

@abstractmethod
def poll(self) -> None: ...

@property
@abstractmethod
def width(self) -> int: ...

@width.setter
@abstractmethod
def width(self, value: int) -> None: ...

@property
@abstractmethod
def height(self) -> int: ...

@height.setter
@abstractmethod
def height(self, value: int) -> None: ...

@property
@abstractmethod
def frame_raw_framebuffer(self) -> retro_camera_frame_raw_framebuffer_t | None: ...

@frame_raw_framebuffer.setter
@abstractmethod
def frame_raw_framebuffer(self, value: retro_camera_frame_raw_framebuffer_t) -> None: ...

@property
@abstractmethod
def frame_opengl_texture(self) -> retro_camera_frame_opengl_texture_t | None: ...

@frame_opengl_texture.setter
@abstractmethod
def frame_opengl_texture(self, value: retro_camera_frame_opengl_texture_t) -> None: ...

@property
@abstractmethod
def initialized(self) -> retro_camera_lifetime_status_t | None: ...

@initialized.setter
@abstractmethod
def initialized(self, value: retro_camera_lifetime_status_t) -> None: ...

@property
@abstractmethod
def deinitialized(self) -> retro_camera_lifetime_status_t | None: ...

@deinitialized.setter
@abstractmethod
def deinitialized(self, value: retro_camera_lifetime_status_t) -> None: ...


__all__ = ["CameraDriver"]
__all__ = ["CameraDriver"]
60 changes: 60 additions & 0 deletions src/libretro/driver/camera/generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from typing import override

from .driver import CameraDriver
from ... import retro_camera_lifetime_status_t, retro_camera_frame_raw_framebuffer_t, \
CameraCapabilityFlags, retro_camera_frame_opengl_texture_t

class CameraFrame:
pass
# TODO: Add a buffer
# TODO: Add dimensions


class GeneratorCameraDriver(CameraDriver):
@override
def __init__(self):
super().__init__()

# TODO: Accept a generator for camera frames

@property
def caps(self) -> CameraCapabilityFlags:
pass

def start(self) -> bool:
pass

def stop(self) -> None:
pass

def poll(self) -> None:
pass

@property
def width(self) -> int:
pass

@property
def height(self) -> int:
pass

@property
def frame_raw_framebuffer(self) -> retro_camera_frame_raw_framebuffer_t | None:
pass

@property
def frame_opengl_texture(self) -> retro_camera_frame_opengl_texture_t | None:
pass

@property
def initialized(self) -> retro_camera_lifetime_status_t | None:
pass

@property
def deinitialized(self) -> retro_camera_lifetime_status_t | None:
pass


__all__ = [
"GeneratorCameraDriver",
]
1 change: 1 addition & 0 deletions src/libretro/driver/disk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .driver import *
39 changes: 39 additions & 0 deletions src/libretro/driver/disk/driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from abc import abstractmethod
from typing import Protocol, runtime_checkable

from libretro.api.disk import (
retro_disk_control_ext_callback,
retro_disk_control_callback,
)


@runtime_checkable
class DiskDriver(Protocol):
@property
@abstractmethod
def version(self) -> int: ...

@property
@abstractmethod
def callback(self) -> retro_disk_control_callback | retro_disk_control_ext_callback | None: ...

@callback.setter
@abstractmethod
def callback(self, value: retro_disk_control_callback | retro_disk_control_ext_callback) -> None: ...

@callback.deleter
@abstractmethod
def callback(self) -> None: ...

@property
@abstractmethod
def eject_state(self) -> bool: ...

@eject_state.setter
@abstractmethod
def eject_state(self, value: bool) -> None: ...


__all__ = [
"DiskDriver",
]
8 changes: 6 additions & 2 deletions src/libretro/driver/environment/composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ def video(self) -> VideoDriver:
def content(self) -> ContentDriver | None:
return self._content

@property
def camera(self) -> CameraDriver | None:
return self._camera

@property
def user(self) -> UserDriver | None:
return self._user
Expand Down Expand Up @@ -611,11 +615,11 @@ def __get_sensor_input(self, port: int, id: int) -> float:
return self._input.sensor.get_sensor_input(port, Sensor(id))

@override
def _get_camera_interface(self, interface: POINTER(retro_camera_callback)) -> bool:
def _get_camera_interface(self, callback_ptr: POINTER(retro_camera_callback)) -> bool:
if not self._camera:
return False

if not interface:
if not callback_ptr:
raise ValueError("RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE doesn't accept NULL")

return False # TODO: Implement
Expand Down

0 comments on commit fece657

Please sign in to comment.