diff --git a/src/sdl2.nim b/src/sdl2.nim index f8c79a9..cf85639 100644 --- a/src/sdl2.nim +++ b/src/sdl2.nim @@ -1,3 +1,5 @@ +## The Simple DirectMedia Layer Library. + import macros import strutils @@ -33,169 +35,347 @@ const type WindowEventID* {.size: sizeof(byte).} = enum - WindowEvent_None = 0, WindowEvent_Shown, WindowEvent_Hidden, WindowEvent_Exposed, - WindowEvent_Moved, WindowEvent_Resized, WindowEvent_SizeChanged, WindowEvent_Minimized, - WindowEvent_Maximized, WindowEvent_Restored, WindowEvent_Enter, WindowEvent_Leave, - WindowEvent_FocusGained, WindowEvent_FocusLost, WindowEvent_Close, - WindowEvent_TakeFocus, WindowEvent_HitTest + ## Event subtype for window events + WindowEvent_None = 0, ## Never used + WindowEvent_Shown, ## Window has been shown + WindowEvent_Hidden, ## Window has been hidden + WindowEvent_Exposed, ## Window has been exposed and should be redrawn + WindowEvent_Moved, ## Window has been moved to data1, data2 + WindowEvent_Resized, ## Window has been resized to data1*data2 + WindowEvent_SizeChanged, + ## The window size has changed, either as a result of an API call or + ## through the system or user changing the window size. + WindowEvent_Minimized, ## Window has been minimized + WindowEvent_Maximized, ## Window has been maximized + WindowEvent_Restored, + ## Window has been restored to normal size and position + WindowEvent_Enter, ## Window has gained mouse focus + WindowEvent_Leave, ## Window has lost mouse focus + WindowEvent_FocusGained, ## Window has gained keyboard focus + WindowEvent_FocusLost, ## Window has lost keyboard focus + WindowEvent_Close, + WindowEvent_TakeFocus, + ## The window manager requests that the window be closed + WindowEvent_HitTest + ## Window had a hit test that wasn't `SDL_HITTEST_NORMAL`. EventType* {.size: sizeof(uint32).} = enum - QuitEvent = 0x100, AppTerminating, AppLowMemory, AppWillEnterBackground, - AppDidEnterBackground, AppWillEnterForeground, AppDidEnterForeground, - DisplayEvent = 0x150, - WindowEvent = 0x200, SysWMEvent, - KeyDown = 0x300, KeyUp, TextEditing, TextInput, KeymapChanged, - MouseMotion = 0x400, MouseButtonDown, MouseButtonUp, MouseWheel, - JoyAxisMotion = 0x600, JoyBallMotion, JoyHatMotion, JoyButtonDown, - JoyButtonUp, JoyDeviceAdded, JoyDeviceRemoved, - ControllerAxisMotion = 0x650, ControllerButtonDown, ControllerButtonUp, - ControllerDeviceAdded, ControllerDeviceRemoved, ControllerDeviceRemapped, - FingerDown = 0x700, FingerUp, FingerMotion, - DollarGesture = 0x800, DollarRecord, MultiGesture, - ClipboardUpdate = 0x900, - DropFile = 0x1000, DropText, DropBegin, DropComplete, - AudioDeviceAdded = 0x1100, AudioDeviceRemoved = 0x1101, - SensorUpdate = 0x1200, - RenderTargetsReset = 0x2000, RenderDeviceReset, - UserEvent = 0x8000, UserEvent1, UserEvent2, UserEvent3, UserEvent4, UserEvent5, - LastEvent = 0xFFFF, + ## The types of events that can be delivered. + + # Application events + QuitEvent = 0x100, ## User-requested quit + AppTerminating, + ## The application is being terminated by the OS + ## Called on iOS in `applicationWillTerminate()` + ## Called on Android in `onDestroy()` + AppLowMemory, + ## The application is low on memory, free memory if possible. + ## Called on iOS in `applicationDidReceiveMemoryWarning()` + ## Called on Android in `onLowMemory()` + AppWillEnterBackground, + ## The application is about to enter the background + ## Called on iOS in `applicationWillResignActive()` + ## Called on Android in `onPause()` + AppDidEnterBackground, + ## The application did enter the background + ## and may not get CPU for some time + ## Called on iOS in `applicationDidEnterBackground()` + ## Called on Android in `onPause()` + AppWillEnterForeground, + ## The application is about to enter the foreground + ## Called on iOS in `applicationWillEnterForeground()` + ## Called on Android in `onResume()` + AppDidEnterForeground, + ## The application is now interactive + ## Called on iOS in `applicationDidBecomeActive()` + ## Called on Android in `onResume()` + + # Display events + DisplayEvent = 0x150, ## Display state change + + # Window events + WindowEvent = 0x200, ## Window state change + SysWMEvent, ## System specific event + + # Keyboard events + KeyDown = 0x300, ## Key pressed + KeyUp, ## Key released + TextEditing, ## Keyboard text editing (composition) + TextInput, ## Keyboard text input + KeymapChanged, + ## Keymap changed due to a system event such as + ## an input language or keyboard layout change. + + # Mouse events + MouseMotion = 0x400, ## Mouse moved + MouseButtonDown, ## Mouse button pressed + MouseButtonUp, ## Mouse button released + MouseWheel, ## Mouse wheel motion + + # Joysticks events + JoyAxisMotion = 0x600, ## Joystick axis motion + JoyBallMotion, ## Joystick trackball motion + JoyHatMotion, ## Joystick hat position change + JoyButtonDown, ## Joystick button pressed + JoyButtonUp, ## Joystick button released + JoyDeviceAdded, ## A new joystick has been inserted into the system + JoyDeviceRemoved, ## An opened joystick has been removed + + # Game controller events + ControllerAxisMotion = 0x650, ## Game controller axis motion + ControllerButtonDown, ## Game controller button pressed + ControllerButtonUp, ## Game controller button released + ControllerDeviceAdded, ## A new Game controller has been inserted into the system + ControllerDeviceRemoved, ## An opened Game controller has been removed + ControllerDeviceRemapped, ## The controller mapping was updated + + # Touch events + FingerDown = 0x700, + FingerUp, + FingerMotion, + + # Gesture events + DollarGesture = 0x800, + DollarRecord, + MultiGesture, + + # Clipboard events + ClipboardUpdate = 0x900, ## The clipboard changed + + # Drag and drop events + DropFile = 0x1000, ## The system requests a file open + DropText, ## Text/plain drag-and-drop event + DropBegin, ## A new set of drops is beginning (`nil` filename) + DropComplete, ## Current set of drops is now complete (`nil` filename) + + # Audio hotplug events + AudioDeviceAdded = 0x1100, ## A new audio device is available + AudioDeviceRemoved = 0x1101, ## An audio device has been removed + + # Sensor events + SensorUpdate = 0x1200, ## A sensor was updated + + # Render events + RenderTargetsReset = 0x2000, + ## The render targets have been reset and their contents need to be updated + RenderDeviceReset, + ## The device has beed reset and all textures need to be recreated + UserEvent = 0x8000, + ## Events `USEREVENT` through `LASTEVENT` are for your use, + ## and should be allocated with `registerEvents()` + UserEvent1, + UserEvent2, + UserEvent3, + UserEvent4, + UserEvent5, + LastEvent = 0xFFFF, ## This last event is only for bounding internal arrays Event* = object - kind*: EventType + ## General event structure + kind*: EventType ## Event type, shared with all events padding: array[56-sizeof(EventType), byte] QuitEventPtr* = ptr QuitEventObj QuitEventObj* = object - kind*: EventType - timestamp*: uint32 + ## The "quit requested" event + kind*: EventType ## `QuitEvent` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + WindowEventPtr* = ptr WindowEventObj WindowEventObj* = object - kind*: EventType - timestamp*: uint32 - windowID*: uint32 - event*: WindowEventID + ## Window state change event data (`event.window.*`) + kind*: EventType ## `WindowEvent` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The associated window + event*: WindowEventID ## WindowEvent ID pad1,pad2,pad3: uint8 - data1*, data2*: cint + data1*, data2*: cint ## event dependent data pad*: array[56-24, byte] + KeyboardEventPtr* = ptr KeyboardEventObj KeyboardEventObj* = object - kind*: EventType - timestamp*: uint32 - windowID*: uint32 - state*: uint8 - repeat*: bool - keysym*: KeySym + ## Keyboard button event structure (`event.key.*`) + kind*: EventType ## `KEYDOWN` or `KEYUP` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The window with keyboard focus, if any + state*: uint8 ## `PRESSED` or `RELEASED` + repeat*: bool ## Non-zero if this is a key repeat + keysym*: KeySym ## The key that was pressed or released pad*: array[24, byte] + TextEditingEventPtr* = ptr TextEditingEventObj TextEditingEventObj* = object - kind*: EventType - timestamp*: uint32 - windowID*: uint32 - text*: array[SDL_TEXTEDITINGEVENT_TEXT_SIZE, char] - start*,length*: int32 + ## Keyboard text editing event structure (`event.edit.*`) + kind*: EventType ## `TEXTEDITING` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The window with keyboard focus, if any + text*: array[SDL_TEXTEDITINGEVENT_TEXT_SIZE, char] ## The editing text + start*: int32 ## The start cursor of selected editing text + length*: int32 ## The length of selected editing text pad*: array[8, byte] + TextInputEventPtr* = ptr TextInputEventObj TextInputEventObj* = object - kind*: EventType - timestamp*: uint32 - windowID*: uint32 - text*: array[SDL_TEXTINPUTEVENT_TEXT_SIZE,char] + ## Keyboard text input event structure (`event.text.*`) + kind*: EventType ## `TEXTINPUT` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The window with keyboard focus, if any + text*: array[SDL_TEXTINPUTEVENT_TEXT_SIZE, char] ## The input text pad*: array[24, byte] + MouseMotionEventPtr* = ptr MouseMotionEventObj - MouseMotionEventObj* = object - kind*: EventType - timestamp*,windowID*: uint32 - which*: uint32 - state*: uint32 - x*,y*, xrel*,yrel*: int32 + MouseMotionEventObj* = object + ## Mouse motion event structure (`event.motion.*`) + kind*: EventType ## `MOUSEMOTION` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The window with mouse focus, if any + which*: uint32 ## The mouse instance id, or `SDL_TOUCH_MOUSEID` + state*: uint32 ## The current button state + x*: int32 ## X coordinate, relative to window + y*: int32 ## Y coordinate, relative to window + xrel*: int32 ## The relative motion in the X direction + yrel*: int32 ## The relative motion in the Y direction pad*: array[20, byte] + MouseButtonEventPtr* = ptr MouseButtonEventObj MouseButtonEventObj* = object - kind*: EventType - timestamp*,windowID*: uint32 - which*: uint32 - button*: uint8 - state*: uint8 - clicks*: uint8 - x*,y*: cint + ## Mouse button event structure (`event.button.*`) + kind*: EventType ## `MOUSEBUTTONDOWN` or `MOUSEBUTTONUP` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The window with mouse focus, if any + which*: uint32 ## The mouse instance id, or `SDL_TOUCH_MOUSEID` + button*: uint8 ## The mouse button index + state*: uint8 ## `PRESSED` or `RELEASED` + clicks*: uint8 ## `1` for single-click, `2` for double-click, etc. + x*: cint ## X coordinate, relative to window + y*: cint ## Y coordinate, relative to window pad*: array[28, byte] + MouseWheelEventPtr* = ptr MouseWheelEventObj MouseWheelEventObj* = object - kind*: EventType - timestamp*,windowID*: uint32 - which*: uint32 - x*,y*: cint + ## Mouse wheel event structure (`event.wheel.*`) + kind*: EventType ## `MOUSEWHEEL` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The window with mouse focus, if any + which*: uint32 ## The mouse instance id, or `SDL_TOUCH_MOUSEID` + x*: cint + ## The amount scrolled horizontally, + ## positive to the right and negative to the left + y*: cint + ## The amount scrolled vertically, + ## positive away from the user and negative toward the user direction*: MouseWheelDirection + ## Set to one of the `SDL_MOUSEWHEEL_*`. + ## When `SDL_MOUSEWHEEL_FLIPPED` the values in X and Y will be opposite. + ## Multiply by `-1` to change them back. pad*: array[28, byte] + JoyAxisEventPtr* = ptr JoyAxisEventObj JoyAxisEventObj* = object - kind*: EventType - timestamp*: uint32 - which*: int32 - axis*: uint8 + ## Joystick axis motion event structure (`event.jaxis.*`) + kind*: EventType ## `JOYAXISMOTION` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + which*: int32 ## The joystick instance id + axis*: uint8 ## The joystick axis index pad1,pad2,pad3: uint8 - value*: int16 + value*: int16 ## The axis value (range: `-32768` to `32767`) + JoyBallEventPtr* = ptr JoyBallEventObj JoyBallEventObj* = object - kind*: EventType - timestamp*: uint32 - which*: int32 - ball*, pad1,pad2,pad3: uint8 - xrel*,yrel*: int16 + ## Joystick trackball motion event structure (`event.jball.*`) + kind*: EventType ## `JOYBALLMOTION` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + which*: int32 ## The joystick instance id + ball*: uint8 ## The joystick trackball index + pad1,pad2,pad3: uint8 + xrel*: int16 ## The relative motion in the X direction + yrel*: int16 ## The relative motion in the Y direction + JoyHatEventPtr* = ptr JoyHatEventObj JoyHatEventObj* = object - kind*: EventType - timestamp*: uint32 - which*: int32 - hat*,value*: uint8 + ## Joystick hat position change event structure (`event.jhat.*`) + kind*: EventType ## `JOYHATMOTION` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + which*: int32 ## The joystick instance id + hat*: uint8 ## The joystick hat index + value*: uint8 + ## The hat position value (`joystick.SDL_HAT_*` consts) + ## Note that zero means the POV is centered. + JoyButtonEventPtr* = ptr JoyButtonEventObj JoyButtonEventObj* = object - kind*: EventType - timestamp*: uint32 - which*: int32 - button*,state*: uint8 + ## Joystick button event structure (`event.jbutton.*`) + kind*: EventType ## `JOYBUTTONDOWN` or `JOYBUTTONUP` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + which*: int32 ## The joystick instance id + button*: uint8 ## The joystick button index + state*: uint8 ## `PRESSED` or `RELEASED` + JoyDeviceEventPtr* = ptr JoyDeviceEventObj JoyDeviceEventObj* = object - kind*: EventType - timestamp*: uint32 + ## Joystick device event structure (`event.jdevice.*`) + kind*: EventType ## `JOYDEVICEADDED` or `JOYDEVICEREMOVED` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` which*: int32 + ## The joystick device index for the `ADDED` event, + ## instance id for the `REMOVED` event + ControllerAxisEventPtr* = ptr ControllerAxisEventObj ControllerAxisEventObj* = object - kind*: EventType - timestamp*: uint32 - which*: int32 - axis*, pad1,pad2,pad3: uint8 - value*: int16 + ## Game controller axis motion event structure (`event.caxis.*`) + kind*: EventType ## `CONTROLLERAXISMOTION` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + which*: int32 ## The joystick instance id + axis*: uint8 ## The controller axis (`GameControllerAxis`) + pad1,pad2,pad3: uint8 + value*: int16 ## The axis value + ControllerButtonEventPtr* = ptr ControllerButtonEventObj ControllerButtonEventObj* = object - kind*: EventType - timestamp*: uint32 - which*: int32 - button*,state*: uint8 + ## Game controller button event structure (`event.cbutton.*`) + kind*: EventType ## `CONTROLLERBUTTONDOWN` or `CONTROLLERBUTTONUP` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + which*: int32 ## The joystick instance id + button*: uint8 ## The controller button (`GameControllerButton`) + state*: uint8 ## `PRESSED` or `RELEASED` + ControllerDeviceEventPtr* = ptr ControllerDeviceEventObj ControllerDeviceEventObj* = object + ## Controller device event structure (`event.cdevice.*`) kind*: EventType - timestamp*: uint32 + ## `CONTROLLERDEVICEADDED`, + ## `CONTROLLERDEVICEREMOVED` or + ## `CONTROLLERDEVICEREMAPPED` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` which*: int32 + ## The joystick device index for the `ADDED` event, + ## instance id for the `REMOVED` or `REMAPPED` event TouchID* = int64 FingerID* = int64 TouchFingerEventPtr* = ptr TouchFingerEventObj TouchFingerEventObj* = object - kind*: EventType - timestamp*: uint32 - touchID*: TouchID - fingerID*: FingerID - x*,y*,dx*,dy*,pressure*: cfloat + ## Touch finger event structure (`event.tfinger.*`) + kind*: EventType ## `FINGERMOTION` or `FINGERDOWN` or `FINGERUP` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + touchID*: TouchID ## The touch device id + fingerID*: FingerID ## Normalized in the range 0...1 + x*: cfloat ## Normalized in the range 0..1 + y*: cfloat ## Normalized in the range 0..1 + dx*: cfloat ## Normalized in the range -1..1 + dy*: cfloat ## Normalized in the range -1..1 + pressure*: cfloat ## Normalized in the range 0..1 pad*: array[24, byte] + MultiGestureEventPtr* = ptr MultiGestureEventObj MultiGestureEventObj* = object - kind*: EventType - timestamp*: uint32 - touchID*: TouchID - dTheta*,dDist*,x*,y*: cfloat + ## Multiple Finger Gesture Event (`event.mgesture.*`) + kind*: EventType ## `MULTIGESTURE` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + touchID*: TouchID ## The touch device index + dTheta*, dDist*, x*, y*: cfloat numFingers*: uint16 Finger* = object @@ -206,46 +386,72 @@ type GestureID = int64 DollarGestureEventPtr* = ptr DollarGestureEventObj DollarGestureEventObj* = object - kind*: EventType - timestamp*: uint32 - touchID*: TouchID - gestureID*: GestureID - numFingers*: uint32 - error*, x*, y*: float + ## Dollar Gesture Event (`event.dgesture.*`) + kind*: EventType ## `DOLLARGESTURE` or `DOLLARRECORD` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + touchID*: TouchID ## The touch device id + gestureID*: GestureID + numFingers*: uint32 + error*: cfloat + x*: cfloat ## Normalized center of gesture + y*: cfloat ## Normalized center of gesture + DropEventPtr* = ptr DropEventObj DropEventObj* = object - kind*: EventType - timestamp*: uint32 - file*: cstring + ## An event used to request a file open by the system (`event.drop.*`) + ## This event is enabled by default, you can disable it with `eventState()` + ## + ## **Note:** If this event is enabled, you must free the filename in the event. + kind*: EventType ## `DROPBEGIN`, `DROPFILE`, `DROPTEXT` or `DROPCOMPLETE` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + file*: cstring ## The file name, which should be freed with `free()` + UserEventPtr* = ptr UserEventObj UserEventObj* = object - kind*: EventType - timestamp*,windowID*: uint32 - code*: int32 - data1*,data2*: pointer + ## A user-defined event type (`event.user.*`) + kind*: EventType ## `USEREVENT` through `LASTEVENT-1` + timestamp*: uint32 ## In milliseconds, populated using `getTicks()` + windowID*: uint32 ## The associated window if any + code*: int32 ## User defined event code + data1*: pointer ## User defined data pointer + data2*: pointer ## User defined data pointer Eventaction* {.size: sizeof(cint).} = enum SDL_ADDEVENT, SDL_PEEKEVENT, SDL_GETEVENT EventFilter* = proc (userdata: pointer; event: ptr Event): Bool32 {.cdecl.} - SDL_Return* {.size: sizeof(cint).} = enum SdlError = -1, SdlSuccess = 0 ##\ - ## Return value for many SDL functions. Any function that returns like this \ - ## should also be discardable - Bool32* {.size: sizeof(cint).} = enum False32 = 0, True32 = 1 ##\ - ## SDL_bool + SDL_Return* {.size: sizeof(cint).} = enum + ## Return value for many SDL functions. + ## Any function that returns like this should also be discardable + SdlError = -1, SdlSuccess = 0 + + Bool32* {.size: sizeof(cint).} = enum ## SDL_bool + False32 = 0, True32 = 1 + KeyState* {.size: sizeof(byte).} = enum KeyReleased = 0, KeyPressed KeySym* {.pure.} = object - scancode*: ScanCode - sym*: cint ##Keycode - modstate*: int16 + ## The SDL keysym object, used in key events. + ## + ## **Note:** If you are looking for translated character input, + ## see the `TextInput` event. + scancode*: ScanCode ## SDL physical key code - see `ScanCode` for details + sym*: cint ## SDL virtual key code - see `Keycode` for details + modstate*: int16 ## current key modifiers unicode*: cint - Point* = tuple[x, y: cint] - Rect* = tuple[x, y: cint, w, h: cint] + Point* = tuple + ## A 2D point + x, y: cint + + Rect* = tuple + ## A rectangle with the origin at the upper left + x, y: cint + w, h: cint GLattr*{.size: sizeof(cint).} = enum + ## OpenGL configuration attributes SDL_GL_RED_SIZE, SDL_GL_GREEN_SIZE, SDL_GL_BLUE_SIZE, @@ -275,8 +481,9 @@ type SDL_GL_CONTEXT_NO_ERROR MouseWheelDirection* {.size: sizeof(uint32).} = enum - SDL_MOUSEWHEEL_NORMAL, - SDL_MOUSEWHEEL_FLIPPED + ## Scroll direction types for the Scroll event + SDL_MOUSEWHEEL_NORMAL, ## The scroll direction is normal + SDL_MOUSEWHEEL_FLIPPED ## The scroll direction is flipped / natural const # GLprofile enum. @@ -296,33 +503,64 @@ const type DisplayMode* = object - format*: cuint - w*,h*,refresh_rate*: cint - driverData*: pointer - - WindowPtr* = ptr object + ## The object that defines a display mode + ## + ## **See also:** + ## * `getNumDisplayModes proc<#getNumDisplayModes,cint>`_ + ## * `getDisplayMode proc<#getDisplayMode,WindowPtr,DisplayMode>`_ + ## * `getDesktopDisplayMode proc<#getDesktopDisplayMode,cint,DisplayMode>`_ + ## * `getCurrentDisplayMode proc<#getCurrentDisplayMode,cint,DisplayMode>`_ + ## * `getClosestDisplayMode proc<#getClosestDisplayMode,cint,ptr.DisplayMode,ptr.DisplayMode>`_ + + format*: cuint ## pixel format + w*: cint ## width, in screen coordinates + h*: cint ## height, in screen coordinates + refresh_rate*: cint ## refresh rate (or zero for unspecified) + driverData*: pointer ## driver-specific data, initialize to 0 + + WindowPtr* = ptr object ## The type used to identify a window RendererPtr* = ptr object TexturePtr* = ptr object CursorPtr* = ptr object - GlContextPtr* = ptr object + GlContextPtr* = ptr object ## An opaque handle to an OpenGL context. SDL_Version* = object + ## Information about the version of SDL in use. + ## + ## Represents the library's version as three levels: major revision + ## (increments with massive changes, additions, and enhancements), + ## minor revision (increments with backwards-compatible changes to the + ## major revision), and patchlevel (increments with fixes to the minor + ## revision). + ## + ## **See also:** + ## * `getVersion proc<#getVersion,SDL_Version>`_ + major*, minor*, patch*: uint8 RendererInfoPtr* = ptr RendererInfo RendererInfo* {.pure, final.} = object - name*: cstring #*< The name of the renderer - flags*: uint32 #*< Supported ::SDL_RendererFlags - num_texture_formats*: uint32 #*< The number of available texture formats - texture_formats*: array[0..16 - 1, uint32] #*< The available texture formats - max_texture_width*: cint #*< The maximimum texture width - max_texture_height*: cint #*< The maximimum texture height + ## Information on the capabilities of a render driver or context + name*: cstring ## The name of the renderer + flags*: uint32 ## Supported `RendererFlags` + num_texture_formats*: uint32 ## The number of available texture formats + texture_formats*: array[0..16 - 1, uint32] ## The available texture formats + max_texture_width*: cint ## The maximimum texture width + max_texture_height*: cint ## The maximimum texture height TextureAccess* {.size: sizeof(cint).} = enum - SDL_TEXTUREACCESS_STATIC, SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_TARGET + ## The access pattern allowed for a texture + SDL_TEXTUREACCESS_STATIC, ## Changes rarely, not lockable + SDL_TEXTUREACCESS_STREAMING, ## Changes frequently, lockable + SDL_TEXTUREACCESS_TARGET ## Texture can be used as a render target + TextureModulate*{.size:sizeof(cint).} = enum - SDL_TEXTUREMODULATE_NONE, SDL_TEXTUREMODULATE_COLOR, SDL_TEXTUREMODULATE_ALPHA + ## The texture channel modulation used in `copy proc<#copy,RendererPtr,TexturPtr,ptr.Rect,ptr.Rect>`_ + SDL_TEXTUREMODULATE_NONE, ## No modulation + SDL_TEXTUREMODULATE_COLOR, ## srcC = srcC * color + SDL_TEXTUREMODULATE_ALPHA ## srcA = srcA * alpha + RendererFlip* = cint SysWMType* {.size: sizeof(cint).}=enum SysWM_Unknown, SysWM_Windows, SysWM_X11, SysWM_DirectFB, @@ -330,41 +568,45 @@ type WMinfo* = object version*: SDL_Version subsystem*: SysWMType - padding*: array[64, byte] ## if the low-level stuff is important to you check \ + padding*: array[64, byte] + ## if the low-level stuff is important to you check ## SDL_syswm.h and cast padding to the right type -const ## WindowFlags - SDL_WINDOW_FULLSCREEN*:cuint = 0x00000001# /**< fullscreen window */ - SDL_WINDOW_OPENGL*:cuint = 0x00000002# /**< window usable with OpenGL context */ - SDL_WINDOW_SHOWN*:cuint = 0x00000004# /**< window is visible */ - SDL_WINDOW_HIDDEN*:cuint = 0x00000008# /**< window is not visible */ - SDL_WINDOW_BORDERLESS*:cuint = 0x00000010# /**< no window decoration */ - SDL_WINDOW_RESIZABLE*:cuint = 0x00000020# /**< window can be resized */ - SDL_WINDOW_MINIMIZED*:cuint = 0x00000040# /**< window is minimized */ - SDL_WINDOW_MAXIMIZED*:cuint = 0x00000080# /**< window is maximized */ - SDL_WINDOW_INPUT_GRABBED*:cuint = 0x00000100# /**< window has grabbed input focus */ - SDL_WINDOW_INPUT_FOCUS*:cuint = 0x00000200# /**< window has input focus */ - SDL_WINDOW_MOUSE_FOCUS*:cuint = 0x00000400# /**< window has mouse focus */ - SDL_WINDOW_FULLSCREEN_DESKTOP*:cuint = ( SDL_WINDOW_FULLSCREEN or 0x00001000 ) - SDL_WINDOW_FOREIGN*:cuint = 0x00000800# /**< window not created by SDL */ - SDL_WINDOW_ALLOW_HIGHDPI*:cuint = 0x00002000# /**< window should be created in high-DPI mode if supported */ - SDL_WINDOW_MOUSE_CAPTURE*:cuint = 0x00004000# /**< window has mouse captured (unrelated to INPUT_GRABBED) */ - SDL_WINDOW_VULKAN*:cuint = 0x10000000# /**< window usable for Vulkan surface */ - SDL_FLIP_NONE*: cint = 0x00000000 # Do not flip - SDL_FLIP_HORIZONTAL*: cint = 0x00000001 # flip horizontally - SDL_FLIP_VERTICAL*: cint = 0x00000002 # flip vertically +const # WindowFlags + SDL_WINDOW_FULLSCREEN*: cuint = 0x00000001 ## fullscreen window + SDL_WINDOW_OPENGL*: cuint = 0x00000002 ## window usable with OpenGL context + SDL_WINDOW_SHOWN*: cuint = 0x00000004 ## window is visible + SDL_WINDOW_HIDDEN*: cuint = 0x00000008 ## window is not visible + SDL_WINDOW_BORDERLESS*: cuint = 0x00000010 ## no window decoration + SDL_WINDOW_RESIZABLE*: cuint = 0x00000020 ## window can be resized + SDL_WINDOW_MINIMIZED*: cuint = 0x00000040 ## window is minimized + SDL_WINDOW_MAXIMIZED*: cuint = 0x00000080 ## window is maximized + SDL_WINDOW_INPUT_GRABBED*: cuint = 0x00000100 ## window has grabbed input focus + SDL_WINDOW_INPUT_FOCUS*: cuint = 0x00000200 ## window has input focus + SDL_WINDOW_MOUSE_FOCUS*: cuint = 0x00000400 ## window has mouse focus + SDL_WINDOW_FULLSCREEN_DESKTOP*: cuint = ( SDL_WINDOW_FULLSCREEN or 0x00001000 ) + SDL_WINDOW_FOREIGN*: cuint = 0x00000800 ## window not created by SDL + SDL_WINDOW_ALLOW_HIGHDPI*: cuint = 0x00002000 + ## window should be created in high-DPI mode if supported + ## On macOS `NSHighResolutionCapable` must be set true + ## in the application's `Info.plist` for this to have any effect. + SDL_WINDOW_MOUSE_CAPTURE*: cuint = 0x00004000 + ## window has mouse captured (unrelated to INPUT_GRABBED) + SDL_WINDOW_VULKAN*: cuint = 0x10000000 ## window usable for Vulkan surface + SDL_FLIP_NONE*: cint = 0x00000000 ## Do not flip + SDL_FLIP_HORIZONTAL*: cint = 0x00000001 ## flip horizontally + SDL_FLIP_VERTICAL*: cint = 0x00000002 ## flip vertically converter toBool*(some: Bool32): bool = bool(some) converter toBool*(some: SDL_Return): bool = some == SdlSuccess converter toCint*(some: TextureAccess): cint = some.cint -## pixel format flags +# pixel format flags const SDL_ALPHA_OPAQUE* = 255 SDL_ALPHA_TRANSPARENT* = 0 -# @} -#* Pixel type. + const SDL_PIXELTYPE_UNKNOWN* = 0 SDL_PIXELTYPE_INDEX1* = 1 @@ -378,12 +620,12 @@ const SDL_PIXELTYPE_ARRAYU32* = 9 SDL_PIXELTYPE_ARRAYF16* = 10 SDL_PIXELTYPE_ARRAYF32* = 11 -#* Bitmap pixel order, high bit -> low bit. +# Bitmap pixel order, high bit -> low bit. const SDL_BITMAPORDER_NONE* = 0 SDL_BITMAPORDER_4321* = 1 SDL_BITMAPORDER_1234* = 2 -#* Packed component order, high bit -> low bit. +# Packed component order, high bit -> low bit. const SDL_PACKEDORDER_NONE* = 0 SDL_PACKEDORDER_XRGB* = 1 @@ -394,7 +636,7 @@ const SDL_PACKEDORDER_BGRX* = 6 SDL_PACKEDORDER_ABGR* = 7 SDL_PACKEDORDER_BGRA* = 8 -#* Array component order, low byte -> high byte. +# Array component order, low byte -> high byte. const SDL_ARRAYORDER_NONE* = 0 SDL_ARRAYORDER_RGB* = 1 @@ -403,7 +645,7 @@ const SDL_ARRAYORDER_BGR* = 4 SDL_ARRAYORDER_BGRA* = 5 SDL_ARRAYORDER_ABGR* = 6 -#* Packed component layout. +# Packed component layout. const SDL_PACKEDLAYOUT_NONE* = 0 SDL_PACKEDLAYOUT_332* = 1 @@ -415,12 +657,6 @@ const SDL_PACKEDLAYOUT_2101010* = 7 SDL_PACKEDLAYOUT_1010102* = 8 -# /* Define a four character code as a Uint32 */ -# #define SDL_FOURCC(A, B, C, D) \ -# ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \ -# (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \ -# (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \ -# (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24)) template SDL_FOURCC (a,b,c,d: uint8): uint32 = uint32(a) or (uint32(b) shl 8) or (uint32(c) shl 16) or (uint32(d) shl 24) @@ -533,18 +769,23 @@ const SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_2101010, 32, 4) SDL_PIXELFORMAT_YV12* = SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2') #*< Planar mode: Y + V + U (3 planes) + ## Planar mode: Y + V + U (3 planes) SDL_PIXELFORMAT_IYUV* = SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V') #*< Planar mode: Y + U + V (3 planes) + ## Planar mode: Y + U + V (3 planes) SDL_PIXELFORMAT_YUY2* = SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2') #*< Packed mode: Y0+U0+Y1+V0 (1 plane) + ## Packed mode: Y0+U0+Y1+V0 (1 plane) SDL_PIXELFORMAT_UYVY* = SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y') #*< Packed mode: U0+Y0+V0+Y1 (1 plane) + ## Packed mode: U0+Y0+V0+Y1 (1 plane) SDL_PIXELFORMAT_YVYU* = SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U') #*< Packed mode: Y0+V0+Y1+U0 (1 plane) + ## Packed mode: Y0+V0+Y1+U0 (1 plane) type - Color* {.pure, final.} = tuple[ - r: uint8, - g: uint8, - b: uint8, - a: uint8] + Color* {.pure, final.} = tuple + r: uint8 + g: uint8 + b: uint8 + a: uint8 Palette* {.pure, final.} = object ncolors*: cint @@ -553,6 +794,7 @@ type refcount*: cint PixelFormat* {.pure, final.} = object + ## **Note:** Everything in the pixel format object is read-only. format*: uint32 palette*: ptr Palette BitsPerPixel*: uint8 @@ -573,45 +815,80 @@ type refcount*: cint next*: ptr PixelFormat - BlitMapPtr* = ptr object{.pure.} ##couldnt find SDL_BlitMap ? + BlitMapPtr* {.pure.} = ptr object ## couldnt find SDL_BlitMap ? SurfacePtr* = ptr Surface Surface* {.pure, final.} = object - flags*: uint32 #*< Read-only - format*: ptr PixelFormat #*< Read-only - w*, h*, pitch*: int32 #*< Read-only - pixels*: pointer #*< Read-write - userdata*: pointer #*< Read-write - locked*: int32 #*< Read-only ## see if this should be Bool32 - lock_data*: pointer #*< Read-only - clip_rect*: Rect #*< Read-only - map: BlitMapPtr #*< Private - refcount*: cint #*< Read-mostly + ## A collection of pixels used in software blitting. + ## + ## **Note:** This object should be treated as read-only, except for + ## `pixels`, which, if not `nil`, contains the raw pixel data + ## for the surface. + flags*: uint32 ## Read-only + format*: ptr PixelFormat ## Read-only + w*, h*, pitch*: int32 ## Read-only + pixels*: pointer ## Read-write + userdata*: pointer ## Application data associated with the surface. Read-write + locked*: int32 ## Read-only ## see if this should be Bool32 + lock_data*: pointer ## Read-only + clip_rect*: Rect ## clipping information. Read-only + map: BlitMapPtr + ## info for fast blit mapping to other surfaces. Private + refcount*: cint + ## Reference count, used when freeing surface. Read-mostly BlendMode* {.size: sizeof(cint).} = enum - BlendMode_None = 0x00000000, #*< No blending - BlendMode_Blend = 0x00000001, #*< dst = (src * A) + (dst * (1-A)) - BlendMode_Add = 0x00000002, #*< dst = (src * A) + dst - BlendMode_Mod = 0x00000004 #*< dst = src * dst - BlitFunction* = proc(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; - dstrect: ptr Rect): cint{.cdecl.} + ## The blend mode used in `copy proc<#copy,RendererPtr,TexturPtr,ptr.Rect,ptr.Rect>`_ and drawing operations. + BlendMode_None = 0x00000000, + ## no blending + ## dstRGBA = srcRGBA + BlendMode_Blend = 0x00000001, + ## alpha blending + ## dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA)) + ## dstA = srcA + (dstA * (1-srcA)) + BlendMode_Add = 0x00000002, + ## additive blending + ## dstRGB = (srcRGB * srcA) + dstRGB + ## dstA = dstA + BlendMode_Mod = 0x00000004 + ## color modulate + ## dstRGB = srcRGB * dstRGB + ## dstA = dstA + + BlitFunction* = proc(src: SurfacePtr; srcrect: ptr Rect; + dst: SurfacePtr; dstrect: ptr Rect): cint{.cdecl.} + ## The type of procedure used for surface blitting procedures. TimerCallback* = proc (interval: uint32; param: pointer): uint32{.cdecl.} + ## Procedure prototype for the timer callback procedure. + ## + ## The callback procedure is passed the current timer interval and returns + ## the next timer interval. If the returned value is the same as the one + ## passed in, the periodic alarm continues, otherwise a new alarm is + ## scheduled. If the callback returns `0`, the periodic alarm is + ## cancelled. + TimerID* = cint -const ##RendererFlags +const ## RendererFlags Renderer_Software*: cint = 0x00000001 + ## The renderer is a software fallback Renderer_Accelerated*: cint = 0x00000002 + ## The renderer uses hardware acceleration Renderer_PresentVsync*: cint = 0x00000004 + ## Present is synchronized with the refresh rate Renderer_TargetTexture*: cint = 0x00000008 + ## Ther render supports rendering to texture -const ## These are the currently supported flags for the ::SDL_surface. - SDL_SWSURFACE* = 0 #*< Just here for compatibility - SDL_PREALLOC* = 0x00000001 #*< Surface uses preallocated memory - SDL_RLEACCEL* = 0x00000002 #*< Surface is RLE encoded - SDL_DONTFREE* = 0x00000004 #*< Surface is referenced internally +const ## These are the currently supported flags for the `Surface`. + SDL_SWSURFACE* = 0 ## Just here for compatibility + SDL_PREALLOC* = 0x00000001 ## Surface uses preallocated memory + SDL_RLEACCEL* = 0x00000002 ## Surface is RLE encoded + SDL_DONTFREE* = 0x00000004 ## Surface is referenced internally -template SDL_MUSTLOCK*(some: SurfacePtr): bool = (some.flags and SDL_RLEACCEL) != 0 +template SDL_MUSTLOCK*(some: SurfacePtr): bool = + ## Checks if the surface needs to be locked before access. + (some.flags and SDL_RLEACCEL) != 0 @@ -627,20 +904,27 @@ const INIT_EVERYTHING* = 0x0000FFFF const SDL_WINDOWPOS_UNDEFINED_MASK* = 0x1FFF0000 -template SDL_WINDOWPOS_UNDEFINED_DISPLAY*(X: cint): untyped = cint(SDL_WINDOWPOS_UNDEFINED_MASK or X) + +template SDL_WINDOWPOS_UNDEFINED_DISPLAY*(X: cint): untyped = + ## Used to indicate that you don't care what the window position is. + cint(SDL_WINDOWPOS_UNDEFINED_MASK or X) + const SDL_WINDOWPOS_UNDEFINED*: cint = SDL_WINDOWPOS_UNDEFINED_DISPLAY(0) template SDL_WINDOWPOS_ISUNDEFINED*(X: cint): bool = (((X) and 0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK) const SDL_WINDOWPOS_CENTERED_MASK* = 0x2FFF0000 -template SDL_WINDOWPOS_CENTERED_DISPLAY*(X: cint): cint = cint(SDL_WINDOWPOS_CENTERED_MASK or X) +template SDL_WINDOWPOS_CENTERED_DISPLAY*(X: cint): cint = + ## Used to indicate that the window position should be centered. + cint(SDL_WINDOWPOS_CENTERED_MASK or X) + const SDL_WINDOWPOS_CENTERED*: cint = SDL_WINDOWPOS_CENTERED_DISPLAY(0) template SDL_WINDOWPOS_ISCENTERED*(X: cint): bool = (((X) and 0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK) template evConv(name, name2, ptype: untyped; valid: openarray[EventType]): untyped = - proc `name`* (event: Event): ptype = + proc `name`*(event: Event): ptype = assert event.kind in valid return cast[ptype](unsafeAddr event) - proc `name2`* (event: Event): ptype = + proc `name2`*(event: Event): ptype = assert event.kind in valid return cast[ptype](unsafeAddr event) @@ -674,16 +958,19 @@ evConv(evUser, user, UserEventPtr, [UserEvent, UserEvent1, UserEvent2, UserEvent #evConv(EvSysWM, syswm, SysWMEventPtr, {SysWMEvent}) const ## SDL_MessageBox flags. If supported will display warning icon, etc. - SDL_MESSAGEBOX_ERROR* = 0x00000010 #*< error dialog - SDL_MESSAGEBOX_WARNING* = 0x00000020 #*< warning dialog - SDL_MESSAGEBOX_INFORMATION* = 0x00000040 #*< informational dialog + SDL_MESSAGEBOX_ERROR* = 0x00000010 ## error dialog + SDL_MESSAGEBOX_WARNING* = 0x00000020 ## warning dialog + SDL_MESSAGEBOX_INFORMATION* = 0x00000040 ## informational dialog - ## Flags for SDL_MessageBoxButtonData. - SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT* = 0x00000001 #*< Marks the default button when return is hit - SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT* = 0x00000002 #*< Marks the default button when escape is hit + # Flags for SDL_MessageBoxButtonData. + SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT* = 0x00000001 + ## Marks the default button when return is hit + SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT* = 0x00000002 + ## Marks the default button when escape is hit type MessageBoxColor* {.pure, final.} = object + ## RGB value used in a message box color scheme r*: uint8 g*: uint8 b*: uint8 @@ -694,39 +981,73 @@ type SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, SDL_MESSAGEBOX_COLOR_MAX MessageBoxColorScheme* {.pure, final.} = object + ## A set of colors to use for message box dialogs colors*: array[MessageBoxColorType, MessageBoxColor] MessageBoxButtonData* {.pure, final.} = object - flags*: cint #*< ::SDL_MessageBoxButtonFlags - buttonid*: cint #*< User defined button id (value returned via SDL_MessageBox) - text*: cstring #*< The UTF-8 button text + ## Individual button data + flags*: cint ## MessageBoxButtonFlags + buttonid*: cint + ## User defined button id (value returned via SDL_MessageBox) + text*: cstring ## The UTF-8 button text MessageBoxData* {.pure, final.} = object - flags*: cint #*< ::SDL_MessageBoxFlags - window*: WindowPtr #*< Parent window, can be NULL - title*, message*: cstring #*< UTF-8 title and message text + flags*: cint ## SDL_MessageBoxFlags + window*: WindowPtr ## Parent window, can be `nil` + title*: cstring ## UTF-8 title + message*: cstring ## UTF-8 message text numbuttons*: cint buttons*: ptr MessageBoxButtonData - colorScheme*: ptr MessageBoxColorScheme #*< ::SDL_MessageBoxColorScheme, can be NULL to use system settings + colorScheme*: ptr MessageBoxColorScheme + ## SDL_MessageBoxColorScheme, can be `nil` to use system settings RWopsPtr* = ptr RWops RWops* {.pure, final.} = object + ## This is the read/write operation structure -- very basic. size*: proc (context: RWopsPtr): int64 {.cdecl, tags: [], raises: [].} - seek*: proc (context: RWopsPtr; offset: int64; whence: cint): int64 {.cdecl, tags: [], raises: [].} - read*: proc (context: RWopsPtr; destination: pointer; size, maxnum: csize): csize {.cdecl, tags: [ReadIOEffect], raises: [].} + ## `Return` the size of the file in this rwops, or `-1` if unknown + seek*: proc (context: RWopsPtr; offset: int64; + whence: cint): int64 {.cdecl, tags: [], raises: [].} + ## Seek to `offset` relative to `whence`, + ## one of stdio's whence values: + ## `RW_SEEK_SET`, `RW_SEEK_CUR`, `RW_SEEK_END` + ## + ## `Return` the final offset in the data stream, or `-1` on error. + # TODO: Add the forementioned consts + + read*: proc (context: RWopsPtr; destination: pointer; + size, maxnum: csize): csize {. + cdecl, tags: [ReadIOEffect], raises: [].} + ## Read up to `maxnum` objects each of size `size` from the data + ## stream to the area pointed at by `p`. + ## + ## `Return` the number of objects read, or `0` at error or end of file. + write*: proc (context: RWopsPtr; source: pointer; size: csize; num: csize): csize {.cdecl, tags: [WriteIOEffect], raises: [].} + ## Write exactly `num` objects each of size `size` from the area + ## pointed at by `p` to data stream. + ## + ## `Return` the number of objects written, + ## or `0` at error or end of file. + close*: proc (context: RWopsPtr): cint {.cdecl, tags: [WriteIOEffect].} + ## Close and free an allocated RWops object. + ## + ## `Return` `0` if successful, + ## or `-1` on write error when flushing data. + kind*: cint mem*: Mem + Mem*{.final.} = object base*: ptr byte here*: ptr byte stop*: ptr byte # SDL_system.h -type VoidCallback* = proc(arg:pointer):void{.cdecl.} +type VoidCallback* = proc(arg: pointer): void {.cdecl.} const SDL_ANDROID_EXTERNAL_STORAGE_READ* = cint(0x01) const SDL_ANDROID_EXTERNAL_STORAGE_WRITE* = cint(0x02) @@ -734,290 +1055,1086 @@ when not defined(SDL_Static): {.push callConv: cdecl, dynlib: LibName.} -## functions whose names have been shortened by elision of a type name +# functions whose names have been shortened by elision of a type name proc getWMInfo*(window: WindowPtr; info: var WMInfo): Bool32 {. importc: "SDL_GetWindowWMInfo".} proc setLogicalSize*(renderer: RendererPtr; w, h: cint): cint {. importc: "SDL_RenderSetLogicalSize".} + ## Set device independent resolution for rendering. + ## + ## `renderer` The renderer for which resolution should be set. + ## + ## `w` The width of the logical resolution + ## + ## `h` The height of the logical resolution + ## + ## This procedure uses the viewport and scaling functionality to allow a + ## fixed logical resolution for rendering, regardless of the actual output + ## resolution. If the actual output resolution doesn't have the same aspect + ## ratio the output rendering will be centered within the output display. + ## + ## If the output display is a window, mouse events in the window will be + ## filtered and scaled so they seem to arrive within the logical resolution. + ## + ## **Note:** If this procedure results in scaling or subpixel drawing by the + ## rendering backend, it will be handled using the appropriate quality hints. + ## + ## `Return` `0` on success or a negative error code on failure. + ## + ## **See also:** + ## * `getLogicalSize proc<#getLogicalSize,RendererPtr,cint,cint>`_ + ## * `setScale proc<#setScale,RendererPtr,cfloat,cfloat>`_ + ## * `setViewport proc<#setViewport,RendererPtr,ptr.Rect>`_ + proc getLogicalSize*(renderer: RendererPtr; w, h: var cint) {. importc: "SDL_RenderGetLogicalSize".} - - -proc setDrawColor*(renderer: RendererPtr; r, g, b: uint8, a = 255'u8): SDL_Return {. - importc: "SDL_SetRenderDrawColor", discardable.} + ## Get device independent resolution for rendering. + ## + ## `renderer` The renderer from which resolution should be queried. + ## + ## `w` A pointer filled with the width of the logical resolution. + ## + ## `h` A pointer filled with the height of the logical resolution. + ## + ## **See also:** + ## * `setLogicalSize proc<#setLogicalSize,RendererPtr,cint,cint>`_ + + +proc setDrawColor*(renderer: RendererPtr; r, g, b: uint8, a = 255'u8): + SDL_Return {.importc: "SDL_SetRenderDrawColor", discardable.} + ## Set the color used for drawing operations (Rect, Line and Clear). + ## + ## `renderer` The renderer for which drawing color should be set. + ## + ## `r` The red value used to draw on the rendering target. + ## + ## `g` The green value used to draw on the rendering target. + ## + ## `b` The blue value used to draw on the rendering target. + ## + ## `a` The alpha value used to draw on the rendering target, + ## usually `SDL_ALPHA_OPAQUE` (`255`). proc setDrawColor*(renderer: RendererPtr; c: Color) = setDrawColor(renderer, c.r, c.g, c.b, c.a) proc getDrawColor*(renderer: RendererPtr; r, g, b, a: var uint8): SDL_Return {. importc: "SDL_GetRenderDrawColor", discardable.} + ## Get the color used for drawing operations (Rect, Line and Clear). + ## + ## `renderer` The renderer from which drawing color should be queried. + ## + ## `r` A pointer to the red value used to draw on the rendering target. + ## + ## `g` A pointer to the green value used to draw on the rendering target. + ## + ## `b` A pointer to the blue value used to draw on the rendering target. + ## + ## `a` A pointer to the alpha value used to draw on the rendering target, + ## usually `SDL_ALPHA_OPAQUE` (`255`). + proc setDrawBlendMode*(renderer: RendererPtr; blendMode: BlendMode): SDL_Return {. importc: "SDL_SetRenderDrawBlendMode", discardable.} -proc getDrawBlendMode*(renderer: RendererPtr; - blendMode: var BlendMode): SDL_Return {. + ## Set the blend mode used for drawing operations (Fill and Line). + ## + ## `renderer` The renderer for which blend mode should be set. + ## + ## `blendMode` `BlendMode` to use for blending. + ## + ## `Return` `0` on success, or `-1` on error + ## + ## **Note:** If the blend mode is not supported, + ## the closest supported mode is chosen. + ## + ## **See also:** + ## * `getDrawBlendMode proc<#getDrawBlendMode,RendererPtr,BlendMode>`_ + +proc getDrawBlendMode*( + renderer: RendererPtr; blendMode: var BlendMode): SDL_Return {. importc: "SDL_GetRenderDrawBlendMode", discardable.} - + ## Get the blend mode used for drawing operations. + ## + ## `renderer` The renderer from which blend mode should be queried. + ## + ## `blendMode` A pointer filled in with the current blend mode. + ## + ## `Return` `0` on success, or `-1` on error. + ## + ## **See also:** + ## * `setDrawBlendMode proc<#setDrawBlendMode,RendererPtr,BlendMode>`_ proc destroy*(texture: TexturePtr) {.importc: "SDL_DestroyTexture".} + ## Destroy the specified texture. + ## + ## **See also:** + ## * `createTextute proc<#createTextute,RendererPtr,uint32,cint,cint,cint>`_ + proc destroy*(renderer: RendererPtr) {.importc: "SDL_DestroyRenderer".} -#proc destroy* (texture: TexturePtr) {.inline.} = texture.destroyTexture -#proc destroy* (renderer: RendererPtr) {.inline.} = renderer.destroyRenderer + ## Destroy the rendering context for a window and free associated textures. + ## + ## **See also:** + ## * `createRenderer proc<#createRenderer,WindowPtr,cint,cint>`_ + proc getDisplayIndex*(window: WindowPtr): cint {.importc: "SDL_GetWindowDisplayIndex".} -#* + proc setDisplayMode*(window: WindowPtr; mode: ptr DisplayMode): SDL_Return {.importc: "SDL_SetWindowDisplayMode".} -#* + proc getDisplayMode*(window: WindowPtr; mode: var DisplayMode): cint {. importc: "SDL_GetWindowDisplayMode".} -#* + proc getPixelFormat*(window: WindowPtr): uint32 {.importc: "SDL_GetWindowPixelFormat".} + ## Get the human readable name of a pixel format. -#* -# \brief Get the numeric ID of a window, for logging purposes. -# proc getID*(window: WindowPtr): uint32 {.importc: "SDL_GetWindowID".} + ## Get the numeric ID of a window, for logging purposes. -#* -# \brief Get the window flags. -# proc getFlags*(window: WindowPtr): uint32 {.importc: "SDL_GetWindowFlags".} -#* -# \brief Set the title of a window, in UTF-8 format. -# -# \sa SDL_GetWindowTitle() -# + ## Get the window flags. + proc setTitle*(window: WindowPtr; title: cstring) {.importc: "SDL_SetWindowTitle".} -#* -# \brief Get the title of a window, in UTF-8 format. -# -# \sa SDL_SetWindowTitle() -# + ## Set the title of a window, in UTF-8 format. + ## + ## **See also:** + ## * `getTitle proc<#getTitle,WindowPtr>`_ + proc getTitle*(window: WindowPtr): cstring {.importc: "SDL_GetWindowTitle".} -#* -# \brief Set the icon for a window. -# -# \param icon The icon for the window. -# + ## Get the title of a window, in UTF-8 format. + ## + ## **See also:** + ## * `setTitle proc<#setTitle,WindowPtr,cstring>`_ + proc setIcon*(window: WindowPtr; icon: SurfacePtr) {.importc: "SDL_SetWindowIcon".} -#* + ## Set the icon for a window. + ## + ## `window` The window for which the icon should be set. + ## + ## `icon` The icon for the window. + proc setData*(window: WindowPtr; name: cstring; - userdata: pointer): pointer {.importc: "SDL_SetWindowData".} -#* + userdata: pointer): pointer {.importc: "SDL_SetWindowData".} + ## Associate an arbitrary named pointer with a window. + ## + ## `window` The window to associate with the pointer. + ## + ## `name` The name of the pointer. + ## + ## `userdata` The associated pointer. + ## + ## `Return` The previous value associated with `name`. + ## + ## **Note:** The name is case-sensitive. + ## + ## **See also:** + ## * `getData proc<#getData,WindowPtr,cstring>`_ + + proc getData*(window: WindowPtr; name: cstring): pointer {.importc: "SDL_GetWindowData".} -#* + ## Retrieve the data pointer associated with a window. + ## + ## `window` The window to query. + ## + ## `name` The name of the pointer. + ## + ## `Return` The value associated with `name`. + ## + ## **See also:** + ## * `setData proc<#setData,WindowPtr,cstring,pointer>`_ + proc setPosition*(window: WindowPtr; x, y: cint) {.importc: "SDL_SetWindowPosition".} + ## Set the position of a window. + ## + ## `window` The window to reposition. + ## + ## `x` The x coordinate of the window in screen coordinates, + ## `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED`. + ## + ## `y` The y coordinate of the window in screen coordinates, + ## `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED`. + ## + ## **Note:** The window coordinate origin is the upper left of the display. + ## + ## **See also:** + ## * `getPosition proc<#getPosition,WindowPtr,cint,cint>`_ + proc getPosition*(window: WindowPtr; x, y: var cint) {.importc: "SDL_GetWindowPosition".} -#* + ## Get the position of a window. + ## + ## `window` The window to query. + ## + ## `x` Pointer to variable for storing the x position, + ## in screen coordinates. May be `nil`. + ## + ## `y` Pointer to variable for storing the y position, + ## in screen coordinates. May be `nil`. + ## + ## **See also:** + ## * `setPosition proc<#setPosition,WindowPtr,cint,cint>`_ + + proc setSize*(window: WindowPtr; w, h: cint) {.importc: "SDL_SetWindowSize".} + ## Set the size of a window's client area. + ## + ## `window` The window to resize. + ## + ## `w` The width of the window, in screen coordinates. Must be `> 0`. + ## + ## `h` The height of the window, in screen coordinates. Must be `> 0`. + ## + ## **Note:** Fullscreen windows automatically match the size of the display + ## mode, and you should use `setDisplayMode()` to change their size. + ## + ## The window size in screen coordinates may differ from the size in pixels, + ## if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform with + ## high-dpi support (e.g. iOS or OS X). Use `getDrawableSize()` or + ## `getRendererOutputSize()` to get the real client area size in pixels. + ## + ## **See also:** + ## * `getSize proc<#getSize,WindowPtr,cint,cint>`_ + ## * `setDisplayMode proc<#setDisplayMode,WindowPtr,ptr.DisplayMode>`_ + proc getSize*(window: WindowPtr; w, h: var cint) {.importc: "SDL_GetWindowSize".} + ## Get the size of a window's client area. + ## + ## `window` The window to query. + ## + ## `w` Pointer to variable for storing the width, in screen coordinates. + ## May be `nil`. + ## + ## `h` Pointer to variable for storing the height, in screen coordinates. + ## May be `nil`. + ## + ## The window size in screen coordinates may differ from the size in pixels, + ## if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform with + ## high-dpi support (e.g. iOS or OS X). Use `glGetDrawableSize()` or + ## `getRendererOutputSize()` to get the real client area size in pixels. + ## + ## **See also:** + ## * `setSize proc<#setSize,WindowPtr,cint,cint>`_ proc setBordered*(window: WindowPtr; bordered: Bool32) {.importc: "SDL_SetWindowBordered".} + ## Set the border state of a window. + ## + ## This will add or remove the window's `SDL_WINDOW_BORDERLESS` flag and + ## add or remove the border from the actual window. This is a no-op if the + ## window's border already matches the requested state. + ## + ## `window` The window of which to change the border state. + ## + ## `bordered` `false` to remove border, `true` to add border. + ## + ## **Note:** You can't change the border state of a fullscreen window. + ## + ## **See also:** + ## * `getFlags proc<#getFlags,WindowPtr>`_ + +proc setFullscreen*(window: WindowPtr; + fullscreen: uint32): SDL_Return {.importc: "SDL_SetWindowFullscreen".} + ## Set a window's fullscreen state. + ## + ## `Return` `0` on success, or `-1` if setting the display mode failed. + ## + ## **See also:** + ## * `setDisplayMode proc<#setDisplayMode,WindowPtr,ptr.DisplayMode>`_ + ## * `getDisplayMode proc<#getDisplayMode,WindowPtr,DisplayMode>`_ - -proc setFullscreen*(window: WindowPtr; fullscreen: uint32): SDL_Return {.importc: "SDL_SetWindowFullscreen".} proc getSurface*(window: WindowPtr): SurfacePtr {.importc: "SDL_GetWindowSurface".} + ## Get the SDL surface associated with the window. + ## + ## `Return` The window's framebuffer surface, or `nil` on error. + ## + ## A new surface will be created with the optimal format for the window, + ## if necessary. This surface will be freed when the window is destroyed. + ## + ## **Note:** You may not combine this with 3D or the rendering API + ## on this window. + ## + ## **See also:** + ## * `updateSurface proc<#updateSurface,WindowPtr>`_ + ## * `updateSurfaceRects proc<#updateSurfaceRects,WindowPtr,ptr.Rect,cint>`_ proc updateSurface*(window: WindowPtr): SDL_Return {.importc: "SDL_UpdateWindowSurface".} + ## Copy the window surface to the screen. + ## + ## `Return` `0` on success, or `-1` on error. + ## + ## **See also:** + ## * `getSurface proc<#getSurface,WindowPtr>`_ + ## * `updateSurfaceRects proc<#updateSurfaceRects,WindowPtr,ptr.Rect,cint>`_ + proc updateSurfaceRects*(window: WindowPtr; rects: ptr Rect; numrects: cint): SDL_Return {.importc: "SDL_UpdateWindowSurfaceRects".} -#* + ## Copy a number of rectangles on the window surface to the screen. + ## + ## `Return` `0` on success, or `-1` on error. + ## + ## **See also:** + ## * `getSurface proc<#getSurface,WindowPtr>`_ + ## * `updateSurface proc<#updateSurface,WindowPtr>`_ + proc setGrab*(window: WindowPtr; grabbed: Bool32) {.importc: "SDL_SetWindowGrab".} + ## Set a window's input grab mode. + ## + ## `window` The window for which the input grab mode should be set. + ## + ## `grabbed` This is `true` to grab input, and `false` to release input. + ## + ## If the caller enables a grab while another window is currently grabbed, + ## the other window loses its grab in favor of the caller's window. + ## + ## **See also:** + ## * `getGrab proc<#getGrab,WindowPtr>`_ + proc getGrab*(window: WindowPtr): Bool32 {.importc: "SDL_GetWindowGrab".} -proc setBrightness*(window: WindowPtr; brightness: cfloat): SDL_Return {.importc: "SDL_SetWindowBrightness".} + ## Get a window's input grab mode. + ## + ## `Return` `true` if input is grabbed, and `false` otherwise. + ## + ## **See also:** + ## * `setGrab proc<#setGrab,WindowPtr,Bool32>`_ + +proc setBrightness*(window: WindowPtr; + brightness: cfloat): SDL_Return {.importc: "SDL_SetWindowBrightness".} + ## Set the brightness (gamma correction) for a window. + ## + ## `Return` `0` on success, + ## or `-1` if setting the brightness isn't supported. + ## + ## **See also:** + ## * `getBrightness proc<#getBrightness,WindowPtr>`_ + ## * `setGammaRamp proc<#setGammaRamp,WindowPtr,ptr.uint16,ptr.uint16,ptr.uint16>`_ proc getBrightness*(window: WindowPtr): cfloat {.importc: "SDL_GetWindowBrightness".} + ## Get the brightness (gamma correction) for a window. + ## + ## `Return` The last brightness value passed to `setWindowBrightness()` + ## + ## **See also:** + ## * `setBrightness proc<#setBrightness,WindowPtr,cfloat>`_ proc setGammaRamp*(window: WindowPtr; red, green, blue: ptr uint16): SDL_Return {.importc: "SDL_SetWindowGammaRamp".} -#* -# \brief Get the gamma ramp for a window. -# -# \param red A pointer to a 256 element array of 16-bit quantities to hold -# the translation table for the red channel, or NULL. -# \param green A pointer to a 256 element array of 16-bit quantities to hold -# the translation table for the green channel, or NULL. -# \param blue A pointer to a 256 element array of 16-bit quantities to hold -# the translation table for the blue channel, or NULL. -# -# \return 0 on success, or -1 if gamma ramps are unsupported. -# -# \sa SDL_SetWindowGammaRamp() -# + ## Set the gamma ramp for a window. + ## + ## `window` The window for which the gamma ramp should be set. + ## + ## `red` The translation table for the red channel, or `nil`. + ## + ## `green` The translation table for the green channel, or `nil`. + ## + ## `blue` The translation table for the blue channel, or `nil`. + ## + ## `Return` `0` on success, or `-1` if gamma ramps are unsupported. + ## + ## Set the gamma translation table for the red, green, and blue channels + ## of the video hardware. Each table is an array of 256 16-bit quantities, + ## representing a mapping between the input and output for that channel. + ## The input is the index into the array, and the output is the 16-bit + ## gamma value at that index, scaled to the output color precision. + ## + ## **See also:** + ## * `getGammaRamp proc<#getGammaRamp,WindowPtr,ptr.uint6,ptr.uint16,ptr.uint16>`_ + proc getGammaRamp*(window: WindowPtr; red: ptr uint16; - green: ptr uint16; blue: ptr uint16): cint {.importc: "SDL_GetWindowGammaRamp".} - - -proc init*(flags: cint): SDL_Return {.discardable, - importc: "SDL_Init".} -# -# This function initializes specific SDL subsystems -# -proc initSubSystem*(flags: uint32):cint {. - importc: "SDL_InitSubSystem".} - -# -# This function cleans up specific SDL subsystems -# -proc quitSubSystem*(flags: uint32) {. - importc: "SDL_QuitSubSystem".} - -# -# This function returns a mask of the specified subsystems which have -# previously been initialized. -# -# If \c flags is 0, it returns a mask of all initialized subsystems. -# -proc wasInit*(flags: uint32): uint32 {. - importc: "SDL_WasInit".} - -proc quit*() {. - importc: "SDL_Quit".} - -proc getPlatform*(): cstring {. - importc: "SDL_GetPlatform".} - -proc getVersion*(ver: var SDL_Version) {. - importc: "SDL_GetVersion".} -proc getRevision*(): cstring {. - importc: "SDL_GetRevision".} -proc getRevisionNumber*(): cint {. - importc: "SDL_GetRevisionNumber".} -proc getBasePath*(): cstring {. - importc: "SDL_GetBasePath".} -proc getPrefPath*(org, app: cstring): cstring {. - importc: "SDL_GetPrefPath".} - - -proc getNumRenderDrivers*(): cint {. - importc: "SDL_GetNumRenderDrivers".} + green: ptr uint16; + blue: ptr uint16): cint {.importc: "SDL_GetWindowGammaRamp".} + ## Get the gamma ramp for a window. + ## + ## `window` The window from which the gamma ramp should be queried. + ## + ## `red` A pointer to a 256 element array of 16-bit quantities to hold + ## the translation table for the red channel, or `nil`. + ## + ## `green` A pointer to a 256 element array of 16-bit quantities to hold + ## the translation table for the green channel, or `nil`. + ## + ## `blue` A pointer to a 256 element array of 16-bit quantities to hold + ## the translation table for the blue channel, or `nil`. + ## + ## `Return` `0` on success, or `-1` if gamma ramps are unsupported. + ## + ## **See also:** + ## * `setGammaRamp proc<#setGammaRamp,WindowPtr,ptr.uint16,ptr.uint16,ptr.uint16>`_ + + + +proc init*(flags: cint): SDL_Return {.discardable, importc: "SDL_Init".} + ## This procedure initializes the subsystems specified by `flags` + ## Unless the `INIT_NOPARACHUTE` flag is set, it will install cleanup + ## signal handlers for some commonly ignored fatal signals (like SIGSEGV). + ## + ## `Return` `0` on success or a negative error code on failure. + +proc initSubSystem*(flags: uint32): cint {.importc: "SDL_InitSubSystem".} + ## initializes specific SDL subsystems. + ## + ## Subsystem initialization is ref-counted, you must call + ## `sdl.quitSubSystem()` for each `sdl.initSubSystem()` to correctly + ## shutdown a subsystem manually (or call `sdl.quit()` to force shutdown). + ## + ## If a subsystem is already loaded then this call + ## will increase the ref-count and return. + +proc quitSubSystem*(flags: uint32) {.importc: "SDL_QuitSubSystem".} + ## cleans up specific SDL subsystems. + +proc wasInit*(flags: uint32): uint32 {.importc: "SDL_WasInit".} + ## This procedure returns a mask of the specified subsystems which have + ## previously been initialized. + ## If `flags` is `0`, it returns a mask of all initialized subsystems. + +proc quit*() {.importc: "SDL_Quit".} + ## This procedure cleans up all initialized subsystems. You should + ## call it upon all exit conditions. + + +proc getPlatform*(): cstring {.importc: "SDL_GetPlatform".} + ## Gets the name of the platform. + +proc getVersion*(ver: var SDL_Version) {.importc: "SDL_GetVersion".} + ## Get the version of SDL that is linked against your program. + ## + ## This procedure may be called safely at any time, even before `init()`. + + # TODO: Add equivalent of the `SDL_VERSION` macro (`version` ? template), + # and this comment: + # If you are linking to SDL dynamically, then it is possible that the + # current version will be different than the version you compiled against. + # This procedure returns the current version, while version() is a + # template that tells you what version you compiled with. + +proc getRevision*(): cstring {.importc: "SDL_GetRevision".} + ## Get the code revision of SDL that is linked against your program. + ## + ## Returns an arbitrary string (a hash value) uniquely identifying the + ## exact revision of the SDL library in use, and is only useful in comparing + ## against other revisions. It is NOT an incrementing number. + +proc getRevisionNumber*(): cint {.importc: "SDL_GetRevisionNumber".} + ## Get the revision number of SDL that is linked against your program. + ## + ## Returns a number uniquely identifying the exact revision of the SDL + ## library in use. It is an incrementing number based on commits to + ## hg.libsdl.org. + +proc getBasePath*(): cstring {.importc: "SDL_GetBasePath".} + ## Get the path where the application resides. + ## + ## Get the "base path". This is the directory where the application was run + ## from, which is probably the installation directory, and may or may not + ## be the process's current working directory. + ## + ## This returns an absolute path in UTF-8 encoding, and is guaranteed to + ## end with a path separator ('\\' on Windows, '/' most other places). + ## + ## The pointer returned by this procedure is owned by you. Please call + ## `free()` on the pointer when you are done with it, or it will be a + ## memory leak. This is not necessarily a fast call, though, so you should + ## call this once near startup and save the string if you need it. + ## + ## Some platforms can't determine the application's path, and on other + ## platforms, this might be meaningless. In such cases, this procedure will + ## return `nil`. + ## + ## `Return` string of base dir in UTF-8 encoding, or `nil` on error. + ## + ## **See also:** + ## * `getPrefPath proc<#getPrefPath,cstring,cstring>`_ + +proc getPrefPath*(org, app: cstring): cstring {.importc: "SDL_GetPrefPath".} + ## Get the user-and-app-specific path where files can be written. + ## + ## Get the "pref dir". This is meant to be where users can write personal + ## files (preferences and save games, etc) that are specific to your + ## application. This directory is unique per user, per application. + ## + ## This procedure will decide the appropriate location in the native + ## filesystem, create the directory if necessary, and return a string of the + ## absolute path to the directory in UTF-8 encoding. + ## + ## On Windows, the string might look like: + ## "C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\" + ## + ## On Linux, the string might look like: + ## "/home/bob/.local/share/My Program Name/" + ## + ## On Mac OS X, the string might look like: + ## "/Users/bob/Library/Application Support/My Program Name/" + ## + ## (etc.) + ## + ## You specify the name of your organization (if it's not a real + ## organization, your name or an Internet domain you own might do) and the + ## name of your application. These should be untranslated proper names. + ## + ## Both the org and app strings may become part of a directory name, so + ## please follow these rules: + ## * Try to use the same org string (including case-sensitivity) for + ## all your applications that use this procedure. + ## * Always use a unique app string for each one, and make sure it never + ## changes for an app once you've decided on it. + ## * Unicode characters are legal, as long as it's UTF-8 encoded, but... + ## * ...only use letters, numbers, and spaces. Avoid punctuation like + ## "Game Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. + ## + ## This returns an absolute path in UTF-8 encoding, and is guaranteed to + ## end with a path separator ('\\' on Windows, '/' most other places). + ## + ## The pointer returned by this procedure is owned by you. Please call + ## `free()` on the pointer when you are done with it, or it will be a + ## memory leak. This is not necessarily a fast call, though, so you should + ## call this once near startup and save the string if you need it. + ## + ## You should assume the path returned by this procedure is the only safe + ## place to write files (and that `getBasePath()`, while it might be + ## writable, or even the parent of the returned path, aren't where you + ## should be writing things). + ## + ## Some platforms can't determine the pref path, and on other + ## platforms, this might be meaningless. In such cases, this procedure will + ## return `nil`. + ## + ## `org` The name of your organization. + ## + ## `app` The name of your application. + ## + ## `Return` UTF-8 string of user dir in platform-dependent notation. + ## `nil` if there's a problem (creating directory failed, etc). + ## + ## **See also:** + ## * `getBasePath proc<#getBasePath>`_ + + +proc getNumRenderDrivers*(): cint {.importc: "SDL_GetNumRenderDrivers".} + ## Get the number of 2D rendering drivers available for the current display. + ## + ## A render driver is a set of code that handles rendering and texture + ## management on a particular display. Normally there is only one, but + ## some drivers may have several available with different capabilities. + ## + ## **See also:** + ## * `getRenderDriverInfo proc<#getRenderDriverInfo,cint,RendererInfo>`_ + ## * `createRenderer proc<#createRenderer,WindowPtr,cint,cint>`_ + proc getRenderDriverInfo*(index: cint; info: var RendererInfo): SDL_Return {. importc: "SDL_GetRenderDriverInfo".} + ## Get information about a specific 2D rendering driver + ## for the current display. + ## + ## `index` The index of the driver to query information about. + ## + ## `info` A pointer to an RendererInfo struct to be filled with + ## information on the rendering driver. + ## + ## `Return` `0` on success, `-1` if the index was out of range. + ## + ## **See also:** + ## * `createRenderer proc<#createRenderer,WindowPtr,cint,cint>`_ + proc createWindowAndRenderer*(width, height: cint; window_flags: uint32; window: var WindowPtr; renderer: var RendererPtr): SDL_Return {. importc: "SDL_CreateWindowAndRenderer".} + ## Create a window and default renderer. + ## + ## `width` The width of the window. + ## + ## `height` The height of the window. + ## + ## `window_flags` The flags used to create the window. + ## + ## `window` A pointer filled with the window, or `nil` on error. + ## + ## `renderer` A pointer filled with the renderer, or `nil` on error. + ## + ## `Return` `0` on success, or `-1` on error. + proc createRenderer*(window: WindowPtr; index: cint; flags: cint): RendererPtr {. importc: "SDL_CreateRenderer".} + ## Create a 2D rendering context for a window. + ## + ## `window` The window where rendering is displayed. + ## + ## `index` The index of the rendering driver to initialize, + ## or `-1` to initialize the first one supporting the requested flags. + ## `flags` `RendererFlags`. + ## + ## `Return` a valid rendering context or `nil` if there was an error. + ## + ## **See also:** + ## `* createSoftwareRenderer proc<#createSoftwareRenderer,SurfacePtr>`_ + ## `* getRendererInfo proc<#getRendererInfo,RendererPtr,RendererInfoPtr>`_ + proc createSoftwareRenderer*(surface: SurfacePtr): RendererPtr {. importc: "SDL_CreateSoftwareRenderer".} + ## Create a 2D software rendering context for a surface. + ## + ## `surface` The surface where rendering is done. + ## + ## `Return` a valid rendering context or `nil` if there was an error. + ## + ## **See also:** + ## * `createRenderer proc<#createRenderer,WindowPtr,cint,cint>`_ + ## * `destroy proc<#destroy,RendererPtr>`_ + proc getRenderer*(window: WindowPtr): RendererPtr {. importc: "SDL_GetRenderer".} + ## Get the renderer associated with a window. + proc getRendererInfo*(renderer: RendererPtr; info: RendererInfoPtr): cint {. importc: "SDL_GetRendererInfo".} + ## Get information about a rendering context. + proc getRendererOutputSize*(renderer: RendererPtr, w: ptr cint, h: ptr cint): cint {. importc: "SDL_GetRendererOutputSize".} + ## Get the output size in pixels of a rendering context. proc createTexture*(renderer: RendererPtr; format: uint32; - access, w, h: cint): TexturePtr {. - importc: "SDL_CreateTexture".} + access, w, h: cint): TexturePtr {.importc: "SDL_CreateTexture".} + ## Create a texture for a rendering context. + ## + ## `renderer` The renderer. + ## + ## `format` The format of the texture. + ## + ## `access` One of the enumerated values in `TextureAccess`. + ## + ## `w` The width of the texture in pixels. + ## + ## `h` The height of the texture in pixels. + ## + ## `Return` The created texture is returned, or `nil` if no rendering + ## context was active, the format was unsupported, or the width or height + ## were out of range. + ## + ## **Note:** The contents of the texture are not defined at creation. + ## + ## **See also:** + ## * `queryTextue proc<#queryTextue,TexturePtr,ptr.uint32,ptr.cint,ptr.cint,ptr.cint>`_ + ## * `updateTexture proc<#updateTexture,TexturePtr,ptr.Rect,pointer,cint>`_ + + +proc createTextureFromSurface*(renderer: RendererPtr; surface: SurfacePtr): + TexturePtr {.importc: "SDL_CreateTextureFromSurface".} + ## Create a texture from an existing surface. + ## + ## `renderer` The renderer. + ## + ## `surface` The surface containing pixel data used to fill the texture. + ## + ## `Return` The created texture is returned, or `nil` on error. + ## + ## **Note:** The surface is not modified or freed by this procedure. + ## + ## **See also:** + ## * `queryTextue proc<#queryTextue,TexturePtr,ptr.uint32,ptr.cint,ptr.cint,ptr.cint>`_ -proc createTextureFromSurface*(renderer: RendererPtr; surface: SurfacePtr): TexturePtr {. - importc: "SDL_CreateTextureFromSurface".} proc createTexture*(renderer: RendererPtr; surface: SurfacePtr): TexturePtr {. inline.} = renderer.createTextureFromSurface(surface) proc queryTexture*(texture: TexturePtr; format: ptr uint32; - access, w, h: ptr cint): SDL_Return {.discardable, - importc: "SDL_QueryTexture".} + access, w, h: ptr cint): SDL_Return {.discardable, importc: "SDL_QueryTexture".} + ## Query the attributes of a texture. + ## + ## `texture` A texture to be queried. + ## + ## `format` A pointer filled in with the raw format of the texture. + ## The actual format may differ, but pixel transfers will use this format. + ## + ## `access` A pointer filled in with the actual access to the texture. + ## + ## `w` A pointer filled in with the width of the texture in pixels. + ## + ## `h` A pointer filled in with the height of the texture in pixels. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid. + proc setTextureColorMod*(texture: TexturePtr; r, g, b: uint8): SDL_Return {. importc: "SDL_SetTextureColorMod".} + ## Set an additional color value used in render copy operations. + ## + ## `texture` The texture to update. + ## + ## `r` The red color value multiplied into copy operations. + ## + ## `g` The green color value multiplied into copy operations. + ## + ## `b` The blue color value multiplied into copy operations. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid or + ## color modulation is not supported. + ## + ## **See also:** + ## * `getTextureColorMod proc<#getTextureColorMod,TexturePtr,uint8,uint8,uint8>`_ proc getTextureColorMod*(texture: TexturePtr; r, g, b: var uint8): SDL_Return {. importc: "SDL_GetTextureColorMod".} + ## Get the additional color value used in render copy operations. + ## + ## `texture` The texture to query. + ## + ## `r` A pointer filled in with the current red color value. + ## + ## `g` A pointer filled in with the current green color value. + ## + ## `b` A pointer filled in with the current blue color value. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid. + ## + ## **See also:** + ## * `setTextureColorMod proc<#setTextureColorMod,TexturePtr,uint8,uint8,uint8>`_ proc setTextureAlphaMod*(texture: TexturePtr; alpha: uint8): SDL_Return {. importc: "SDL_SetTextureAlphaMod", discardable.} + ## Set an additional alpha value used in render copy operations. + ## + ## `texture` The texture to update. + ## + ## `alpha` The alpha value multiplied into copy operations. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid or + ## alpha modulation is not supported. + ## + ## **See also:** + ## * `getTextureAlphaMod proc<#getTextureAlphaMod,TexturePtr,uint8>`_ proc getTextureAlphaMod*(texture: TexturePtr; alpha: var uint8): SDL_Return {. importc: "SDL_GetTextureAlphaMod", discardable.} + ## Get the additional alpha value used in render copy operations. + ## + ## `texture` The texture to query. + ## + ## `alpha` A pointer filled in with the current alpha value. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid. + ## + ## **See also:** + ## * `setTextureAlphaMod proc<#setTextureAlphaMod,TexturePtr,uint8>`_ proc setTextureBlendMode*(texture: TexturePtr; blendMode: BlendMode): SDL_Return {. importc: "SDL_SetTextureBlendMode", discardable.} - -proc getTextureBlendMode*(texture: TexturePtr; - blendMode: var BlendMode): SDL_Return {.importc: "SDL_GetTextureBlendMode", discardable.} + ## Set the blend mode used for texture copy operations. + ## + ## `texture` The texture to update. + ## + ## `blendMode` `BlendMode` to use for texture blending. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid or + ## the blend mode is not supported. + ## + ## **Note:** If the blend mode is not supported, + ## the closest supported mode is chosen. + ## + ## **See also:** + ## * `getTextureBlendMode proc<#getTextureBlendMode,TexturePtr,BlendMode>`_ + +proc getTextureBlendMode*(texture: TexturePtr, blendMode: var BlendMode): + SDL_Return {.importc: "SDL_GetTextureBlendMode", discardable.} + ## Get the blend mode used for texture copy operations. + ## + ## `texture` The texture to query. + ## + ## `blendMode` A pointer filled in with the current blend mode. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid. + ## + ## **See also:** + ## * `setTextureBlendMode proc<#setTextureBlendMode,TexturePtr,BlendMode>`_ proc updateTexture*(texture: TexturePtr; rect: ptr Rect; pixels: pointer; pitch: cint): SDL_Return {.importc: "SDL_UpdateTexture", discardable.} + ## Update the given texture rectangle with new pixel data. + ## + ## `texture` The texture to update + ## + ## `rect` A pointer to the rectangle of pixels to update, or `nil` to + ## update the entire texture. + ## + ## `pixels` The raw pixel data in the format of the texture. + ## + ## `pitch` The number of bytes in a row of pixel data, + ## including padding between lines. + ## + ## The pixel data must be in the format of the texture. + ## The pixel format can be queried with `queryTexture()`. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid. + ## + ## **Note:** This is a fairly slow procedure. + proc updateYUVTexture*(texture: TexturePtr; rect: ptr Rect; Yplane: pointer; - Ypitch: cint; Uplane: pointer; Upitch: cint; Vplane: pointer; Vpitch: cint): SDL_Return {. - importc: "SDL_UpdateYUVTexture", discardable.} + Ypitch: cint; Uplane: pointer; Upitch: cint; Vplane: pointer; Vpitch: cint): + SDL_Return {.importc: "SDL_UpdateYUVTexture", discardable.} + ## Update a rectangle within a planar YV12 or IYUV texture + ## with new pixel data. + ## + ## `texture` The texture to update + ## + ## `rect` A pointer to the rectangle of pixels to update, + ## or `nil` to update the entire texture. + ## + ## `yPlane` The raw pixel data for the Y plane. + ## + ## `yPitch` The number of bytes between rows of pixel data for the Y plane. + ## + ## `uPlane` The raw pixel data for the U plane. + ## + ## `uPitch` The number of bytes between rows of pixel data for the U plane. + ## + ## `vPlane` The raw pixel data for the V plane. + ## + ## `vPitch` The number of bytes between rows of pixel data for the V plane. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid. + ## + ## **Note:** You can use `updateTexture()` as long as your pixel data is + ## a contiguous block of Y and U/V planes in the proper order, + ## but this procedure is available if your pixel data is not contiguous. proc lockTexture*(texture: TexturePtr; rect: ptr Rect; pixels: ptr pointer; pitch: ptr cint): SDL_Return {.importc: "SDL_LockTexture", discardable.} + ## Lock a portion of the texture for write-only pixel access. + ## + ## `texture` The texture to lock for access, + ## which was created with `SDL_TEXTUREACCESS_STREAMING`. + ## + ## `rect` A pointer to the rectangle to lock for access. + ## If the rect is `nil`, the entire texture will be locked. + ## + ## `pixels` This is filled in with a pointer to the locked pixels, + ## appropriately offset by the locked area. + ## + ## `pitch` This is filled in with the pitch of the locked pixels. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid or + ## was not created with `SDL_TEXTUREACCESS_STREAMING`. + ## + ## **See also:** + ## * `unlockTexture proc<#unlockTexture,TexturePtr>`_ proc unlockTexture*(texture: TexturePtr) {.importc: "SDL_UnlockTexture".} + ## Lock a portion of the texture for write-only pixel access. + ## Expose it as a SDL surface. + ## + ## `texture` The texture to lock for access, which was created with + ## `SDL_TEXTUREACCESS_STREAMING`. + ## + ## `rect` A pointer to the rectangle to lock for access. + ## If the rect is `nil`, the entire texture will be locked. + ## + ## `surface` This is filled in with a SDL surface + ## representing the locked area. + ## Surface is freed internally after calling + ## `sdl.unlockTexture()` or `sdl.destroyTexture()`. + ## + ## `Return` `0` on success, or `-1` if the texture is not valid + ## or was not created with `SDL_TEXTUREACCESS_STREAMING`. + ## + ## **See also:** + ## * `lockTexture proc<#lockTexture,TexturePtr,ptr.Rect,ptr.pointer,ptr.cint>`_ proc renderTargetSupported*(renderer: RendererPtr): Bool32 {. importc: "SDL_RenderTargetSupported".} + ## Determines whether a window supports the use of render targets. + ## + ## `renderer` The renderer that will be checked. + ## + ## `Return` `true` if supported, `false` if not. proc setRenderTarget*(renderer: RendererPtr; texture: TexturePtr): SDL_Return {.discardable, importc: "SDL_SetRenderTarget".} -#* -# + ## Set a texture as the current rendering target. + ## + ## `renderer` The renderer. + ## + ## `texture` The targeted texture, which must be created with the + ## `SDL_TEXTUREACCESS_TARGET` flag, or `nil` for the default render target + ## + ## `Return` `0` on success, or `-1` on error. + ## + ## **See also:** + ## * `getRenderTarget proc<#getRenderTarget,RendererPtr>`_ + proc getRenderTarget*(renderer: RendererPtr): TexturePtr {. importc: "SDL_GetRenderTarget".} + ## Get the current render target or `nil` for the default render target. + ## + ## `Return` The current render target. + ## + ## **See also:** + ## * `setRenderTarget proc<#setRenderTarget,RendererPtr,TexturePtr>`_ - - - -#* -# \brief Set the drawing area for rendering on the current target. -# -# \param rect The rectangle representing the drawing area, or NULL to set the viewport to the entire target. -# -# The x,y of the viewport rect represents the origin for rendering. -# -# \note When the window is resized, the current viewport is automatically -# centered within the new window size. -# -# \sa SDL_RenderGetViewport() -# \sa SDL_RenderSetLogicalSize() -# proc setViewport*(renderer: RendererPtr; rect: ptr Rect): SDL_Return {. importc: "SDL_RenderSetViewport", discardable.} + ## Set the drawing area for rendering on the current target. + ## + ## `renderer` The renderer for which the drawing area should be set. + ## + ## `rect` The rectangle representing the drawing area, or `nil` to set + ## the viewport to the entire target. + ## The `x`,`y` of the viewport rect represents the origin for rendering. + ## + ## `Return` `0` on success, or `-1` on error. + ## + ## **Note:** If the window associated with the renderer is resized, + ## the viewport is automatically reset. + ## + ## **See also:** + ## * `getViewport proc<#getViewport,RendererPtr,Rect>`_ + ## * `setLogicalSize proc<#setLogicalSize,RendererPtr,cint,cint>`_ + proc getViewport*(renderer: RendererPtr; rect: var Rect) {. importc: "SDL_RenderGetViewport".} + ## Get the drawing area for the current target. + ## + ## **See also:** + ## * `setViewport proc<#setViewport,RendererPtr,ptr.Rect>`_ proc setScale*(renderer: RendererPtr; scaleX, scaleY: cfloat): SDL_Return {. importc: "SDL_RenderSetScale", discardable.} + ## Set the drawing scale for rendering on the current target. + ## + ## `renderer` The renderer for which the drawing scale should be set. + ## + ## `scaleX` The horizontal scaling factor. + ## + ## `scaleY` The vertical scaling factor. + ## + ## The drawing coordinates are scaled by the x/y scaling factors + ## before they are used by the renderer. This allows resolution + ## independent drawing with a single coordinate system. + ## + ## **Note:** If this results in scaling or subpixel drawing by the rendering + ## backend, it will be handled using the appropriate quality hints. + ## For best results use integer scaling factors. + ## + ## **See also:** + ## * `getScale proc<#getScale,RendererPtr,cfloat,cfloat>`_ + ## * `setLogicalSize proc<#setLogicalSize,RendererPtr,cint,cint>`_ + proc getScale*(renderer: RendererPtr; scaleX, scaleY: var cfloat) {. importc: "SDL_RenderGetScale".} + ## Get the drawing scale for the current target. + ## + ## `renderer` The renderer from which drawing scale should be queried. + ## + ## `scaleX` A pointer filled in with the horizontal scaling factor. + ## + ## `scaleY` A pointer filled in with the vertical scaling factor. + ## + ## **See also:** + ## * `setScale proc<#setScale,RendererPtr,cfloat,cfloat>`_ + proc drawPoint*(renderer: RendererPtr; x, y: cint): SDL_Return {. importc: "SDL_RenderDrawPoint", discardable.} -#* + ## Draw a point on the current rendering target. + ## + ## `renderer` The renderer which should draw a point. + ## + ## `x` The x coordinate of the point. + ## + ## `y` The y coordinate of the point. + proc drawPoints*(renderer: RendererPtr; points: ptr Point; count: cint): SDL_Return {.importc: "SDL_RenderDrawPoints", discardable.} - -proc drawLine*(renderer: RendererPtr; - x1, y1, x2, y2: cint): SDL_Return {. + ## Draw multiple points on the current rendering target. + ## + ## `renderer` The renderer which should draw multiple points. + ## + ## `points` The points to draw. + ## + ## `count` The number of points to draw. + ## + ## `Return` `0` on success, or `-1` on error. + +proc drawLine*(renderer: RendererPtr; x1, y1, x2, y2: cint): SDL_Return {. importc: "SDL_RenderDrawLine", discardable.} -#* + ## Draw a line on the current rendering target. + ## + ## `renderer` The renderer which should draw a line. + ## + ## `x1` The x coordinate of the start point. + ## + ## `y1` The y coordinate of the start point. + ## + ## `x2` The x coordinate of the end point. + ## + ## `y2` The y coordinate of the end point. + proc drawLines*(renderer: RendererPtr; points: ptr Point; count: cint): SDL_Return {.importc: "SDL_RenderDrawLines", discardable.} + ## Draw a series of connected lines on the current rendering target. + ## + ## `renderer` The renderer which should draw multiple lines. + ## + ## `points` The points along the lines. + ## + ## `count` The number of points, drawing `count-1` lines. proc drawRect*(renderer: RendererPtr; rect: var Rect): SDL_Return{. importc: "SDL_RenderDrawRect", discardable.} + proc drawRect*(renderer: RendererPtr; rect: ptr Rect = nil): SDL_Return{. importc: "SDL_RenderDrawRect", discardable.} + ## Draw a rectangle on the current rendering target. + ## + ## `renderer` The renderer which should draw a rectangle. + ## + ## `rect` A pointer to the destination rectangle, + ## or `nil` to outline the entire rendering target. proc drawRects*(renderer: RendererPtr; rects: ptr Rect; count: cint): SDL_Return {.importc: "SDL_RenderDrawRects".} + ## Draw some number of rectangles on the current rendering target. + ## + ## `renderer` The renderer which should draw multiple rectangles. + ## + ## `rects` A pointer to an array of destination rectangles. + ## + ## `count` The number of rectangles. + proc fillRect*(renderer: RendererPtr; rect: var Rect): SDL_Return {. importc: "SDL_RenderFillRect", discardable.} + proc fillRect*(renderer: RendererPtr; rect: ptr Rect = nil): SDL_Return {. importc: "SDL_RenderFillRect", discardable.} -#* + ## Fill a rectangle on the current rendering target with the drawing color. + ## + ## `renderer` The renderer which should fill a rectangle. + ## + ## `rect` A pointer to the destination rectangle, + ## or `nil` for the entire rendering target. + proc fillRects*(renderer: RendererPtr; rects: ptr Rect; count: cint): SDL_Return {.importc: "SDL_RenderFillRects", discardable.} + ## Fill some number of rectangles on the current rendering target + ## with the drawing color. + ## + ## `renderer` The renderer which should fill multiple rectangles. + ## + ## `rects` A pointer to an array of destination rectangles. + ## + ## `count` The number of rectangles. proc copy*(renderer: RendererPtr; texture: TexturePtr; - srcrect, dstrect: ptr Rect): SDL_Return {. + srcrect, dstrect: ptr Rect): SDL_Return {. importc: "SDL_RenderCopy", discardable.} + ## Copy a portion of the texture to the current rendering target. + ## + ## `renderer` The renderer which should copy parts of a texture. + ## + ## `texture` The source texture. + ## + ## `srcrect` A pointer to the source rectangle, + ## or `nil` for the entire texture. + ## + ## `dstrect` A pointer to the destination rectangle, + ## or `nil` for the entire rendering target. + proc copyEx*(renderer: RendererPtr; texture: TexturePtr; srcrect, dstrect: var Rect; angle: cdouble; center: ptr Point; @@ -1027,69 +2144,153 @@ proc copyEx*(renderer: RendererPtr; texture: TexturePtr; srcrect, dstrect: ptr Rect; angle: cdouble; center: ptr Point; flip: RendererFlip = SDL_FLIP_NONE): SDL_Return {. importc: "SDL_RenderCopyEx", discardable.} + ## Copy a portion of the source texture to the current rendering target, + ## rotating it by angle around the given center. + ## + ## `renderer` The renderer which should copy parts of a texture. + ## + ## `texture` The source texture. + ## + ## `srcrect` A pointer to the source rectangle, + ## or `nil` for the entire texture. + ## + ## `dstrect` A pointer to the destination rectangle, + ## or `nil` for the entire rendering target. + ## + ## `angle` An angle in degrees that indicates the rotation + ## that will be applied to dstrect, rotating it in a clockwise direction. + ## + ## `center` A pointer to a point indicating the point + ## around which `dstrect` will be rotated + ## (if `nil`, rotation will be done around `dstrect.w/2`, `dstrect.h/2`). + ## + ## `flip` `RendererFlip` value stating which flipping actions should be + ## performed on the texture. proc clear*(renderer: RendererPtr): cint {. importc: "SDL_RenderClear", discardable.} + ## Clear the current rendering target with the drawing color. + ## + ## This procedure clears the entire rendering target, ignoring the viewport, + ## and the clip rectangle. + proc readPixels*(renderer: RendererPtr; rect: var Rect; format: cint; pixels: pointer; pitch: cint): cint {.importc: "SDL_RenderReadPixels".} proc readPixels*(renderer: RendererPtr; rect: ptr Rect; format: cint; pixels: pointer; pitch: cint): cint {.importc: "SDL_RenderReadPixels".} -proc present*(renderer: RendererPtr) {.importc: "SDL_RenderPresent".} + ## Read pixels from the current rendering target. + ## + ## `renderer` The renderer from which pixels should be read. + ## + ## `rect` A pointer to the rectangle to read, + ## or `nil` for the entire render target. + ## + ## `format` The desired format of the pixel data, + ## or `0` to use the formatof the rendering target. + ## + ## `pixels` A pointer to be filled in with the pixel data. + ## + ## `pitch` The pitch of the pixels parameter. + ## + ## `Return` `0` on success, or `-1` if pixel reading is not supported. + ## + ## `Warning:` This is a very slow operation, + ## and should not be used frequently. +proc present*(renderer: RendererPtr) {.importc: "SDL_RenderPresent".} + ## Update the screen with rendering performed. proc glBindTexture*(texture: TexturePtr; texw, texh: var cfloat): cint {. importc: "SDL_GL_BindTexture".} -proc glUnbindTexture*(texture: TexturePtr) {. - importc: "SDL_GL_UnbindTexture".} + ## Bind the texture to the current OpenGL/ES/ES2 context for use + ## with OpenGL instructions. + ## + ## `texture` The SDL texture to bind. + ## + ## `texw` A pointer to a float that will be filled with the texture width. + ## + ## `texh` A pointer to a float that will be filled with the texture height. + +proc glUnbindTexture*(texture: TexturePtr) {.importc: "SDL_GL_UnbindTexture".} + ## Unbind a texture from the current OpenGL/ES/ES2 context. + proc createRGBSurface*(flags: cint; width, height, depth: cint; Rmask, Gmask, BMask, Amask: uint32): SurfacePtr {. importc: "SDL_CreateRGBSurface".} + ## Allocate and free an RGB surface. + ## + ## If the depth is 4 or 8 bits, an empty palette is allocated for the surface. + ## If the depth is greater than 8 bits, the pixel format is set using the + ## flags `[rgb]Mask`. + ## + ## If the procedure runs out of memory, it will return `nil`. + ## + ## `flags` The `flags` are obsolete and should be set to `0`. + ## + ## `width` The width in pixels of the surface to create. + ## + ## `height` The height in pixels of the surface to create. + ## + ## `depth` The depth in bits of the surface to create. + ## + ## `rMask` The red mask of the surface to create. + ## + ## `gMask` The green mask of the surface to create. + ## + ## `bMask` The blue mask of the surface to create. + ## + ## `aMask` The alpha mask of the surface to create. + proc createRGBSurfaceFrom*(pixels: pointer; width, height, depth, pitch: cint; Rmask, Gmask, Bmask, Amask: uint32): SurfacePtr {. importc: "SDL_CreateRGBSurfaceFrom".} -proc freeSurface*(surface: SurfacePtr) {. - importc: "SDL_FreeSurface".} +proc freeSurface*(surface: SurfacePtr) {.importc: "SDL_FreeSurface".} proc setSurfacePalette*(surface: SurfacePtr; palette: ptr Palette): cint {. importc:"SDL_SetSurfacePalette".} -#* -# \brief Sets up a surface for directly accessing the pixels. -# -# Between calls to SDL_LockSurface() / SDL_UnlockSurface(), you can write -# to and read from \c surface->pixels, using the pixel format stored in -# \c surface->format. Once you are done accessing the surface, you should -# use SDL_UnlockSurface() to release it. -# -# Not all surfaces require locking. If SDL_MUSTLOCK(surface) evaluates -# to 0, then you can read and write to the surface at any time, and the -# pixel format of the surface will not change. -# -# No operating system or library calls should be made between lock/unlock -# pairs, as critical system locks may be held during this time. -# -# SDL_LockSurface() returns 0, or -1 if the surface couldn't be locked. -# -# \sa SDL_UnlockSurface() -# + ## Set the palette used by a surface. + ## + ## `Return` `0`, or `-1` if the surface format doesn't use a palette. + ## + ## **Note:** A single palette can be shared with many surfaces. + proc lockSurface*(surface: SurfacePtr): cint {.importc: "SDL_LockSurface".} -#* \sa SDL_LockSurface() + ## Sets up a surface for directly accessing the pixels. + ## + ## Between calls to `lockSurface()` / `unlockSurface()`, you can write + ## to and read from `surface.pixels`, using the pixel format stored in + ## `surface.format`. Once you are done accessing the surface, you should + ## use `unlockSurface()` to release it. + ## + ## Not all surfaces require locking. If `mustLock(surface)` evaluates + ## to `0`, then you can read and write to the surface at any time, and the + ## pixel format of the surface will not change. + ## + ## No operating system or library calls should be made between lock/unlock + ## pairs, as critical system locks may be held during this time. + ## + ## `lockSurface()` returns `0`, or `-1` if the surface couldn't be locked. + ## + ## **See also:** + ## * `unlockSurface proc<#unlockSurface,SurfacePtr>`_ + proc unlockSurface*(surface: SurfacePtr) {.importc: "SDL_UnlockSurface".} -#* -# Load a surface from a seekable SDL data stream (memory or file). -# -# If \c freesrc is non-zero, the stream will be closed after being read. -# -# The new surface should be freed with SDL_FreeSurface(). -# -# \return the new surface, or NULL if there was an error. -# + ## **See also:** + ## * `lockSurface proc<#lockSurface,SurfacePtr>`_ + proc loadBMP_RW*(src: RWopsPtr; freesrc: cint): SurfacePtr {. importc: "SDL_LoadBMP_RW".} - + ## Load a surface from a seekable SDL data stream (memory or file). + ## + ## If `freesrc` is non-zero, the stream will be closed after being read. + ## + ## The new surface should be freed with `freeSurface()`. + ## + ## `Return` the new surface, or `nil` if there was an error. proc rwFromFile*(file: cstring; mode: cstring): RWopsPtr {.importc: "SDL_RWFromFile".} @@ -1097,92 +2298,266 @@ proc rwFromFP*(fp: File; autoclose: Bool32): RWopsPtr {.importc: "SDL_RWFromFP". proc rwFromMem*(mem: pointer; size: cint): RWopsPtr {.importc: "SDL_RWFromMem".} proc rwFromConstMem*(mem: pointer; size: cint): RWopsPtr {.importc: "SDL_RWFromConstMem".} -proc allocRW* : RWopsPtr {.importc: "SDL_AllocRW".} -proc freeRW* (area: RWopsPtr) {.importc: "SDL_FreeRW".} +proc allocRW*: RWopsPtr {.importc: "SDL_AllocRW".} +proc freeRW*(area: RWopsPtr) {.importc: "SDL_FreeRW".} -#* -# Load a surface from a file. -# -# Convenience macro. -# -#* proc saveBMP_RW*(surface: SurfacePtr; dst: RWopsPtr; freedst: cint): SDL_Return {.importc: "SDL_SaveBMP_RW".} + ## Save a surface to a seekable SDL data stream (memory or file). + ## + ## Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the + ## BMP directly. Other RGB formats with 8-bit or higher get converted to a + ## 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit + ## surface before they are saved. YUV and paletted 1-bit and 4-bit formats + ## are not supported. + ## + ## If `freedst` is non-zero, the stream will be closed after being written. + ## + ## `Return` `0` if successful or `-1` if there was an error. + proc setSurfaceRLE*(surface: SurfacePtr; flag: cint): cint {. importc:"SDL_SetSurfaceRLE".} + ## Sets the RLE acceleration hint for a surface. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## **Note:** If RLE is enabled, colorkey and alpha blending blits are + ## much faster, but the surface must be locked before directly + ## accessing the pixels. + proc setColorKey*(surface: SurfacePtr; flag: cint; key: uint32): cint {. importc: "SDL_SetColorKey".} + ## Sets the color key (transparent pixel) in a blittable surface. + ## + ## `surface` The surface to update. + ## + ## `flag` Non-zero to enable colorkey and `0` to disable colorkey. + ## + ## `key` The transparent pixel in the native surface format. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## You can pass `SDL_RLEACCEL` to enable RLE accelerated blits. proc getColorKey*(surface: SurfacePtr; key: var uint32): cint {. importc: "SDL_GetColorKey".} + ## Gets the color key (transparent pixel) in a blittable surface. + ## + ## `surface` The surface to update. + ## + ## `key` A pointer filled in with the transparent pixel + ## in the native surface format. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid or + ## colorkey is not enabled. + proc setSurfaceColorMod*(surface: SurfacePtr; r, g, b: uint8): cint {. importc: "SDL_SetSurfaceColorMod".} + ## Set an additional color value used in blit operations. + ## + ## `surface` The surface to update. + ## + ## `r` The red color value multiplied into blit operations. + ## + ## `g` The green color value multiplied into blit operations. + ## + ## `b` The blue color value multiplied into blit operations. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## **See also:** + ## * `getSurfaceColorMod proc<#getSurfaceColorMod,SurfacePtr,uint8,uint8,uint8>`_ proc getSurfaceColorMod*(surface: SurfacePtr; r, g, b: var uint8): cint {. importc: "SDL_GetSurfaceColorMod".} + ## Get the additional color value used in blit operations. + ## + ## `surface` The surface to query. + ## + ## `r` A pointer filled in with the current red color value. + ## + ## `g` A pointer filled in with the current green color value. + ## + ## `b` A pointer filled in with the current blue color value. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## **See also:** + ## * `setSurfaceColorMod proc<#setSurfaceColorMod,SurfacePtr,uint8,uint8,uint8>`_ proc setSurfaceAlphaMod*(surface: SurfacePtr; alpha: uint8): cint {. importc: "SDL_SetSurfaceAlphaMod".} + ## Set an additional alpha value used in blit operations. + ## + ## `surface` The surface to update. + ## + ## `alpha` The alpha value multiplied into blit operations. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## **See also:** + ## * `getSurfaceAlphaMod proc<#getSurfaceAlphaMod,SurfacePtr,uint8>`_ + proc getSurfaceAlphaMod*(surface: SurfacePtr; alpha: var uint8): cint {. importc: "SDL_GetSurfaceAlphaMod".} + ## Get the additional alpha value used in blit operations. + ## + ## `surface` The surface to query. + ## + ## `alpha` A pointer filled in with the current alpha value. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## **See also:** + ## * `setSurfaceAlphaMod proc<#setSurfaceAlphaMod,SurfacePtr,uint8>`_ proc setSurfaceBlendMode*(surface: SurfacePtr; blendMode: BlendMode): cint {. importc: "SDL_SetSurfaceBlendMode".} + ## Set the blend mode used for blit operations. + ## + ## `surface` The surface to update. + ## + ## `blendMode` BlendMode to use for blit blending. + ## + ## `Return` `0` on success, or `-1` if the parameters are not valid. + ## + ## **See also:** + ## * `getSurfaceBlendMode proc<#getSurfaceBlendMode,SurfacePtr,ptr.BlendMode>`_ + proc getSurfaceBlendMode*(surface: SurfacePtr; blendMode: ptr BlendMode): cint {. importc: "SDL_GetSurfaceBlendMode".} + ## Get the blend mode used for blit operations. + ## + ## `surface` The surface to query. + ## + ## `blendMode` A pointer filled in with the current blend mode. + ## + ## `Return` `0` on success, or `-1` if the surface is not valid. + ## + ## **See also:** + ## * `setSurfaceBlendMode proc<#setSurfaceBlendMode,SurfacePtr,BlendMode>`_ + proc setClipRect*(surface: SurfacePtr; rect: ptr Rect): Bool32 {. importc: "SDL_SetClipRect".} + ## Sets the clipping rectangle for the destination surface in a blit. + ## If the clip rectangle is `nil`, clipping will be disabled. + ## If the clip rectangle doesn't intersect the surface, the procedure will + ## return `false` and blits will be completely clipped. Otherwise the + ## procedure returns `true` and blits to the surface will be clipped to + ## the intersection of the surface area and the clipping rectangle. + ## + ## Note that blits are automatically clipped to the edges of the source + ## and destination surfaces. + proc getClipRect*(surface: SurfacePtr; rect: ptr Rect) {. importc: "SDL_GetClipRect".} + ## Gets the clipping rectangle for the destination surface in a blit. + ## + ## `rect` must be a pointer to a valid rectangle which will be filled + ## with the correct values. + proc setClipRect*(renderer: RendererPtr; rect: ptr Rect): cint {. importc: "SDL_RenderSetClipRect".} + ## Set the clip rectangle for the current target. + ## + ## `renderer` The renderer for which clip rectangle should be set. + ## + ## `rect` A pointer to the rectangle to set as the clip rectangle, + ## or `nil` to disable clipping. + ## + ## `Return` `0` on success, or `-1` on error. + ## + ## **See also:** + ## * `getClipRect proc<#getClipRect,RendererPtr,ptr.Rect>`_ + proc getClipRect*(renderer: RendererPtr; rect: ptr Rect): cint {. importc: "SDL_RenderGetClipRect".} + ## Get the clip rectangle for the current target. + ## + ## `renderer` The renderer from which clip rectangle should be queried. + ## + ## `rect` A pointer filled in with the current clip rectangle, + ## relative to the viewport, or `nil` to disable clipping. + ## + ## **See also:** + ## * `setClipRect proc<#setClipRect,SurfacePtr,ptr.Rect>`_ + proc isClipEnabled*(renderer: RendererPtr): cint {. importc: "SDL_RenderIsClipEnabled".} + ## Get whether clipping is enabled on the given renderer. + ## + ## `renderer` The renderer from which clip state should be queried. + ## + ## **See also:** + ## * `getClipRect proc<#getClipRect,RendererPtr,ptr.Rect>`_ + proc convertSurface*(src: SurfacePtr; fmt: ptr PixelFormat; flags: cint): SurfacePtr {.importc: "SDL_ConvertSurface".} + ## Creates a new surface of the specified format, and then copies and maps + ## the given surface to it so the blit of the converted surface will be as + ## fast as possible. If this procedure fails, it returns `nil`. + ## + ## The `flags` parameter is passed to `createRGBSurface()` and has those + ## semantics. You can also pass `SDL_RLEACCEL` in the flags parameter and + ## SDL will try to RLE accelerate colorkey and alpha blits in the resulting + ## surface. + proc convertSurfaceFormat*(src: SurfacePtr; pixel_format, flags: uint32): SurfacePtr {.importc: "SDL_ConvertSurfaceFormat".} proc convertPixels*(width, height: cint; src_format: uint32; src: pointer; src_pitch: cint; dst_format: uint32; dst: pointer; dst_pitch: cint): cint {. importc: "SDL_ConvertPixels".} -#* -# Performs a fast fill of the given rectangle with \c color. -# -# If \c rect is NULL, the whole surface will be filled with \c color. -# -# The color should be a pixel of the format used by the surface, and -# can be generated by the SDL_MapRGB() function. -# -# \return 0 on success, or -1 on error. -# + ## Copy a block of pixels of one format to another format. + ## + ## `Return` `0` on success, or `-1` if there was an error. + proc fillRect*(dst: SurfacePtr; rect: ptr Rect; color: uint32): SDL_Return {. importc: "SDL_FillRect", discardable.} + ## Performs a fast fill of the given rectangle with `color`. + ## If `rect` is `nil`, the whole surface will be filled with `color`. + ## The color should be a pixel of the format used by the surface, and + ## can be generated by the `mapRGB()` procedure. + ## + ## `Return` `0` on success, or `-1` on error. + proc fillRects*(dst: SurfacePtr; rects: ptr Rect; count: cint; color: uint32): cint {.importc: "SDL_FillRects".} proc upperBlit*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; dstrect: ptr Rect): SDL_Return {.importc: "SDL_UpperBlit".} + ## This is the public blit procedure, `blitSurface()`, and it performs + ## rectangle validation and clipping before passing it to `lowerBlit()`. proc lowerBlit*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; dstrect: ptr Rect): SDL_Return {.importc: "SDL_LowerBlit".} + ## This is a semi-private blit procedure and it performs low-level surface + ## blitting only. + proc softStretch*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; dstrect: ptr Rect): SDL_Return {.importc: "SDL_SoftStretch".} + ## Perform a fast, low quality, stretch blit between two surfaces of the + ## same pixel format. + ## + ## **Note:** This procedure uses a static buffer, and is not thread-safe. proc upperBlitScaled*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; dstrect: ptr Rect): SDL_Return {.importc: "SDL_UpperBlitScaled".} + ## This is the public scaled blit procedure, `blitScaled()`, + ## and it performs rectangle validation and clipping before + ## passing it to `lowerBlitScaled()`. + proc lowerBlitScaled*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; dstrect: ptr Rect): SDL_Return {.importc: "SDL_LowerBlitScaled".} - + ## This is a semi-private blit procedure and it performs low-level surface + ## scaled blitting only. proc readU8*(src: RWopsPtr): uint8 {.importc: "SDL_ReadU8".} @@ -1202,164 +2577,466 @@ proc writeBE64*(dst: RWopsPtr; value: uint64): csize {.importc: "SDL_WriteBE64". proc showMessageBox*(messageboxdata: ptr MessageBoxData; buttonid: var cint): cint {.importc: "SDL_ShowMessageBox".} + ## Create a modal message box. + ## + ## `messageboxdata` The `MessageBoxData` object with title, text, etc. + ## + ## `buttonid` The pointer to which user id of hit button should be copied. + ## + ## `Return` `-1` on error, otherwise `0` and `buttonid` contains user id + ## of button hit or `-1` if dialog was closed. + ## + ## **Note:** This procedure should be called on the thread that created + ## the parent window, or on the main thread if the messagebox has no parent. + ## It will block execution of that thread until the user clicks a button or + ## closes the messagebox. proc showSimpleMessageBox*(flags: uint32; title, message: cstring; window: WindowPtr): cint {.importc: "SDL_ShowSimpleMessageBox".} - # \return 0 on success, -1 on error - - + ## Create a simple modal message box. + ## + ## `flags` `MessageBoxFlags` + ## + ## `title` UTF-8 title text + ## + ## `message` UTF-8 message text + ## + ## `window` The parent window, or `nil` for no parent + ## + ## `Return` `0` on success, `-1` on error + ## + ## **See also:** + ## * `showMessageBox proc<#showMessageBox,ptr.MessageBoxData,cint>`_ proc getNumVideoDrivers*(): cint {.importc: "SDL_GetNumVideoDrivers".} + ## Get the number of video drivers compiled into SDL. + ## + ## **See also:** + ## * `getVideoDriver proc<#getVideoDriver,cint>`_ + proc getVideoDriver*(index: cint): cstring {.importc: "SDL_GetVideoDriver".} + ## Get the name of a built in video driver. + ## + ## **Note:** The video drivers are presented in the order in which they are + ## normally checked during initialization. + ## + ## **See also:** + ## * `getNumVideoDrivers proc<#getNumVideoDrivers>`_ + proc videoInit*(driver_name: cstring): SDL_Return {.importc: "SDL_VideoInit".} + ## Initialize the video subsystem, optionally specifying a video driver. + ## + ## `driver_name` Initialize a specific driver by name, or `nil` for the + ## default video driver. + ## + ## `Return` `0` on success, `-1` on error. + ## + ## This procedure initializes the video subsystem; setting up a connection + ## to the window manager, etc, and determines the available display modes + ## and pixel formats, but does not initialize a window or graphics mode. + ## + ## **See also:** + ## * `videoQuit proc<#videoQuit>`_ + proc videoQuit*() {.importc: "SDL_VideoQuit".} + ## Shuts down the video subsystem. + ## + ## This procedure closes all windows, and restores the original video mode. + ## + ## **See also:** + ## * `videoInit proc<#videoInit,cstring>`_ + proc getCurrentVideoDriver*(): cstring {.importc: "SDL_GetCurrentVideoDriver".} + ## Returns the name of the currently initialized video driver. + ## + ## `Return` The name of the current video driver or `nil` if no driver + ## has been initialized. + ## + ## **See also:** + ## * `getNumVideoDrivers proc<#getNumVideoDrivers>`_ + ## * `getVideoDriver proc<#getVideoDriver,cint>`_ + proc getNumVideoDisplays*(): cint {.importc: "SDL_GetNumVideoDisplays".} + ## Returns the number of available video displays. + ## + ## **See also:** + ## * `getDisplayBounds proc<#getDisplayBounds,cint,Rect>`_ proc getDisplayBounds*(displayIndex: cint; rect: var Rect): SDL_Return {. importc: "SDL_GetDisplayBounds".} -proc getNumDisplayModes*(displayIndex: cint): cint {.importc: "SDL_GetNumDisplayModes".} -#* + ## Get the desktop area represented by a display, + ## with the primary display located at `0,0`. + ## + ## `Return` `0` on success, or `-1` if the index is out of range. + ## + ## **See also:** + ## * `getNumVideoDisplays proc<#getNumVideoDisplays>`_ + +proc getNumDisplayModes*(displayIndex: cint): cint {. + importc: "SDL_GetNumDisplayModes".} + ## Returns the number of available display modes. + ## + ## **See also:** + ## * `getDisplayMode proc<#getDisplayMode,WindowPtr,DisplayMode>`_ + proc getDisplayMode*(displayIndex: cint; modeIndex: cint; mode: var DisplayMode): SDL_Return {.importc: "SDL_GetDisplayMode".} + ## Fill in information about a specific display mode. + ## + ## **Note:** The display modes are sorted in this priority: + ## * `bits per pixel` -> more colors to fewer colors + ## * `width` -> largest to smallest + ## * `height` -> largest to smallest + ## * `refresh rate` -> highest to lowest + ## + ## **See also:** + ## * `getNumDisplayModes proc<#getNumDisplayModes,cint>`_ proc getDesktopDisplayMode*(displayIndex: cint; mode: var DisplayMode): SDL_Return {.importc: "SDL_GetDesktopDisplayMode".} + ## Fill in information about the desktop display mode. + proc getCurrentDisplayMode*(displayIndex: cint; mode: var DisplayMode): SDL_Return {.importc: "SDL_GetCurrentDisplayMode".} + ## Fill in information about the current display mode. proc getClosestDisplayMode*(displayIndex: cint; mode: ptr DisplayMode; - closest: ptr DisplayMode): ptr DisplayMode {.importc: "SDL_GetClosestDisplayMode".} + closest: ptr DisplayMode): ptr DisplayMode {. + importc: "SDL_GetClosestDisplayMode".} + ## Get the closest match to the requested display mode. + ## + ## `displayIndex` The index of display from which mode should be queried. + ## + ## `mode` The desired display mode. + ## + ## `closest` A pointer to a display mode to be filled in with the closest + ## match of the available display modes. + ## + ## `Return` The passed in value `closest`, or `nil` if no matching + ## video mode was available. + ## + ## The available display modes are scanned, and `closest` is filled + ## in with the closest mode matching the requested mode and returned. + ## The mode `format` and `refresh_rate` default to the desktop mode + ## if they are `0`. + ## + ## The modes are scanned with size being first priority, `format` being + ## second priority, and finally checking the `refresh_rate`. If all the + ## available modes are too small, then `nil` is returned. + ## + ## **See also:** + ## * `getNumDisplayModes proc<#getNumDisplayModes,cint>`_ + ## * `getDisplayMode proc<#getDisplayMode,WindowPtr,DisplayMode>`_ + proc getDisplayDPI*(displayIndex: cint; ddpi, hdpi, vdpi: ptr cfloat): SDL_Return {.importc: "SDL_GetDisplayDPI".} -#* -#* + ## Get the dots/pixels-per-inch for a display. + ## + ## **Note:** Diagonal, horizontal and vertical DPI can all be optionally + ## returned if the parameter is non-nil. + ## + ## `Return` `0` on success, or `-1` if no DPI information is available + ## or the index is out of range. + ## + ## **See also:** + ## * `getNumVideoDisplays proc<#getNumVideoDisplays>`_ + proc createWindow*(title: cstring; x, y, w, h: cint; flags: uint32): WindowPtr {.importc: "SDL_CreateWindow".} -#* -proc createWindowFrom*(data: pointer): WindowPtr {.importc: "SDL_CreateWindowFrom".} - -#* -# \brief Get a window from a stored ID, or NULL if it doesn't exist. -# -proc getWindowFromID*(id: uint32): WindowPtr {.importc: "SDL_GetWindowFromID".} + ## Create a window with the specified position, dimensions, and flags. + ## + ## `title` The title of the window, in UTF-8 encoding. + ## + ## `x` The x position of the window, + ## `SDL_WINDOWPOS_CENTERED`, or `SDL_WINDOWPOS_UNDEFINED`. + ## + ## `y` The y position of the window, + ## `SDL_WINDOWPOS_CENTERED`, or `SDL_WINDOWPOS_UNDEFINED`. + ## + ## `w` The width of the window, in screen coordinates. + ## + ## `h` The height of the window, in screen coordinates. + ## + ## `flags` The flags for the window, a mask of any of the following: + ## * `SDL_WINDOW_FULLSCREEN`, + ## * `SDL_WINDOW_OPENGL`, + ## * `SDL_WINDOW_HIDDEN`, + ## * `SDL_WINDOW_BORDERLESS`, + ## * `SDL_WINDOW_RESIZABLE`, + ## * `SDL_WINDOW_MAXIMIZED`, + ## * `SDL_WINDOW_MINIMIZED`, + ## * `SDL_WINDOW_INPUT_GRABBED`, + ## * `SDL_WINDOW_ALLOW_HIGHDPI`, + ## * `SDL_WINDOW_VULKAN`, + ## + ## `Return` the id of the window created, + ## or `nil` if window creation failed. + ## + ## If the window is created with the `SDL_WINDOW_ALLOW_HIGHDPI` flag, its size + ## in pixels may differ from its size in screen coordinates on platforms with + ## high-DPI support (e.g. iOS and Mac OS X). Use `getSize()` to query + ## the client area's size in screen coordinates, and `glGetDrawableSize()`, + ## `vulkanGetDrawableSize()`, or `getRendererOutputSize()` + ## to query the drawable size in pixels. + ## + ## If the window is created with any of the `SDL_WINDOW_OPENGL` or + ## `SDL_WINDOW_VULKAN` flags, then the corresponding `loadLibrary` function + ## (`glLoadLibrary` or `vulkanLoadLibrary`) is called and the + ## corresponding `UnloadLibrary` function is called by + ## `destroyWindow()`. + ## + ## If `SDL_WINDOW_VULKAN` is specified and there isn't a working Vulkan driver, + ## `createWindow()` will fail because `vulkanLoadLibrary()` will fail. + ## + ## If `WINDOW_METAL` is specified on an OS that does not support Metal, + ## `createWindow()` will fail. + ## + ## **Note:** On non-Apple devices, SDL requires you to either not link to the + ## Vulkan loader or link to a dynamic library version. This limitation + ## may be removed in a future version of SDL. + ## + ## **See also:** + ## * `destroy proc<#destroy,WindowPtr>`_ + ## * `glLoadLibrary proc<#glLoadLibrary,cstring>`_ + ## * `vulkanLoadLibrary proc<#vulkanLoadLibrary,cstring>`_ + # TODO: Add `SDL_WINDOW_METAL` +proc createWindowFrom*(data: pointer): WindowPtr {.importc: "SDL_CreateWindowFrom".} + ## Create an SDL window from an existing native window. + ## + ## `data` A pointer to driver-dependent window creation data. + ## + ## `Return` the id of the window created, + ## or `nil` if window creation failed. + ## + ## **See also:** + ## * `destroy proc<#destroy,WindowPtr>`_ +proc getWindowFromID*(id: uint32): WindowPtr {.importc: "SDL_GetWindowFromID".} + ## Get a window from a stored ID, or `nil` if it doesn't exist. -# proc showWindow*(window: WindowPtr) {.importc: "SDL_ShowWindow".} + ## Show a window. + ## + ## **See also:** + ## * `hideWindow proc<#hideWindow,WindowPtr>`_ + proc hideWindow*(window: WindowPtr) {.importc: "SDL_HideWindow".} -#* + ## Hide a window. + ## + ## **See also:** + ## * `showWindow proc<#showWindow,WindowPtr>`_ + proc raiseWindow*(window: WindowPtr) {.importc: "SDL_RaiseWindow".} + ## Raise a window above other windows and set the input focus. + proc maximizeWindow*(window: WindowPtr) {.importc: "SDL_MaximizeWindow".} + ## Make a window as large as possible. + ## + ## **See also:** + ## * `restoreWindow proc<#restoreWindow,WindowPtr>`_ + proc minimizeWindow*(window: WindowPtr) {.importc: "SDL_MinimizeWindow".} -#* -# + ## Minimize a window to an iconic representation. + ## + ## **See also:** + ## * `restoreWindow proc<#restoreWindow,WindowPtr>`_ + + proc restoreWindow*(window: WindowPtr) {.importc: "SDL_RestoreWindow".} + ## Restore the size and position of a minimized or maximized window. + ## + ## **See also:** + ## * `maximizeWindow proc<#maximizeWindow,WindowPtr>`_ + ## * `minimizeWindow proc<#minimizeWindow,WindowPtr>`_ + proc destroyWindow*(window: WindowPtr) {.importc: "SDL_DestroyWindow".} + ## Destroy a window. proc isScreenSaverEnabled*(): Bool32 {.importc: "SDL_IsScreenSaverEnabled".} + ## Returns whether the screensaver is currently enabled (default off). + ## + ## **See also:** + ## * `enableScreenSaver proc<#enableScreenSaver>`_ + ## * `disableScreenSaver proc<#disableScreenSaver>`_ + proc enableScreenSaver*() {.importc: "SDL_EnableScreenSaver".} + ## Allow the screen to be blanked by a screensaver. + ## + ## **See also:** + ## * `isScreenSaverEnabled proc<#isScreenSaverEnabled>`_ + ## * `disableScreenSaver proc<#disableScreenSaver>`_ + proc disableScreenSaver*() {.importc: "SDL_DisableScreenSaver".} + ## Prevent the screen from being blanked by a screensaver. + ## + ## **See also:** + ## * `isScreenSaverEnabled proc<#isScreenSaverEnabled>`_ + ## * `enableScreenSaver proc<#enableScreenSaver>`_ proc getTicks*(): uint32 {.importc: "SDL_GetTicks".} + ## Get the number of milliseconds since the SDL library initialization. + ## This value wraps if the program runs for more than ~49 days. + proc getPerformanceCounter*(): uint64 {.importc: "SDL_GetPerformanceCounter".} + ## Get the current value of the high resolution counter. + proc getPerformanceFrequency*(): uint64 {.importc: "SDL_GetPerformanceFrequency".} + ## Get the count per second of the high resolution counter. + proc delay*(ms: uint32) {.importc: "SDL_Delay".} -#* -# \brief Add a new timer to the pool of timers already running. -# -# \return A timer ID, or NULL when an error occurs. -# + ## Wait a specified number of milliseconds before returning. + proc addTimer*(interval: uint32; callback: TimerCallback; param: pointer): TimerID {.importc: "SDL_AddTimer".} -#* -# \brief Remove a timer knowing its ID. -# -# \return A boolean value indicating success or failure. -# -# \warning It is not safe to remove a timer multiple times. -# + ## Add a new timer to the pool of timers already running. + ## + ## `Return` a timer ID, or `0` when an error occurs. + proc removeTimer*(id: TimerID): Bool32 {.importc: "SDL_RemoveTimer".} + ## Remove a timer knowing its ID. + ## + ## `Return` a boolean value indicating success or failure. + ## + ## `Warning:` It is not safe to remove a timer multiple times. -#* -# \name OpenGL support functions -# -#@{ -#* -# \brief Dynamically load an OpenGL library. -# -# \param path The platform dependent OpenGL library name, or NULL to open the -# default OpenGL library. -# -# \return 0 on success, or -1 if the library couldn't be loaded. -# -# This should be done after initializing the video driver, but before -# creating any OpenGL windows. If no OpenGL library is loaded, the default -# library will be loaded upon creation of the first OpenGL window. -# -# \note If you do this, you need to retrieve all of the GL functions used in -# your program from the dynamic library using SDL_GL_GetProcAddress(). -# -# \sa SDL_GL_GetProcAddress() -# \sa SDL_GL_UnloadLibrary() -# -#extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); -proc glLoadLibrary* (path: cstring): SDL_Return {.discardable, +proc glLoadLibrary*(path: cstring): SDL_Return {.discardable, importc: "SDL_GL_LoadLibrary".} -#extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc); -proc glGetProcAddress* (procedure: cstring): pointer {. + ## Dynamically load an OpenGL library. + ## + ## `path` The platform dependent OpenGL library name, + ## or `nil` to open the default OpenGL library. + ## + ## `Return` `0` on success, or `-1` if the library couldn't be loaded. + ## + ## This should be done after initializing the video driver, but before + ## creating any OpenGL windows. If no OpenGL library is loaded, the default + ## library will be loaded upon creation of the first OpenGL window. + ## + ## **Note:** If you do this, you need to retrieve + ## all of the GL procedures used in your program + ## from the dynamic library using `glGetProcAddress()`. + ## + ## **See also:** + ## * `glGetProcAddress proc<#glGetProcAddress,cstring>`_ + ## * `glUnloadLibrary proc<#glUnloadLibrary>`_ + + +proc glGetProcAddress*(procedure: cstring): pointer {. importc: "SDL_GL_GetProcAddress".} -#extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void); -proc glUnloadLibrary* {. - importc: "SDL_GL_UnloadLibrary".} -#extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char -# *extension); -proc glExtensionSupported* (extension: cstring): bool {. + ## Get the address of an OpenGL procedure. + +proc glUnloadLibrary* {.importc: "SDL_GL_UnloadLibrary".} + ## Unload the OpenGL library previously loaded by `glLoadLibrary()`. + ## + ## **See also:** + ## * `glLoadLibrary proc<#glLoadLibrary,cstring>`_ + +proc glExtensionSupported*(extension: cstring): bool {. importc: "SDL_GL_ExtensionSupported".} + ## `Return` `true` if an OpenGL extension is supported + ## for the current context. -#extern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value); -proc glSetAttribute* (attr: GLattr; value: cint): cint {. + +proc glSetAttribute*(attr: GLattr; value: cint): cint {. importc: "SDL_GL_SetAttribute".} -#extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value); -proc glGetAttribute* (attr: GLattr; value: var cint): cint {. - importc: "SDL_GL_GetAttribute".} + ## Set an OpenGL window attribute before window creation. + ## + ## `Return` `0` on success, or `-1` if the attribute could not be set. +proc glGetAttribute*(attr: GLattr; value: var cint): cint {. + importc: "SDL_GL_GetAttribute".} + ## Get the actual value for an attribute from the current context. + ## + ## `Return` `0` on success, + ## or `-1` if the attribute could not be retrieved. + ## The integer at `value` will be modified in either case. + proc glCreateContext*(window: WindowPtr): GlContextPtr {. importc: "SDL_GL_CreateContext".} - ## Create an OpenGL context for use with an OpenGL window, and make it current. -proc glMakeCurrent* (window: WindowPtr; context: GlContextPtr): cint {. + ## Create an OpenGL context for use with an OpenGL window, + ## and make it current. + ## + ## **See also:** + ## * `glDeleteContext proc<#glDeleteContext,GLContextPtr>`_ + +proc glMakeCurrent*(window: WindowPtr; context: GlContextPtr): cint {. importc: "SDL_GL_MakeCurrent".} + ## Set up an OpenGL context for rendering into an OpenGL window. + ## + ## **Note:** The context must have been created with a compatible window. -proc glGetCurrentWindow* : WindowPtr {. - importc: "SDL_GL_GetCurrentWindow".} -proc glGetCurrentContext*: GlContextPtr {. - importc: "SDL_GL_GetCurrentContext".} +proc glGetCurrentWindow*: WindowPtr {.importc: "SDL_GL_GetCurrentWindow".} + ## Get the currently active OpenGL window. -proc glGetDrawableSize* (window: WindowPtr; w,h: var cint) {. - importc: "SDL_GL_GetDrawableSize".} +proc glGetCurrentContext*: GlContextPtr {.importc: "SDL_GL_GetCurrentContext".} + ## Get the currently active OpenGL context. -proc glSetSwapInterval* (interval: cint): cint {. +proc glGetDrawableSize*(window: WindowPtr; w,h: var cint) {. + importc: "SDL_GL_GetDrawableSize".} + ## Get the size of a window's underlying drawable in pixels + ## (for use with glViewport). + ## + ## `window` Window from which the drawable size should be queried. + ## + ## `w` Pointer to variable for storing the width in pixels, may be `nil`. + ## + ## `h` Pointer to variable for storing the height in pixels, may be `nil`. + ## + ## This may differ from `getSize()` if we're rendering to a high-DPI + ## drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a + ## platform with high-DPI support (Apple calls this "Retina"), and not + ## disabled by the `HINT_VIDEO_HIGHDPI_DISABLED` hint. + ## + ## **See also:** + ## * `getSize proc<#getSize,WindowPtr,cint,cint>`_ + ## * `createWindow proc<#createWindow,cstring,cint,cint,cint,cint,uint32>`_ + # TODO: Add `HINT_VIDEO_HIGHDPI_DISABLED` + +proc glSetSwapInterval*(interval: cint): cint {. importc: "SDL_GL_SetSwapInterval".} -proc glGetSwapInterval* : cint {. - importc: "SDL_GL_GetSwapInterval".} - -proc glSwapWindow*(window: WindowPtr) {. - importc: "SDL_GL_SwapWindow".} + ## Set the swap interval for the current OpenGL context. + ## + ## `interval` `0` for immediate updates, `1` for updates synchronized + ## with the vertical retrace. If the system supports it, you may specify + ## `-1` to allow late swaps to happen immediately instead of waiting for + ## the next retrace. + ## + ## `Return` `0` on success, or `-1` if setting the swap interval + ## is not supported. + ## + ## **See also:** + ## * `glGetSwapInterval proc<#glGetSwapInterval>`_ + +proc glGetSwapInterval*: cint {.importc: "SDL_GL_GetSwapInterval".} + ## Get the swap interval for the current OpenGL context. + ## + ## `Return` `0` if there is no vertical retrace synchronization, + ## `1` if the buffer swap is synchronized with the vertical retrace, and + ## `-1` if late swaps happen immediately instead of waiting for the next + ## retrace. If the system can't determine the swap interval, or there isn't + ## a valid current context, this will return `0` as a safe default. + ## + ## **See also:** + ## * `glSetSwapInterval proc<#glSetSwapInterval,cint>`_ + +proc glSwapWindow*(window: WindowPtr) {.importc: "SDL_GL_SwapWindow".} ## Swap the OpenGL buffers for a window, if double-buffering is supported. -proc glDeleteContext* (context: GlContextPtr) {. - importc: "SDL_GL_DeleteContext".} - +proc glDeleteContext*(context: GlContextPtr) {.importc: "SDL_GL_DeleteContext".} + ## Delete an OpenGL context. + ## + ## **See also:** + ## * `glCreateContext proc<#glCreateContext,WindowPtr>`_ -##SDL_vulkan.h +# SDL_vulkan.h type VkHandle = int64 type VkNonDispatchableHandle = int64 @@ -1367,108 +3044,423 @@ type VkNonDispatchableHandle = int64 type VulkanInstance* = VkHandle type VulkanSurface* = VkNonDispatchableHandle -#extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path); -proc vulkanLoadLibrary*(path: cstring):cint {. + +proc vulkanLoadLibrary*(path: cstring): cint {. importc: "SDL_Vulkan_LoadLibrary".} + ## Dynamically load a Vulkan loader library. + ## + ## `path` The platform dependent Vulkan loader library name, or `nil`. + ## + ## `Return` `0` on success, or `-1` if the library couldn't be loaded. + ## + ## If `path` is `nil` SDL will use the value of the environment variable + ## `SDL_VULKAN_LIBRARY`, if set, otherwise it loads the default Vulkan + ## loader library. + ## + ## This should be called after initializing the video driver, but before + ## creating any Vulkan windows. If no Vulkan loader library is loaded, the + ## default library will be loaded upon creation of the first Vulkan window. + ## + ## **Note:** It is fairly common for Vulkan applications to link with + ## `libvulkan` instead of explicitly loading it at run time. This will + ## work with SDL provided the application links to a dynamic library and + ## both it and SDL use the same search path. + ## + ## **Note:** If you specify a non-`nil` `path`, an application should + ## retrieve all of the Vulkan procedures it uses from the dynamic library + ## using `vulkanGetVkGetInstanceProcAddr()` unless you can guarantee + ## `path` points to the same vulkan loader library the application + ## linked to. + ## + ## **Note:** On Apple devices, if `path` is `nil`, SDL will attempt to find + ## the `vkGetInstanceProcAddr` address within all the mach-o images of + ## the current process. This is because it is fairly common for Vulkan + ## applications to link with libvulkan (and historically MoltenVK was + ## provided as a static library). If it is not found then, on macOS, SDL + ## will attempt to load `vulkan.framework/vulkan`, `libvulkan.1.dylib`, + ## followed by `libvulkan.dylib`, in that order. + ## On iOS SDL will attempt to load `libvulkan.dylib` only. Applications + ## using a dynamic framework or .dylib must ensure it is included in its + ## application bundle. + ## + ## **Note:** On non-Apple devices, application linking with a static + ## libvulkan is not supported. Either do not link to the Vulkan loader or + ## link to a dynamic library version. + ## + ## **Note:** This procedures will fail if there are no working Vulkan drivers + ## installed. + ## + ## **See also:** + ## * `vulkanGetVkGetInstanceProcAddr proc<#vulkanGetVkGetInstanceProcAddr>`_ + ## * `vulkanUnloadLibrary proc<#vulkanUnloadLibrary>`_ -#extern DECLSPEC void *SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void); proc vulkanGetVkGetInstanceProcAddr*(): pointer {. importc: "SDL_Vulkan_GetVkGetInstanceProcAddr".} + ## Get the address of the `vkGetInstanceProcAddr` procedure. + ## + ## **Note:** This should be called after either calling `vulkanLoadLibrary` + ## or creating a `Window` with the `SDL_WINDOW_VULKAN` flag. + +proc vulkanUnloadLibrary*() {.importc: "SDL_Vulkan_UnloadLibrary".} + ## Unload the Vulkan loader library previously loaded by + ## `vulkanLoadLibrary()`. + ## + ## **See also:** + ## * `vulkanLoadLibrary proc<#vulkanLoadLibrary,cstring>`_ + +proc vulkanGetInstanceExtensions*(window: WindowPtr, pCount: ptr cuint, + pNames: cstringArray): Bool32 {.importc: "SDL_Vulkan_GetInstanceExtensions".} + ## Get the names of the Vulkan instance extensions needed to create + ## a surface with `vulkan_CreateSurface()`. + ## + ## `window` `nil` or window for which the required Vulkan instance + ## extensions should be retrieved. + ## + ## `pCount` Pointer to an `cuint` related to the number of + ## required Vulkan instance extensions. + ## + ## `pNames` `nil` or a pointer to an array to be filled with the + ## required Vulkan instance extensions. + ## + ## `Return` `true` on success, `false` on error. + ## + ## If `pNames` is `nil`, then the number of required Vulkan instance + ## extensions is returned in `pCount`. Otherwise, `pCount` must point + ## to a variable set to the number of elements in the `pNames` array, + ## and on return the variable is overwritten with the number of names + ## actually written to `pNames`. If `pCount` is less than the number + ## of required extensions, at most `pCount` structures will be written. + ## If `pCount` is smaller than the number of required extensions, + ## `0` will be returned instead `1`, to indicate that not all the required + ## extensions were returned. + ## + ## **Note:** If `window` is not `nil`, it will be checked against its + ## creation flags to ensure that the Vulkan flag is present. This parameter + ## will be removed in a future major release. + ## + ## **Note:** The returned list of extensions will contain VK_KHR_surface + ## and zero or more platform specific extensions + ## + ## **Note:** The extension names queried here must be enabled when calling + ## `vulkanCreateInstance`, otherwise surface creation will fail. + ## + ## **Note:** `window` should have been created with the + ## `SDL_WINDOW_VULKAN` flag or be `nil`. + ## + ## **See also:** + ## * `vulkanCreateSurface proc<#vulkanCreateSurface,WindowPtr,VulkanInstance,ptr.VulkanSurface>`_ -#extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); -proc vulkanUnloadLibrary*() {. - importc: "SDL_Vulkan_UnloadLibrary".} - -#extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_GetInstanceExtensions( -# SDL_Window *window, -# unsigned int *pCount, -# const char **pNames); -proc vulkanGetInstanceExtensions*(window: WindowPtr, pCount: ptr cuint, pNames: cstringArray): Bool32 {. - importc: "SDL_Vulkan_GetInstanceExtensions".} - -#extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface( -# SDL_Window *window, -# VkInstance instance, -# VkSurfaceKHR* surface); proc vulkanCreateSurface*(window: WindowPtr, instance: VulkanInstance, surface: ptr VulkanSurface): Bool32 {. importc: "SDL_Vulkan_CreateSurface".} + ## Create a Vulkan rendering surface for a window. + ## + ## `window` `Window` to which to attach the rendering surface. + ## + ## `instance` Handle to the Vulkan instance to use. + ## + ## `surface` receives the handle of the newly created surface. + ## + ## `Return` `true` on success, `false` on error. + ## + ## .. code-block:: nim + ## var + ## instance: VulkanInstance + ## window: WindowPtr + ## + ## # create instance and window + ## + ## # create the Vulkan surface + ## var surface: VulkanSurface + ## if not vulkanCreateSurface(window, instance, addr(surface)): + ## handleError() + ## + ## **Note:** `window` should have been created with the + ## `SDL_WINDOW_VULKAN` flag. + ## + ## **Note:** `instance` should have been created with the + ## extensions returned by `vulkanCreateSurface()` enabled. + ## + ## **See also:** + ## * `vulkanGetInstanceExtensions proc<#vulkanGetInstanceExtensions,WindowPtr,ptr.cuint,cstringArray>`_ -#extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window * window, -# int *w, int *h); proc vulkanGetDrawableSize*(window: WindowPtr, w, h: ptr cint) {. importc: "SDL_Vulkan_GetDrawableSize".} - -##SDL_keyboard.h: + ## Get the size of a window's underlying drawable in pixels + ## (for use with setting viewport, scissor & etc). + ## + ## `window` `Window` from which the drawable size should be queried. + ## + ## `w` Pointer to variable for storing the width in pixels, + ## may be `nil`. + ## + ## `h` Pointer to variable for storing the height in pixels, + ## may be `nil`. + ## + ## This may differ from `getSize()` if we're rendering to a high-DPI + ## drawable, i.e. the window was created with `WINDOW_ALLOW_HIGHDPI` on a + ## platform with high-DPI support (Apple calls this "Retina"), + ## and not disabled by the `HINT_VIDEO_HIGHDPI_DISABLED` hint. + ## + ## **Note:** On macOS high-DPI support must be enabled for an application by + ## setting `NSHighResolutionCapable` to `true` in its `Info.plist`. + ## + ## **See also:** + ## * `getSize proc<#getSize,WindowPtr,cint,cint>`_ + ## * `createWindow proc<#createWindow,cstring,cint,cint,cint,cint,uint32>`_ + +# SDL_keyboard.h: proc getKeyboardFocus*: WindowPtr {.importc: "SDL_GetKeyboardFocus".} - #Get the window which currently has keyboard focus. + ## Get the window which currently has keyboard focus. + proc getKeyboardState*(numkeys: ptr int = nil): ptr array[0 .. SDL_NUM_SCANCODES.int, uint8] {.importc: "SDL_GetKeyboardState".} - #Get the snapshot of the current state of the keyboard + ## Get a snapshot of the current state of the keyboard. + ## + ## `numkeys` if non-`nil`, receives the length of the returned array. + ## + ## `Return` an array of key states. Indexes into this array are obtained + ## by using `Scancode` values. + ## + ## Example: + ## + ## .. code-block:: nim + ## let state = getKeyboardState(nil) + ## if state[SCANCODE_RETURN.int] > 0: + ## echo " is pressed." + proc getModState*: Keymod {.importc: "SDL_GetModState".} - #Get the current key modifier state for the keyboard + ## Get the current key modifier state for the keyboard + proc setModState*(state: Keymod) {.importc: "SDL_SetModState".} - #Set the current key modifier state for the keyboard + ## Set the current key modifier state for the keyboard. + ## + ## **Note:** This does not change the keyboard state, + ## only the key modifier flags. + proc getKeyFromScancode*(scancode: ScanCode): cint {.importc: "SDL_GetKeyFromScancode".} - #Get the key code corresponding to the given scancode according to the current keyboard layout + ## Get the key code corresponding to the given scancode according + ## to the current keyboard layout. + ## + ## See `Keycode` for details. + ## + ## **See also:** + ## * `getKeyName proc<#getKeyName,cint>`_ + proc getScancodeFromKey*(key: cint): ScanCode {.importc: "SDL_GetScancodeFromKey".} - #Get the scancode corresponding to the given key code according to the current keyboard layout + ## Get the scancode corresponding to the given key code + ## according to the current keyboard layout. + ## + ## See `Scancode` for details. + ## + ## **See also:** + ## * `getScancodeName proc<#getScancodeName,ScanCode>`_ + proc getScancodeName*(scancode: ScanCode): cstring {.importc: "SDL_GetScancodeName".} - #Get a human-readable name for a scancode + ## Get a human-readable name for a scancode. + ## + ## `Return` a pointer to the name for the scancode. + ## If the scancode doesn't have a name, this procedure + ## returns an empty string (""). + ## + ## **See also:** + ## * `ScanCode type<#ScanCode>`_ + proc getScancodeFromName*(name: cstring): ScanCode {.importc: "SDL_GetScancodeFromName".} - #Get a scancode from a human-readable name -proc getKeyName*(key: cint): cstring {. - importc: "SDL_GetKeyName".} - #Get a human-readable name for a key -proc getKeyFromName*(name: cstring): cint {. - importc: "SDL_GetKeyFromName".} - #Get a key code from a human-readable name -proc startTextInput* {. - importc: "SDL_StartTextInput".} - #Start accepting Unicode text input events -proc isTextInputActive*: bool {. - importc: "SDL_IsTextInputActive".} -proc stopTextInput* {. - importc: "SDL_StopTextInput".} -proc setTextInputRect*(rect: ptr Rect) {. - importc: "SDL_SetTextInputRect".} + ## Get a scancode from a human-readable name. + ## + ## `Return` scancode, or `SDL_SCANCODE_UNKNOWN` if the name wasn't recognized. + ## + ## **See also:** + ## * `ScanCode type<#ScanCode>`_ + +proc getKeyName*(key: cint): cstring {.importc: "SDL_GetKeyName".} + ## Get a human-readable name for a key. + ## + ## `Return` a pointer to a UTF-8 string that stays valid at least until + ## the next call to this procedure. If you need it around any longer, + ## you must copy it. If the key doesn't have a name, this procedure returns + ## an empty string (""). + +proc getKeyFromName*(name: cstring): cint {.importc: "SDL_GetKeyFromName".} + ## Get a key code from a human-readable name. + ## + ## `Return` key code, or `K_UNKNOWN` if the name wasn't recognized. + +proc startTextInput* {.importc: "SDL_StartTextInput".} + ## Start accepting Unicode text input events. + ## + ## This procedure will show the on-screen keyboard if supported. + ## + ## **See also:** + ## * `stopTextInput proc<#stopTextInput>`_ + ## * `setTextInputRect proc<#setTextInputRect,ptr.Rect>`_ + ## * `hasScreenKeyboardSupport proc<#hasScreenKeyboardSupport>`_ + +proc isTextInputActive*: bool {.importc: "SDL_IsTextInputActive".} + ## Return whether or not Unicode text input events are enabled. + ## + ## **See also:** + ## * `startTextInput proc<#startTextInput>`_ + ## * `stopTextInput proc<#stopTextInput>`_ + +proc stopTextInput* {.importc: "SDL_StopTextInput".} + ## Stop receiving any text input events. + ## + ## This procedure will hide the on-screen keyboard if supported. + ## + ## **See also:** + ## * `startTextInput proc<#startTextInput>`_ + ## * `hasScreenKeyboardSupport proc<#hasScreenKeyboardSupport>`_ + +proc setTextInputRect*(rect: ptr Rect) {.importc: "SDL_SetTextInputRect".} + ## Set the rectangle used to type Unicode text inputs. + ## + ## This is used as a hint for IME and on-screen keyboard placement. + ## + ## **See also:** + ## * `startTextInput proc<#startTextInput>`_ + proc hasScreenKeyboardSupport*: bool {.importc: "SDL_HasScreenKeyboardSupport".} + ## Returns whether the platform has some screen keyboard support. + ## + ## `Return` `true` if some keyboard support is available else `false`. + ## + ## **Note:** Not all screen keyboard procedures are supported + ## on all platforms. + ## + ## **See also:** + ## * `isScreenKeyboardShown proc<#isScreenKeyboardShown,WindowPtr>`_ + proc isScreenKeyboardShown*(window: WindowPtr): bool {.importc: "SDL_IsScreenKeyboardShown".} + ## Returns whether the screen keyboard is shown for given window. + ## + ## `window` The window for which screen keyboard should be queried. + ## + ## `Return` `true` if screen keyboard is shown else `false`. + ## + ## **See also:** + ## * `hasScreenKeyboardSupport proc<#hasScreenKeyboardSupport>`_ proc getMouseFocus*(): WindowPtr {.importc: "SDL_GetMouseFocus".} -#* -# \brief Retrieve the current state of the mouse. -# -# The current button state is returned as a button bitmask, which can -# be tested using the SDL_BUTTON(X) macros, and x and y are set to the -# mouse cursor position relative to the focus window for the currently -# selected mouse. You can pass NULL for either x or y. -# + ## Get the window which currently has mouse focus. + proc getMouseState*(x, y: var cint): uint8 {.importc: "SDL_GetMouseState", discardable.} + proc getMouseState*(x, y: ptr cint): uint8 {.importc: "SDL_GetMouseState", discardable.} -#* + ## Retrieve the current state of the mouse. + ## + ## The current button state is returned as a button bitmask, which can + ## be tested using the `button()` template, and `x` and `y` are set to the + ## mouse cursor position relative to the focus window for the currently + ## selected mouse. You can pass `nil` for either `x` or `y`. + proc getRelativeMouseState*(x, y: var cint): uint8 {. importc: "SDL_GetRelativeMouseState".} -#* + ## Retrieve the relative state of the mouse. + ## + ## The current button state is returned as a button bitmask, which can + ## be tested using the `button()` template, and x and y are set to the + ## mouse deltas since the last call to `getRelativeMouseState()`. + proc warpMouseInWindow*(window: WindowPtr; x, y: cint) {. importc: "SDL_WarpMouseInWindow".} -#* + ## Moves the mouse to the given position within the window. + ## + ## `window` The window to move the mouse into, + ## or `nil` for the current mouse focus + ## + ## `x` The x coordinate within the window + ## + ## `y` The y coordinate within the window + ## + ## **Note:** This procedure generates a mouse motion event. + proc setRelativeMouseMode*(enabled: Bool32): SDL_Return {. importc: "SDL_SetRelativeMouseMode".} -#* + ## Set relative mouse mode. + ## + ## `enabled` Whether or not to enable relative mode + ## + ## `Return` `0` on success, or `-1` if relative mode is not supported. + ## + ## While the mouse is in relative mode, the cursor is hidden, and the + ## driver will try to report continuous motion in the current window. + ## Only relative motion events will be delivered, the mouse position + ## will not change. + ## + ## **Note:** This procedure will flush any pending mouse motion. + ## + ## **See also:** + ## * `getRelativeMouseMode proc<#getRelativeMouseMode>`_ + proc captureMouse*(enabled: Bool32): SDL_Return {. importc: "SDL_CaptureMouse" .} -#* + ## Capture the mouse, to track input outside an SDL window. + ## + ## `enabled` Whether or not to enable capturing + ## + ## Capturing enables your app to obtain mouse events globally, instead of + ## just within your window. Not all video targets support this procedure. + ## When capturing is enabled, the current window will get all mouse events, + ## but unlike relative mode, no change is made to the cursor and it is + ## not restrained to your window. + ## + ## This procedure may also deny mouse input to other windows - both those in + ## your application and others on the system - so you should use this + ## procedure sparingly, and in small bursts. For example, you might want to + ## track the mouse while the user is dragging something, until the user + ## releases a mouse button. It is not recommended that you capture the mouse + ## for long periods of time, such as the entire time your app is running. + ## + ## While captured, mouse events still report coordinates relative to the + ## current (foreground) window, but those coordinates may be outside the + ## bounds of the window (including negative values). Capturing is only + ## allowed for the foreground window. If the window loses focus while + ## capturing, the capture will be disabled automatically. + ## + ## While capturing is enabled, the current window will have the + ## `SDL_WINDOW_MOUSE_CAPTURE` flag set. + ## + ## `Return` `0` on success, or `-1` if not supported. + proc getRelativeMouseMode*(): Bool32 {.importc: "SDL_GetRelativeMouseMode".} -#* + ## Query whether relative mouse mode is enabled. + ## + ## **See also:** + ## * `setRelativeMouseMode proc<#setRelativeMouseMode,Bool32>`_ + proc createCursor*(data, mask: ptr uint8; w, h, hot_x, hot_y: cint): CursorPtr {.importc: "SDL_CreateCursor".} -#* + ## Create a cursor, using the specified bitmap data and mask (in MSB format). + ## + ## The cursor width must be a multiple of 8 bits. + ## + ## The cursor is created in black and white according to the following: + ## + ## :: + ## ==== ==== ======================================== + ## data mask resulting pixel on screen + ## ==== ==== ======================================== + ## 0 1 White + ## 1 1 Black + ## 0 0 Transparent + ## 1 0 Inverted color if possible, black if not. + ## ==== ==== ========================================= + ## + ## **See also:** + ## * `freeCursor proc<#freeCursor,CursorPtr>`_ + proc createColorCursor*(surface: SurfacePtr; hot_x, hot_y: cint): CursorPtr {. importc: "SDL_CreateColorCursor".} -#* + ## Create a color cursor. + ## + ## **See also:** + ## * `freeCursor proc<#freeCursor,CursorPtr>`_ + type SystemCursor* = enum + ## Cursor types for `sdl.createSystemCursor()`. SDL_SYSTEM_CURSOR_ARROW, ## Arrow SDL_SYSTEM_CURSOR_IBEAM, ## I-beam SDL_SYSTEM_CURSOR_WAIT, ## Wait @@ -1484,232 +3476,319 @@ type proc createSystemCursor*(c: SystemCursor): CursorPtr {. importc: "SDL_CreateSystemCursor".} + ## Create a system cursor. + ## + ## **See also:** + ## * `freeCursor proc<#freeCursor,CursorPtr>`_ + proc setCursor*(cursor: CursorPtr) {.importc: "SDL_SetCursor".} + ## Set the active cursor. + proc getCursor*(): CursorPtr {.importc: "SDL_GetCursor".} -proc freeCursor* (cursor: CursorPtr) {.importc: "SDL_FreeCursor".} -proc showCursor* (toggle: bool): Bool32 {.importc: "SDL_ShowCursor", discardable.} + ## Return the active cursor. + +proc freeCursor*(cursor: CursorPtr) {.importc: "SDL_FreeCursor".} + ## Frees a cursor created with `createCursor()` or similar procedures. + ## + ## **See also:** + ## * `createCursor proc<#createCursor,ptr.uint8,cint,cint,cint,cint>`_ + ## * `createColorCursor proc<#createColorCursor,SurfacePtr,cint,cint>`_ + ## * `createSystemCursor proc<#createSystemCursor,SystemCursor>`_ + +proc showCursor*(toggle: bool): Bool32 {.importc: "SDL_ShowCursor", discardable.} + ## Toggle whether or not the cursor is shown. + ## + ## `toggle` `1` to show the cursor, `0` to hide it, + ## `-1` to query the current state. + ## + ## `Return` `1` if the cursor is shown, or `0` if the cursor is hidden. # Function prototypes -#* -# Pumps the event loop, gathering events from the input devices. -# -# This function updates the event queue and internal input device state. -# -# This should only be run in the thread that sets the video mode. -# + proc pumpEvents*() {.importc: "SDL_PumpEvents".} + ## Pumps the event loop, gathering events from the input devices. + ## + ## This procedure updates the event queue and internal input device state. + ## + ## This should only be run in the thread that sets the video mode. -#* -# Checks the event queue for messages and optionally returns them. -# -# If \c action is ::SDL_ADDEVENT, up to \c numevents events will be added to -# the back of the event queue. -# -# If \c action is ::SDL_PEEKEVENT, up to \c numevents events at the front -# of the event queue, within the specified minimum and maximum type, -# will be returned and will not be removed from the queue. -# -# If \c action is ::SDL_GETEVENT, up to \c numevents events at the front -# of the event queue, within the specified minimum and maximum type, -# will be returned and will be removed from the queue. -# -# \return The number of events actually stored, or -1 if there was an error. -# -# This function is thread-safe. -# proc peepEvents*(events: ptr Event; numevents: cint; action: Eventaction; minType: uint32; maxType: uint32): cint {.importc: "SDL_PeepEvents".} -#@} -#* -# Checks to see if certain event types are in the event queue. -# + ## Checks the event queue for messages and optionally returns them. + ## + ## If `action` is `SDL_ADDEVENT`, up to `numevents` events will be added to + ## the back of the event queue. + ## + ## If `action` is `SDL_PEEKEVENT`, up to `numevents` events at the front + ## of the event queue, within the specified minimum and maximum type, + ## will be returned and will not be removed from the queue. + ## + ## If `action` is `SDL_GETEVENT`, up to `numevents` events at the front + ## of the event queue, within the specified minimum and maximum type, + ## will be returned and will be removed from the queue. + ## + ## `Return` the number of events actually stored, + ## or `-1` if there was an error. + ## + ## This procedure is thread-safe. + + proc hasEvent*(kind: uint32): Bool32 {.importc: "SDL_HasEvent".} + ## Checks to see if certain event types are in the event queue. + proc hasEvents*(minType: uint32; maxType: uint32): Bool32 {.importc: "SDL_HasEvents".} + proc flushEvent*(kind: uint32) {.importc: "SDL_FlushEvent".} + ## This procedure clears events from the event queue. + ## + ## This procedure only affects currently queued events. + ## If you want to make sure that all pending OS events are flushed, + ## you can call `pumpEvents()` on the main thread immediately before + ## flush call. + proc flushEvents*(minType: uint32; maxType: uint32) {.importc: "SDL_FlushEvents".} proc pollEvent*(event: var Event): Bool32 {.importc: "SDL_PollEvent".} + ## Polls for currently pending events. + ## + ## `Return` `1` if there are any pending events, + ## or `0` if there are none available. + ## + ## `event` If not `nil`, the next event is removed from the queue + ## and stored in that area. + proc waitEvent*(event: var Event): Bool32 {.importc: "SDL_WaitEvent".} -proc waitEventTimeout*(event: var Event; timeout: cint): Bool32 {.importc: "SDL_WaitEventTimeout".} -#* -# \brief Add an event to the event queue. -# -# \return 1 on success, 0 if the event was filtered, or -1 if the event queue -# was full or there was some other error. -# + ## Waits indefinitely for the next available event. + ## + ## `Return` `1`, or `0` if there was an error while waiting for events. + ## + ## `event` If not `nil`, the next event is removed from the queue + ## and stored in that area. + +proc waitEventTimeout*(event: var Event; timeout: cint): Bool32 {. + importc: "SDL_WaitEventTimeout".} + ## Waits until the specified timeout (in milliseconds) + ## for the next available event. + ## + ## `Return` `1`, or `0` if there was an error while waiting for events. + ## + ## `event` If not `nil`, the next event is removed from the queue + ## and stored in that area. + ## `timeout` The timeout (in milliseconds) + ## to wait for next event. + proc pushEvent*(event: ptr Event): cint {.importc: "SDL_PushEvent".} + ## Add an event to the event queue. + ## + ## `Return` `1` on success, `0` if the event was filtered, + ## or `-1` if the event queue was full or there was some other error. -#* proc setEventFilter*(filter: EventFilter; userdata: pointer) {.importc: "SDL_SetEventFilter".} -#* -# Return the current event filter - can be used to "chain" filters. -# If there is no event filter set, this function returns SDL_FALSE. -# -proc getEventFilter*(filter: var EventFilter; userdata: var pointer): Bool32 {.importc: "SDL_GetEventFilter".} -#* -# Add a function which is called when an event is added to the queue. -# -proc addEventWatch*(filter: EventFilter; userdata: pointer) {.importc: "SDL_AddEventWatch".} -#* -# Remove an event watch function added with SDL_AddEventWatch() -# -proc delEventWatch*(filter: EventFilter; userdata: pointer) {.importc: "SDL_DelEventWatch".} -#* -# Run the filter function on the current event queue, removing any -# events for which the filter returns 0. -# -proc filterEvents*(filter: EventFilter; userdata: pointer) {.importc: "SDL_FilterEvents".} -#@{ -# -#/** -# This function allows you to set the state of processing certain events. -# - If \c state is set to ::SDL_IGNORE, that event will be automatically -# dropped from the event queue and will not event be filtered. -# - If \c state is set to ::SDL_ENABLE, that event will be processed -# normally. -# - If \c state is set to ::SDL_QUERY, SDL_EventState() will return the -# current processing state of the specified event. -# -proc eventState*(kind: EventType; state: cint): uint8 {.importc: "SDL_EventState".} -#@} -# -#/** -# This function allocates a set of user-defined events, and returns -# the beginning event number for that set of events. -# -# If there aren't enough user-defined events left, this function -# returns (uint32)-1 -# -proc registerEvents*(numevents: cint): uint32 {.importc: "SDL_RegisterEvents".} + ## Sets up a filter to process all events before they change internal state + ## and are posted to the internal event queue. + ## + ## The filter is prototyped as: + ## + ## proc EventFilter(userdata: pointer; event: ptr Event): cint {.cdecl.} + ## + ## If the filter returns `1`, then the event will be added + ## to the internal queue. + ## If it returns `0`, then the event will be dropped from the queue, + ## but the internal state will still be updated. This allows selective + ## filtering of dynamically arriving events. + ## + ## `Warning:` Be very careful of what you do in the event filter procedure, + ## as it may run in a different thread! + ## + ## There is one caveat when dealing with the `QuitEvent` event type. The + ## event filter is only called when the window manager desires to close the + ## application window. If the event filter returns `1`, then the window + ## will be closed, otherwise the window will remain open if possible. + ## + ## If the quit event is generated by an interrupt signal, it will bypass the + ## internal queue and be delivered to the application at the next event poll. + + +proc getEventFilter*(filter: var EventFilter; userdata: var pointer): Bool32 {. + importc: "SDL_GetEventFilter".} + ## Return the current event filter - can be used to "chain" filters. + ## If there is no event filter set, this procedure returns `false`. + +proc addEventWatch*(filter: EventFilter; userdata: pointer) {. + importc: "SDL_AddEventWatch".} + ## Add a procedure which is called when an event is added to the queue. + +proc delEventWatch*(filter: EventFilter; userdata: pointer) {. + importc: "SDL_DelEventWatch".} + ## Remove an event watch procedure added with `addEventWatch()` + +proc filterEvents*(filter: EventFilter; userdata: pointer) {. + importc: "SDL_FilterEvents".} + ## Run the filter procedure on the current event queue, removing any + ## events for which the filter returns `0`. + +proc eventState*(kind: EventType; state: cint): uint8 {. + importc: "SDL_EventState".} + ## This procedure allows you to set the state of processing certain events. + ## + ## * If `state` is set to `SDL_IGNORE`, that event will be automatically + ## dropped from the event queue and will not be filtered. + ## * If `state` is set to `SDL_ENABLE`, that event will be processed normally. + ## * If `state` is set to `SDL_QUERY`, `eventState()` will return the + ## current processing state of the specified event. +proc registerEvents*(numevents: cint): uint32 {.importc: "SDL_RegisterEvents".} + ## This procedure allocates a set of user-defined events, and returns + ## the beginning event number for that set of events. + ## + ## If there aren't enough user-defined events left, this procedure + ## returns `-1'u32`. proc setError*(fmt: cstring) {.varargs, importc: "SDL_SetError".} + ## Set the error message for the current thread. + ## + ## `Return` `-1`, there is no error handling for this procedure. + proc getError*(): cstring {.importc: "SDL_GetError".} + ## Get the last error message that was set. + ## + ## SDL API procedures may set error messages and then succeed, so you should + ## only use the error value if a procedure fails. + ## + ## This returns a pointer to a static buffer for convenience and should not + ## be called by multiple threads simultaneously. + ## + ## `Return` a `cstring` of the last error message that was set. + proc clearError*() {.importc: "SDL_ClearError".} + ## Clear the error message for the current thread. -#extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(uint32 format); -proc getPixelFormatName* (format: uint32): cstring {. +proc getPixelFormatName*(format: uint32): cstring {. importc: "SDL_GetPixelFormatName".} ## Get the human readable name of a pixel format -#extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(uint32 format, -# int *bpp, -# uint32 * Rmask, -# uint32 * Gmask, -# uint32 * Bmask, -# uint32 * Amask); -proc pixelFormatEnumToMasks* (format: uint32; bpp: var cint; +proc pixelFormatEnumToMasks*(format: uint32; bpp: var cint; Rmask, Gmask, Bmask, Amask: var uint32): bool {. importc: "SDL_PixelFormatEnumToMasks".} - ##Convert one of the enumerated pixel formats to a bpp and RGBA masks. - ##Returns TRUE or FALSE if the conversion wasn't possible. - - -#extern DECLSPEC uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp, -# uint32 Rmask, -# uint32 Gmask, -# uint32 Bmask, -# uint32 Amask); -proc masksToPixelFormatEnum* (bpp: cint; Rmask, Gmask, Bmask, Amask: uint32): uint32 {. - importc: "SDL_MasksToPixelFormatEnum".} - ##Convert a bpp and RGBA masks to an enumerated pixel format. - ##The pixel format, or ::SDL_PIXELFORMAT_UNKNOWN if the conversion wasn't possible. - -#extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_AllocFormat(uint32 pixel_format); -proc allocFormat* (pixelFormat: uint32): ptr PixelFormat {. + ## Convert one of the enumerated pixel formats to a bpp and RGBA masks. + ## Returns `true` or `false` if the conversion wasn't possible. + ## **See also:** + ## * `masksToPixelFormatEnum proc<#masksToPixelFormatEnum,cint,uint32,uint32,uint32,uint32>`_ + + +proc masksToPixelFormatEnum*(bpp: cint; Rmask, Gmask, Bmask, Amask: uint32): + uint32 {.importc: "SDL_MasksToPixelFormatEnum".} + ## Convert a bpp and RGBA masks to an enumerated pixel format. + ## The pixel format, or `SDL_PIXELFORMAT_UNKNOWN` if the conversion wasn't possible. + ## + ## **See also:** + ## * `pixelFormatEnumToMasks proc<#pixelFormatEnumToMasks,uint32,cint,uint32,uint32,uint32,uint32>`_ + +proc allocFormat*(pixelFormat: uint32): ptr PixelFormat {. importc: "SDL_AllocFormat".} -##Create an SDL_PixelFormat structure from a pixel format enum. + ## Create a `PixelFormat` object from a pixel format enum. -#extern DECLSPEC void SDLCALL SDL_FreeFormat(SDL_PixelFormat *format); -proc freeFormat* (format: ptr PixelFormat) {. +proc freeFormat*(format: ptr PixelFormat) {. importc: "SDL_FreeFormat".} - ##Free an SDL_PixelFormat structure. + ## Free a `PixelFormat` object. -#extern DECLSPEC SDL_Palette *SDLCALL SDL_AllocPalette(int ncolors); -proc allocPalette* (numColors: cint): ptr Palette {. +proc allocPalette*(numColors: cint): ptr Palette {. importc: "SDL_AllocPalette".} - ##Create a palette structure with the specified number of color entries. - ##Returns A new palette, or NULL if there wasn't enough memory. - ##Note: The palette entries are initialized to white. + ## Create a palette structure with the specified number of color entries. + ## Returns A new palette, or `nil` if there wasn't enough memory. + ## Note: The palette entries are initialized to white. -#extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format, -# SDL_Palette *palette); -proc setPixelFormatPalette* (format: ptr PixelFormat; palette: ptr Palette): cint {. +proc setPixelFormatPalette*(format: ptr PixelFormat; palette: ptr Palette): cint {. importc: "SDL_SetPixelFormatPalette".} - ##Set the palette for a pixel format structure. + ## Set the palette for a pixel format object. -#extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette, -# const SDL_Color * colors, -# int firstcolor, int ncolors); -proc setPaletteColors* (palette: ptr Palette; colors: ptr Color; first, numColors: cint): SDL_Return {.discardable, - importc: "SDL_SetPaletteColors".} +proc setPaletteColors*(palette: ptr Palette; colors: ptr Color; + first, numColors: cint): SDL_Return {. + discardable, importc: "SDL_SetPaletteColors".} ## Set a range of colors in a palette. -#extern DECLSPEC void SDLCALL SDL_FreePalette(SDL_Palette * palette); -proc freePalette* (palette: ptr Palette) {. + +proc freePalette*(palette: ptr Palette) {. importc: "SDL_FreePalette".} - ##Free a palette created with SDL_AllocPalette(). + ## Free a palette created with `allocPalette()`. -#extern DECLSPEC uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format, -# uint8 r, uint8 g, uint8 b); -proc mapRGB* (format: ptr PixelFormat; r,g,b: uint8): uint32 {. +proc mapRGB*(format: ptr PixelFormat; r,g,b: uint8): uint32 {. importc: "SDL_MapRGB".} - ##Maps an RGB triple to an opaque pixel value for a given pixel format. + ## Maps an RGB triple to an opaque pixel value for a given pixel format. + ## + ## **See also:** + ## * `mapRGBA proc<#mapRGBA,ptr.PixelFormat,uint8,uint8,uint8,uint8>`_ -#extern DECLSPEC uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format, -# uint8 r, uint8 g, uint8 b, -# uint8 a); -proc mapRGBA* (format: ptr PixelFormat; r,g,b,a: uint8): uint32 {. +proc mapRGBA*(format: ptr PixelFormat; r,g,b,a: uint8): uint32 {. importc: "SDL_MapRGBA".} - ##Maps an RGBA quadruple to a pixel value for a given pixel format. + ## Maps an RGBA quadruple to a pixel value for a given pixel format. + ## + ## **See also:** + ## * `mapRGB proc<#mapRGB,ptr.PixelFormat,uint8,uint8,uint8>`_ -#extern DECLSPEC void SDLCALL SDL_GetRGB(uint32 pixel, -# const SDL_PixelFormat * format, -# uint8 * r, uint8 * g, uint8 * b); -proc getRGB* (pixel: uint32; format: ptr PixelFormat; r,g,b: var uint8) {. +proc getRGB*(pixel: uint32; format: ptr PixelFormat; r,g,b: var uint8) {. importc: "SDL_GetRGB".} - ##Get the RGB components from a pixel of the specified format. + ## Get the RGB components from a pixel of the specified format. + ## + ## **See also:** + ## * `getRGBA proc<#getRGBA,uint32,ptr.PixelFormat,uint8,uint8,uint8,uint8>`_ -#extern DECLSPEC void SDLCALL SDL_GetRGBA(uint32 pixel, -# const SDL_PixelFormat * format, -# uint8 * r, uint8 * g, uint8 * b, -# uint8 * a); -proc getRGBA* (pixel: uint32; format: ptr PixelFormat; r,g,b,a: var uint8) {. +proc getRGBA*(pixel: uint32; format: ptr PixelFormat; r,g,b,a: var uint8) {. importc: "SDL_GetRGBA".} ##Get the RGBA components from a pixel of the specified format. + ## + ## **See also:** + ## * `getRGB proc<#getRGB,uint32,ptr.PixelFormat,uint8,uint8,uint8>`_ -#extern DECLSPEC void SDLCALL SDL_CalculateGammaRamp(float gamma, uint16 * ramp); -proc calculateGammaRamp* (gamma: cfloat; ramp: ptr uint16) {. +proc calculateGammaRamp*(gamma: cfloat; ramp: ptr uint16) {. importc: "SDL_CalculateGammaRamp".} - ##Calculate a 256 entry gamma ramp for a gamma value. + ## Calculate a 256 entry gamma ramp for a gamma value. # SDL_clipboard.h proc setClipboardText*(text: cstring): cint {.importc: "SDL_SetClipboardText".} + ## Put UTF-8 text into the clipboard. + ## + ## **See also:** + ## * `getClipboardText proc<#getClipboardText>`_ + proc getClipboardText*(): cstring {.importc: "SDL_GetClipboardText".} + ## Get UTF-8 text from the clipboard, which must be freed with `free()`. + ## + ## **See also:** + ## * `setClipboardText proc<#setClipboardText,cstring>`_ + proc hasClipboardText*(): Bool32 {.importc: "SDL_HasClipboardText".} + ## Returns a flag indicating whether the clipboard exists and contains + ## a text string that is non-empty. + ## + ## **See also:** + ## * `getClipboardText proc<#getClipboardText>`_ + proc freeClipboardText*(text: cstring) {.importc: "SDL_free".} proc getNumTouchFingers*(id: TouchID): cint {.importc: "SDL_GetNumTouchFingers".} + ## Get the number of active fingers for a given touch device. + proc getTouchFinger*(id: TouchID, index: cint): ptr Finger {.importc: "SDL_GetTouchFinger".} + ## Get the finger object of the given touch, with the given index. + # SDL_system.h when defined(windows): - proc direct3D9GetAdapterIndex* (displayIndex: cint): cint {. + proc direct3D9GetAdapterIndex*(displayIndex: cint): cint {. importc: "SDL_Direct3D9GetAdapterIndex".} ## Returns the D3D9 adapter index that matches the specified display index. ## This adapter index can be passed to IDirect3D9::CreateDevice and controls ## on which monitor a full screen application will appear. - #extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer); - proc getD3D9Device* (renderer: RendererPtr): pointer {. + proc getD3D9Device*(renderer: RendererPtr): pointer {. importc:"SDL_RenderGetD3D9Device".} - ## Returns the D3D device associated with a renderer, or NULL if it's not a D3D renderer. + ## Returns the D3D device associated with a renderer, or `nil` if it's not a D3D renderer. ## Once you are done using the device, you should release it to avoid a resource leak. - #extern DECLSPEC void SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex ); - proc dXGIGetOutputInfo* (displayIndex: cint, adapterIndex,outputIndex: ptr cint) {.importc: "SDL_DXGIGetOutputInfo".} + proc dXGIGetOutputInfo*(displayIndex: cint, adapterIndex,outputIndex: ptr cint) {.importc: "SDL_DXGIGetOutputInfo".} ## Returns the DXGI Adapter and Output indices for the specified display index. ## These can be passed to EnumAdapters and EnumOutputs respectively to get the objects ## required to create a DX10 or DX11 device and swap chain. @@ -1717,47 +3796,37 @@ when defined(windows): elif defined(iPhone) or defined(ios): - #extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback( - # SDL_Window * window, int interval, - # void (*callback)(void*), void *callbackParam); - proc iPhoneSetAnimationCallback*(window: WindowPtr, interval:cint, callback: VoidCallback, callbackParam: pointer): cint {. + proc iPhoneSetAnimationCallback*(window: WindowPtr, interval:cint, + callback: VoidCallback, callbackParam: pointer): cint {. importc: "SDL_iPhoneSetAnimationCallback".} - #extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); - proc iPhoneSetEventPump*(enabled: bool) {. - importc: "SDL_iPhoneSetEventPump".} + proc iPhoneSetEventPump*(enabled: bool) {.importc: "SDL_iPhoneSetEventPump".} - #extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardShow(SDL_Window * window); proc iPhoneKeyboardShow*(window:WindowPtr): cint {. importc: "SDL_iPhoneKeyboardShow".} - #extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardHide(SDL_Window * window); + proc iPhoneKeyboardHide*(window:WindowPtr): cint {. importc: "SDL_iPhoneKeyboardHide".} - #extern DECLSPEC SDL_bool SDLCALL SDL_iPhoneKeyboardIsShown(SDL_Window * window); + proc iPhoneKeyboardIsShown*(window:WindowPtr): bool {. importc: "SDL_iPhoneKeyboardIsShown".} - #extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardToggle(SDL_Window * window); + proc iPhoneKeyboardToggle*(window:WindowPtr): cint {. importc: "SDL_iPhoneKeyboardToggle".} elif defined(android): - #extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(); proc androidGetJNIEnv*(): pointer {.importc: "SDL_AndroidGetJNIEnv".} - #extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(); proc androidGetActivity*(): pointer {.importc: "SDL_AndroidGetActivity".} - #extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(); proc androidGetExternalStorageState*(): cint {. importc: "SDL_AndroidGetExternalStorageState".} - #extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(); - proc androidGetInternalStoragePath* (): cstring {. + proc androidGetInternalStoragePath*(): cstring {. importc: "SDL_AndroidGetInternalStoragePath".} - #extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(); - proc androidGetExternalStoragePath* (): cstring {. + proc androidGetExternalStoragePath*(): cstring {. importc: "SDL_AndroidGetExternalStoragePath".} const @@ -1766,10 +3835,8 @@ const SDL_DISABLE* = 0 SDL_ENABLE* = 1 -##define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY) proc getEventState*(kind: EventType): uint8 {.inline.} = eventState(kind, SDL_QUERY) -##define SDL_BUTTON(X) (1 << ((X)-1)) template SDL_BUTTON*(x: uint8): uint8 = (1'u8 shl (x - 1'u8)) const BUTTON_LEFT* = 1'u8 @@ -1784,38 +3851,43 @@ const BUTTON_X2MASK* = SDL_BUTTON(BUTTON_X2) const SDL_TOUCH_MOUSEID* = high(uint32) + ## Used as the device ID for mouse events simulated with touch input + + +# compatibility functions -## compatibility functions +proc createRGBSurface*(width, height, depth: int32): SurfacePtr {.inline.} = + sdl2.createRGBSurface(0, width, height, depth, 0, 0, 0, 0) -proc createRGBSurface* (width, height, depth: int32): SurfacePtr {.inline.} = sdl2.createRGBSurface( - 0, width, height, depth, 0,0,0,0) -proc getSize*(window: WindowPtr): Point {.inline.} = getSize(window, result.x, result.y) +proc getSize*(window: WindowPtr): Point {.inline.} = + getSize(window, result.x, result.y) proc destroyTexture*(texture: TexturePtr) {.inline.} = destroy(texture) -#proc destroy* (texture: TexturePtr) {.inline.} = texture.destroyTexture + proc destroyRenderer*(renderer: RendererPtr) {.inline.} = destroy(renderer) -#proc destroy* (renderer: RendererPtr) {.inline.} = renderer.destroyRenderer -proc destroy* (window: WindowPtr) {.inline.} = window.destroyWindow -proc destroy* (cursor: CursorPtr) {.inline.} = cursor.freeCursor -proc destroy* (surface: SurfacePtr) {.inline.} = surface.freeSurface -proc destroy* (format: ptr PixelFormat) {.inline.} = format.freeFormat -proc destroy* (palette: ptr Palette) {.inline.} = palette.freePalette +proc destroy*(window: WindowPtr) {.inline.} = window.destroyWindow + ## Destroy a window. +proc destroy*(cursor: CursorPtr) {.inline.} = cursor.freeCursor +proc destroy*(surface: SurfacePtr) {.inline.} = surface.freeSurface +proc destroy*(format: ptr PixelFormat) {.inline.} = format.freeFormat +proc destroy*(palette: ptr Palette) {.inline.} = palette.freePalette proc blitSurface*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; - dstrect: ptr Rect): SDL_Return {.inline, discardable.} = upperBlit(src, srcrect, dst, dstrect) + dstrect: ptr Rect): SDL_Return {.inline, discardable.} = + upperBlit(src, srcrect, dst, dstrect) proc blitScaled*(src: SurfacePtr; srcrect: ptr Rect; dst: SurfacePtr; - dstrect: ptr Rect): SDL_Return {.inline, discardable.} = upperBlitScaled(src, srcrect, dst, dstrect) + dstrect: ptr Rect): SDL_Return {.inline, discardable.} = + upperBlitScaled(src, srcrect, dst, dstrect) -#proc init*(flags: cint): SDL_Return {.inline, deprecated.} = sdl2.init(flags) -#proc quit*() {.inline,deprecated.} = sdl2.quit() +proc loadBMP*(file: string): SurfacePtr {.inline.} = + ## Load a surface from a file. + loadBMP_RW(rwFromFile(cstring(file), "rb"), 1) -#/#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1) -proc loadBMP*(file: string): SurfacePtr {.inline.} = loadBMP_RW(rwFromFile(cstring(file), "rb"), 1) -##define SDL_SaveBMP(surface, file) \ -# SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1) proc saveBMP*(surface: SurfacePtr; file: string): SDL_Return {. - inline, discardable.} = saveBMP_RW(surface, rwFromFile(file, "wb"), 1) + inline, discardable.} = + ## Save a surface to a file. + saveBMP_RW(surface, rwFromFile(file, "wb"), 1) proc color*(r, g, b, a: range[0..255]): Color = (r.uint8, g.uint8, b.uint8, a.uint8) @@ -1833,25 +3905,65 @@ proc contains*(some: Rect; point: Point): bool = const HINT_RENDER_SCALE_QUALITY* = "SDL_RENDER_SCALE_QUALITY" - -proc setHint*(name: cstring, value: cstring): bool {. - importc: "SDL_SetHint".} + ## A variable controlling the scaling quality + ## + ## This variable can be set to the following values: + ## * "0" or "nearest" - Nearest pixel sampling + ## * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D) + ## * "2" or "best" - Currently this is the same as "linear" + ## + ## By default nearest pixel sampling is used. + +proc setHint*(name: cstring, value: cstring): bool {.importc: "SDL_SetHint".} + ## Set a hint with normal priority. + ## + ## `Return` `true` if the hint was set, `false` otherwise. proc setHintWithPriority*(name: cstring, value: cstring, priority: cint): bool {. importc: "SDL_SetHintWithPriority".} - -proc getHint*(name: cstring): cstring {. - importc: "SDL_GetHint".} - -proc size* (ctx:RWopsPtr): int64 {.inline.} = + ## Set a hint with a specific priority. + ## + ## The priority controls the behavior when setting a hint that already + ## has a value. Hints will replace existing hints of their priority and + ## lower. Environment variables are considered to have override priority. + ## + ## `Return` `true` if the hint was set, `false` otherwise. + +proc getHint*(name: cstring): cstring {.importc: "SDL_GetHint".} + ## Get a hint. + ## + ## `Return` the string value of a hint variable. + +proc size*(ctx: RWopsPtr): int64 {.inline.} = + ## `Return` the size of the file in this rwops, or `-1` if unknown. ctx.size(ctx) -proc seek* (ctx:RWopsPtr; offset:int64; whence:cint): int64 {.inline.} = - ctx.seek(ctx,offset,whence) -proc read* (ctx:RWopsPtr; `ptr`: pointer; size,maxnum:csize): csize{.inline.} = + +proc seek*(ctx: RWopsPtr; offset: int64; whence: cint): int64 {.inline.} = + ## Seek to `offset` relative to `whence`, one of stdio's whence values: + ## `RW_SEEK_SET`, `RW_SEEK_CUR`, `RW_SEEK_END`. + ## + ## `Return` the final offset in the data stream, or `-1` on error. + # TODO: Add `RW_SEEK_SET`, `RW_SEEK_CUR`, `RW_SEEK_END`. + ctx.seek(ctx, offset, whence) + +proc read*(ctx: RWopsPtr; `ptr`: pointer; size, maxnum: csize): csize {.inline.} = + ## Read up to `maxnum` objects each of size `size` from the data + ## stream to the area pointed at by `p`. + ## + ## `Return` the number of objects read, or `0` at error or end of file. ctx.read(ctx, `ptr`, size, maxnum) -proc write* (ctx:RWopsPtr; `ptr`:pointer; size,num:csize): csize{.inline.} = + +proc write*(ctx: RWopsPtr; `ptr`: pointer; size, num: csize): csize {.inline.} = + ## Write exactly `num` objects each of size `size` from the area + ## pointed at by `p` to data stream. + ## + ## `Return` the number of objects written, or `0` at error or end of file. ctx.write(ctx, `ptr`, size, num) -proc close* (ctx:RWopsPtr): cint {.inline.} = + +proc close*(ctx: RWopsPtr): cint {.inline.} = + ## Close and free an allocated `sdl.RWops` object. + ## + ## `Return` `0` if successful or `-1` on write error when flushing data. ctx.close(ctx) when not defined(SDL_Static): diff --git a/src/sdl2/audio.nim b/src/sdl2/audio.nim index 44b2a7f..6ac6f10 100644 --- a/src/sdl2/audio.nim +++ b/src/sdl2/audio.nim @@ -1,5 +1,3 @@ -import sdl2 -# # Simple DirectMedia Layer # Copyright (C) 1997-2013 Sam Lantinga # @@ -18,40 +16,33 @@ import sdl2 # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -# -#* -# \file SDL_audio.h -# -# Access to the raw audio mixing buffer for the SDL library. -# -# Set up for C function definitions, even when using C++ -#* -# \brief Audio format flags. -# -# These are what the 16 bits in AudioFormat currently mean... -# (Unspecified bits are always zero). -# -# \verbatim -# ++-----------------------sample is signed if set -# || -# || ++-----------sample is bigendian if set -# || || -# || || ++---sample is float if set -# || || || -# || || || +---sample bit size---+ -# || || || | | -# 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 -# \endverbatim -# -# There are macros in SDL 2.0 and later to query these bits. -# + + +## Access to the raw audio mixing buffer for the SDL library. + +import sdl2 + + type AudioFormat* = uint16 -#* -# \name Audio flags -# -# @{ + ## Audio format flags. + ## + ## These are what the 16 bits in `AudioFormat` currently mean... + ## (Unspecified bits are always zero). + ## + ## ++-----------------------sample is signed if set + ## || + ## || ++-----------sample is bigendian if set + ## || || + ## || || ++---sample is float if set + ## || || || + ## || || || +---sample bit size---+ + ## || || || | | + ## 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + ## + ## There are templates in SDL 2.0 and later to query these bits. + const SDL_AUDIO_MASK_BITSIZE* = uint32(0x000000FF) SDL_AUDIO_MASK_DATATYPE* = uint32(1 shl 8) @@ -79,47 +70,35 @@ template SDL_AUDIO_ISLITTLEENDIAN*(x: uint32): bool = template SDL_AUDIO_ISUNSIGNED*(x: uint32): bool = not SDL_AUDIO_ISSIGNED(x) -#* -# \name Audio format flags -# -# Defaults to LSB byte order. + +# Audio format flags # -# @{ +# Defaults to LSB byte order. const - AUDIO_U8* = 0x00000008 #*< Unsigned 8-bit samples - AUDIO_S8* = 0x00008008 #*< Signed 8-bit samples - AUDIO_U16LSB* = 0x00000010 #*< Unsigned 16-bit samples - AUDIO_S16LSB* = 0x00008010 #*< Signed 16-bit samples - AUDIO_U16MSB* = 0x00001010 #*< As above, but big-endian byte order - AUDIO_S16MSB* = 0x00009010 #*< As above, but big-endian byte order + AUDIO_U8* = 0x00000008 ## Unsigned 8-bit samples + AUDIO_S8* = 0x00008008 ## Signed 8-bit samples + AUDIO_U16LSB* = 0x00000010 ## Unsigned 16-bit samples + AUDIO_S16LSB* = 0x00008010 ## Signed 16-bit samples + AUDIO_U16MSB* = 0x00001010 ## As above, but big-endian byte order + AUDIO_S16MSB* = 0x00009010 ## As above, but big-endian byte order AUDIO_U16* = AUDIO_U16LSB AUDIO_S16* = AUDIO_S16LSB -# @} -#* -# \name int32 support -# -# @{ +# int32 support const - AUDIO_S32LSB* = 0x00008020 #*< 32-bit integer samples - AUDIO_S32MSB* = 0x00009020 #*< As above, but big-endian byte order + AUDIO_S32LSB* = 0x00008020 ## 32-bit integer samples + AUDIO_S32MSB* = 0x00009020 ## As above, but big-endian byte order AUDIO_S32* = AUDIO_S32LSB -# @} -#* -# \name float32 support -# -# @{ + +# float32 support const - AUDIO_F32LSB* = 0x00008120 #*< 32-bit floating point samples - AUDIO_F32MSB* = 0x00009120 #*< As above, but big-endian byte order + AUDIO_F32LSB* = 0x00008120 ## 32-bit floating point samples + AUDIO_F32MSB* = 0x00009120 ## As above, but big-endian byte order AUDIO_F32* = AUDIO_F32LSB -# @} -#* -# \name Native audio byte ordering -# -# @{ + +# Native audio byte ordering when false: - ## TODO system.cpuEndian + # TODO system.cpuEndian when SDL_BYTEORDER == SDL_LIL_ENDIAN: const AUDIO_U16SYS* = AUDIO_U16LSB @@ -132,69 +111,98 @@ when false: AUDIO_S16SYS* = AUDIO_S16MSB AUDIO_S32SYS* = AUDIO_S32MSB AUDIO_F32SYS* = AUDIO_F32MSB -# @} -#* -# \name Allow change flags -# -# Which audio format changes are allowed when opening a device. + +# Allow change flags # -# @{ +# Which audio format changes are allowed when opening a device. const SDL_AUDIO_ALLOW_FREQUENCY_CHANGE* = 0x00000001 SDL_AUDIO_ALLOW_FORMAT_CHANGE* = 0x00000002 SDL_AUDIO_ALLOW_CHANNELS_CHANGE* = 0x00000004 SDL_AUDIO_ALLOW_ANY_CHANGE* = (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE or SDL_AUDIO_ALLOW_FORMAT_CHANGE or SDL_AUDIO_ALLOW_CHANNELS_CHANGE) -# @} -# @} + # Audio flags -#* -# This function is called when the audio device needs more data. -# -# \param userdata An application-specific parameter saved in -# the AudioSpec structure -# \param stream A pointer to the audio data buffer. -# \param len The length of that buffer in bytes. -# -# Once the callback returns, the buffer will no longer be valid. -# Stereo samples are stored in a LRLRLR ordering. -# type AudioCallback* = proc (userdata: pointer; stream: ptr uint8; len: cint) {.cdecl.} -#* -# The calculated values in this structure are calculated by SDL_OpenAudio(). -# + ## This procedure is called when the audio device needs more data. + ## + ## `userdata` An application-specific parameter + ## saved in `AudioSpec` object. + ## + ## `stream` A pointer to the audio data buffer. + ## + ## `len` The length of that buffer in bytes. + ## + ## Once the callback returns, the buffer will no longer be valid. + ## Stereo samples are stored in a LRLRLR ordering. + ## + ## You can choose to avoid callbacks and use `queueAudio()` instead, + ## if you like. Just open your audio device with a `nil` callback. + type AudioSpec* = object - freq*: cint #*< DSP frequency -- samples per second - format*: AudioFormat #*< Audio data format - channels*: uint8 #*< Number of channels: 1 mono, 2 stereo - silence*: uint8 #*< Audio buffer silence value (calculated) - samples*: uint16 #*< Audio buffer size in samples (power of 2) - padding*: uint16 #*< Necessary for some compile environments - size*: uint32 #*< Audio buffer size in bytes (calculated) + ## The calculated values in this object are calculated by `OpenAudio()`. + ## + ## For multi-channel audio, the default SDL channel mapping is: + ## * 2: FL FR (stereo) + ## * 3: FL FR LFE (2.1 surround) + ## * 4: FL FR BL BR (quad) + ## * 5: FL FR FC BL BR (quad + center) + ## * 6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR) + ## * 7: FL FR FC LFE BC SL SR (6.1 surround) + ## * 8: FL FR FC LFE BL BR SL SR (7.1 surround) + freq*: cint ## DSP frequency -- samples per second + format*: AudioFormat ## Audio data format + channels*: uint8 ## Number of channels: 1 mono, 2 stereo + silence*: uint8 ## Audio buffer silence value (calculated) + samples*: uint16 ## Audio buffer size in samples (power of 2) + padding*: uint16 ## Necessary for some compile environments + size*: uint32 ## Audio buffer size in bytes (calculated) callback*: AudioCallback + ## Callback that feeds the audio device (`nil` to use `queueAudio()`). userdata*: pointer + ## Userdata passed to callback (ignored for `nil` callbacks). AudioCVT* {.packed.} = object - needed*: cint #*< Set to 1 if conversion possible - src_format*: AudioFormat #*< Source audio format - dst_format*: AudioFormat #*< Target audio format - rate_incr*: cdouble #*< Rate conversion increment - buf*: ptr uint8 #*< Buffer to hold entire audio data - len*: cint #*< Length of original audio buffer - len_cvt*: cint #*< Length of converted audio buffer - len_mult*: cint #*< buffer must be len*len_mult big - len_ratio*: cdouble #*< Given len, final size is len*len_ratio - filters*: array[10, AudioFilter] #*< Filter list - filter_index*: cint #*< Current audio conversion function + ## A structure to hold a set of audio conversion filters and buffers. + ## + ## Note that various parts of the conversion pipeline can take advantage + ## of SIMD operations (like SSE2, for example). `AudioCVT` doesn't + ## require you to pass it aligned data, but can possibly run much faster + ## if you set both its `buf` field to a pointer that is aligned to 16 + ## bytes, and its `len` field to something that's a multiple of 16, + ## if possible. + ## + ## This structure is 84 bytes on 32-bit architectures, make sure GCC + ## doesn't pad it out to 88 bytes to guarantee ABI compatibility between + ## compilers. The next time we rev the ABI, make sure to size the ints + ## and add padding. + needed*: cint ## Set to 1 if conversion possible + src_format*: AudioFormat ## Source audio format + dst_format*: AudioFormat ## Target audio format + rate_incr*: cdouble ## Rate conversion increment + buf*: ptr uint8 ## Buffer to hold entire audio data + len*: cint ## Length of original audio buffer + len_cvt*: cint ## Length of converted audio buffer + len_mult*: cint ## buffer must be len*len_mult big + len_ratio*: cdouble ## Given len, final size is len*len_ratio + filters*: array[10, AudioFilter] ## Filter list + filter_index*: cint ## Current audio conversion function AudioFilter* = proc (cvt: ptr AudioCVT; format: AudioFormat){.cdecl.} type AudioStream = object - # The AudioStream object. SDL2 doesn't make the contents of this object - # visible to users of the C API, so we don't make it visible either. + ## a new audio conversion interface. + ## + ## The benefits vs `AudioCVT`: + ## * it can handle resampling data in chunks without generating + ## artifacts, when it doesn't have the complete buffer available. + ## * it can handle incoming data in any variable size. + ## * You push data as you have it, and pull it when you need it. + ## + ## This is opaque to the outside world. cvt_before_resampling*: AudioCVT cvt_after_resampling*: AudioCVT queue*: pointer @@ -218,20 +226,22 @@ type resampler_padding_samples*: cint resampler_padding*: ptr cfloat resampler_state*: pointer - resampler_func*: proc(stream: AudioStreamPtr, inbuf: pointer, inbuflen: cint, outbuf: pointer, outbuflen: cint): cint + resampler_func*: proc(stream: AudioStreamPtr, + inbuf: pointer, inbuflen: cint, + outbuf: pointer, outbuflen: cint): cint reset_resampler_func*: proc(stream: AudioStreamPtr) cleanup_resampler_func*: proc(stream: AudioStreamPtr) AudioStreamPtr* = ptr AudioStream ## (Available since SDL 2.0.7) - ## A pointer to an `SDL_AudioStream`_. Audio streams were added to SDL2 + ## A pointer to an `AudioStream`. Audio streams were added to SDL2 ## in version 2.0.7, to provide an easier-to-use alternative to - ## `SDL_AudioCVT`_. + ## `AudioCVT`. ## ## .. _SDL_AudioStream: https://wiki.libsdl.org/Tutorials/AudioStream ## .. _SDL_AudioCVT: https://wiki.libsdl.org/SDL_AudioCVT ## - ## See Also: + ## **See also:** ## * `newAudioStream proc<#newAudioStream,AudioFormat,uint8,cint,AudioFormat,uint8,cint>`_ ## * `newAudioStream proc<#newAudioStream,AudioSpec,AudioSpec>`_ ## * `put proc<#put,AudioStreamPtr,pointer,cint>`_ @@ -242,9 +252,7 @@ type ## * `destroy proc<#destroy,AudioStreamPtr>`_ when false: - #* - # A structure to hold a set of audio conversion filters and buffers. - # + when defined(GNUC):#__GNUC__): # This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't # pad it out to 88 bytes to guarantee ABI compatibility between compilers. @@ -257,24 +265,17 @@ when false: const AudioCVT_PACKED* = true -#* -# SDL Audio Device IDs. -# -# A successful call to SDL_OpenAudio() is always device id 1, and legacy -# SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls -# always returns devices >= 2 on success. The legacy calls are good both -# for backwards compatibility and when you don't care about multiple, -# specific, or capture devices. -# + type AudioDeviceID* = uint32 + ## SDL Audio Device IDs. + ## + ## A successful call to `openAudio()` is always device id `1`, and legacy + ## SDL audio APIs assume you want this device ID. + ## `openAudioDevice()` calls always returns devices >= `2` on success. + ## The legacy calls are good both for backwards compatibility and when you + ## don't care about multiple, specific, or capture devices. -#* -# \name Audio state -# -# Get the current audio state. -# -# @{ type AudioStatus* {.size: sizeof(cint).} = enum SDL_AUDIO_STOPPED = 0, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED @@ -286,303 +287,437 @@ when defined(SDL_Static): else: {.push callConv: cdecl, dynlib: LibName.} -# Function prototypes -#* -# \name Driver discovery functions -# -# These functions return the list of built in audio drivers, in the -# order that they are normally initialized by default. -# -# @{ -proc getNumAudioDrivers*(): cint {. - importc: "SDL_GetNumAudioDrivers".} -proc getAudioDriver*(index: cint): cstring {. - importc: "SDL_GetAudioDriver".} -# @} -#* -# \name Initialization and cleanup -# -# \internal These functions are used internally, and should not be used unless -# you have a specific need to specify the audio driver you want to -# use. You should normally use SDL_Init() or SDL_InitSubSystem(). -# -# @{ -proc audioInit*(driver_name: cstring): cint {. - importc: "SDL_AudioInit".} -proc audioQuit*() {. - importc: "SDL_AudioQuit".} -# @} -#* -# This function returns the name of the current audio driver, or NULL -# if no driver has been initialized. -# -proc getCurrentAudioDriver*(): cstring {. - importc: "SDL_GetCurrentAudioDriver".} -#* -# This function opens the audio device with the desired parameters, and -# returns 0 if successful, placing the actual hardware parameters in the -# structure pointed to by \c obtained. If \c obtained is NULL, the audio -# data passed to the callback function will be guaranteed to be in the -# requested format, and will be automatically converted to the hardware -# audio format if necessary. This function returns -1 if it failed -# to open the audio device, or couldn't set up the audio thread. -# -# When filling in the desired audio spec structure, -# - \c desired->freq should be the desired audio frequency in samples-per- -# second. -# - \c desired->format should be the desired audio format. -# - \c desired->samples is the desired size of the audio buffer, in -# samples. This number should be a power of two, and may be adjusted by -# the audio driver to a value more suitable for the hardware. Good values -# seem to range between 512 and 8096 inclusive, depending on the -# application and CPU speed. Smaller values yield faster response time, -# but can lead to underflow if the application is doing heavy processing -# and cannot fill the audio buffer in time. A stereo sample consists of -# both right and left channels in LR ordering. -# Note that the number of samples is directly related to time by the -# following formula: \code ms = (samples*1000)/freq \endcode -# - \c desired->size is the size in bytes of the audio buffer, and is -# calculated by SDL_OpenAudio(). -# - \c desired->silence is the value used to set the buffer to silence, -# and is calculated by SDL_OpenAudio(). -# - \c desired->callback should be set to a function that will be called -# when the audio device is ready for more data. It is passed a pointer -# to the audio buffer, and the length in bytes of the audio buffer. -# This function usually runs in a separate thread, and so you should -# protect data structures that it accesses by calling SDL_LockAudio() -# and SDL_UnlockAudio() in your code. -# - \c desired->userdata is passed as the first parameter to your callback -# function. -# -# The audio device starts out playing silence when it's opened, and should -# be enabled for playing by calling \c SDL_PauseAudio(0) when you are ready -# for your audio callback function to be called. Since the audio driver -# may modify the requested size of the audio buffer, you should allocate -# any local mixing buffers after you open the audio device. -# +proc getNumAudioDrivers*(): cint {.importc: "SDL_GetNumAudioDrivers".} + ## Driver discovery procedures. + ## + ## These procedures return the list of built in audio drivers, in the + ## order that they are normally initialized by default. + +proc getAudioDriver*(index: cint): cstring {.importc: "SDL_GetAudioDriver".} + ## Driver discovery procedures. + ## + ## These procedures return the list of built in audio drivers, in the + ## order that they are normally initialized by default. + +proc audioInit*(driver_name: cstring): cint {.importc: "SDL_AudioInit".} + ## Initialization. + ## + ## `Internal:` These procedures are used internally, and should not be used + ## unless you have a specific need to specify the audio driver you want to + ## use. You should normally use `init()` or `initSubSystem()`. + +proc audioQuit*() {.importc: "SDL_AudioQuit".} + ## Cleanup. + ## + ## `Internal`: These procedures are used internally, and should not be used + ## unless you have a specific need to specify the audio driver you want to + ## use. You should normally use `init()` or `initSubSystem()`. + +proc getCurrentAudioDriver*(): cstring {.importc: "SDL_GetCurrentAudioDriver".} + ## This procedure returns the name of the current audio driver, or `nil` + ## if no driver has been initialized. + proc openAudio*(desired: ptr AudioSpec; obtained: ptr AudioSpec): cint {. importc: "SDL_OpenAudio".} + ## This procedure opens the audio device with the desired parameters, and + ## returns `0` if successful, placing the actual hardware parameters in the + ## object pointed to by `obtained`. If `obtained` is `nil`, the audio + ## data passed to the callback procedure will be guaranteed to be in the + ## requested format, and will be automatically converted to the hardware + ## audio format if necessary. This procedure returns `-1` if it failed + ## to open the audio device, or couldn't set up the audio thread. + ## + ## When filling in the `desired` audio spec object, + ## * `desired.freq` should be the desired audio frequency + ## in samples-per- second. + ## * `desired.format` should be the desired audio format. + ## * `desired.samples` is the desired size of the audio buffer, + ## in samples. This number should be a power of two, and may be adjusted + ## by the audio driver to a value more suitable for the hardware. + ## Good values seem to range between `512` and `8096` inclusive, depending + ## on the application and CPU speed. Smaller values yield faster + ## response time, but can lead to underflow if the application is doing + ## heavy processing and cannot fill the audio buffer in time. A stereo + ## sample consists of both right and left channels in LR ordering. + ## + ## Note that the number of samples is directly related to time by the + ## following formula: + ## + ## `ms = (samples*1000)/freq` + ## + ## * `desired.size` is the size in bytes of the audio buffer, and is + ## calculated by `openAudio()`. + ## * `desired.silence` is the value used to set the buffer to silence, + ## and is calculated by `openAudio()`. + ## * `desired.callback` should be set to a procedure that will be called + ## when the audio device is ready for more data. It is passed a pointer + ## to the audio buffer, and the length in bytes of the audio buffer. + ## This procedure usually runs in a separate thread, and so you should + ## protect data structures that it accesses by calling `lockAudio()` + ## and `unlockAudio()` in your code. Alternately, you may pass a `nil` + ## pointer here, and call `queueAudio()` with some frequency, to queue + ## more audio samples to be played (or for capture devices, call + ## `sdl.dequeueAudio()` with some frequency, to obtain audio samples). + ## * `desired.userdata` is passed as the first parameter to your callback + ## procedure. If you passed a `nil` callback, this value is ignored. + ## + ## The audio device starts out playing silence when it's opened, and should + ## be enabled for playing by calling `pauseAudio(0)` when you are ready + ## for your audio callback procedure to be called. Since the audio driver + ## may modify the requested size of the audio buffer, you should allocate + ## any local mixing buffers after you open the audio device. -#* -# Get the number of available devices exposed by the current driver. -# Only valid after a successfully initializing the audio subsystem. -# Returns -1 if an explicit list of devices can't be determined; this is -# not an error. For example, if SDL is set up to talk to a remote audio -# server, it can't list every one available on the Internet, but it will -# still allow a specific host to be specified to SDL_OpenAudioDevice(). -# -# In many common cases, when this function returns a value <= 0, it can still -# successfully open the default device (NULL for first argument of -# SDL_OpenAudioDevice()). -# proc getNumAudioDevices*(iscapture: cint): cint {. importc: "SDL_GetNumAudioDevices".} -#* -# Get the human-readable name of a specific audio device. -# Must be a value between 0 and (number of audio devices-1). -# Only valid after a successfully initializing the audio subsystem. -# The values returned by this function reflect the latest call to -# SDL_GetNumAudioDevices(); recall that function to redetect available -# hardware. -# -# The string returned by this function is UTF-8 encoded, read-only, and -# managed internally. You are not to free it. If you need to keep the -# string for any length of time, you should make your own copy of it, as it -# will be invalid next time any of several other SDL functions is called. -# + ## Get the number of available devices exposed by the current driver. + ## + ## Only valid after a successfully initializing the audio subsystem. + ## Returns `-1` if an explicit list of devices can't be determined; this is + ## not an error. For example, if SDL is set up to talk to a remote audio + ## server, it can't list every one available on the Internet, but it will + ## still allow a specific host to be specified to `openAudioDevice()`. + ## + ## In many common cases, when this procedure returns a value <= `0`, + ## it can still successfully open the default device (`nil` for first + ## argument of `openAudioDevice()`). + proc getAudioDeviceName*(index: cint; iscapture: cint): cstring {. importc: "SDL_GetAudioDeviceName".} -#* -# Open a specific audio device. Passing in a device name of NULL requests -# the most reasonable default (and is equivalent to calling SDL_OpenAudio()). -# -# The device name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but -# some drivers allow arbitrary and driver-specific strings, such as a -# hostname/IP address for a remote audio server, or a filename in the -# diskaudio driver. -# -# \return 0 on error, a valid device ID that is >= 2 on success. -# -# SDL_OpenAudio(), unlike this function, always acts on device ID 1. -# + ## Get the human-readable name of a specific audio device. + ## + ## Must be a value between `0` and `(number of audio devices-1)`. + ## Only valid after a successfully initializing the audio subsystem. + ## The values returned by this procedure reflect the latest call to + ## `getNumAudioDevices()`; recall that procedure to redetect available + ## hardware. + ## + ## The string returned by this procedure is UTF-8 encoded, read-only, and + ## managed internally. You are not to free it. If you need to keep the + ## string for any length of time, you should make your own copy of it, as it + ## will be invalid next time any of several other SDL prodedures is called. + proc openAudioDevice*(device: cstring; iscapture: cint; desired: ptr AudioSpec; - obtained: ptr AudioSpec; allowed_changes: cint): AudioDeviceID {. - importc: "SDL_OpenAudioDevice".} + obtained: ptr AudioSpec; + allowed_changes: cint): AudioDeviceID {. + importc: "SDL_OpenAudioDevice".} + ## Open a specific audio device. + ## + ## Passing in a device name of `nil` requests the most reasonable default + ## (and is equivalent to calling `openAudio()`). + ## + ## The device name is a UTF-8 string reported by `getAudioDeviceName()`, + ## but some drivers allow arbitrary and driver-specific strings, such as a + ## hostname/IP address for a remote audio server, or a filename in the + ## diskaudio driver. + ## + ## `Return` `0` on error, a valid device ID that is >= `2` on success. + ## + ## `openAudio()`, unlike this procedure, always acts on device ID `1`. + + +proc getAudioStatus*(): AudioStatus {.importc: "SDL_GetAudioStatus".} + ## Get the current audio state. -proc getAudioStatus*(): AudioStatus {. - importc: "SDL_GetAudioStatus".} proc getAudioDeviceStatus*(dev: AudioDeviceID): AudioStatus {. importc: "SDL_GetAudioDeviceStatus".} + ## Get the current audio state. -#* -# \brief Use this function to get the number of bytes of still-queued audio. -# -# \param dev the device ID of which we will query queued audio size -# -# \return the number of bytes (not samples!) of queued audio. -# -# \sa SDL_GetQueuedAudioSize() -# proc getQueuedAudioSize*(dev: AudioDeviceID): uint32 {. importc: "SDL_GetQueuedAudioSize".} + ## Get the number of bytes of still-queued audio. + ## + ## `For playback device:` + ## This is the number of bytes that have been queued for playback with + ## `sdl.queueAudio()`, but have not yet been sent to the hardware. This + ## number may shrink at any time, so this only informs of pending data. + ## + ## Once we've sent it to the hardware, this procedure can not decide the + ## exact byte boundary of what has been played. It's possible that we just + ## gave the hardware several kilobytes right before you called this + ## procedure, but it hasn't played any of it yet, or maybe half of it, etc. + ## + ## `For capture device:` + ## This is the number of bytes that have been captured by the device and + ## are waiting for you to dequeue. This number may grow at any time, so + ## this only informs of the lower-bound of available data. + ## + ## You may not queue audio on a device that is using an application-supplied + ## callback; calling this procedure on such a device always returns `0`. + ## You have to queue audio with `sdl.queueAudio()` / + ## `sdl.dequeueAudio()`, or use the audio callback, but not both. + ## + ## You should not call `lockAudio()` on the device before querying; SDL + ## handles locking internally for this procedure. + ## + ## `dev` The device ID of which we will query queued audio size. + ## + ## `Return` number of bytes (not samples!) of queued audio. + ## + ## **See also:** + ## * `queueAudio proc<#queueAudio,AudioDeviceID,pointer,uint32>`_ -#* -# \brief Use this function to queue more audio on non-callback devices. -# -# \param dev the device ID to which we will queue audio -# \param data the data to queue to the device for later playback -# \param len the number of bytes (not samples!) to which (data) points -# -# \return 0 on success or a negative error code on failure; call SDL_GetError() for more information. -# -# \sa SDL_QueueAudio() -# proc queueAudio*(dev: AudioDeviceID, data: pointer, len: uint32): cint {. importc: "SDL_QueueAudio".} - - - #* -# \brief Use this function to dequeue audio on non-callback devices. -# -# \param dev the device ID to which we will queue audio -# \param data the data to queue to the device for later playback -# \param len the number of bytes (not samples!) to which (data) points -# -# \return 0 on success or a negative error code on failure; call SDL_GetError() for more information. -# -# \sa SDL_DequeueAudio() -# - + ## Queue more audio on non-callback devices. + ## + ## (If you are looking to retrieve queued audio from a non-callback capture + ## device, you want `sdl.dequeueAudio()` instead. This will return `-1` + ## to signify an error if you use it with capture devices.) + ## + ## SDL offers two ways to feed audio to the device: you can either supply a + ## callback that SDL triggers with some frequency to obtain more audio + ## (pull method), or you can supply no callback, and then SDL will expect + ## you to supply data at regular intervals (push method) with this procedure. + ## + ## There are no limits on the amount of data you can queue, short of + ## exhaustion of address space. Queued data will drain to the device as + ## necessary without further intervention from you. If the device needs + ## audio but there is not enough queued, it will play silence to make up + ## the difference. This means you will have skips in your audio playback + ## if you aren't routinely queueing sufficient data. + ## + ## This procedure copies the supplied data, so you are safe to free it when + ## the procedure returns. This procedure is thread-safe, but queueing to the + ## same device from two threads at once does not promise which buffer will + ## be queued first. + ## + ## You may not queue audio on a device that is using an application-supplied + ## callback; doing so returns an error. You have to use the audio callback + ## or queue audio with this procedure, but not both. + ## + ## You should not call `lockAudio()` on the device before queueing; SDL + ## handles locking internally for this procedure. + ## + ## `dev` The device ID to which we will queue audio. + ## + ## `data` The data to queue to the device for later playback. + ## + ## `len` The number of bytes (not samples!) to which (data) points. + ## + ## `Return` `0` on success, `-1` on error. + ## + ## **See also:** + ## * `getQueuedAudioSize proc<#getQueuedAudioSize,AudioDeviceID>`_ + proc dequeueAudio*(dev: AudioDeviceID, data: pointer, len: uint32): cint {. importc: "SDL_DequeueAudio".} + ## Dequeue more audio on non-callback devices. + ## + ## (If you are looking to queue audio for output on a non-callback playback + ## device, you want `sdl.queueAudio()` instead. This will always return + ## `0` if you use it with playback devices.) + ## + ## SDL offers two ways to retrieve audio from a capture device: you can + ## either supply a callback that SDL triggers with some frequency as the + ## device records more audio data, (push method), or you can supply no + ## callback, and then SDL will expect you to retrieve data at regular + ## intervals (pull method) with this procedure. + ## + ## There are no limits on the amount of data you can queue, short of + ## exhaustion of address space. Data from the device will keep queuing as + ## necessary without further intervention from you. This means you will + ## eventually run out of memory if you aren't routinely dequeueing data. + ## + ## Capture devices will not queue data when paused; if you are expecting + ## to not need captured audio for some length of time, use + ## `sdl.pauseAudioDevice()` to stop the capture device from queueing more + ## data. This can be useful during, say, level loading times. When + ## unpaused, capture devices will start queueing data from that point, + ## having flushed any capturable data available while paused. + ## + ## This procedure is thread-safe, but dequeueing from the same device from + ## two threads at once does not promise which thread will dequeued data + ## first. + ## + ## You may not dequeue audio from a device that is using an + ## application-supplied callback; doing so returns an error. You have to use + ## the audio callback, or dequeue audio with this procedure, but not both. + ## + ## You should not call `sdl.lockAudio()` on the device before queueing; + ## SDL handles locking internally for this procedure. + ## + ## `dev` The device ID from which we will dequeue audio. + ## + ## `data` A pointer into where audio data should be copied. + ## + ## `len` The number of bytes (not samples!) to which (data) points. + ## + ## `Return` number of bytes dequeued, which could be less than requested. + ## + ## **See also:** + ## * `getQueuedAudioSize proc<#getQueuedAudioSize,AudioDeviceID>`_ + +proc pauseAudio*(pause_on: cint) {.importc: "SDL_PauseAudio".} + ## Pause audio procedures. + ## + ## These procedures pause and unpause the audio callback processing. + ## They should be called with a parameter of `0` after opening the audio + ## device to start playing sound. This is so you can safely initialize + ## data for your callback procedure after opening the audio device. + ## Silence will be written to the audio device during the pause. -# @} -# Audio State -#* -# \name Pause audio functions -# -# These functions pause and unpause the audio callback processing. -# They should be called with a parameter of 0 after opening the audio -# device to start playing sound. This is so you can safely initialize -# data for your callback function after opening the audio device. -# Silence will be written to the audio device during the pause. -# -# @{ -proc pauseAudio*(pause_on: cint) {. - importc: "SDL_PauseAudio".} proc pauseAudioDevice*(dev: AudioDeviceID; pause_on: cint) {. importc: "SDL_PauseAudioDevice".} -# @} -# Pause audio functions -#* -# This function loads a WAVE from the data source, automatically freeing -# that source if \c freesrc is non-zero. For example, to load a WAVE file, -# you could do: -# \code -# SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); -# \endcode -# -# If this function succeeds, it returns the given AudioSpec, -# filled with the audio data format of the wave data, and sets -# \c *audio_buf to a malloc()'d buffer containing the audio data, -# and sets \c *audio_len to the length of that audio buffer, in bytes. -# You need to free the audio buffer with SDL_FreeWAV() when you are -# done with it. -# -# This function returns NULL and sets the SDL error message if the -# wave file cannot be opened, uses an unknown data format, or is -# corrupt. Currently raw and MS-ADPCM WAVE files are supported. -# + ## Pause audio procedures. + ## + ## These procedures pause and unpause the audio callback processing. + ## They should be called with a parameter of `0` after opening the audio + ## device to start playing sound. This is so you can safely initialize + ## data for your callback procedure after opening the audio device. + ## Silence will be written to the audio device during the pause. proc loadWAV_RW*(src: ptr RWops; freesrc: cint; spec: ptr AudioSpec; audio_buf: ptr ptr uint8; audio_len: ptr uint32): ptr AudioSpec {. importc: "SDL_LoadWAV_RW".} + ## Load the audio data of a WAVE file into memory. + ## + ## Loading a WAVE file requires `src`, `spec`, `audio_buf` and + ## `audio_len` to be valid pointers. The entire data portion of the file + ## is then loaded into memory and decoded if necessary. + ## + ## If `freesrc` is non-zero, the data source gets automatically closed and + ## freed before the procedure returns. + ## + ## Supported are RIFF WAVE files with the formats PCM + ## (8, 16, 24, and 32 bits), IEEE Float (32 bits), Microsoft ADPCM and IMA + ## ADPCM (4 bits), and A-law and µ-law (8 bits). Other formats are currently + ## unsupported and cause an error. + ## + ## If this procedure succeeds, the pointer returned by it is equal to + ## `spec` and the pointer to the audio data allocated by the procedure is + ## written to `audio_buf` and its length in bytes to `audio_len`. + ## The `sdl.AudioSpec` members `freq`, `channels`, and `format` are + ## set to the values of the audio data in the buffer. The `samples` member + ## is set to a sane default and all others are set to zero. + ## + ## It's necessary to use `sdl.freeWAV()` to free the audio data returned + ## in `audio_buf` when it is no longer used. + ## + ## Because of the underspecification of the Waveform format, there are many + ## problematic files in the wild that cause issues with strict decoders. To + ## provide compatibility with these files, this decoder is lenient in regards + ## to the truncation of the file, the fact chunk, and the size of the RIFF + ## chunk. The hints `sdl.HINT_WAVE_RIFF_CHUNK_SIZE`, + ## `sdl.HINT_WAVE_TRUNCATION`, and `sdl.HINT_WAVE_FACT_CHUNK` + ## can be used to tune the behavior of the loading process. + ## + ## Any file that is invalid (due to truncation, corruption, or wrong values + ## in the headers), too big, or unsupported causes an error. Additionally, + ## any critical I/O error from the data source will terminate the loading + ## process with an error. The procedure returns `nil` on error and in all + ## cases (with the exception of `src` being `nil`), an appropriate error + ## message will be set. + ## + ## It is required that the data source supports seeking. + ## + ## Example: + ## + ## .. code-block:: nim + ## sdl.loadWAV_RW(sdl.rwFromFile("sample.wav", "rb"), 1, ...) + ## + ## `src` The data source with the WAVE data + ## + ## `freesrc` A integer value that makes the procedure close the data source + ## if non-zero + ## + ## `spec` A pointer filled with the audio format of the audio data + ## + ## `audio_buf` A pointer filled with the audio data allocated by the + ## procedure + ## + ## `audio_len` A pointer filled with the length of the audio data buffer + ## in bytes + ## + ## `Return` `nil` on error, or non-`nil` on success. -#* -# Loads a WAV from a file. -# Compatibility convenience function. -# template loadWAV*(file: string, spec: ptr AudioSpec, audio_buf: ptr ptr uint8, audio_len: ptr uint32): ptr AudioSpec = + ## Loads a WAV from a file. + ## Compatibility convenience template. loadWAV_RW(rwFromFile(file, "rb"), 1, spec, audio_buf, audio_len) -#* -# This function frees data previously allocated with SDL_LoadWAV_RW() -# -proc freeWAV*(audio_buf: ptr uint8) {. - importc: "SDL_FreeWAV".} -#* -# This function takes a source format and rate and a destination format -# and rate, and initializes the \c cvt structure with information needed -# by SDL_ConvertAudio() to convert a buffer of audio data from one format -# to the other. -# -# \return -1 if the format conversion is not supported, 0 if there's -# no conversion needed, or 1 if the audio filter is set up. -# +proc freeWAV*(audio_buf: ptr uint8) {.importc: "SDL_FreeWAV".} + ## This procedure frees data previously allocated with `loadWAV_RW()` + proc buildAudioCVT*(cvt: ptr AudioCVT; src_format: AudioFormat; src_channels: uint8; src_rate: cint; dst_format: AudioFormat; dst_channels: uint8; dst_rate: cint): cint {. importc: "SDL_BuildAudioCVT".} -#* -# Once you have initialized the \c cvt structure using SDL_BuildAudioCVT(), -# created an audio buffer \c cvt->buf, and filled it with \c cvt->len bytes of -# audio data in the source format, this function will convert it in-place -# to the desired format. -# -# The data conversion may expand the size of the audio data, so the buffer -# \c cvt->buf should be allocated after the \c cvt structure is initialized by -# SDL_BuildAudioCVT(), and should be \c cvt->len*cvt->len_mult bytes long. -# -proc convertAudio*(cvt: ptr AudioCVT): cint {. - importc: "SDL_ConvertAudio".} - -#* -# This takes two audio buffers of the playing audio format and mixes -# them, performing addition, volume adjustment, and overflow clipping. -# The volume ranges from 0 - 128, and should be set to ::SDL_MIX_MAXVOLUME -# for full audio volume. Note this does not change hardware volume. -# This is provided for convenience -- you can mix your own audio data. -# + ## This procedure takes a source format and rate and a destination format + ## and rate, and initializes the `cvt` object with information needed + ## by `convertAudio()` to convert a buffer of audio data from one format + ## to the other. An unsupported format causes an error and `-1` will be + ## returned. + ## + ## `Return` `0` if no conversion is needed, + ## `1` if the audio filter is set up, or `-1` on error. + +proc convertAudio*(cvt: ptr AudioCVT): cint {.importc: "SDL_ConvertAudio".} + ## Once you have initialized the `cvt` object using `buildAudioCVT()`, + ## created an audio buffer `cvt.buf`, and filled it with `cvt.len` bytes + ## of audio data in the source format, this procedure will convert it + ## in-place to the desired format. + ## + ## The data conversion may expand the size of the audio data, so the buffer + ## `cvt.buf` should be allocated after the `cvt` object is initialized + ## by `buildAudioCVT()`, and should be `cvt.len*cvt.len_mult` bytes long. + ## + ## `Return` `0` on success or `-1` if `cvt.buf` is `nil`. + proc mixAudio*(dst: ptr uint8; src: ptr uint8; len: uint32; volume: cint) {. importc: "SDL_MixAudio".} -#* -# This works like SDL_MixAudio(), but you specify the audio format instead of -# using the format of audio device 1. Thus it can be used when no audio -# device is open at all. -# + ## This takes two audio buffers of the playing audio format and mixes + ## them, performing addition, volume adjustment, and overflow clipping. + ## The volume ranges from `0 - 128`, and should be set to `MIX_MAXVOLUME` + ## for full audio volume. Note this does not change hardware volume. + ## This is provided for convenience -- you can mix your own audio data. + proc mixAudioFormat*(dst: ptr uint8; src: ptr uint8; - format: AudioFormat; len: uint32; volume: cint) {. + format: AudioFormat; len: uint32; volume: cint) {. importc: "SDL_MixAudioFormat".} -#* -# \name Audio lock functions -# -# The lock manipulated by these functions protects the callback function. -# During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that -# the callback function is not running. Do not call these from the callback -# function or you will cause deadlock. -# -# @{ -proc lockAudio*() {. - importc: "SDL_LockAudio".} -proc lockAudioDevice*(dev: AudioDeviceID) {. - importc: "SDL_LockAudioDevice".} -proc unlockAudio*() {. - importc: "SDL_UnlockAudio".} -proc unlockAudioDevice*(dev: AudioDeviceID) {. - importc: "SDL_UnlockAudioDevice".} -# @} -# Audio lock functions -#* -# This function shuts down audio processing and closes the audio device. -# -proc closeAudio*() {. - importc: "SDL_CloseAudio".} -proc closeAudioDevice*(dev: AudioDeviceID) {. - importc: "SDL_CloseAudioDevice".} -# Ends C function definitions when using C++ + ## This works like `mixAudio()`, but you specify the audio format instead + ## of using the format of audio device `1`. + ## Thus it can be used when no audio device is open at all. + +proc lockAudio*() {.importc: "SDL_LockAudio".} + ## Audio lock procedure. + ## + ## The lock manipulated by these procedures protects the callback procedure. + ## During a `lockAudio()`/`unlockAudio()` pair, you can be guaranteed + ## that the callback procedure is not running. Do not call these from the + ## callback procedure or you will cause deadlock. + +proc lockAudioDevice*(dev: AudioDeviceID) {.importc: "SDL_LockAudioDevice".} + ## Audio lock procedure. + ## + ## The lock manipulated by these procedures protects the callback procedure. + ## During a `lockAudio()`/`unlockAudio()` pair, you can be guaranteed + ## that the callback procedure is not running. Do not call these from the + ## callback procedure or you will cause deadlock. + +proc unlockAudio*() {.importc: "SDL_UnlockAudio".} + ## Audio unlock procedure. + ## + ## The lock manipulated by these procedures protects the callback procedure. + ## During a `lockAudio()`/`unlockAudio()` pair, you can be guaranteed + ## that the callback procedure is not running. Do not call these from the + ## callback procedure or you will cause deadlock. + +proc unlockAudioDevice*(dev: AudioDeviceID) {.importc: "SDL_UnlockAudioDevice".} + ## Audio unlock procedure. + ## + ## The lock manipulated by these procedures protects the callback procedure. + ## During a `lockAudio()`/`unlockAudio()` pair, you can be guaranteed + ## that the callback procedure is not running. Do not call these from the + ## callback procedure or you will cause deadlock. + +proc closeAudio*() {.importc: "SDL_CloseAudio".} + ## This procedure shuts down audio processing and closes the audio device. + +proc closeAudioDevice*(dev: AudioDeviceID) {.importc: "SDL_CloseAudioDevice".} + ## This procedure shuts down audio processing and closes the audio device. proc newAudioStream*( @@ -604,7 +739,7 @@ proc newAudioStream*( ## * `dst_channels` The number of channels of the desired audio output ## * `dst_rate The` sampling rate of the desired audio output ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ ## * `newAudioStream proc<#newAudioStream,AudioSpec,AudioSpec>`_ @@ -612,7 +747,7 @@ proc newAudioStream*(srcSpec, destSpec: AudioSpec): AudioStreamPtr = ## (Available since SDL 2.0.7) ## Create a new audio stream that converts from `srcSpec` to `destSpec`. ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ ## * `newAudioStream proc<#newAudioStream,AudioFormat,uint8,cint,AudioFormat,uint8,cint>`_ newAudioStream( @@ -624,14 +759,16 @@ proc put*( buf: pointer, len: cint): cint {.importc: "SDL_AudioStreamPut".} ## (Available since SDL 2.0.7) - ## Add data to be converted/resampled to the stream. Returns 0 on success, or -1 on error. - ## + ## Add data to be converted/resampled to the stream.Returns 0 on success, or -1 on error. + ## + ## Returns 0 on success, or -1 on error. + ## ## Parameters: ## * `stream` The stream the audio data is being added to ## * `buf` A pointer to the audio data to add ## * `len` The number of bytes to write to the stream ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ proc get*( @@ -647,17 +784,18 @@ proc get*( ## * `buf` A buffer to fill with audio data ## * `len` The maximum number of bytes to fill ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ -proc available*(stream: AudioStreamPtr): cint {.importc: "SDL_AudioStreamAvailable".} +proc available*(stream: AudioStreamPtr): cint {. + importc: "SDL_AudioStreamAvailable".} ## (Available since SDL 2.0.7) ## Get the number of converted/resampled bytes available (BYTES, not samples!). ## The stream may be buffering data behind the scenes until it has enough to ## resample correctly, so this number might be lower than what you expect, or even ## be zero. Add more data or flush the stream if you need the data now. ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ proc flush*(stream: AudioStreamPtr): cint {.importc: "SDL_AudioStreamFlush".} @@ -670,21 +808,21 @@ proc flush*(stream: AudioStreamPtr): cint {.importc: "SDL_AudioStreamFlush".} ## be audio gaps in the output. Generally this is intended to signal the ## end of input, so the complete output becomes available. ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ proc clear*(stream: AudioStreamPtr) {.importc: "SDL_AudioStreamClear".} ## (Available since SDL 2.0.7) ## Clear any pending data in the stream without converting it. ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ proc destroy*(stream: AudioStreamPtr) {.importc: "SDL_FreeAudioStream".} ## (Available since SDL 2.0.7) ## Free an audio stream. ## - ## See also: + ## **See also:** ## * `AudioStreamPtr type<#AudioStreamPtr>`_ diff --git a/src/sdl2/gamecontroller.nim b/src/sdl2/gamecontroller.nim index 64773d3..3e30f31 100644 --- a/src/sdl2/gamecontroller.nim +++ b/src/sdl2/gamecontroller.nim @@ -1,6 +1,3 @@ -import "../sdl2" -import "joystick" - discard """ Simple DirectMedia Layer Copyright (C) 1997-2014 Sam Lantinga @@ -20,30 +17,27 @@ discard """ 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. +""" +## SDL game controller event handling +## +## In order to use these functions, `sdl.init()` must have been called +## with the `SDL_INIT_JOYSTICK` flag. This causes SDL to scan the system +## for game controllers, and load appropriate drivers. +## +## If you would like to receive controller updates while the application +## is in the background, you should set the following hint before calling +## init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS -\file SDL_gamecontroller.h - -Include file for SDL game controller event handling +import "../sdl2" +import "joystick" -""" -## -# \file SDL_gamecontroller.h -# -# In order to use these functions, SDL_Init() must have been called -# with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system -# for game controllers, and load appropriate drivers. -# -# If you would like to receive controller updates while the application -# is in the background, you should set the following hint before calling -# SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS -# - -# The gamecontroller structure used to identify an SDL game controller# / type GameController* = object + ## The gamecontroller structure used to identify an SDL game controller. + GameControllerPtr* = ptr GameController GameControllerBindType* {.size: sizeof(cint).} = enum @@ -56,6 +50,8 @@ type type GameControllerButtonBind* = object + ## Get the SDL joystick layer binding + ## for this controller button/axis mapping case bindType*: GameControllerBindType of SDL_CONTROLLER_BINDTYPE_NONE: nil @@ -71,128 +67,91 @@ when defined(SDL_Static): else: {.push callConv: cdecl, dynlib: LibName.} -## -# To count the number of game controllers in the system for the following: -# int nJoysticks = SDL_NumJoysticks(); -# int nGameControllers = 0; -# for ( int i = 0; i < nJoysticks; i++ ) { -# if ( SDL_IsGameController(i) ) { -# nGameControllers++; -# } -# } -# -# Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is: -# guid,name,mappings -# -# Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones. -# Under Windows there is a reserved GUID of "xinput" that covers any XInput devices. -# The mapping format for joystick is: -# bX - a joystick button, index X -# hX.Y - hat X with value Y -# aX - axis X of the joystick -# Buttons can be used as a controller axis and vice versa. -# -# This string shows an example of a valid mapping for a controller -# "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7", -# -# / - -## -# Add or update an existing mapping configuration -# -# \return 1 if mapping is added, 0 if updated, -1 on error -# / -proc gameControllerAddMapping* (mappingString: cstring): cint {. +proc gameControllerAddMapping*(mappingString: cstring): cint {. importc: "SDL_GameControllerAddMapping".} + ## Add or update an existing mapping configuration. + ## + ## `Return` `1` if mapping is added, `0` if updated, `-1` on error. -## -# Get a mapping string for a GUID -# -# \return the mapping string. Must be freed with SDL_free. Returns NULL if no mapping is available -# / -proc gameControllerMappingForGUID* (guid: JoystickGuid): cstring {. +proc gameControllerMappingForGUID*(guid: JoystickGuid): cstring {. importc: "SDL_GameControllerMappingForGUID".} + ## Get a mapping string for a GUID. + ## + ## `Return` the mapping string. Must be freed with `sdl.free()`. + ## Returns `nil` if no mapping is available -## -# Get a mapping string for an open GameController -# -# \return the mapping string. Must be freed with SDL_free. Returns NULL if no mapping is available -# / -proc mapping* (gameController: GameControllerPtr): cstring {. +proc mapping*(gameController: GameControllerPtr): cstring {. importc: "SDL_GameControllerMapping".} + ## Get a mapping string for an open GameController. + ## + ## `Return` the mapping string. Must be freed with `sdl.free()`. + ## Returns `nil` if no mapping is available -## -# Is the joystick on this index supported by the game controller interface? -# / -proc isGameController* (joystickIndex: cint): Bool32 {. +proc isGameController*(joystickIndex: cint): Bool32 {. importc: "SDL_IsGameController".} + ## Is the joystick on this index supported by the game controller interface? - -## -# Get the implementation dependent name of a game controller. -# This can be called before any controllers are opened. -# If no name can be found, this function returns NULL. -# / -proc gameControllerNameForIndex* (joystickIndex: cint): cstring {. +proc gameControllerNameForIndex*(joystickIndex: cint): cstring {. importc: "SDL_GameControllerNameForIndex".} + ## Get the implementation dependent name of a game controller. + ## + ## This can be called before any controllers are opened. + ## If no name can be found, this procedure returns `nil`. -## -# Open a game controller for use. -# The index passed as an argument refers to the N'th game controller on the system. -# This index is the value which will identify this controller in future controller -# events. -# -# \return A controller identifier, or NULL if an error occurred. -# / -proc gameControllerOpen* (joystickIndex: cint): GameControllerPtr {. +proc gameControllerOpen*(joystickIndex: cint): GameControllerPtr {. importc: "SDL_GameControllerOpen".} - -## -# Return the name for this currently opened controller -# / -proc name* (gameController: GameControllerPtr): cstring {. + ## Open a game controller for use. + ## + ## The index passed as an argument refers to the N'th game controller + ## on the system. + ## + ## This index is not the value which will identify this controller in future + ## controller events. The joystick's instance id (`JoystickID`) will be + ## used there instead. + ## + ## `Return` a controller identifier, or `nil` if an error occurred. + +proc name*(gameController: GameControllerPtr): cstring {. importc: "SDL_GameControllerName".} + ## `Return` the name for this currently opened controller. -## -# Returns SDL_TRUE if the controller has been opened and currently connected, -# or SDL_FALSE if it has not. -# / -proc getAttached* (gameController: GameControllerPtr): Bool32 {. +proc getAttached*(gameController: GameControllerPtr): Bool32 {. importc: "SDL_GameControllerGetAttached".} + ## `Returns` `true` if the controller has been opened and currently + ## connected, or `false` if it has not. -## -# Get the underlying joystick object used by a controller -# / -proc getJoystick* (gameController: GameControllerPtr): JoystickPtr {. +proc getJoystick*(gameController: GameControllerPtr): JoystickPtr {. importc: "SDL_GameControllerGetJoystick".} + ## Get the underlying joystick object used by a controller. -## -# Enable/disable controller event polling. -# -# If controller events are disabled, you must call SDL_GameControllerUpdate() -# yourself and check the state of the controller when you want controller -# information. -# -# The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE. -# / -proc gameControllerEventState* (state: cint): cint {. +proc gameControllerEventState*(state: cint): cint {. importc: "SDL_GameControllerEventState".} + ## Enable/disable controller event polling. + ## + ## If controller events are disabled, you must call + ## `gameControllerUpdate()` yourself and check the state of the + ## controller when you want controller information. + ## + ## The state can be one of `SDL_QUERY`, `SDL_ENABLE` or `SDL_IGNORE`. -## -# Update the current state of the open game controllers. -# -# This is called automatically by the event loop if any game controller -# events are enabled. -# / -proc gameControllerUpdate* () {. - importc: "SDL_GameControllerUpdate".} +proc gameControllerUpdate*() {.importc: "SDL_GameControllerUpdate".} + ## Update the current state of the open game controllers. + ## + ## This is called automatically by the event loop if any game controller + ## events are enabled. -## -# The list of axes available from a controller -# / type GameControllerAxis* {.size: sizeof(cint).} = enum + ## The list of axes available from a controller. + ## + ## Thumbstick axis values range + ## from `JOYSTICK_AXIS_MIN` to `JOYSTICK_AXIS_MAX`, + ## and are centered within ~8000 of zero, + ## though advanced UI will allow users to set + ## or autodetect the dead zone, which varies between controllers. + ## + ## Trigger axis values range from `0` to `JOYSTICK_AXIS_MAX`. SDL_CONTROLLER_AXIS_INVALID = -1, SDL_CONTROLLER_AXIS_LEFTX, SDL_CONTROLLER_AXIS_LEFTY, @@ -202,41 +161,34 @@ type SDL_CONTROLLER_AXIS_TRIGGERRIGHT, SDL_CONTROLLER_AXIS_MAX -converter toInt* (some: GameControllerAxis): uint8 = uint8(some) +converter toInt*(some: GameControllerAxis): uint8 = uint8(some) -## -# turn this string into a axis mapping -# / -proc gameControllerGetAxisFromString* (pchString: cstring): GameControllerAxis {. +proc gameControllerGetAxisFromString*(pchString: cstring): GameControllerAxis {. importc: "SDL_GameControllerGetAxisFromString".} + ## Turn this string into a axis mapping. -## -# turn this axis enum into a string mapping -# / -proc gameControllerGetStringForAxis* (axis: GameControllerAxis): cstring {. +proc gameControllerGetStringForAxis*(axis: GameControllerAxis): cstring {. importc: "SDL_GameControllerGetStringForAxis".} + ## Turn this axis enum into a string mapping. -## -# Get the SDL joystick layer binding for this controller button mapping -# / -proc getBindForAxis* (gameController: GameControllerPtr, axis: GameControllerAxis): GameControllerButtonBind {. - importc: "SDL_GameControllerGetBindForAxis".} +proc getBindForAxis*(gameController: GameControllerPtr, + axis: GameControllerAxis): GameControllerButtonBind {. + importc: "SDL_GameControllerGetBindForAxis".} + ## Get the SDL joystick layer binding for this controller button mapping. -## -# Get the current state of an axis control on a game controller. -# -# The state is a value ranging from -32768 to 32767. -# -# The axis indices start at index 0. -# / -proc getAxis* (gameController: GameControllerPtr, axis: GameControllerAxis): int16 {. +proc getAxis*(gameController: GameControllerPtr, + axis: GameControllerAxis): int16 {. importc: "SDL_GameControllerGetAxis".} + ## Get the current state of an axis control on a game controller. + ## + ## The state is a value ranging from `-32768` to `32767` + ## (except for the triggers, which range from `0` to `32767`. + ## + ## The axis indices start at index `0`. -## -# The list of buttons available from a controller -# / type GameControllerButton* {.size: sizeof(cint).} = enum + ## The list of buttons available from a controller SDL_CONTROLLER_BUTTON_INVALID = -1, SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_B, @@ -255,40 +207,36 @@ type SDL_CONTROLLER_BUTTON_DPAD_RIGHT, SDL_CONTROLLER_BUTTON_MAX -converter toInt* (some: GameControllerButton): uint8 = uint8(some) +converter toInt*(some: GameControllerButton): uint8 = uint8(some) -## -# turn this string into a button mapping -# / -proc gameControllerGetButtonFromString* (pchString: cstring): GameControllerButton {. +proc gameControllerGetButtonFromString*( + pchString: cstring): GameControllerButton {. importc: "SDL_GameControllerGetButtonFromString".} + ## Turn this string into a button mapping. -## -# turn this button enum into a string mapping -# / -proc gameControllerGetStringForButton* (button: GameControllerButton): cstring {. +proc gameControllerGetStringForButton*( + button: GameControllerButton): cstring {. importc: "SDL_GameControllerGetStringForButton".} + ## Turn this button enum into a string mapping. -## -# Get the SDL joystick layer binding for this controller button mapping -# / -proc getBindForButton* (gameController: GameControllerPtr, button: GameControllerButton): GameControllerButtonBind {. +proc getBindForButton*( + gameController: GameControllerPtr, + button: GameControllerButton): GameControllerButtonBind {. importc: "SDL_GameControllerGetBindForButton".} + ## Get the SDL joystick layer binding for this controller button mapping. - -## -# Get the current state of a button on a game controller. -# -# The button indices start at index 0. -# / -proc getButton* (gameController: GameControllerPtr, button: GameControllerButton): uint8 {. +proc getButton*( + gameController: GameControllerPtr, + button: GameControllerButton): uint8 {. importc: "SDL_GameControllerGetButton".} + ## Get the current state of a button on a game controller. + ## + ## The button indices start at index `0`. -## -# Close a controller previously opened with SDL_GameControllerOpen(). -# / -proc close* (gameController: GameControllerPtr) {. +proc close*(gameController: GameControllerPtr) {. importc: "SDL_GameControllerClose".} + ## Close a controller previously opened with `gameControllerOpen()`. + when not defined(SDL_Static): {.pop.} diff --git a/src/sdl2/gfx.nim b/src/sdl2/gfx.nim index a25e87e..af3f674 100644 --- a/src/sdl2/gfx.nim +++ b/src/sdl2/gfx.nim @@ -1,29 +1,27 @@ +# SDL2_gfxPrimitives.h: graphics primitives for SDL # +# Copyright (C) 2012 Andreas Schiffler # -#SDL2_gfxPrimitives.h: graphics primitives for SDL +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. # -#Copyright (C) 2012 Andreas Schiffler +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: # -#This software is provided 'as-is', without any express or implied -#warranty. In no event will the authors be held liable for any damages -#arising from the use of this software. +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. # -#Permission is granted to anyone to use this software for any purpose, -#including commercial applications, and to alter it and redistribute it -#freely, subject to the following restrictions: +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. # -#1. The origin of this software must not be misrepresented; you must not -#claim that you wrote the original software. If you use this software -#in a product, an acknowledgment in the product documentation would be -#appreciated but is not required. +# 3. This notice may not be removed or altered from any source +# distribution. # -#2. Altered source versions must be plainly marked as such, and must not be -#misrepresented as being the original software. -# -#3. This notice may not be removed or altered from any source -#distribution. -# -#Andreas Schiffler -- aschiffler at ferzkopp dot net +# Andreas Schiffler -- aschiffler at ferzkopp dot net # # @@ -43,11 +41,17 @@ else: const FPS_UPPER_LIMIT* = 200 + ## Highest possible rate supported by framerate controller in Hz (1/s). FPS_LOWER_LIMIT* = 1 + ## Lowest possible rate supported by framerate controller in Hz (1/s). FPS_DEFAULT* = 30 + ## Default rate of framerate controller in Hz (1/s). + type FpsManager* {.pure, final.} = object + ## Object holding the state and timing information + ## of the framerate controller. framecount*: cint rateticks*: cfloat baseticks*: cint @@ -59,186 +63,801 @@ type when not defined(SDL_Static): {.push callConv:cdecl, dynlib: LibName.} -# ---- Function Prototypes -# Note: all ___Color routines expect the color to be in format 0xAABBGGRR -# Pixel -proc pixelColor*(renderer: RendererPtr; x, y: int16; color: uint32): SDL_Return {.importc, discardable.} -proc pixelRGBA*(renderer: RendererPtr; x: int16; y: int16; r: uint8; - g: uint8; b: uint8; a: uint8): SDL_Return {.importc, discardable.} +proc pixelColor*(renderer: RendererPtr; x, y: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Pixel draw with alpha blending enabled if `a` < `255`. + ## + ## `x`, `y` Coordinates of the pixel. + +proc pixelRGBA*(renderer: RendererPtr; x: int16; y: int16; r: uint8; g: uint8; + b: uint8; a: uint8): SDL_Return {.importc, discardable.} + ## Pixel draw with alpha blending enabled if `a` < `255`. + ## + ## `x`, `y` Coordinates of the pixel. + # Horizontal line -proc hlineColor*(renderer: RendererPtr; x1: int16; x2: int16; - y: int16; color: uint32): SDL_Return {.importc, discardable.} +proc hlineColor*(renderer: RendererPtr; x1: int16; x2: int16; y: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw horizontal line with alpha blending. + ## + ## `x1` X coordinate of the first point (i.e. left) of the line. + ## + ## `x2` X coordinate of the second point (i.e. right) of the line. + ## + ## `y` Y coordinate of the points of the line. + proc hlineRGBA*(renderer: RendererPtr; x1: int16; x2: int16; y: int16; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw horizontal line with alpha blending. + ## + ## `x1` X coordinate of the first point (i.e. left) of the line. + ## + ## `x2` X coordinate of the second point (i.e. right) of the line. + ## + ## `y` Y coordinate of the points of the line. + # Vertical line -proc vlineColor*(renderer: RendererPtr; x,y1,y2: int16; - color: uint32): SDL_Return {.importc, discardable.} -proc vlineRGBA*(renderer: RendererPtr; x,y1,y2: int16; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} +proc vlineColor*(renderer: RendererPtr; x, y1, y2: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw vertical line with alpha blending. + ## + ## `x` X coordinate of the points of the line. + ## + ## `y1` Y coordinate of the first point (i.e. top) of the line. + ## + ## `y2` Y coordinate of the second point (i.e. bottom) of the line. + +proc vlineRGBA*(renderer: RendererPtr; x, y1, y2: int16; + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw vertical line with alpha blending. + ## + ## `x` X coordinate of the points of the line. + ## + ## `y1` Y coordinate of the first point (i.e. top) of the line. + ## + ## `y2` Y coordinate of the second point (i.e. bottom) of the line. + # Rectangle -proc rectangleColor*(renderer: RendererPtr; x1,y1,x2,y2: int16; - color: uint32): SDL_Return {.importc, discardable.} -proc rectangleRGBA*(renderer: RendererPtr; x1,y1,x2,y2: int16; r,g,b,a: uint8): SDL_Return {. - importc, discardable.} +proc rectangleColor*(renderer: RendererPtr; x1, y1, x2, y2: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw rectangle with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the rectangle. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the rectangle. + +proc rectangleRGBA*(renderer: RendererPtr; x1, y1, x2, y2: int16; + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw rectangle with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the rectangle. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the rectangle. + # Rounded-Corner Rectangle -proc roundedRectangleColor*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16; +proc roundedRectangleColor*(renderer: RendererPtr; x1, y1, x2, y2, rad: int16; color: uint32): SDL_Return {.importc, discardable.} -proc roundedRectangleRGBA*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} + ## Draw rounded-corner rectangle with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the rectangle. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the rectangle. + ## + ## `rad` The radius of the corner arc. + +proc roundedRectangleRGBA*(renderer: RendererPtr; x1, y1, x2, y2, rad: int16; + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw rounded-corner rectangle with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the rectangle. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the rectangle. + ## + ## `rad` The radius of the corner arc. + # Filled rectangle (Box) proc boxColor*(renderer: RendererPtr; x1, y1, x2, y2: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw box (filled rectangle) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the box. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the box. + proc boxRGBA*(renderer: RendererPtr; x1, y1, x2, y2: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw box (filled rectangle) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the box. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the box. + # Rounded-Corner Filled rectangle (Box) -proc roundedBoxColor*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16; - color: uint32): SDL_Return {.importc, discardable.} -proc roundedBoxRGBA*(renderer: RendererPtr; x1,y1,x2,y2,rad: int16; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} +proc roundedBoxColor*(renderer: RendererPtr; x1, y1, x2, y2, rad: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw rounded-corner box (filled rectangle) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the box. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the box. + ## + ## `rad` The radius of the cornder arcs of the box. + +proc roundedBoxRGBA*(renderer: RendererPtr; x1, y1, x2, y2, rad: int16; + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw rounded-corner box (filled rectangle) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point (i.e. top right) + ## of the box. + ## + ## `x2`, `y2` Coordinates of the second point (i.e. bottom left) + ## of the box. + ## + ## `rad` The radius of the cornder arcs of the box. + # Line -proc lineColor*(renderer: RendererPtr; x1,y1,x2,y2: int16; - color: uint32): SDL_Return {.importc, discardable.} -proc lineRGBA*(renderer: RendererPtr; x1,y1,x2,y2: int16; r,g,b,a: uint8): SDL_Return {. - importc, discardable.} +proc lineColor*(renderer: RendererPtr; x1, y1, x2, y2: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw line with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the line. + ## + ## `x2`, `y2` Coordinates of the second point of the line. + +proc lineRGBA*(renderer: RendererPtr; x1, y1, x2, y2: int16; + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw line with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the line. + ## + ## `x2`, `y2` Coordinates of the second point of the line. + # AA Line -proc aalineColor*(renderer: RendererPtr; x1: int16; y1: int16; - x2: int16; y2: int16; color: uint32): SDL_Return {.importc, discardable.} +proc aalineColor*(renderer: RendererPtr; + x1: int16; y1: int16; + x2: int16; y2: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw anti-aliased line with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the aa-line. + ## + ## `x2`, `y2` Coordinates of the second point of the aa-line. + proc aalineRGBA*(renderer: RendererPtr; x1: int16; y1: int16; x2: int16; y2: int16; r: uint8; g: uint8; b: uint8; a: uint8): SDL_Return {.importc, discardable.} + ## Draw anti-aliased line with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the aa-line. + ## + ## `x2`, `y2` Coordinates of the second point of the aa-line. + # Thick Line proc thickLineColor*(renderer: RendererPtr; x1, y1, x2, y2: int16; width: uint8; color: uint32): SDL_Return {.importc, discardable.} + ## Draw thick line with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the line. + ## + ## `x2`, `y2` Coordinates of the second point of the line. + ## + ## `width` Width of the line in pixels. Must be `>0`. + proc thickLineRGBA*(renderer: RendererPtr; x1, y1, x2, y2: int16; - width, r, g, b, a: uint8): SDL_Return {.importc, discardable.} + width, r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw thick line with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the line. + ## + ## `x2`, `y2` Coordinates of the second point of the line. + ## + ## `width` Width of the line in pixels. Must be `>0`. + # Circle proc circleColor*(renderer: RendererPtr; x, y, rad: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw circle with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the circle. + ## + ## `rad` Radius in pixels of the circle. + proc circleRGBA*(renderer: RendererPtr; x, y, rad: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw circle with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the circle. + ## + ## `rad` Radius in pixels of the circle. + # Arc proc arcColor*(renderer: RendererPtr; x, y, rad, start, finish: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw arc with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the arc. + ## + ## `rad` Radius in pixels of the arc. + ## + ## `start`, `end` Starting and ending radius in degrees of the arc. + ## `0` degrees is down, increasing counterclockwise. + proc arcRGBA*(renderer: RendererPtr; x, y, rad, start, finish: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw arc with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the arc. + ## + ## `rad` Radius in pixels of the arc. + ## + ## `start`, `end` Starting and ending radius in degrees of the arc. + ## `0` degrees is down, increasing counterclockwise. + # AA Circle proc aacircleColor*(renderer: RendererPtr; x, y, rad: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw anti-aliased circle with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the aa-circle. + ## + ## `rad` Radius in pixels of the aa-circle. + proc aacircleRGBA*(renderer: RendererPtr; x, y, rad: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw anti-aliased circle with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the aa-circle. + ## + ## `rad` Radius in pixels of the aa-circle. + # Filled Circle proc filledCircleColor*(renderer: RendererPtr; x, y, r: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw filled circle with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the filled circle. + ## + ## `rad` Radius in pixels of the filled circle. + proc filledCircleRGBA*(renderer: RendererPtr; x, y, rad: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw filled circle with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the filled circle. + ## + ## `rad` Radius in pixels of the filled circle. + # Ellipse proc ellipseColor*(renderer: RendererPtr; x: int16; y: int16; - rx: int16; ry: int16; color: uint32): SDL_Return {.importc, discardable.} + rx: int16; ry: int16; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw ellipse with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the ellipse. + ## + ## `rx` Horizontal radius in pixels of the ellipse. + ## + ## `ry` Vertical radius in pixels of the ellipse. + proc ellipseRGBA*(renderer: RendererPtr; x: int16; y: int16; rx: int16; ry: int16; r: uint8; g: uint8; b: uint8; a: uint8): SDL_Return {.importc, discardable.} + ## Draw ellipse with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the ellipse. + ## + ## `rx` Horizontal radius in pixels of the ellipse. + ## + ## `ry` Vertical radius in pixels of the ellipse. + # AA Ellipse proc aaellipseColor*(renderer: RendererPtr; x, y, rx, ry: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw anti-aliased ellipse with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the aa-ellipse. + ## + ## `rx` Horizontal radius in pixels of the aa-ellipse. + ## + ## `ry` Vertical radius in pixels of the aa-ellipse. + proc aaellipseRGBA*(renderer: RendererPtr; x, y, rx, ry: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw anti-aliased ellipse with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the aa-ellipse. + ## + ## `rx` Horizontal radius in pixels of the aa-ellipse. + ## + ## `ry` Vertical radius in pixels of the aa-ellipse. + # Filled Ellipse proc filledEllipseColor*(renderer: RendererPtr; x, y, rx, ry: int16; color: uint32): SDL_Return {.importc, discardable.} + ## Draw filled ellipse with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the filled ellipse. + ## + ## `rx` Horizontal radius in pixels of the filled ellipse. + ## + ## `ry` Vertical radius in pixels of the filled ellipse. + proc filledEllipseRGBA*(renderer: RendererPtr; x, y, rx, ry: int16; r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw filled ellipse with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the filled ellipse. + ## + ## `rx` Horizontal radius in pixels of the filled ellipse. + ## + ## `ry` Vertical radius in pixels of the filled ellipse. + # Pie proc pieColor*(renderer: RendererPtr; x, y, rad, start, finish: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw pie (outline) with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the pie. + ## + ## `rad` Radius in pixels of the pie. + ## + ## `start`, `end` Starting and ending radius in degrees of the pie. + proc pieRGBA*(renderer: RendererPtr; x, y, rad, start, finish: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw pie (outline) with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the pie. + ## + ## `rad` Radius in pixels of the pie. + ## + ## `start`, `end` Starting and ending radius in degrees of the pie. + # Filled Pie proc filledPieColor*(renderer: RendererPtr; x, y, rad, start, finish: int16; - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw filled pie with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the filled pie. + ## + ## `rad` Radius in pixels of the filled pie. + ## + ## `start`, `end` Starting and ending radius in degrees + ## of the filled pie. + proc filledPieRGBA*(renderer: RendererPtr; x, y, rad, start, finish: int16; - r, g, b, a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw filled pie with alpha blending. + ## + ## `x`, `y` Coordinates of the center of the filled pie. + ## + ## `rad` Radius in pixels of the filled pie. + ## + ## `start`, `end` Starting and ending radius in degrees + ## of the filled pie. + # Trigon proc trigonColor*(renderer: RendererPtr; x1,y1,x2,y2,x3,y3: int16, - color: uint32): SDL_Return {.importc, discardable.} + color: uint32): SDL_Return {.importc, discardable.} + ## Draw trigon (triangle outline) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the trigon. + ## + ## `x2`, `y2` Coordinates of the second point of the trigon. + ## + ## `x3`, `y3` Coordinates of the third point of the trigon. + proc trigonRGBA*(renderer: RendererPtr; x1, y1, x2, y2, x3, y3: int16; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} + r,g,b,a: uint8): SDL_Return {.importc, discardable.} + ## Draw trigon (triangle outline) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the trigon. + ## + ## `x2`, `y2` Coordinates of the second point of the trigon. + ## + ## `x3`, `y3` Coordinates of the third point of the trigon. + # AA-Trigon proc aaTrigonColor*(renderer: RendererPtr; x1, y1, x2, y2, x3, y3: int16; color: uint32): SDL_Return {.importc: "aatrigonColor", discardable.} + ## Draw anti-aliased trigon (triangle outline) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the aa-trigon. + ## + ## `x2`, `y2` Coordinates of the second point of the aa-trigon. + ## + ## `x3`, `y3` Coordinates of the third point of the aa-trigon. + proc aaTrigonRGBA*(renderer: RendererPtr; x1, y1, x2, y2, x3, y3: int16; - r,g,b,a: uint8): SDL_Return {.importc: "aatrigonRGBA", - discardable.} + r, g, b, a: uint8): SDL_Return {.importc: "aatrigonRGBA", discardable.} + ## Draw anti-aliased trigon (triangle outline) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the aa-trigon. + ## + ## `x2`, `y2` Coordinates of the second point of the aa-trigon. + ## + ## `x3`, `y3` Coordinates of the third point of the aa-trigon. + # Filled Trigon proc filledTrigonColor*(renderer: RendererPtr; x1: int16; y1: int16; x2: int16; y2: int16; x3: int16; y3: int16; color: uint32): SDL_Return {.importc, discardable.} + ## Draw filled trigon (triangle) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the filled trigon. + ## + ## `x2`, `y2` Coordinates of the first point of the filled trigon. + ## + ## `x3`, `y3` Coordinates of the first point of the filled trigon. + proc filledTrigonRGBA*(renderer: RendererPtr; x1: int16; y1: int16; x2: int16; y2: int16; x3: int16; y3: int16; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw filled trigon (triangle) with alpha blending. + ## + ## `x1`, `y1` Coordinates of the first point of the filled trigon. + ## + ## `x2`, `y2` Coordinates of the first point of the filled trigon. + ## + ## `x3`, `y3` Coordinates of the first point of the filled trigon. + # Polygon proc polygonColor*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16; n: cint; color: uint32): SDL_Return {.importc, discardable.} + ## Draw polygon with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + proc polygonRGBA*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16; - n: cint; r,g,b,a: uint8): SDL_Return {.importc, discardable.} + n: cint; r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw polygon with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + # AA-Polygon proc aaPolygonColor*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16; - n: cint; color: uint32): SDL_Return {.importc: "aapolygonColor", - discardable.} + n: cint; color: uint32): SDL_Return {. + importc: "aapolygonColor", discardable.} + ## Draw anti-aliased polygon with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the aa-polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + proc aaPolygonRGBA*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16; - n: cint; r,g,b,a: uint8): SDL_Return {.importc: "aapolygonRGBA", - discardable.} + n: cint; r,g,b,a: uint8): SDL_Return {. + importc: "aapolygonRGBA", discardable.} + ## Draw anti-aliased polygon with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the aa-polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + # Filled Polygon proc filledPolygonColor*(renderer: RendererPtr; vx: ptr int16; - vy: ptr int16; n: cint; color: uint32): SDL_Return {.importc, discardable.} + vy: ptr int16; n: cint; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw filled polygon with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the filled polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + proc filledPolygonRGBA*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16; n: cint; r: uint8; g: uint8; b: uint8; a: uint8): SDL_Return {.importc, discardable.} + ## Draw filled polygon with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the filled polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + # Textured Polygon proc texturedPolygon*(renderer: RendererPtr; vx: ptr int16; vy: ptr int16; n: cint; texture: SurfacePtr; - texture_dx: cint; texture_dy: cint): SDL_Return {.importc, discardable.} + texture_dx: cint; + texture_dy: cint): SDL_Return {.importc, discardable.} + ## Draw polygon filled with the given texture. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the textured polygon. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + ## + ## `texture` The `sdl.Surface` to use to fill the polygon. + ## + ## `texture_dx`, `texture_dy` The offset of the texture + ## relative to the screen. If you move the polygon `10` pixels to the left + ## and want the texture to appear the same, you need to increase + ## the `texture_dx` value. + # Bezier proc bezierColor*(renderer: RendererPtr; vx,vy: ptr int16; - n: cint; s: cint; color: uint32): SDL_Return {.importc, discardable.} + n: cint; s: cint; + color: uint32): SDL_Return {.importc, discardable.} + ## Draw a bezier curve with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the bezier curve. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + ## + ## `s` Number of steps for the interpolation. Minimum number is `2`. + proc bezierRGBA*(renderer: RendererPtr; vx, vy: ptr int16; - n: cint; s: cint; r, g, b, a: uint8): SDL_Return {.importc, discardable.} + n: cint; s: cint; + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw a bezier curve with alpha blending. + ## + ## `vx`, `vy` Vertex arrays containing coordinates of the points + ## of the bezier curve. + ## + ## `n` Number of points in the vertex array. Minimum number is `3`. + ## + ## `s` Number of steps for the interpolation. Minimum number is `2`. + # Characters/Strings proc gfxPrimitivesSetFont*(fontdata: pointer; cw: uint32; ch: uint32) {.importc.} + ## Sets or resets the current global font data. + ## + ## The font data array is organized in follows: + ## + ## `[fontdata] = [character 0][character 1]...[character 255]` + ## where + ## `[character n] = [byte 1 row 1][byte 2 row 1]...[byte {pitch} row 1] + ## [byte 1 row 2] ...[byte {pitch} row height]` + ## where + ## `[byte n] = [bit 0]...[bit 7]` + ## where + ## `[bit n] = [0 for transparent pixel|1 for colored pixel]` + ## + ## `fontdata` Pointer to array of font data. Set to `nil`, to reset + ## global font to the default `8x8` font. + ## + ## `cw`, `ch` Width and height of character in bytes. + ## Ignored if `fontdata` == `nil`. + proc gfxPrimitivesSetFontRotation*(rotation: uint32) {.importc.} + ## Sets current global font character rotation steps. + ## + ## Default is `0` (no rotation). + ## + ## `1` = 90deg clockwise. + ## + ## `2` = 180deg clockwise. + ## + ## `3` = 270deg clockwise. + ## + ## Changing the rotation, will reset the character cache. + ## + ## `rotation` Number of 90deg clockwise steps to rotate. + proc characterColor*(renderer: RendererPtr; x: int16; y: int16; c: char; color: uint32): SDL_Return {.importc.} + ## Draw a character of the currently set font. + ## + ## `x`, `y` Coordinates of the upper left corner of the character. + ## + ## `c` The character to draw. + proc characterRGBA*(renderer: RendererPtr; x: int16; y: int16; c: char; - r,g,b,a: uint8): SDL_Return {.importc.} + r, g, b, a: uint8): SDL_Return {.importc.} + ## Draw a character of the currently set font. + ## + ## `x`, `y` Coordinates of the upper left corner of the character. + ## + ## `c` The character to draw. + proc stringColor*(renderer: RendererPtr; x: int16; y: int16; s: cstring; color: uint32): SDL_Return {.importc.} + ## Draw a string in the currently set font. + ## + ## `x`, `y` Coordinates of the upper left corner of the string. + ## + ## `s` The string to draw. + proc stringRGBA*(renderer: RendererPtr; x: int16; y: int16; s: cstring; - r,g,b,a: uint8): SDL_Return {.importc, discardable.} + r, g, b, a: uint8): SDL_Return {.importc, discardable.} + ## Draw a string in the currently set font. + ## + ## `x`, `y` Coordinates of the upper left corner of the string. + ## + ## `s` The string to draw. + # Ends C function definitions when using C++ proc rotozoomSurface*(src: SurfacePtr; angle, zoom: cdouble; - smooth: cint): SurfacePtr {.importc.} + smooth: cint): SurfacePtr {.importc.} + ## Rotates and zooms a surface and optional anti-aliasing. + ## + ## Rotates and zoomes a 32-bit or 8-bit `src` surface to newly created + ## `dst` surface. If the surface is not 8-bit or 32-bit RGBA/ABGR, + ## it will be converted into a 32-bit RGBA format on the fly. + ## + ## `angle` The angle to rotate in degrees. + ## + ## `zoom` The scaling factor. + ## + ## `smooth` Antialiasing flag. Set to `SMOOTHING_ON` to enable. + ## + ## `Return` the new rotozoomed surface. + proc rotozoomSurfaceXY*(src: SurfacePtr; angle, zoomX, zoomY: cdouble; - smooth: cint): SurfacePtr {.importc.} + smooth: cint): SurfacePtr {.importc.} + ## Rotates and zooms a surface with different horizontal and vertical + ## scaling factors and optional anti-aliasing. + ## + ## Rotates and zooms a 32-bit or 8-bit `src` surface to newly created + ## `dst` surface. If the surface is not 8-bit or 32-bit RGBA/ABGR, + ## it will be converted into a 32-bit RGBA format on the fly. + ## + ## `angle` The angle to rotate in degrees. + ## + ## `zoomx` The horizontal scaling factor. + ## + ## `zoomy` The vertical scaling factor. + ## + ## `smooth` Antialiasing flag. Set to `SMOOTHING_ON` to enable. + ## + ## `Return` the new rotozoomed surface. + proc rotozoomSurfaceSize*(width, height: cint; angle, zoom: cdouble; - dstwidth, dstheight: var cint) {.importc.} + dstwidth, dstheight: var cint) {.importc.} + ## `Return` the size of the resulting target surface + ## for a `rotozoomSurface()` call. + ## + ## `width` The source surface width. + ## + ## `height` The source surface height. + ## + ## `angle` The angle to rotate in degrees. + ## + ## `zoom` The scaling factor. + ## + ## `dstwidth` The calculated width of the rotozoomed destination surface. + ## + ## `dstheight` The calculated height of the rotozoomed destination surface. + proc rotozoomSurfaceSizeXY*(width, height: cint; angle, zoomX, zoomY: cdouble; dstwidth, dstheight: var cint) {.importc.} + ## `Return` the size of the resulting target surface + ## for a `rotozoomSurfaceXY()` call. + ## + ## `width` The source surface width. + ## + ## `height` The source surface height. + ## + ## `angle` The angle to rotate in degrees. + ## + ## `zoomx` The horizontal scaling factor. + ## + ## `zoomy` The vertical scaling factor. + ## + ## `dstwidth` The calculated width of the rotozoomed destination surface. + ## + ## `dstheight` The calculated height of the rotozoomed destination surface. + proc zoomSurface*(src: SurfacePtr; zoomX, zoomY: cdouble; - smooth: cint): SurfacePtr {.importc.} + smooth: cint): SurfacePtr {.importc.} + ## Zoom a surface by independent horizontal and vertical factors + ## with optional smoothing. + ## + ## `zoomx` The horizontal zoom factor. + ## + ## `zoomy` The vertical zoom factor. + ## + ## `smooth` Antialiasing flag. Set to `SMOOTHING_ON` to enable. + ## + ## `Return` the new, zoomed surface. + proc zoomSurfaceSize*(width, height: cint; zoomX, zoomY: cdouble; - dstWidth, dstHeight: var cint) {.importc.} + dstWidth, dstHeight: var cint) {.importc.} + ## Calculates the size of the target surface for a `zoomSurface()` call. + ## + ## The minimum size of the target surface is `1`. + ## The input facors can be positive or negative. + ## + ## `width` The width of the soruce surface to zoom. + ## + ## `height` The height of the source surface to zoom. + ## + ## `zoomx` The horizontal zoom factor. + ## + ## `zoomy` The vertical zoom factor. + ## + ## `dstwidth` Pointer to an integer to store the calculated width + ## of the zoomed target surface. + ## + ## `dstheight` Pointer to an integer to store the calculated height + ## of the zoomed target surface. + proc shrinkSurface*(src: SurfacePtr; factorx, factorY: cint): SurfacePtr {.importc.} + ## Shrink a surface by an integer ratio using averaging. + ## + ## `factorx` The horizontal shrinking ratio. + ## + ## `factory` The vertical shrinking ratio. + ## + ## `Return` the new, shrunken surface. + proc rotateSurface90Degrees*(src: SurfacePtr; - numClockwiseTurns: cint): SurfacePtr {.importc.} + numClockwiseTurns: cint): SurfacePtr {.importc.} + ## Rotates a 32 bit surface in increments of 90 degrees. + ## + ## Specialized `90` degree rotator which rotates a `src` surface + ## in `90` degree increments clockwise returning a new surface. + ## Faster than rotozoomer since no scanning or interpolation takes place. + ## + ## Input surface must be 8/16/24/32-bit. + ## + ## (code contributed by J. Schiller, improved by C. Allport and A. Schiffler) + ## + ## `numClockwiseTurns` Number of clockwise `90` degree turns to apply + ## to the source. + ## + ## `Return` the new, rotated surface, + ## or `nil` for surfaces with incorrect input format. + proc init*(manager: var FpsManager) {.importc: "SDL_initFramerate".} + ## Initialize the framerate manager, set default framerate + ## of 30Hz and reset delay interpolation. + proc setFramerate*(manager: var FpsManager; rate: cint): SDL_Return {. importc: "SDL_setFramerate", discardable.} + ## Set the framerate in Hz. + ## + ## Sets a new framerate for the manager and reset delay interpolation. + ## Rate values must be between `FPS_LOWER_LIMIT` and `FPS_UPPER_LIMIT` + ## inclusive to be accepted. + ## + ## `Return` `0` or value for sucess and `-1` for error. + proc getFramerate*(manager: var FpsManager): cint {.importc: "SDL_getFramerate".} + ## `Return` the current target framerate in Hz or `-1` on error. + proc getFramecount*(manager: var FpsManager): cint {.importc: "SDL_getFramecount".} -proc delay*(manager: var FpsManager): cint {.importc: "SDL_framerateDelay", discardable.} + ## Get the current framecount from the framerate manager. + ## A frame is counted each time `framerateDelay()` is called. + ## + ## `Return` current frame count or `-1` on error. + +proc delay*(manager: var FpsManager): cint {. + importc: "SDL_framerateDelay", discardable.} + ## Generate a delay to accomodate currently set framerate. + ## Call once in the graphics/rendering loop. + ## If the computer cannot keep up with the rate (i.e. drawing too slow), + ## the delay is zero and the delay interpolation is reset. + ## + ## `Return` time that passed since the last call to the procedure in ms. + ## May return `0`. + when not defined(SDL_Static): {.pop.} diff --git a/src/sdl2/haptic.nim b/src/sdl2/haptic.nim index 72021e2..1ecb3e2 100644 --- a/src/sdl2/haptic.nim +++ b/src/sdl2/haptic.nim @@ -1,7 +1,3 @@ -import "../sdl2" -import "joystick" - -# # Simple DirectMedia Layer # Copyright (C) 1997-2014 Sam Lantinga # @@ -22,761 +18,639 @@ import "joystick" # 3. This notice may not be removed or altered from any source distribution. # -# -# \file SDL_haptic.h -# -# \brief The SDL Haptic subsystem allows you to control haptic (force feedback) -# devices. -# -# The basic usage is as follows: -# - Initialize the Subsystem (::SDL_INIT_HAPTIC). -# - Open a Haptic Device. -# - SDL_HapticOpen() to open from index. -# - SDL_HapticOpenFromJoystick() to open from an existing joystick. -# - Create an effect (::SDL_HapticEffect). -# - Upload the effect with SDL_HapticNewEffect(). -# - Run the effect with SDL_HapticRunEffect(). -# - (optional) Free the effect with SDL_HapticDestroyEffect(). -# - Close the haptic device with SDL_HapticClose(). -# -# \par Simple rumble example: -# \code -# haptic: HapticPtr; -# -# // Open the device -# haptic = SDL_HapticOpen( 0 ); -# if (haptic == NULL) -# return -1; -# -# // Initialize simple rumble -# if (SDL_HapticRumbleInit( haptic ) != 0) -# return -1; -# -# // Play effect at 50% strength for 2 seconds -# if (SDL_HapticRumblePlay( haptic, 0.5, 2000 ) != 0) -# return -1; -# SDL_Delay( 2000 ); -# -# // Clean up -# SDL_HapticClose( haptic ); -# \endcode -# -# \par Complete example: -# \code -# int test_haptic( joystick: Joystick ) { -# haptic: HapticPtr; -# SDL_HapticEffect effect; -# effect: cint_id; -# -# // Open the device -# haptic = SDL_HapticOpenFromJoystick( joystick ); -# if (haptic == NULL) return -1; // Most likely joystick isn't haptic -# -# // See if it can do sine waves -# if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_SINE)==0) { -# SDL_HapticClose(haptic); // No sine effect -# return -1; -# } -# -# // Create the effect -# memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default -# effect.type = SDL_HAPTIC_SINE; -# effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates -# effect.periodic.direction.dir[0] = 18000; // Force comes from south -# effect.periodic.period = 1000; // 1000 ms -# effect.periodic.magnitude = 20000; // 20000/32767 strength -# effect.periodic.length = 5000; // 5 seconds long -# effect.periodic.attack_length = 1000; // Takes 1 second to get max strength -# effect.periodic.fade_length = 1000; // Takes 1 second to fade away -# -# // Upload the effect -# effect_id = SDL_HapticNewEffect( haptic, &effect ); -# -# // Test the effect -# SDL_HapticRunEffect( haptic, effect_id, 1 ); -# SDL_Delay( 5000); // Wait for the effect to finish -# -# // We destroy the effect, although closing the device also does this -# SDL_HapticDestroyEffect( haptic, effect_id ); -# -# // Close the device -# SDL_HapticClose(haptic); -# -# return 0; // Success -# } -# \endcode -# -# You can also find out more information on my blog: -# http://bobbens.dyndns.org/journal/2010/sdl_haptic/ -# -# \author Edgar Simo Serra -# / +## The SDL haptic subsystem allows you to control +## haptic (force feedback) devices. +## +## The basic usage is as follows: +## * Initialize the Subsystem (`sdl2.INIT_HAPTIC`). +## * Open a haptic Device. +## - `hapticOpen proc<#hapticOpen,cint>`_ to open from index. +## - `hapticOpenFromJoystick proc<#hapticOpenFromJoystick,JoystickPtr>`_ to open from an existing joystick. +## * Create an effect (`HapticEffect type<#HapticEffect>`_). +## * Upload the effect with `newEffect proc<#newEffect,HapticPtr,ptr.HapticEffect>`_. +## * Run the effect with `runEffect proc<#runEffect,HapticPtr,cint,uint32>`_. +## * (optional) Free the effect with `destroyEffect proc<#destroyEffect,HapticPtr,cint>`_. +## * Close the haptic device with `close proc<#close,HapticPtr>`_. + +import "../sdl2" +import "joystick" -# -# \typedef SDL_Haptic -# -# \brief The haptic structure used to identify an SDL haptic. -# -# \sa SDL_HapticOpen -# \sa SDL_HapticOpenFromJoystick -# \sa SDL_HapticClose type Haptic* = object - HapticPtr* = ptr Haptic - - -# -# \name Haptic features -# -# Different haptic features a device can have. + ## The haptic object used to identify an SDL haptic. + ## + ## **See also:** + ## * `hapticOpen proc<#hapticOpen,cint>`_ + ## * `hapticOpenFromJoystick proc<#hapticOpenFromJoystick,JoystickPtr>`_ + ## * `close proc<#close,HapticPtr>`_ -# @{ - -# -# \name Haptic effects + HapticPtr* = ptr Haptic -# @{ - -# -# \brief Constant effect supported. -# -# Constant haptic effect. -# -# \sa SDL_HapticCondition const SDL_HAPTIC_CONSTANT* = (1 shl 0) - -# -# \brief Sine wave effect supported. -# -# Periodic haptic effect that simulates sine waves. -# -# \sa SDL_HapticPeriodic + ## Constant haptic effect. + ## + ## **See also:** + ## * `HapticCondition type<#HapticCondition>`_ const SDL_HAPTIC_SINE* = (1 shl 1) - -# -# \brief Left/Right effect supported. -# -# Haptic effect for direct control over high/low frequency motors. -# -# \sa SDL_HapticLeftRight -# \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry, -# we ran out of bits, and this is important for XInput devices. + ## Sine wave effect supported. + ## + ## Periodic haptic effect that simulates sine waves. + ## + ## **See also:** + ## * `HapticPeriodic type<#HapticPeriodic>`_ const SDL_HAPTIC_LEFTRIGHT* = (1 shl 2) + ## Left/Right effect supported. + ## + ## Haptic effect for direct control over high/low frequency motors. + ## + ## **See also:** + ## * `HapticLeftRight type<#HapticLeftRight>`_ + ## + ## `Warning:` this value was `SDL_HAPTIC_SQUARE` right before 2.0.0 shipped. + ## Sorry, we ran out of bits, and this is important for XInput devices. + # !!! FIXME: put this back when we have more bits in 2.1 # const SDL_HAPTIC_SQUARE* = (1 shl 2) -# -# \brief Triangle wave effect supported. -# -# Periodic haptic effect that simulates triangular waves. -# -# \sa SDL_HapticPeriodic const SDL_HAPTIC_TRIANGLE* = (1 shl 3) - -# -# \brief Sawtoothup wave effect supported. -# -# Periodic haptic effect that simulates saw tooth up waves. -# -# \sa SDL_HapticPeriodic + ## Triangle wave effect supported. + ## + ## Periodic haptic effect that simulates triangular waves. + ## + ## **See also:** + ## * `HapticPeriodic type<#HapticPeriodic>`_ const SDL_HAPTIC_SAWTOOTHUP* = (1 shl 4) - -# -# \brief Sawtoothdown wave effect supported. -# -# Periodic haptic effect that simulates saw tooth down waves. -# -# \sa SDL_HapticPeriodic + ## Sawtoothup wave effect supported. + ## + ## Periodic haptic effect that simulates saw tooth up waves. + ## + ## **See also:** + ## * `HapticPeriodic type<#HapticPeriodic>`_ const SDL_HAPTIC_SAWTOOTHDOWN* = (1 shl 5) - -# -# \brief Ramp effect supported. -# -# Ramp haptic effect. -# -# \sa SDL_HapticRamp + ## Sawtoothdown wave effect supported. + ## + ## Periodic haptic effect that simulates saw tooth down waves. + ## + ## **See also:** + ## * `HapticPeriodic type<#HapticPeriodic>`_ const SDL_HAPTIC_RAMP* = (1 shl 6) - -# -# \brief Spring effect supported - uses axes position. -# -# Condition haptic effect that simulates a spring. Effect is based on the -# axes position. -# -# \sa SDL_HapticCondition + ## Ramp effect supported. + ## + ## Ramp haptic effect. + ## + ## **See also:** + ## * `HapticRamp type<#HapticRamp>`_ const SDL_HAPTIC_SPRING* = (1 shl 7) - -# -# \brief Damper effect supported - uses axes velocity. -# -# Condition haptic effect that simulates dampening. Effect is based on the -# axes velocity. -# -# \sa SDL_HapticCondition + ## Spring effect supported - uses axes position. + ## + ## Condition haptic effect that simulates a spring. + ## Effect is based on the axes position. + ## + ## **See also:** + ## * `HapticCondition type<#HapticCondition>`_ const SDL_HAPTIC_DAMPER* = (1 shl 8) - -# -# \brief Inertia effect supported - uses axes acceleration. -# -# Condition haptic effect that simulates inertia. Effect is based on the axes -# acceleration. -# -# \sa SDL_HapticCondition + ## Damper effect supported - uses axes velocity. + ## + ## Condition haptic effect that simulates dampening. + ## Effect is based on the axes velocity. + ## + ## **See also:** + ## * `HapticCondition type<#HapticCondition>`_ const SDL_HAPTIC_INERTIA* = (1 shl 9) - -# -# \brief Friction effect supported - uses axes movement. -# -# Condition haptic effect that simulates friction. Effect is based on the -# axes movement. -# -# \sa SDL_HapticCondition + ## Inertia effect supported - uses axes acceleration. + ## + ## Condition haptic effect that simulates inertia. + ## Effect is based on the axes acceleration. + ## + ## **See also:** + ## * `HapticCondition type<#HapticCondition>`_ const SDL_HAPTIC_FRICTION* = (1 shl 10) - -# -# \brief Custom effect is supported. -# -# User defined custom haptic effect. + ## Friction effect supported - uses axes movement. + ## + ## Condition haptic effect that simulates friction. + ## Effect is based on the axes movement. + ## + ## **See also:** + ## * `HapticCondition type<#HapticCondition>`_ const SDL_HAPTIC_CUSTOM* = (1 shl 11) - -# @} # Haptic effects - -# These last few are features the device has, not effects - -# -# \brief Device can set global gain. -# -# Device supports setting the global gain. -# -# \sa SDL_HapticSetGain + ## Custom effect is supported. + ## + ## User defined custom haptic effect. const SDL_HAPTIC_GAIN* = (1 shl 12) - -# -# \brief Device can set autocenter. -# -# Device supports setting autocenter. -# -# \sa SDL_HapticSetAutocenter + ## Device supports setting the global gain. + ## + ## **See also:** + ## * `setGain proc<#setGain,HapticPtr,int>`_ const SDL_HAPTIC_AUTOCENTER* = (1 shl 13) - -# -# \brief Device can be queried for effect status. -# -# Device can be queried for effect status. -# -# \sa SDL_HapticGetEffectStatus + ## Device supports setting autocenter. + ## + ## **See also:** + ## * `setAutoCenter proc<#setAutoCenter,HapticPtr,int>`_ const SDL_HAPTIC_STATUS* = (1 shl 14) - -# -# \brief Device can be paused. -# -# \sa SDL_HapticPause -# \sa SDL_HapticUnpause + ## Device supports querying effect status. + ## + ## **See also:** + ## * `getEffectStatus proc<#getEffectStatus,HapticPtr,cint>`_ const SDL_HAPTIC_PAUSE* = (1 shl 15) - - -# -# \name Direction encodings - -# @{ - -# -# \brief Uses polar coordinates for the direction. -# -# \sa HapticDirection + ## Devices supports being paused. + ## + ## **See also:** + ## * `pause proc<#pause,HapticPtr>`_ + ## * `unpause proc<#unpause,HapticPtr>`_ const SDL_HAPTIC_POLAR* = 0 - -# -# \brief Uses cartesian coordinates for the direction. -# -# \sa HapticDirection + ## Uses polar coordinates for the direction. + ## + ## **See also:** + ## * `HapticDirection type<#HapticDirection>`_ const SDL_HAPTIC_CARTESIAN* = 1 - -# -# \brief Uses spherical coordinates for the direction. -# -# \sa HapticDirection + ## Uses cartesian coordinates for the direction. + ## + ## **See also:** + ## * `HapticDirection type<#HapticDirection>`_ const SDL_HAPTIC_SPHERICAL* = 2 - -# @} # Direction encodings - -# @} # Haptic features - -# -# Misc defines. - - -# -# \brief Used to play a device an infinite number of times. -# -# \sa SDL_HapticRunEffect + ## Uses spherical coordinates for the direction. + ## + ## **See also:** + ## * `HapticDirection type<#HapticDirection>`_ const SDL_HAPTIC_INFINITY* = 4294967295'u + ## Used to play a device an infinite number of times. + ## + ## **See also:** + ## * `runEffect proc<#runEffect,HapticPtr,cint,uint32>`_ -# -# \brief Structure that represents a haptic direction. -# -# Directions can be specified by: -# - ::SDL_HAPTIC_POLAR : Specified by polar coordinates. -# - ::SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates. -# - ::SDL_HAPTIC_SPHERICAL : Specified by spherical coordinates. -# -# Cardinal directions of the haptic device are relative to the positioning -# of the device. North is considered to be away from the user. -# -# The following diagram represents the cardinal directions: -# \verbatim -# .--. -# |__| .-------. -# |=.| |.-----.| -# |--| || || -# | | |'-----'| -# |__|~')_____(' -# [ COMPUTER ] -# -# -# North (0,-1) -# ^ -# | -# | = (1,0) West <----[ HAPTIC ]----> East (-1,0) -# | -# | -# v -# South (0,1) -# -# -# [ USER ] -# \|||/ = (o o) -# ---ooO-(_)-Ooo--- -# \endverbatim -# -# If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a -# degree starting north and turning clockwise. ::SDL_HAPTIC_POLAR only uses -# the first \c dir parameter. The cardinal directions would be: -# - North: 0 (0 degrees) -# - East: 9000 (90 degrees) -# - South: 18000 (180 degrees) -# - West: 27000 (270 degrees) -# -# If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions -# = (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses -# the first three \c dir parameters. The cardinal directions would be: -# - North: 0,-1, 0 -# - East: -1, 0, 0 -# - South: 0, 1, 0 -# - West: 1, 0, 0 -# -# The Z axis represents the height of the effect if supported, otherwise -# it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you -# can use any multiple you want, only the direction matters. -# -# If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations. -# The first two \c dir parameters are used. The \c dir parameters are as -# follows (all values are in hundredths of degrees): -# - Degrees from (1, 0) rotated towards (0, 1). -# - Degrees towards (0, 0, 1) (device needs at least 3 axes). -# -# -# Example of force coming from the south with all encodings (force coming -# from the south means the user will have to pull the stick to counteract): -# \code -# HapticDirection direction; -# -# // Cartesian directions -# direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding. -# direction.dir[0] = 0; // X position -# direction.dir[1] = 1; // Y position -# // Assuming the device has 2 axes, we don't need to specify third parameter. -# -# // Polar directions -# direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding. -# direction.dir[0] = 18000; // Polar only uses first parameter -# -# // Spherical coordinates -# direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding -# direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters. -# \endcode -# -# \sa SDL_HAPTIC_POLAR -# \sa SDL_HAPTIC_CARTESIAN -# \sa SDL_HAPTIC_SPHERICAL -# \sa SDL_HapticEffect -# \sa SDL_HapticNumAxes - type HapticDirection* = object - kind: uint8 # < The type of encoding. - dir: array[3, int32] # < The encoded direction. - + ## Object that represents a haptic direction. + ## + ## This is the direction where the force comes from, + ## instead of the direction in which the force is exerted. + ## + ## Directions can be specified by: + ## * `SDL_HAPTIC_POLAR` : Specified by polar coordinates. + ## * `SDL_HAPTIC_CARTESIAN` : Specified by cartesian coordinates. + ## * `SDL_HAPTIC_SPHERICAL` : Specified by spherical coordinates. + ## + ## Cardinal directions of the haptic device + ## are relative to the positioning of the device. + ## North is considered to be away from the user. + ## + ## If type is `SDL_HAPTIC_POLAR`, direction is encoded by hundredths of a + ## degree starting north and turning clockwise. + ## `SDL_HAPTIC_POLAR` only uses the first `dir` parameter. + ## + ## The cardinal directions would be: + ## * North: `0` (0 degrees) + ## * East: `9000` (90 degrees) + ## * South: `18000` (180 degrees) + ## * West: `27000` (270 degrees) + ## + ## If type is `SDL_HAPTIC_CARTESIAN`, direction is encoded by three positions + ## (X axis, Y axis and Z axis (with 3 axes)). + ## `SDL_HAPTIC_CARTESIAN` uses the first three `dir` parameters. + ## + ## The cardinal directions would be: + ## * North: `0,-1, 0` + ## * East: `1, 0, 0` + ## * South: `0, 1, 0` + ## * West: `-1, 0, 0` + ## + ## The Z axis represents the height of the effect if supported, otherwise + ## it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), + ## you can use any multiple you want, only the direction matters. + ## + ## If type is `SDL_HAPTIC_SPHERICAL`, direction is encoded by two rotations. + ## The first two `dir` parameters are used. + ## + ## The `dir` parameters are as follows + ## (all values are in hundredths of degrees): + ## * Degrees from (`1, 0`) rotated towards (`0, 1`). + ## * Degrees towards (`0, 0, 1`) (device needs at least 3 axes). + ## + ## Example of force coming from the south with all encodings + ## (force coming from the south means the user will have to pull + ## the stick to counteract): + ## + ## .. code-block:: nim + ## var direction: HapticDirection + ## # Cartesian directions + ## direction.type = SDL_HAPTIC_CARTESIAN + ## direction.dir[0] = 0 # X position + ## direction.dir[1] = 1 # Y position + ## # Assuming the device has 2 axes, + ## # we don't need to specify third parameter. + ## # Polar directions + ## direction.type = SDL_HAPTIC_POLAR + ## direction.dir[0] = 18000 # Polar only uses first parameter + ## # Spherical coordinates + ## direction.type = SDL_HAPTIC_SPHERICAL # Spherical encoding + ## direction.dir[0] = 9000 + ## # Since we only have two axes we don't need more parameters. + ## + ## The following diagram represents the cardinal directions: + ## :: + ##   .--. + ## |__| .-------. + ## |=.| |.-----.| + ## |--| || || + ## | | |'-----'| + ## |__|~')_____(' + ## [ COMPUTER ] + ## + ## + ## North (0,-1) + ## ^ + ## | + ## | + ## (-1,0) West <----[ HAPTIC ]----> East (1,0) + ## | + ## | + ## v + ## South (0,1) + ## + ## + ## [ USER ] + ## \|||/ + ## (o o) + ## ---ooO-(_)-Ooo--- + ## + ## **See also:** + ## * `SDL_HAPTIC_POLAR const<#SDL_HAPTIC_POLAR>`_ + ## * `SDL_HAPTIC_CARTESIAN const<#SDL_HAPTIC_CARTESIAN>`_ + ## * `SDL_HAPTIC_SPHERICAL const<#SDL_HAPTIC_SPHERICAL>`_ + ## * `HapticEffect type<#HapticEffect>`_ + ## * `numAxes proc<#numAxes,HapticPtr>`_ + kind: uint8 ## The type of encoding. + dir: array[3, int32] ## The encoded direction. -# -# \brief A structure containing a template for a Constant effect. -# -# The struct is exclusive to the ::SDL_HAPTIC_CONSTANT effect. -# -# A constant effect applies a constant force in the specified direction -# to the joystick. -# -# \sa SDL_HAPTIC_CONSTANT -# \sa SDL_HapticEffect type HapticConstant* = object + ## An object containing a template for a Constant effect. + ## + ## The object is exclusively to the `HAPTIC_CONSTANT` effect. + ## + ## A constant effect applies a constant force + ## in the specified direction to the joystick. + ## + ## **See also:** + ## * `SDL_HAPTIC_CONSTANT const<#SDL_HAPTIC_CONSTANT>`_ + ## * `HapticEffect type<#HapticEffect>`_ # Header - kind: uint16 # < ::SDL_HAPTIC_CONSTANT - direction: HapticDirection # < Direction of the effect. + kind: uint16 ## SDL_HAPTIC_CONSTANT + direction: HapticDirection ## Direction of the effect. # Replay - length: uint32 # < Duration of the effect. - delay: uint16 # < Delay before starting the effect. + length: uint32 ## Duration of the effect. + delay: uint16 ## Delay before starting the effect. # Trigger - button: uint16 # < Button that triggers the effect. - interval: uint16 # < How soon it can be triggered again after button. + button: uint16 ## Button that triggers the effect. + interval: uint16 ## How soon it can be triggered again after button. # Constant - level: int16 # < Strength of the constant effect. + level: int16 ## Strength of the constant effect. # Envelope - attack_length: uint16 # < Duration of the attack. - attack_level: uint16 # < Level at the start of the attack. - fade_length: uint16 # < Duration of the fade. - fade_level: uint16 # < Level at the end of the fade. - -# -# \brief A structure containing a template for a Periodic effect. -# -# The struct handles the following effects: -# - ::SDL_HAPTIC_SINE -# - ::SDL_HAPTIC_LEFTRIGHT -# - ::SDL_HAPTIC_TRIANGLE -# - ::SDL_HAPTIC_SAWTOOTHUP -# - ::SDL_HAPTIC_SAWTOOTHDOWN -# -# A periodic effect consists in a wave-shaped effect that repeats itself -# over time. The type determines the shape of the wave and the parameters -# determine the dimensions of the wave. -# -# Phase is given by hundredth of a cycle meaning that giving the phase a value -# of 9000 will displace it 25% of its period. Here are sample values: -# - 0: No phase displacement. -# - 9000: Displaced 25% of its period. -# - 18000: Displaced 50% of its period. -# - 27000: Displaced 75% of its period. -# - 36000: Displaced 100% of its period, same as 0, but 0 is preferred. -# -# Examples: -# \verbatim -# SDL_HAPTIC_SINE -# __ __ __ __ -# / \ / \ / \ / -# / \__/ \__/ \__/ -# -# SDL_HAPTIC_SQUARE -# __ __ __ __ __ -# | | | | | | | | | | -# | |__| |__| |__| |__| | -# -# SDL_HAPTIC_TRIANGLE -# /\ /\ /\ /\ /\ -# / \ / \ / \ / \ / -# / \/ \/ \/ \/ -# -# SDL_HAPTIC_SAWTOOTHUP -# /| /| /| /| /| /| /| -# / | / | / | / | / | / | / | -# / |/ |/ |/ |/ |/ |/ | -# -# SDL_HAPTIC_SAWTOOTHDOWN -# \ |\ |\ |\ |\ |\ |\ | -# \ | \ | \ | \ | \ | \ | \ | -# \| \| \| \| \| \| \| -# \endverbatim -# -# \sa SDL_HAPTIC_SINE -# \sa SDL_HAPTIC_LEFTRIGHT -# \sa SDL_HAPTIC_TRIANGLE -# \sa SDL_HAPTIC_SAWTOOTHUP -# \sa SDL_HAPTIC_SAWTOOTHDOWN -# \sa SDL_HapticEffect + attack_length: uint16 ## Duration of the attack. + attack_level: uint16 ## Level at the start of the attack. + fade_length: uint16 ## Duration of the fade. + fade_level: uint16 ## Level at the end of the fade. type HapticPeriodic* = object + ## An object containing a template for a Periodic effect. + ## + ## The object handles the following effects: + ## * `HAPTIC_SINE` + ## * `HAPTIC_LEFTRIGHT` + ## * `HAPTIC_TRIANGLE` + ## * `HAPTIC_SAWTOOTHUP` + ## * `HAPTIC_SAWTOOTHDOWN` + ## + ## A periodic effect consists in a wave-shaped effect that repeats itself + ## over time. The type determines the shape of the wave and the parameters + ## determine the dimensions of the wave. + ## + ## Phase is given by hundredth of a degree meaning that giving the phase + ## a value of `9000` will displace it 25% of its period. + ## + ## Here are sample values: + ## * `0`: No phase displacement. + ## * `9000`: Displaced 25% of its period. + ## * `18000`: Displaced 50% of its period. + ## * `27000`: Displaced 75% of its period. + ## * `36000`: Displaced 100% of its period, \ + ## same as `0`, but `0` is preferred. + ## + ## Examples: + ## :: + ## SDL_HAPTIC_SINE + ## __ __ __ __ + ## / \ / \ / \ / + ## / \__/ \__/ \__/ + ## + ## SDL_HAPTIC_SQUARE + ## __ __ __ __ __ + ## | | | | | | | | | | + ## | |__| |__| |__| |__| | + ## + ## SDL_HAPTIC_TRIANGLE + ## /\ /\ /\ /\ /\ + ## / \ / \ / \ / \ / + ## / \/ \/ \/ \/ + ## + ## SDL_HAPTIC_SAWTOOTHUP + ## /| /| /| /| /| /| /| + ## / | / | / | / | / | / | / | + ## / |/ |/ |/ |/ |/ |/ | + ## + ## SDL_HAPTIC_SAWTOOTHDOWN + ## \ |\ |\ |\ |\ |\ |\ | + ## \ | \ | \ | \ | \ | \ | \ | + ## \| \| \| \| \| \| \| + ## + ## **See also:** + ## * `SDL_HAPTIC_SINE const<#SDL_HAPTIC_SINE>`_ + ## * `SDL_HAPTIC_LEFTRIGHT const<#SDL_HAPTIC_LEFTRIGHT>`_ + ## * `SDL_HAPTIC_TRIANGLE const<#SDL_HAPTIC_TRIANGLE>`_ + ## * `SDL_HAPTIC_SAWTOOTHDOWN const<#SDL_HAPTIC_SAWTOOTHDOWN>`_ + ## * `SDL_HAPTIC_SAWTOOTHUP const<#SDL_HAPTIC_SAWTOOTHUP>`_ + ## * `HapticEffect type<#HapticEffect>`_ # Header - kind: uint16 # < ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT, - # ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or - # ::SDL_HAPTIC_SAWTOOTHDOWN - direction: HapticDirection # < Direction of the effect. + kind: uint16 ## SDL_HAPTIC_SINE, SDL_HAPTIC_LEFTRIGHT, + ## SDL_HAPTIC_TRIANGLE, SDL_HAPTIC_SAWTOOTHUP or + ## SDL_HAPTIC_SAWTOOTHDOWN + direction: HapticDirection ## Direction of the effect. # Replay - length: uint32 # < Duration of the effect. - delay: uint16 # < Delay before starting the effect. + length: uint32 ## Duration of the effect. + delay: uint16 ## Delay before starting the effect. # Trigger - button: uint16 # < Button that triggers the effect. - interval: uint16 # < How soon it can be triggered again after button. + button: uint16 ## Button that triggers the effect. + interval: uint16 ## How soon it can be triggered again after button. # Periodic - period: uint16 # < Period of the wave. - magnitude: int16 # < Peak value. - offset: int16 # < Mean value of the wave. - phase: uint16 # < Horizontal shift given by hundredth of a cycle. + period: uint16 ## Period of the wave. + magnitude: int16 ## Peak value. + offset: int16 ## Mean value of the wave. + phase: uint16 ## Horizontal shift given by hundredth of a cycle. # Envelope - attack_length: uint16 # < Duration of the attack. - attack_level: uint16 # < Level at the start of the attack. - fade_length: uint16 # < Duration of the fade. - fade_level: uint16 # < Level at the end of the fade. - -# -# \brief A structure containing a template for a Condition effect. -# -# The struct handles the following effects: -# - ::SDL_HAPTIC_SPRING: Effect based on axes position. -# - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity. -# - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration. -# - ::SDL_HAPTIC_FRICTION: Effect based on axes movement. -# -# Direction is handled by condition internals instead of a direction member. -# The condition effect specific members have three parameters. The first -# refers to the X axis, the second refers to the Y axis and the third -# refers to the Z axis. The right terms refer to the positive side of the -# axis and the left terms refer to the negative side of the axis. Please -# refer to the ::HapticDirection diagram for which side is positive and -# which is negative. -# -# \sa HapticDirection -# \sa SDL_HAPTIC_SPRING -# \sa SDL_HAPTIC_DAMPER -# \sa SDL_HAPTIC_INERTIA -# \sa SDL_HAPTIC_FRICTION -# \sa SDL_HapticEffect + attack_length: uint16 ## Duration of the attack. + attack_level: uint16 ## Level at the start of the attack. + fade_length: uint16 ## Duration of the fade. + fade_level: uint16 ## Level at the end of the fade. type HapticCondition* = object + ## An object containing a template for a Condition effect. + ## + ## The object handles the following effects: + ## * `HAPTIC_SPRING`: Effect based on axes position. + ## * `HAPTIC_DAMPER`: Effect based on axes velocity. + ## * `HAPTIC_INERTIA`: Effect based on axes acceleration. + ## * `HAPTIC_FRICTION`: Effect based on axes movement. + ## + ## Direction is handled by condition internals + ## instead of a direction member. + ## + ## The condition effect specific members have three parameters. The first + ## refers to the X axis, the second refers to the Y axis and the third + ## refers to the Z axis. The right terms refer to the positive side + ## of the axis and the left terms refer to the negative side of the axis. + ## + ## Please refer to the `HapticDirection` diagram for which side is + ## positive and which is negative. + ## + ## **See also:** + ## * `HapticDirection type<#HapticDirection>`_ + ## * `SDL_HAPTIC_SPRING const<#SDL_HAPTIC_SPRING>`_ + ## * `SDL_HAPTIC_DAMPER const<#SDL_HAPTIC_DAMPER>`_ + ## * `SDL_HAPTIC_INERTIA const<#SDL_HAPTIC_INERTIA>`_ + ## * `SDL_HAPTIC_FRICTION const<#SDL_HAPTIC_FRICTION>`_ + ## * `HapticEffect type<#HapticEffect>`_ # Header - kind: uint16 # < ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER, - # ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION - direction: HapticDirection # < Direction of the effect - Not used ATM. + kind: uint16 ## SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER, + ## SDL_HAPTIC_INERTIA or SDL_HAPTIC_FRICTION + direction: HapticDirection ## Direction of the effect - Not used ATM. # Replay - length: uint32 # < Duration of the effect. - delay: uint16 # < Delay before starting the effect. + length: uint32 ## Duration of the effect. + delay: uint16 ## Delay before starting the effect. # Trigger - button: uint16 # < Button that triggers the effect. - interval: uint16 # < How soon it can be triggered again after button. + button: uint16 ## Button that triggers the effect. + interval: uint16 ## How soon it can be triggered again after button. # Condition - right_sat: array[3, uint16] # < Level when joystick is to the positive side. - left_sat: array[3, uint16] # < Level when joystick is to the negative side. - right_coeff: array[3, int16] # < How fast to increase the force towards the positive side. - left_coeff: array[3, int16] # < How fast to increase the force towards the negative side. - deadband: array[3, uint16] # < Size of the dead zone. - center: array[3, int16] # < Position of the dead zone. - -# -# \brief A structure containing a template for a Ramp effect. -# -# This struct is exclusively for the ::SDL_HAPTIC_RAMP effect. -# -# The ramp effect starts at start strength and ends at end strength. -# It augments in linear fashion. If you use attack and fade with a ramp -# the effects get added to the ramp effect making the effect become -# quadratic instead of linear. -# -# \sa SDL_HAPTIC_RAMP -# \sa SDL_HapticEffect + right_sat: array[3, uint16] ## Level when joystick is to the positive side. + left_sat: array[3, uint16] ## Level when joystick is to the negative side. + right_coeff: array[3, int16] ## How fast to increase the force towards the positive side. + left_coeff: array[3, int16] ## How fast to increase the force towards the negative side. + deadband: array[3, uint16] ## Size of the dead zone. + center: array[3, int16] ## Position of the dead zone. type HapticRamp* = object + ## An object containing a template for a Ramp effect. + ## + ## This object is exclusively for the `HAPTIC_RAMP` effect. + ## + ## The ramp effect starts at start strength and ends at end strength. + ## It augments in linear fashion. If you use attack and fade with a ramp + ## the effects get added to the ramp effect making the effect become + ## quadratic instead of linear. + ## + ## **See also:** + ## * `SDL_HAPTIC_RAMP const<#SDL_HAPTIC_RAMP>`_ + ## * `HapticEffect type<#HapticEffect>`_ # Header - kind: uint16 # < ::SDL_HAPTIC_RAMP - direction: HapticDirection # < Direction of the effect. + kind: uint16 ## SDL_HAPTIC_RAMP + direction: HapticDirection ## Direction of the effect. # Replay - length: uint32 # < Duration of the effect. - delay: uint16 # < Delay before starting the effect. + length: uint32 ## Duration of the effect. + delay: uint16 ## Delay before starting the effect. # Trigger - button: uint16 # < Button that triggers the effect. - interval: uint16 # < How soon it can be triggered again after button. + button: uint16 ## Button that triggers the effect. + interval: uint16 ## How soon it can be triggered again after button. # Ramp - start: int16 # < Beginning strength level. - fin: int16 # < Ending strength level. + start: int16 ## Beginning strength level. + fin: int16 ## Ending strength level. # Envelope - attack_length: uint16 # < Duration of the attack. - attack_level: uint16 # < Level at the start of the attack. - fade_length: uint16 # < Duration of the fade. - fade_level: uint16 # < Level at the end of the fade. - -# -# \brief A structure containing a template for a Left/Right effect. -# -# This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect. -# -# The Left/Right effect is used to explicitly control the large and small -# motors, commonly found in modern game controllers. One motor is high -# frequency, the other is low frequency. -# -# \sa SDL_HAPTIC_LEFTRIGHT -# \sa SDL_HapticEffect + attack_length: uint16 ## Duration of the attack. + attack_level: uint16 ## Level at the start of the attack. + fade_length: uint16 ## Duration of the fade. + fade_level: uint16 ## Level at the end of the fade. type HapticLeftRight* = object + ## An object containing a template for a Left/Right effect. + ## + ## This object is exclusively for the `HAPTIC_LEFTRIGHT` effect. + ## + ## The Left/Right effect is used to explicitly control the large and small + ## motors, commonly found in modern game controllers. + ## The small (right) motor is high frequency, + ## and the large (left) motor is low frequency. + ## + ## **See also:** + ## * `SDL_HAPTIC_LEFTRIGHT const<#SDL_HAPTIC_LEFTRIGHT>`_ + ## * `HapticEffect type<#HapticEffect>`_ # Header - kind: uint16 # < ::SDL_HAPTIC_LEFTRIGHT + kind: uint16 ## SDL_HAPTIC_LEFTRIGHT # Replay - length: uint32 # < Duration of the effect. + length: uint32 ## Duration of the effect. # Rumble - large_magnitude: uint16 # < Control of the large controller motor. - small_magnitude: uint16 # < Control of the small controller motor. + large_magnitude: uint16 ## Control of the large controller motor. + small_magnitude: uint16 ## Control of the small controller motor. -# -# \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect. -# -# A custom force feedback effect is much like a periodic effect, where the -# application can define its exact shape. You will have to allocate the -# data yourself. Data should consist of channels# samples uint16 samples. -# -# If channels is one, the effect is rotated using the defined direction. -# Otherwise it uses the samples in data for the different axes. -# -# \sa SDL_HAPTIC_CUSTOM -# \sa SDL_HapticEffect type HapticCustom* = object + ## An object containing a template for the `HAPTIC_CUSTOM` effect. + ## + ## This object is exclusively for the `HAPTIC_CUSTOM` effect. + ## + ## A custom force feedback effect is much like a periodic effect, where + ## the application can define its exact shape. You will have to allocate + ## the data yourself. + ## Data should consist of channels * samples `uint16` samples. + ## + ## If channels is one, the effect is rotated using the defined direction. + ## Otherwise it uses the samples in data for the different axes. + ## + ## **See also:** + ## * `SDL_HAPTIC_CUSTOM const<#SDL_HAPTIC_CUSTOM>`_ + ## * `HapticEffect type<#HapticEffect>`_ # Header - kind: uint16 # < ::SDL_HAPTIC_CUSTOM - direction: HapticDirection # < Direction of the effect. + kind: uint16 ## SDL_HAPTIC_CUSTOM + direction: HapticDirection ## Direction of the effect. # Replay - length: uint32 # < Duration of the effect. - delay: uint16 # < Delay before starting the effect. + length: uint32 ## Duration of the effect. + delay: uint16 ## Delay before starting the effect. # Trigger - button: uint16 # < Button that triggers the effect. - interval: uint16 # < How soon it can be triggered again after button. + button: uint16 ## Button that triggers the effect. + interval: uint16 ## How soon it can be triggered again after button. # Custom - channels: uint8 # < Axes to use, minimum of one. - period: uint16 # < Sample periods. - samples: uint16 # < Amount of samples. - data: ptr uint16 # < Should contain channels*samples items. + channels: uint8 ## Axes to use, minimum of one. + period: uint16 ## Sample periods. + samples: uint16 ## Amount of samples. + data: ptr uint16 ## Should contain `channels*samples` items. # Envelope - attack_length: uint16 # < Duration of the attack. - attack_level: uint16 # < Level at the start of the attack. - fade_length: uint16 # < Duration of the fade. - fade_level: uint16 # < Level at the end of the fade. - -# -# \brief The generic template for any haptic effect. -# -# All values max at 32767 (0x7FFF). Signed values also can be negative. -# Time values unless specified otherwise are in milliseconds. -# -# You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767 -# value. Neither delay, interval, attack_length nor fade_length support -# ::SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends. -# -# Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of -# ::SDL_HAPTIC_INFINITY. -# -# Button triggers may not be supported on all devices, it is advised to not -# use them if possible. Buttons start at index 1 instead of index 0 like -# the joystick. -# -# If both attack_length and fade_level are 0, the envelope is not used, -# otherwise both values are used. -# -# Common parts: -# \code -# // Replay - All effects have this -# uint32 length; // Duration of effect (ms). -# uint16 delay; // Delay before starting effect. -# -# // Trigger - All effects have this -# uint16 button; // Button that triggers effect. -# uint16 interval; // How soon before effect can be triggered again. -# -# // Envelope - All effects except condition effects have this -# uint16 attack_length; // Duration of the attack (ms). -# uint16 attack_level; // Level at the start of the attack. -# uint16 fade_length; // Duration of the fade out (ms). -# uint16 fade_level; // Level at the end of the fade. -# \endcode -# -# -# Here we have an example of a constant effect evolution in time: -# \verbatim -# Strength -# ^ -# | -# | effect level --> _________________ -# | / \ -# | / \ -# | / \ -# | / \ -# | attack_level --> | \ -# | | | <--- fade_level -# | -# +--------------------------------------------------> Time -# [--] [---] -# attack_length fade_length -# -# [------------------][-----------------------] -# delay length -# \endverbatim -# -# Note either the attack_level or the fade_level may be above the actual -# effect level. -# -# \sa SDL_HapticConstant -# \sa SDL_HapticPeriodic -# \sa SDL_HapticCondition -# \sa SDL_HapticRamp -# \sa SDL_HapticLeftRight -# \sa SDL_HapticCustom + attack_length: uint16 ## Duration of the attack. + attack_level: uint16 ## Level at the start of the attack. + fade_length: uint16 ## Duration of the fade. + fade_level: uint16 ## Level at the end of the fade. type HapticEffect* = object {.union.} + ## The generic template for any haptic effect. + ## + ## All values max at `32767` (`0x7FFF`). + ## Signed values also can be negative. + ## Time values unless specified otherwise are in milliseconds. + ## + ## You can also pass `HAPTIC_INFINITY` to length instead of a `0`-`32767` + ## value. Neither delay, interval, attack_length nor fade_length support + ## `HAPTIC_INFINITY`. Fade will also not be used since effect never ends. + ## + ## Additionally, the `HAPTIC_RAMP` effect does not support a duration of + ## `HAPTIC_INFINITY`. + ## + ## Button triggers may not be supported on all devices, it is advised to + ## not use them if possible. Buttons start at index `1` instead of index + ## `0` like the joystick. + ## + ## If both `attack_length` and `fade_level` are `0`, + ## the envelope is not used, otherwise both values are used. + ## + ## Common parts: + ## + ## .. code-block:: nim + ## # Replay - All effects have this + ## length: uint32 # Duration of effect (ms). + ## delay: uint16 # Delay before starting effect. + ## # Trigger - All effects have this + ## button: uint16 # Button that triggers effect. + ## interval: uint16 # How soon before effect can be triggered again. + ## # Envelope - All effects except condition effects have this + ## attack_length: uint16 # Duration of the attack (ms). + ## attack_level: uint16 # Level at the start of the attack. + ## fade_length: uint16 # Duration of the fade out (ms). + ## fade_level: uint16 # Level at the end of the fade. + ## + ## Here we have an example of a constant effect evolution in time: + ## :: + ## Strength + ## ^ + ## | + ## | effect level --> _________________ + ## | / \ + ## | / \ + ## | / \ + ## | / \ + ## | attack_level --> | \ + ## | | | <--- fade_level + ## | + ## +--------------------------------------------------> Time + ## [--] [---] + ## attack_length fade_length + ## + ## [------------------][-----------------------] + ## delay length + ## + ## Note either the attack_level or the fade_level may be above the actual + ## effect level. + ## + ## **See also:** + ## * `HapticConstant type<#HapticConstant>`_ + ## * `HapticPeriodic type<#HapticPeriodic>`_ + ## * `HapticCondition type<#HapticCondition>`_ + ## * `HapticRamp type<#HapticRamp>`_ + ## * `HapticLeftRight type<#HapticLeftRight>`_ + ## * `HapticCustom type<#HapticCustom>`_ # Common for all force feedback effects - kind: uint16 # < Effect type. - constant: HapticConstant # < Constant effect. - periodic: HapticPeriodic # < Periodic effect. - condition: HapticCondition # < Condition effect. - ramp: HapticRamp # < Ramp effect. - leftright: HapticLeftRight # < Left/Right effect. - custom: HapticCustom # < Custom effect. - + kind: uint16 ## Effect type. + constant: HapticConstant ## Constant effect. + periodic: HapticPeriodic ## Periodic effect. + condition: HapticCondition ## Condition effect. + ramp: HapticRamp ## Ramp effect. + leftright: HapticLeftRight ## Left/Right effect. + custom: HapticCustom ## Custom effect. when defined(SDL_Static): @@ -784,410 +658,427 @@ when defined(SDL_Static): else: {.push callConv: cdecl, dynlib: LibName.} -# Function prototypes -# -# \brief Count the number of haptic devices attached to the system. -# -# \return Number of haptic devices detected on the system. - -proc numHaptics*():cint {.importc: "SDL_NumHaptics".} - -# -# \brief Get the implementation dependent name of a Haptic device. -# -# This can be called before any joysticks are opened. -# If no name can be found, this function returns NULL. -# -# \param device_index Index of the device to get its name. -# \return Name of the device or NULL on error. -# -# \sa SDL_NumHaptics - -proc hapticName*(device_index: cint):cstring {.importc: "SDL_HapticName".} - -# -# \brief Opens a Haptic device for usage. -# -# The index passed as an argument refers to the N'th Haptic device on this -# system. -# -# When opening a haptic device, its gain will be set to maximum and -# autocenter will be disabled. To modify these values use -# SDL_HapticSetGain() and SDL_HapticSetAutocenter(). -# -# \param device_index Index of the device to open. -# \return Device identifier or NULL on error. -# -# \sa SDL_HapticIndex -# \sa SDL_HapticOpenFromMouse -# \sa SDL_HapticOpenFromJoystick -# \sa SDL_HapticClose -# \sa SDL_HapticSetGain -# \sa SDL_HapticSetAutocenter -# \sa SDL_HapticPause -# \sa SDL_HapticStopAll - -proc hapticOpen*(device_index: cint):HapticPtr {.importc: "SDL_HapticOpen".} - -# -# \brief Checks if the haptic device at index has been opened. -# -# \param device_index Index to check to see if it has been opened. -# \return 1 if it has been opened or 0 if it hasn't. -# -# \sa SDL_HapticOpen -# \sa SDL_HapticIndex - -proc hapticOpened*(device_index: cint):cint {.importc: "SDL_HapticOpened".} - -# -# \brief Gets the index of a haptic device. -# -# \param haptic Haptic device to get the index of. -# \return The index of the haptic device or -1 on error. -# -# \sa SDL_HapticOpen -# \sa SDL_HapticOpened - -proc index*(haptic: HapticPtr):cint {.importc: "SDL_HapticIndex".} - -# -# \brief Gets whether or not the current mouse has haptic capabilities. -# -# \return SDL_TRUE if the mouse is haptic, SDL_FALSE if it isn't. -# -# \sa SDL_HapticOpenFromMouse - -proc mouseIsHaptic*():cint {.importc: "SDL_MouseIsHaptic".} - -# -# \brief Tries to open a haptic device from the current mouse. -# -# \return The haptic device identifier or NULL on error. -# -# \sa SDL_MouseIsHaptic -# \sa SDL_HapticOpen - -proc hapticOpenFromMouse*():HapticPtr {.importc: "SDL_HapticOpenFromMouse".} - -# -# \brief Checks to see if a joystick has haptic features. -# -# \param joystick Joystick to test for haptic capabilities. -# \return 1 if the joystick is haptic, 0 if it isn't -# or -1 if an error ocurred. -# -# \sa SDL_HapticOpenFromJoystick - -proc joystickIsHaptic*(joystick: Joystick):cint {.importc: "SDL_JoystickIsHaptic".} - -# -# \brief Opens a Haptic device for usage from a Joystick device. -# -# You must still close the haptic device seperately. It will not be closed -# with the joystick. -# -# When opening from a joystick you should first close the haptic device before -# closing the joystick device. If not, on some implementations the haptic -# device will also get unallocated and you'll be unable to use force feedback -# on that device. -# -# \param joystick Joystick to create a haptic device from. -# \return A valid haptic device identifier on success or NULL on error. -# -# \sa SDL_HapticOpen -# \sa SDL_HapticClose - -proc hapticOpenFromJoystick*(joystick: JoystickPtr):HapticPtr {.importc: "SDL_HapticOpenFromJoystick".} - -# -# \brief Closes a Haptic device previously opened with SDL_HapticOpen(). -# -# \param haptic Haptic device to close. +proc numHaptics*(): cint {.importc: "SDL_NumHaptics".} + ## Count the number of haptic devices attached to the system. + ## + ## `Return` number of haptic devices detected on the system. + +proc hapticName*(device_index: cint): cstring {.importc: "SDL_HapticName".} + ## Get the implementation dependent name of a haptic device. + ## + ## This can be called before any joysticks are opened. + ## If no name can be found, this procedure returns `nil`. + ## + ## `device_index` Index of the device to get its name. + ## + ## `Return` name of the device or `nil` on error. + ## + ## **See also:** + ## * `numHaptics proc<#numHaptics>`_ + +proc hapticOpen*(device_index: cint): HapticPtr {.importc: "SDL_HapticOpen".} + ## Opens a haptic device for usage. + ## + ## The index passed as an argument refers to the N'th haptic device + ## on this system. + ## + ## When opening a haptic device, its gain will be set to maximum and + ## autocenter will be disabled. To modify these values use + ## `hapticSetGain()` and `hapticSetAutocenter()`. + ## + ## `device_index` Index of the device to open. + ## + ## `Return` device identifier or `nil` on error. + ## + ## **See also:** + ## * `index proc<#index,HapticPtr>`_ + ## * `hapticOpenFromMouse proc<#hapticOpenFromMouse>`_ + ## * `hapticOpenFromJoystick proc<#hapticOpenFromJoystick,JoystickPtr>`_ + ## * `close proc<#close,HapticPtr>`_ + ## * `setGain proc<#setGain,HapticPtr,int>`_ + ## * `setAutocenter proc<#setAutocenter,HapticPtr,int>`_ + ## * `pause proc<#pause,HapticPtr>`_ + ## * `stopAll proc<#stopAll,HapticPtr>`_ + +proc hapticOpened*(device_index: cint): cint {.importc: "SDL_HapticOpened".} + ## Checks if the haptic device at index has been opened. + ## + ## `device_index` Index to check to see if it has been opened. + ## + ## `Return` `1` if it has been opened or `0` if it hasn't. + ## + ## **See also:** + ## * `hapticOpen proc<#hapticOpen,cint>`_ + ## * `index proc<#index,HapticPtr>`_ + +proc index*(haptic: HapticPtr): cint {.importc: "SDL_HapticIndex".} + ## Gets the index of a haptic device. + ## + ## `haptic` Haptic device to get the index of. + ## + ## `Return` The index of the haptic device or `-1` on error. + ## + ## **See also:** + ## * `hapticOpen proc<#hapticOpen,cint>`_ + ## * `hapticOpened proc<#hapticOpened,cint>`_ + +proc mouseIsHaptic*(): cint {.importc: "SDL_MouseIsHaptic".} + ## Gets whether or not the current mouse has haptic capabilities. + ## + ## `Return` `1` if the mouse is haptic, `0` if it isn't. + ## + ## **See also:** + ## * `hapticOpenFromMouse proc<#hapticOpenFromMouse>`_ + +proc hapticOpenFromMouse*(): HapticPtr {.importc: "SDL_HapticOpenFromMouse".} + ## Tries to open a haptic device from the current mouse. + ## + ## `Return` The haptic device identifier or `nil` on error. + ## + ## **See also:** + ## * `mouseIsHaptic proc<#mouseIsHaptic>`_ + ## * `hapticOpen proc<#hapticOpen,cint>`_ + +proc joystickIsHaptic*(joystick: Joystick): cint {.importc: "SDL_JoystickIsHaptic".} + ## Checks to see if a joystick has haptic features. + ## + ## `joystick` Joystick to test for haptic capabilities. + ## + ## `Return` `1` if the joystick is haptic, `0` if it isn't + ## or `-1` if an error ocurred. + ## + ## **See also:** + ## * `hapticOpenFromJoystick proc<#hapticOpenFromJoystick,JoystickPtr>`_ + +proc hapticOpenFromJoystick*(joystick: JoystickPtr): HapticPtr {. + importc: "SDL_HapticOpenFromJoystick".} + ## Opens a haptic device for usage from a joystick device. + ## + ## You must still close the haptic device separately. + ## It will not be closed with the joystick. + ## + ## When opening from a joystick you should first close the haptic device + ## before closing the joystick device. If not, on some implementations the + ## haptic device will also get unallocated and you'll be unable to use + ## force feedback on that device. + ## + ## `joystick` Joystick to create a haptic device from. + ## + ## `Return` A valid haptic device identifier on success or `nil` on error. + ## + ## **See also:** + ## * `hapticOpen proc<#hapticOpen,cint>`_ + ## * `close proc<#close,HapticPtr>`_ proc close*(haptic: HapticPtr) {.importc: "SDL_HapticClose".} - -# -# \brief Returns the number of effects a haptic device can store. -# -# On some platforms this isn't fully supported, and therefore is an -# approximation. Always check to see if your created effect was actually -# created and do not rely solely on SDL_HapticNumEffects(). -# -# \param haptic The haptic device to query effect max. -# \return The number of effects the haptic device can store or -# -1 on error. -# -# \sa SDL_HapticNumEffectsPlaying -# \sa SDL_HapticQuery + ## Closes a haptic device previously opened with `hapticOpen proc<#hapticOpen,cint>`_. + ## + ## `haptic` Haptic device to close. proc numEffects*(haptic: HapticPtr):cint {.importc: "SDL_HapticNumEffects".} - -# -# \brief Returns the number of effects a haptic device can play at the same -# time. -# -# This is not supported on all platforms, but will always return a value. -# Added here for the sake of completeness. -# -# \param haptic The haptic device to query maximum playing effects. -# \return The number of effects the haptic device can play at the same time -# or -1 on error. -# -# \sa SDL_HapticNumEffects -# \sa SDL_HapticQuery - -proc numEffectsPlaying*(haptic: HapticPtr):cint {.importc: "SDL_HapticNumEffectsPlaying".} - -# -# \brief Gets the haptic devices supported features in bitwise matter. -# -# Example: -# \code -# if (SDL_HapticQuery(haptic) & SDL_HAPTIC_CONSTANT) { -# printf("We have constant haptic effect!"); -# } -# \endcode -# -# \param haptic The haptic device to query. -# \return Haptic features in bitwise manner (OR'd). -# -# \sa SDL_HapticNumEffects -# \sa SDL_HapticEffectSupported - -proc query*(haptic: HapticPtr):uint {.importc: "SDL_HapticQuery".} - - -# -# \brief Gets the number of haptic axes the device has. -# -# \sa HapticDirection + ## Returns the number of effects a haptic device can store. + ## + ## On some platforms this isn't fully supported, and therefore is an + ## approximation. Always check to see if your created effect was actually + ## created and do not rely solely on `hapticNumEffects()`. + ## + ## `haptic` The haptic device to query effect max. + ## + ## `Return` The number of effects the haptic device can store + ## or `-1` on error. + ## + ## **See also:** + ## * `numEffectsPlaying proc<#numEffectsPlaying,HapticPtr>`_ + ## * `query proc<#query,HapticPtr>`_ + +proc numEffectsPlaying*(haptic: HapticPtr): cint {. + importc: "SDL_HapticNumEffectsPlaying".} + ## Returns the number of effects a haptic device can play at the same time. + ## + ## This is not supported on all platforms, but will always return a value. + ## Added here for the sake of completeness. + ## + ## `haptic` The haptic device to query maximum playing effects. + ## + ## `Return` The number of effects the haptic device can play + ## at the same time or `-1` on error. + ## + ## **See also:** + ## * `numEffects proc<#numEffects,HapticPtr>`_ + ## * `query proc<#query,HapticPtr>`_ + +proc query*(haptic: HapticPtr): uint {.importc: "SDL_HapticQuery".} + ## Gets the haptic device's supported features in bitwise manner. + ## + ## Example: + ## + ## .. code-block:: nim + ## if hapticQuery(haptic) and HAPTIC_CONSTANT: + ## echo("We have constant haptic effect!") + ## + ## `haptic` The haptic device to query. + ## + ## `Return` Haptic features in bitwise manner (OR'd). + ## + ## **See also:** + ## * `numEffects proc<#numEffects,HapticPtr>`_ + ## * `effectSupported proc<#effectSupported,HapticPtr,ptr.HapticEffect>`_ proc numAxes*(haptic: HapticPtr):cint {.importc: "SDL_HapticNumAxes".} - -# -# \brief Checks to see if effect is supported by haptic. -# -# \param haptic Haptic device to check on. -# \param effect Effect to check to see if it is supported. -# \return SDL_TRUE if effect is supported, SDL_FALSE if it isn't or -1 on error. -# -# \sa SDL_HapticQuery -# \sa SDL_HapticNewEffect - -proc effectSupported*(haptic: HapticPtr, effect: ptr HapticEffect):cint {.importc: "SDL_HapticEffectSupported".} - -# -# \brief Creates a new haptic effect on the device. -# -# \param haptic Haptic device to create the effect on. -# \param effect Properties of the effect to create. -# \return The id of the effect on success or -1 on error. -# -# \sa SDL_HapticUpdateEffect -# \sa SDL_HapticRunEffect -# \sa SDL_HapticDestroyEffect - -proc newEffect*(haptic: HapticPtr, effect: ptr HapticEffect):cint {.importc: "SDL_HapticNewEffect".} - -# -# \brief Updates the properties of an effect. -# -# Can be used dynamically, although behaviour when dynamically changing -# direction may be strange. Specifically the effect may reupload itself -# and start playing from the start. You cannot change the type either when -# running SDL_HapticUpdateEffect(). -# -# \param haptic Haptic device that has the effect. -# \param effect Effect to update. -# \param data New effect properties to use. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticNewEffect -# \sa SDL_HapticRunEffect -# \sa SDL_HapticDestroyEffect - -proc updateEffect*(haptic: HapticPtr, effect: cint, data: ptr HapticEffect):cint {.importc: "SDL_HapticUpdateEffect".} - -# -# \brief Runs the haptic effect on its associated haptic device. -# -# If iterations are ::SDL_HAPTIC_INFINITY, it'll run the effect over and over -# repeating the envelope (attack and fade) every time. If you only want the -# effect to last forever, set ::SDL_HAPTIC_INFINITY in the effect's length -# parameter. -# -# \param haptic Haptic device to run the effect on. -# \param effect Identifier of the haptic effect to run. -# \param iterations Number of iterations to run the effect. Use -# ::SDL_HAPTIC_INFINITY for infinity. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticStopEffect -# \sa SDL_HapticDestroyEffect -# \sa SDL_HapticGetEffectStatus - -proc runEffect*(haptic: HapticPtr, effect: cint, iterations: uint32):cint {.importc: "SDL_HapticRunEffect".} - -# -# \brief Stops the haptic effect on its associated haptic device. -# -# \param haptic Haptic device to stop the effect on. -# \param effect Identifier of the effect to stop. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticRunEffect -# \sa SDL_HapticDestroyEffect - -proc stopEffect*(haptic: HapticPtr, effect: cint):cint {.importc: "SDL_HapticStopEffect".} - -# -# \brief Destroys a haptic effect on the device. -# -# This will stop the effect if it's running. Effects are automatically -# destroyed when the device is closed. -# -# \param haptic Device to destroy the effect on. -# \param effect Identifier of the effect to destroy. -# -# \sa SDL_HapticNewEffect - -proc destroyEffect*(haptic: HapticPtr, effect: cint) {.importc: "SDL_HapticDestroyEffect".} - -# -# \brief Gets the status of the current effect on the haptic device. -# -# Device must support the ::SDL_HAPTIC_STATUS feature. -# -# \param haptic Haptic device to query the effect status on. -# \param effect Identifier of the effect to query its status. -# \return 0 if it isn't playing, 1 if it is playing or -1 on error. -# -# \sa SDL_HapticRunEffect -# \sa SDL_HapticStopEffect - -proc getEffectStatus*(haptic: HapticPtr, effect: cint):cint {.importc: "SDL_HapticGetEffectStatus".} - -# -# \brief Sets the global gain of the device. -# -# Device must support the ::SDL_HAPTIC_GAIN feature. -# -# The user may specify the maximum gain by setting the environment variable -# SDL_HAPTIC_GAIN_MAX which should be between 0 and 100. All calls to -# SDL_HapticSetGain() will scale linearly using SDL_HAPTIC_GAIN_MAX as the -# maximum. -# -# \param haptic Haptic device to set the gain on. -# \param gain Value to set the gain to, should be between 0 and 100. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticQuery - -proc setGain*(haptic: HapticPtr, gain: int ):cint {.importc: "SDL_HapticSetGain".} - -# -# \brief Sets the global autocenter of the device. -# -# Autocenter should be between 0 and 100. Setting it to 0 will disable -# autocentering. -# -# Device must support the ::SDL_HAPTIC_AUTOCENTER feature. -# -# \param haptic Haptic device to set autocentering on. -# \param autocenter Value to set autocenter to, 0 disables autocentering. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticQuery - -proc setAutocenter*(haptic: HapticPtr, autocenter: int ):cint {.importc: "SDL_HapticSetAutocenter".} - -# -# \brief Pauses a haptic device. -# -# Device must support the ::SDL_HAPTIC_PAUSE feature. Call -# SDL_HapticUnpause() to resume playback. -# -# Do not modify the effects nor add new ones while the device is paused. -# That can cause all sorts of weird errors. -# -# \param haptic Haptic device to pause. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticUnpause - -proc pause*(haptic: HapticPtr):cint {.importc: "SDL_HapticPause".} - -# -# \brief Unpauses a haptic device. -# -# Call to unpause after SDL_HapticPause(). -# -# \param haptic Haptic device to pause. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticPause - -proc unpause*(haptic: HapticPtr):cint {.importc: "SDL_HapticUnpause".} - -# -# \brief Stops all the currently playing effects on a haptic device. -# -# \param haptic Haptic device to stop. -# \return 0 on success or -1 on error. - -proc stopAll*(haptic: HapticPtr):cint {.importc: "SDL_HapticStopAll".} - -# -# \brief Checks to see if rumble is supported on a haptic device. -# -# \param haptic Haptic device to check to see if it supports rumble. -# \return SDL_TRUE if effect is supported, SDL_FALSE if it isn't or -1 on error. -# -# \sa SDL_HapticRumbleInit -# \sa SDL_HapticRumblePlay -# \sa SDL_HapticRumbleStop - -proc rumbleSupported*(haptic: HapticPtr):cint {.importc: "SDL_HapticRumbleSupported".} - -# -# \brief Initializes the haptic device for simple rumble playback. -# -# \param haptic Haptic device to initialize for simple rumble playback. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticOpen -# \sa SDL_HapticRumbleSupported -# \sa SDL_HapticRumblePlay -# \sa SDL_HapticRumbleStop - -proc rumbleInit*(haptic: HapticPtr):cint {.importc: "SDL_HapticRumbleInit".} - -# -# \brief Runs simple rumble on a haptic device -# -# \param haptic Haptic device to play rumble effect on. -# \param strength Strength of the rumble to play as a 0-1 float value. -# \param length Length of the rumble to play in milliseconds. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticRumbleSupported -# \sa SDL_HapticRumbleInit -# \sa SDL_HapticRumbleStop - -proc rumblePlay*(haptic: HapticPtr, strength: float, length: uint32 ):cint {.importc: "SDL_HapticRumblePlay".} - -# -# \brief Stops the simple rumble on a haptic device. -# -# \param haptic Haptic to stop the rumble on. -# \return 0 on success or -1 on error. -# -# \sa SDL_HapticRumbleSupported -# \sa SDL_HapticRumbleInit -# \sa SDL_HapticRumblePlay + ## Gets the number of haptic axes the device has. + ## + ## **See also:** + ## * `HapticDirection type<#HapticDirection>`_ + +proc effectSupported*(haptic: HapticPtr, effect: ptr HapticEffect): cint {. + importc: "SDL_HapticEffectSupported".} + ## Checks to see if effect is supported by haptic. + ## + ## `haptic` Haptic device to check on. + ## + ## `effect` Effect to check to see if it is supported. + ## + ## `Return` `1` if effect is supported, `0` if it isn't + ## or `-1` on error. + ## + ## **See also:** + ## * `query proc<#query,HapticPtr>`_ + ## * `newEffect proc<#newEffect,HapticPtr,ptr.HapticEffect>`_ + +proc newEffect*(haptic: HapticPtr, effect: ptr HapticEffect): cint {. + importc: "SDL_HapticNewEffect".} + ## Creates a new haptic effect on the device. + ## + ## `haptic` Haptic device to create the effect on. + ## + ## `effect` Properties of the effect to create. + ## + ## `Return` The identifier of the effect on success or `-1` on error. + ## + ## **See also:** + ## * `updateEffect proc<#updateEffect,HapticPtr,cint,ptr.HapticEffect>`_ + ## * `runEffect proc<#runEffect,HapticPtr,cint,uint32>`_ + ## * `destroyEffect proc<#destroyEffect,HapticPtr,cint>`_ + +proc updateEffect*(haptic: HapticPtr, effect: cint, + data: ptr HapticEffect): cint {.importc: "SDL_HapticUpdateEffect".} + ## Updates the properties of an effect. + ## + ## Can be used dynamically, although behavior when dynamically changing + ## direction may be strange. Specifically the effect may reupload itself + ## and start playing from the start. You cannot change the type either + ## when running `hapticUpdateEffect()`. + ## + ## `haptic` Haptic device that has the effect. + ## + ## `effect` Identifier of the effect to update. + ## + ## `data` New effect properties to use. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `newEffect proc<#newEffect,HapticPtr,ptr.HapticEffect>`_ + ## * `runEffect proc<#runEffect,HapticPtr,cint,uint32>`_ + ## * `destroyEffect proc<#destroyEffect,HapticPtr,cint>`_ + +proc runEffect*(haptic: HapticPtr, effect: cint, + iterations: uint32): cint {.importc: "SDL_HapticRunEffect".} + ## Runs the haptic effect on its associated haptic device. + ## + ## If iterations are `HAPTIC_INFINITY`, it'll run the effect over and over + ## repeating the envelope (attack and fade) every time. + ## If you only want the effect to last forever, set `HAPTIC_INFINITY` + ## in the effect's length parameter. + ## + ## `haptic` Haptic device to run the effect on. + ## + ## `effect` Identifier of the haptic effect to run. + ## + ## `iterations` Number of iterations to run the effect. + ## Use `HAPTIC_INFINITY` for infinity. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `stopEffect proc<#stopEffect,HapticPtr,cint>`_ + ## * `destroyEffect proc<#destroyEffect,HapticPtr,cint>`_ + ## * `getEffectStatus proc<#getEffectStatus,HapticPtr,cint>`_ + +proc stopEffect*(haptic: HapticPtr, + effect: cint): cint {.importc: "SDL_HapticStopEffect".} + ## Stops the haptic effect on its associated haptic device. + ## + ## `haptic` Haptic device to stop the effect on. + ## + ## `effect` Identifier of the effect to stop. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `runEffect proc<#runEffect,HapticPtr,cint,uint32>`_ + ## * `destroyEffect proc<#destroyEffect,HapticPtr,cint>`_ + +proc destroyEffect*(haptic: HapticPtr, + effect: cint) {.importc: "SDL_HapticDestroyEffect".} + ## Destroys a haptic effect on the device. + ## + ## This will stop the effect if it's running. Effects are automatically + ## destroyed when the device is closed. + ## + ## `haptic` Device to destroy the effect on. + ## + ## `effect` Identifier of the effect to destroy. + ## + ## **See also:** + ## * `newEffect proc<#newEffect,HapticPtr,ptr.HapticEffect>`_ + +proc getEffectStatus*(haptic: HapticPtr, effect: cint): cint {. + importc: "SDL_HapticGetEffectStatus".} + ## Gets the status of the current effect on the haptic device. + ## + ## Device must support the `HAPTIC_STATUS` feature. + ## + ## `haptic` Haptic device to query the effect status on. + ## + ## `effect` Identifier of the effect to query its status. + ## + ## `Return` `0` if it isn't playing, `1` if it is playing + ## or `-1` on error. + ## + ## **See also:** + ## * `runEffect proc<#runEffect,HapticPtr,cint,uint32>`_ + ## * `stopEffect proc<#stopEffect,HapticPtr,cint>`_ + +proc setGain*(haptic: HapticPtr, + gain: int): cint {.importc: "SDL_HapticSetGain".} + ## Sets the global gain of the device. + ## + ## Device must support the `HAPTIC_GAIN` feature. + ## + ## The user may specify the maximum gain by setting the environment variable + ## `HAPTIC_GAIN_MAX` which should be between `0` and `100`. All calls to + ## `hapticSetGain()` will scale linearly using `HAPTIC_GAIN_MAX` as the + ## maximum. + ## + ## `haptic` Haptic device to set the gain on. + ## + ## `gain` Value to set the gain to, should be between `0` and `100`. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `query proc<#query,HapticPtr>`_ + +proc setAutocenter*(haptic: HapticPtr, autocenter: int): cint {. + importc: "SDL_HapticSetAutocenter".} + ## Sets the global autocenter of the device. + ## + ## Autocenter should be between `0` and `100`. + ## Setting it to `0` will disable autocentering. + ## + ## Device must support the `HAPTIC_AUTOCENTER` feature. + ## + ## `haptic` Haptic device to set autocentering on. + ## + ## `autocenter` Value to set autocenter to, `0` disables autocentering. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `query proc<#query,HapticPtr>`_ + +proc pause*(haptic: HapticPtr): cint {.importc: "SDL_HapticPause".} + ## Pauses a haptic device. + ## + ## Device must support the `HAPTIC_PAUSE` feature. + ## Call `unpause()` to resume playback. + ## + ## Do not modify the effects nor add new ones while the device is paused. + ## That can cause all sorts of weird errors. + ## + ## `haptic` Haptic device to pause. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `unpause proc<#unpause,HapticPtr>`_ + +proc unpause*(haptic: HapticPtr): cint {.importc: "SDL_HapticUnpause".} + ## Unpauses a haptic device. + ## + ## Call to unpause after `pause()`. + ## + ## `haptic` Haptic device to unpause. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `pause proc<#pause,HapticPtr>`_ + +proc stopAll*(haptic: HapticPtr): cint {.importc: "SDL_HapticStopAll".} + ## Stops all the currently playing effects on a haptic device. + ## + ## `haptic` Haptic device to stop. + ## + ## `Return` `0` on success or `-1` on error. + +proc rumbleSupported*(haptic: HapticPtr): cint {. + importc: "SDL_HapticRumbleSupported".} + ## Checks to see if rumble is supported on a haptic device. + ## + ## `haptic` Haptic device to check to see if it supports rumble. + ## + ## `Return` `1` if effect is supported, `0` if it isn't + ## or `-1` on error. + ## + ## **See also:** + ## * `rumbleInit proc<#rumbleInit,HapticPtr>`_ + ## * `rumblePlay proc<#rumblePlay,HapticPtr,float,uint32>`_ + ## * `rumbleStop proc<#rumbleStop,HapticPtr>`_ + +proc rumbleInit*(haptic: HapticPtr): cint {.importc: "SDL_HapticRumbleInit".} + ## Initializes the haptic device for simple rumble playback. + ## + ## `haptic` Haptic device to initialize for simple rumble playback. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `hapticOpen proc<#hapticOpen,cint>`_ + ## * `rumbleSupported proc<#rumbleSupported,HapticPtr>`_ + ## * `rumblePlay proc<#rumblePlay,HapticPtr,float,uint32>`_ + ## * `rumbleStop proc<#rumbleStop,HapticPtr>`_ + +proc rumblePlay*(haptic: HapticPtr, strength: float, length: uint32): cint {. + importc: "SDL_HapticRumblePlay".} + ## Runs simple rumble on a haptic device + ## + ## `haptic` Haptic device to play rumble effect on. + ## + ## `strength` Strength of the rumble to play as a `0`-`1` float value. + ## + ## `length` Length of the rumble to play in milliseconds. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `rumbleSupported proc<#rumbleSupported,HapticPtr>`_ + ## * `rumbleInit proc<#rumbleInit,HapticPtr>`_ + ## * `rumbleStop proc<#rumbleStop,HapticPtr>`_ proc rumbleStop*(haptic: HapticPtr):cint {.importc: "SDL_HapticRumbleStop".} + ## Stops the simple rumble on a haptic device. + ## + ## `haptic` Haptic to stop the rumble on. + ## + ## `Return` `0` on success or `-1` on error. + ## + ## **See also:** + ## * `rumbleSupported proc<#rumbleSupported,HapticPtr>`_ + ## * `rumbleInit proc<#rumbleInit,HapticPtr>`_ + ## * `rumbleStop proc<#rumbleStop,HapticPtr>`_ + when not defined(SDL_Static): {.pop.} diff --git a/src/sdl2/image.nim b/src/sdl2/image.nim index 01f6baa..05300f3 100644 --- a/src/sdl2/image.nim +++ b/src/sdl2/image.nim @@ -1,3 +1,6 @@ +## A simple library to load images of various formats as SDL surfaces. + + import sdl2 when not defined(SDL_Static): @@ -17,36 +20,48 @@ const IMG_INIT_WEBP* = 0x00000008 when not defined(SDL_Static): - {.push callConv:cdecl, dynlib: LibName.} + {.push callConv: cdecl, dynlib: LibName.} proc linkedVersion*(): ptr SDL_version {.importc: "IMG_Linked_Version".} + ## Gets the version of the dynamically linked image library. proc init*(flags: cint = IMG_INIT_JPG or IMG_INIT_PNG): cint {.importc: "IMG_Init".} ## It returns the flags successfully initialized, or 0 on failure. - ## This is completely different than SDL_Init() -_- + ## This is completely different than sdl2.init() -_- proc quit*() {.importc: "IMG_Quit".} -# Load an image from an SDL data source. -# The 'type' may be one of: "BMP", "GIF", "PNG", etc. -# -# If the image format supports a transparent pixel, SDL will set the -# colorkey for the surface. You can enable RLE acceleration on the -# surface afterwards by calling: -# SDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey); -# -proc loadTyped_RW*(src: RWopsPtr; freesrc: cint; `type`: cstring): SurfacePtr {.importc: "IMG_LoadTyped_RW".} + ## Unloads libraries loaded with `init()`. + +proc loadTyped_RW*(src: RWopsPtr; freesrc: cint; + `type`: cstring): SurfacePtr {.importc: "IMG_LoadTyped_RW".} + ## Load an image from an SDL data source. + ## + ## `kind` may be one of: `"BMP"`, `"GIF"`, `"PNG"`, etc. + ## + ## If the image format supports a transparent pixel, SDL will set the + ## colorkey for the surface. You can enable RLE acceleration on the + ## surface afterwards by calling: + ## + ## .. code-block:: nim + ## setColorKey(image, SDL_RLEACCEL, image.format.colorkey) + # Convenience functions proc load*(file: cstring): SurfacePtr {.importc: "IMG_Load".} -proc load_RW*(src: RWopsPtr; freesrc: cint): SurfacePtr {.importc: "IMG_Load_RW".} - ##Load an image directly into a render texture. -# -proc loadTexture*(renderer: RendererPtr; file: cstring): TexturePtr {.importc: "IMG_LoadTexture".} +proc load_RW*(src: RWopsPtr; + freesrc: cint): SurfacePtr {.importc: "IMG_Load_RW".} + ## Load an image directly into a render texture. + +proc loadTexture*(renderer: RendererPtr; + file: cstring): TexturePtr {.importc: "IMG_LoadTexture".} proc loadTexture_RW*(renderer: RendererPtr; src: RWopsPtr; - freesrc: cint): TexturePtr {.importc: "IMG_LoadTexture_RW".} -proc loadTextureTyped_RW*(renderer: RendererPtr; src: RWopsPtr; - freesrc: cint; `type`: cstring): TexturePtr {.importc: "IMG_LoadTextureTyped_RW".} + freesrc: cint): TexturePtr {. + importc: "IMG_LoadTexture_RW".} +proc loadTextureTyped_RW*(renderer: RendererPtr; + src: RWopsPtr; + freesrc: cint; + `type`: cstring): TexturePtr {. + importc: "IMG_LoadTextureTyped_RW".} -#discard """ # Functions to detect a file type, given a seekable source proc isICO*(src: RWopsPtr): cint {.importc: "IMG_isICO".} proc isCUR*(src: RWopsPtr): cint {.importc: "IMG_isCUR".} @@ -81,7 +96,6 @@ proc loadWEBP_RW*(src: RWopsPtr): SurfacePtr {.importc: "IMG_LoadWEBP_RW".} proc readXPMFromArray*(xpm: cstringArray): SurfacePtr {.importc: "IMG_ReadXPMFromArray".} # Saving functions proc savePNG*(surface: SurfacePtr, file: cstring): cint {.importc: "IMG_SavePNG".} -#""" when not defined(SDL_Static): {.pop.} diff --git a/src/sdl2/joystick.nim b/src/sdl2/joystick.nim index a9f2017..a760633 100644 --- a/src/sdl2/joystick.nim +++ b/src/sdl2/joystick.nim @@ -1,6 +1,3 @@ -import "../sdl2" - - discard """ Simple DirectMedia Layer Copyright (C) 1997-2014 Sam Lantinga @@ -20,36 +17,34 @@ freely, subject to the following restrictions: misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. +""" +## Include file for SDL joystick event handling +## +## The term "device_index" identifies currently plugged in joystick devices +## between 0 and SDL_NumJoysticks, with the exact joystick behind a +## device_index changing as joysticks are plugged and unplugged. +## +## The term "instance_id" is the current instantiation of a joystick device in +## the system, if the joystick is removed and then re-inserted then it will get +## a new instance_id, instance_id's are monotonically increasing identifiers of +## a joystick plugged in. +## +## The term JoystickGUID is a stable 128-bit identifier for a joystick device +## that does not change over time, it identifies class of the device +## (a X360 wired controller for example). This identifier is platform dependent. +## +## In order to use these functions, `init()` must have been called with +## the `INIT_JOYSTICK` flag. This causes SDL to scan the system for joysticks, +## and load appropriate drivers. +## +## If you would like to receive joystick updates while the application +## is in the background, you should set the following hint before calling +## `init()`: `SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS` +import "../sdl2" -\file SDL_joystick.h - -Include file for SDL joystick event handling - -The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks, with the exact joystick - behind a device_index changing as joysticks are plugged and unplugged. - -The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted - then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in. - -The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of - the device (a X360 wired controller for example). This identifier is platform dependent. - -""" -#* -# \file SDL_joystick.h -# -# In order to use these functions, SDL_Init() must have been called -# with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system -# for joysticks, and load appropriate drivers. -# -# If you would like to receive joystick updates while the application -# is in the background, you should set the following hint before calling -# SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS -# - -# The joystick structure used to identify an SDL joystick# +# The joystick structure used to identify an SDL joystick type Joystick* = object JoystickPtr* = ptr Joystick @@ -59,213 +54,244 @@ type JoystickGuid* = object data: array[16, uint8] JoystickID* = int32 + ## This is a unique ID for a joystick for the time it is connected to the + ## system, and is never reused for the lifetime of the application. If the + ## joystick is disconnected and reconnected, it will get a new ID. + ## + ## The ID value starts at `0` and increments from there. + ## The value `-1` is an invalid ID. when defined(SDL_Static): static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2." else: {.push callConv: cdecl, dynlib: LibName.} -# Function prototypes# / -## -# Count the number of joysticks attached to the system right now -# / -proc numJoysticks*(): cint {. - importc: "SDL_NumJoysticks".} -## -# Get the implementation dependent name of a joystick. -# This can be called before any joysticks are opened. -# If no name can be found, this function returns NULL. -# / +proc numJoysticks*(): cint {.importc: "SDL_NumJoysticks".} + ## Count the number of joysticks attached to the system right now. + proc joystickNameForIndex*(device_index: cint): cstring {. importc: "SDL_JoystickNameForIndex".} + ## Get the implementation dependent name of a joystick. + ## + ## This can be called before any joysticks are opened. + ## If no name can be found, this procedure returns `nil`. -## -# Open a joystick for use. -# The index passed as an argument refers tothe N'th joystick on the system. -# This index is the value which will identify this joystick in future joystick -# events. -# -# \return A joystick identifier, or NULL if an error occurred. -# / proc joystickOpen*(device_index: cint): JoystickPtr {. importc: "SDL_JoystickOpen".} + ## Open a joystick for use. + ## + ## The index passed as an argument refers to the N'th joystick on the system. + ## This index is not the value which will identify this joystick in future + ## joystick events. The joystick's instance id (`JoystickID`) will be used + ## there instead. + ## + ## `Return` a joystick identifier, or `nil` if an error occurred. -## -# Return the name for this currently opened joystick. -# If no name can be found, this function returns NULL. -# / proc joystickName*(joystick: ptr Joystick): cstring {.importc: "SDL_JoystickName".} -proc name* (joystick: ptr Joystick): cstring {.inline.} = joystick.joystickName + ## `Return` the name for this currently opened joystick. + ## If no name can be found, this procedure returns `nil`. + +proc name*(joystick: ptr Joystick): cstring {.inline.} = + ## `Return` the name for this currently opened joystick. + ## If no name can be found, this procedure returns `nil`. + joystick.joystickName -## -# Return the GUID for the joystick at this index -# / proc joystickGetDeviceGUID*(device_index: cint): JoystickGUID {. importc: "SDL_JoystickGetDeviceGUID".} + ## Return the GUID for the joystick at this index. + ## + ## This can be called before any joysticks are opened. -# * -# Return the GUID for this opened joystick -# proc joystickGetGUID*(joystick: JoystickPtr): JoystickGUID {. importc: "SDL_JoystickGetGUID".} -proc getGUID* (joystick: JoystickPtr): JoystickGUID {.inline.} = joystick.joystickGetGUID + ## `Return` the GUID for this opened joystick. + +proc getGUID*(joystick: JoystickPtr): JoystickGUID {.inline.} = + ## `Return` the GUID for this opened joystick. + joystick.joystickGetGUID -# * -# Return a string representation for this guid. pszGUID must point to at least 33 bytes -# (32 for the string plus a NULL terminator). -# proc joystickGetGUIDString*(guid: JoystickGUID, pszGUID: cstring, cbGUID: cint) {. importc: "SDL_JoystickGetGUIDString".} + ## `Return` a string representation for this guid. + ## + ## `pszGUID` must point to at least 33 bytes + ## (32 for the string plus a `nil` terminator). -# * -# convert a string into a joystick formatted guid -# proc joystickGetGUIDFromString*(pchGUID: cstring): JoystickGUID {. importc: "SDL_JoystickGetGUIDFromString".} + ## Convert a string into a joystick GUID. -# * -# Returns SDL_TRUE if the joystick has been opened and currently connected, or SDL_FALSE if it has not. -# proc joystickGetAttached*(joystick: JoystickPtr): Bool32 {. importc: "SDL_JoystickGetAttached".} -proc getAttached* (joystick: JoystickPtr): Bool32 {.inline.} = joystick.joystickGetAttached + ## `Return` `true` if the joystick has been opened and currently + ## connected, or `false` if it has not. + +proc getAttached* (joystick: JoystickPtr): Bool32 {.inline.} = + ## `Return` `true` if the joystick has been opened and currently + ## connected, or `false` if it has not. + joystick.joystickGetAttached -# * -# Get the instance ID of an opened joystick or -1 if the joystick is invalid. -# proc joystickInstanceID*(joystick: JoystickPtr): JoystickID {. importc: "SDL_JoystickInstanceID".} -proc instanceID* (joystick: JoystickPtr): JoystickID {.inline.} = joystick.joystickInstanceID + ## Get the instance ID of an opened joystick, + ## or `-1` if the joystick is invalid. + +proc instanceID*(joystick: JoystickPtr): JoystickID {.inline.} = + ## Get the instance ID of an opened joystick, + ## or `-1` if the joystick is invalid. + joystick.joystickInstanceID -# * -# Get the number of general axis controls on a joystick. -# proc joystickNumAxes*(joystick: JoystickPtr): cint {. importc: "SDL_JoystickNumAxes".} -proc numAxes* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumAxes - -# * -# Get the number of trackballs on a joystick. -# -# Joystick trackballs have only relative motion events associated -# with them and their state cannot be polled. -# events are enabled. -# + ## Get the number of general axis controls on a joystick. + +proc numAxes* (joystick: JoystickPtr): cint {.inline.} = + ## Get the number of general axis controls on a joystick. + joystick.joystickNumAxes + proc joystickNumBalls*(joystick: JoystickPtr): cint {. importc: "SDL_JoystickNumBalls".} -proc numBalls* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumBalls + ## Get the number of trackballs on a joystick. + ## + ## Joystick trackballs have only relative motion events associated + ## with them and their state cannot be polled. + +proc numBalls*(joystick: JoystickPtr): cint {.inline.} = + ## Get the number of trackballs on a joystick. + ## + ## Joystick trackballs have only relative motion events associated + ## with them and their state cannot be polled. + joystick.joystickNumBalls -# -# Get the number of POV hats on a joystick. -# proc joystickNumHats*(joystick: JoystickPtr): cint {. importc: "SDL_JoystickNumHats".} -proc numHats* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumHats + ## Get the number of POV hats on a joystick. + +proc numHats*(joystick: JoystickPtr): cint {.inline.} = + ## Get the number of POV hats on a joystick. + joystick.joystickNumHats -# -# Get the number of buttons on a joystick. -# proc joystickNumButtons*(joystick: JoystickPtr): cint {. importc: "SDL_JoystickNumButtons".} -proc numButtons* (joystick: JoystickPtr): cint {.inline.} = joystick.joystickNumButtons - -# -# Update the current state of the open joysticks. -# -# This is called automatically by the event loop if any joystick -# -proc joystickUpdate*() {. - importc: "SDL_JoystickUpdate".} - -# -# Enable/disable joystick event polling. -# -# If joystick events are disabled, you must call SDL_JoystickUpdate() -# yourself and check the state of the joystick when you want joystick -# information. -# -# The state can be one of ::SDL_QUERY, ::SDL_ENABLE or ::SDL_IGNORE. -# + ## Get the number of buttons on a joystick. + +proc numButtons*(joystick: JoystickPtr): cint {.inline.} = + ## Get the number of buttons on a joystick. + joystick.joystickNumButtons + +proc joystickUpdate*() {.importc: "SDL_JoystickUpdate".} + ## Update the current state of the open joysticks. + ## + ## This is called automatically by the event loop if any joystick + ## events are enabled. + proc joystickEventState*(state: cint): cint {. importc: "SDL_JoystickEventState".} + ## Enable/disable joystick event polling. + ## + ## If joystick events are disabled, you must call `joystickUpdate()` + ## yourself and check the state of the joystick when you want joystick + ## information. + ## + ## The `state` can be one of `SDL_QUERY`, `SDL_ENABLE` or `SDL_IGNORE`. -# -# Get the current state of an axis control on a joystick. -# -# The state is a value ranging from -32768 to 32767. -# -# The axis indices start at index 0. -# proc joystickGetAxis*(joystick: JoystickPtr, axis: cint): int16 {. - importc: "SDL_JoystickGetAxis".} -proc getAxis* (joystick: JoystickPtr, axis: cint): int16 {.inline.} = joystick.joystickGetAxis(axis) + importc: "SDL_JoystickGetAxis".}SDL_ + ## Get the current state of an aSDL_xis control on a joystick. + ##SDL_ + ##SDL_ The state is a value ranging SDL_from `-32768` to `32767`. + ##SDL_ + ##SDL_ The axis indices start at indSDL_ex `0`. +SDL_ +SDL_proc getAxis*(joystick: JoystickPtSDL_r, axis: cint): int16 {.inline.} = + ## Get the current state of an aSDL_xis control on a joystick. + ## + ## The state is a value ranging from `-32768` to `32767`. + ## + ## The axis indices start at index `0`. + joystick.joystickGetAxis(axis) -# -# \name Hat positions -# -# @{# const - SDL_HAT_CENTERED*:cint = (0x00000000) - SDL_HAT_UP*:cint = (0x00000001) - SDL_HAT_RIGHT*:cint = (0x00000002) - SDL_HAT_DOWN*:cint = (0x00000004) - SDL_HAT_LEFT*:cint = (0x00000008) - SDL_HAT_RIGHTUP*:cint = (SDL_HAT_RIGHT or SDL_HAT_UP) - SDL_HAT_RIGHTDOWN*:cint = (SDL_HAT_RIGHT or SDL_HAT_DOWN) - SDL_HAT_LEFTUP*:cint = (SDL_HAT_LEFT or SDL_HAT_UP) - SDL_HAT_LEFTDOWN*:cint = (SDL_HAT_LEFT or SDL_HAT_DOWN) -# @}# - -# -# Get the current state of a POV hat on a joystick. -# -# The hat indices start at index 0. -# -# \return The return value is one of the following positions: -# - ::SDL_HAT_CENTERED -# - ::SDL_HAT_UP -# - ::SDL_HAT_RIGHT -# - ::SDL_HAT_DOWN -# - ::SDL_HAT_LEFT -# - ::SDL_HAT_RIGHTUP -# - ::SDL_HAT_RIGHTDOWN -# - ::SDL_HAT_LEFTUP -# - ::SDL_HAT_LEFTDOWN -# + SDL_HAT_CENTERED*: cint = 0x00000000 + SDL_HAT_UP*: cint = 0x00000001 + SDL_HAT_RIGHT*: cint = 0x00000002 + SDL_HAT_DOWN*: cint = 0x00000004 + SDL_HAT_LEFT*: cint = 0x00000008 + SDL_HAT_RIGHTUP*: cint = SDL_HAT_RIGHT or SDL_HAT_UP + SDL_HAT_RIGHTDOWN*: cint = SDL_HAT_RIGHT or SDL_HAT_DOWN + SDL_HAT_LEFTUP*: cint = SDL_HAT_LEFT or SDL_HAT_UP + SDL_HAT_LEFTDOWN*: cint = SDL_HAT_LEFT or SDL_HAT_DOWN + + proc joystickGetHat*(joystick: JoystickPtr, hat: cint): uint8 {. importc: "SDL_JoystickGetHat".} -proc getHat* (joystick: JoystickPtr, hat: cint): uint8 {.inline.} = joystick.joystickGetHat(hat) - -# -# Get the ball axis change since the last poll. -# -# \return 0, or -1 if you passed it invalid parameters. -# -# The ball indices start at index 0. -# + ## Get the current state of a POV hat on a joystick. + ## + ## The hat indices start at index `0`. + ## + ## `Return` The return value is one of the following positions: + ## * SDL_HAT_CENTERED + ## * SDL_HAT_UP + ## * SDL_HAT_RIGHT + ## * SDL_HAT_DOWN + ## * SDL_HAT_LEFT + ## * SDL_HAT_RIGHTUP + ## * SDL_HAT_RIGHTDOWN + ## * SDL_HAT_LEFTUP + ## * SDL_HAT_LEFTDOWN + +proc getHat*(joystick: JoystickPtr, hat: cint): uint8 {.inline.} = + ## Get the current state of a POV hat on a joystick. + ## + ## The hat indices start at index `0`. + ## + ## `Return` The return value is one of the following positions: + ## * SDL_HAT_CENTERED + ## * SDL_HAT_UP + ## * SDL_HAT_RIGHT + ## * SDL_HAT_DOWN + ## * SDL_HAT_LEFT + ## * SDL_HAT_RIGHTUP + ## * SDL_HAT_RIGHTDOWN + ## * SDL_HAT_LEFTUP + ## * SDL_HAT_LEFTDOWN + joystick.joystickGetHat(hat) + proc joystickGetBall*(joystick: JoystickPtr, ball: cint, dx: ptr cint, dy: ptr cint): cint {. importc: "SDL_JoystickGetBall".} -proc getBall* (joystick: JoystickPtr, ball: cint, dx: ptr cint, dy: ptr cint): cint {.inline.} = joystick.joystickGetBall(ball, dx, dy) + ## Get the ball axis change since the last poll. + ## + ## `Return` `0`, or `-1` if you passed it invalid parameters. + ## + ## The ball indices start at index `0`. + +proc getBall*(joystick: JoystickPtr, ball: cint, dx: ptr cint, dy: ptr cint): cint {.inline.} = + ## Get the ball axis change since the last poll. + ## + ## `Return` `0`, or `-1` if you passed it invalid parameters. + ## + ## The ball indices start at index `0`. + joystick.joystickGetBall(ball, dx, dy) -# -# Get the current state of a button on a joystick. -# -# The button indices start at index 0. -# proc joystickGetButton*(joystick: JoystickPtr, button: cint): uint8 {. importc: "SDL_JoystickGetButton".} -proc getButton* (joystick: JoystickPtr, button: cint): uint8 {.inline.} = joystick.joystickGetButton(button) + ## Get the current state of a button on a joystick. + ## + ## The button indices start at index `0`. + +proc getButton* (joystick: JoystickPtr, button: cint): uint8 {.inline.} = + ## Get the current state of a button on a joystick. + ## + ## The button indices start at index `0`. + joystick.joystickGetButton(button) -# -# Close a joystick previously opened with SDL_JoystickOpen(). -# -proc joystickClose*(joystick: JoystickPtr) {. - importc: "SDL_JoystickClose".} -proc close* (joystick: JoystickPtr) {.inline.} = joystick.joystickClose() +proc joystickClose*(joystick: JoystickPtr) {.importc: "SDL_JoystickClose".} + ## Close a joystick previously opened with `joystickOpen()`. -# Ends C function definitions when using C++ +proc close* (joystick: JoystickPtr) {.inline.} = + ## Close a joystick previously opened with `joystickOpen()`. + joystick.joystickClose() -# vi: set ts=4 sw=4 expandtab: when not defined(SDL_Static): {.pop.} diff --git a/src/sdl2/mixer.nim b/src/sdl2/mixer.nim index 4d19f26..d069d80 100644 --- a/src/sdl2/mixer.nim +++ b/src/sdl2/mixer.nim @@ -1,4 +1,3 @@ -# # SDL_mixer: An audio mixer library based on the SDL library # Copyright (C) 1997-2013 Sam Lantinga # @@ -19,6 +18,8 @@ # 3. This notice may not be removed or altered from any source distribution. # +## Multi-channel audio mixer library. + {.deadCodeElim: on.} # Dynamically link to the correct library for our system: @@ -48,35 +49,77 @@ else: # These are not recognized by c2nim, but that's easy to fix: -# This function gets the version of the dynamically linked SDL_mixer library. -# it should NOT be used to fill a version structure, instead you should -# use the SDL_MIXER_VERSION() macro. -# - proc linkedVersion*(): ptr SDL_version {.importc: "Mix_Linked_Version".} + ## Gets the version of the dynamically linked mixer + ## library. + # TODO: Add the equivalent of the SDL_MIXER_VERSION() macro + # (version() template ?) and this comment: + # It should NOT be used to fill a version structure, instead you + # should use the `version()` template. const MIX_INIT_FLAC* : cint = 0x00000001 + ## (.flac) requiring the FLAC library on system + ## also any command-line player, which is not mixed by `mixer` MIX_INIT_MOD* : cint = 0x00000002 + ## (.mod .xm .s3m .669 .it .med and more) requiring libmikmod on system MIX_INIT_MODPLUG* : cint = 0x00000004 MIX_INIT_MP3* : cint = 0x00000008 + ## (.mp3) requiring SMPEG or MAD library on system MIX_INIT_OGG* : cint = 0x00000010 + ## (.ogg) requiring ogg/vorbis libraries on system MIX_INIT_FLUIDSYNTH* : cint = 0x00000020 -# Loads dynamic libraries and prepares them for use. Flags should be -# one or more flags from MIX_InitFlags OR'd together. -# It returns the flags successfully initialized, or 0 on failure. -# - proc init*(flags: cint): cint {.importc: "Mix_Init".} -# Unloads libraries loaded with Mix_Init + ## Loads dynamic libraries and prepares them for use. + ## + ## `flags` bitwise OR'd set of sample/music formats to support by loading + ## a library now from `mixer.INIT_*` + ## + ## Initialize by loading support as indicated by the flags, or at least + ## return success if support is already loaded. You may call this multiple + ## times, which will actually require you to call `mixer.quit()` + ## just once to clean up. You may call this procedure with a `0` to retrieve + ## whether support was built-in or not loaded yet. + ## + ## `Note:` you can call `mixer.init()` with the right + ## `mixer.INIT_*` flags OR'd together before you program gets busy, + ## to prevent a later hiccup while it loads and unloads the library, + ## and to check that you do have the support that you need before you try + ## and use it. + ## + ## `Note:` this procedure does not always set the error string, so do not + ## depend on `mixer.getError()` being meaningful all the time. + ## + ## `Return` the flags successfully initialized, or `0` on failure. proc quit*() {.importc: "Mix_Quit".} -# The default mixer has 8 simultaneous mixing channels + ## Unloads libraries loaded with `init()`. + ## + ## This procedure cleans up all dynamically loaded library handles, freeing + ## memory. If support is required again it will be initialized again, either + ## by `mixer.init()` or loading a sample or some music with dynamic + ## support required. You may call this procedure when `mixer.load*` + ## procedures are no longer needed for the `mixer.INIT_*` formats. + ## You should call this procedure for each time `mixer.init()` was + ## called, otherwise it may not free all the dynamic library resources until + ## the program ends. This is done so that multiple unrelated modules of a + ## program may call `mixer.init()` and `mixer.quit()` without + ## affecting the others performance and needs. + ## + ## `Note:` Since each call to `init()` may set different + ## flags, there is no way, currently, to request how many times each one + ## was `init`ialized. In other words, the only way to quit for sure is to do + ## a loop like so: + ## + ## .. code-block:: nim + ## # force a quit + ## while init(0) != 0: + ## mixer.quit() const - MIX_CHANNELS* = 8 + MIX_CHANNELS* = 8 ## The default mixer has `8` simultaneous mixing channels # Good default values for a PC soundcard @@ -94,18 +137,42 @@ const type ChunkPtr* = ptr Chunk Chunk* = object + ## The internal format for an audio chunk + ## + ## This stores the sample data, the length in bytes of that data, + ## and the volume to use when mixing the sample. allocated*: cint + ## a boolean indicating whether to free abuf when the chunk is freed. + ## `0` if the memory was not allocated and thus not owned by this chunk. + ## `1` if the memory was allocated and is thus owned by this chunk. abuf*: ptr uint8 - alen*: uint32 - volume*: uint8 # Per-sample volume, 0-128 + ## Pointer to the sample data, + ## which is in the output format and sample rate. + alen*: uint32 ## Length of abuf in bytes. + volume*: uint8 ## Per-sample volume, + ## `0` = silent, `128` = max volume. This takes effect when mixing. # The different fading types supported type Fading* {.size: sizeof(cint).} = enum + ## Return values from `mixer.fadingMusic()` and + ## `mixer.fadingChannel()` are of these enumerated values. + ## + ## If no fading is taking place on the queried channel or music, + ## then `MIX_NO_FADING` is returned. Otherwise they are self explanatory. MIX_NO_FADING, MIX_FADING_OUT, MIX_FADING_IN + MusicType* {.size: sizeof(cint).} = enum + ## Return values from `mixer.getMusicType()` + ## are of these enumerated values. + ## + ## If no music is playing then `MUS_NONE` is returned. ## + ## If music is playing via an external command then `MUS_CMD` is returned. + ## Otherwise they are self explanatory. + ## + ## These are types of music files (not libraries used to load them). MUS_NONE, MUS_CMD, MUS_WAV, MUS_MOD, MUS_MID, MUS_OGG, MUS_MP3, MUS_MP3_MAD, MUS_FLAC, MUS_MODPLUG @@ -116,518 +183,1393 @@ type type MusicPtr* = ptr Music Music* = object + ## The internal format for a music chunk interpreted via mikmod + # Open the mixer with a certain audio format proc openAudio*(frequency: cint; format: uint16; channels: cint; - chunksize: cint): cint {.importc: "Mix_OpenAudio".} -# Dynamically change the number of channels managed by the mixer. -# If decreasing the number of channels, the upper channels are -# stopped. -# This function returns the new number of allocated channels. -# + chunksize: cint): cint {.importc: "Mix_OpenAudio".} + ## Open the mixer with a certain audio format. + ## + ## `frequency` Output sampling frequency in samples per second (Hz). + ## you might use `mixer.DEFAULT_FREQUENCY` (22050) since that is a good + ## value for most games. + ## `frequency` would be `44100` for 44.1KHz, which is CD audio rate. + ## Most games use `22050`, because `44100` requires too much CPU power + ## on older computers. + ## + ## `format` Output sample format, based on SDL audio support. + ## See `audio.nim` (`AUDIO_*`). + ## + ## `channels` Number of sound channels in output. + ## Set to `2` for stereo, `1` for mono. + ## This has nothing to do with mixing channels. + ## `mixer.Channels` (8) mixing channels will be allocated by default. + ## + ## `chunksize` Bytes used per output sample. + ## `chunksize` is the size of each mixed sample. + ## The smaller this is the more your hooks will be called. + ## If make this too small on a slow system, sound may skip. + ## If made to large, sound effects will lag behind the action more. + ## You want a happy medium for your target computer. + ## You also may make this `4096`, or larger, if you are just playing music. + ## + ## This must be called before using other procedures in this library. + ## + ## SDL must be initialized with `sdl.INIT_AUDIO` before this call. + ## + ## You may call this procedures multiple times, however you will have to call + ## `mixer.closeAudio()` just as many times for the device to actually + ## close. The format will not changed on subsequent calls until fully closed. + ## So you will have to close all the way before trying to open with different + ## format parameters. + ## + ## `Return` `0` on success, `-1` on errors. + proc allocateChannels*(numchans: cint): cint {. importc: "Mix_AllocateChannels".} -# Find out what the actual audio device parameters are. -# This function returns 1 if the audio has been opened, 0 otherwise. -# - -proc querySpec*(frequency: ptr cint; format: ptr uint16; channels: ptr cint): cint {. - importc: "Mix_QuerySpec".} -# Load a wave file or a music (.mod .s3m .it .xm) file - -proc loadWAV_RW*(src: RWopsPtr; freesrc: cint): ptr Chunk {.importc: "Mix_LoadWAV_RW".} + ## Set the number of channels being mixed. + ## + ## `numchans` Number of channels to allocate for mixing. + ## A negative number will not do anything, it will tell you + ## how many channels are currently allocated. + ## + ## This can be called multiple times, even with sounds playing. + ## If `numchans` is less than the current number of channels, + ## then the higher channels will be stopped, freed, and therefore + ## not mixed any longer. It's probably not a good idea to change + ## the size 1000 times a second though. + ## + ## If any channels are deallocated, any callback set by + ## `mixer.channelFinished()` will be called when each channel + ## is halted to be freed. + ## + ## `Note:` passing in zero WILL free all mixing channels, + ## however music will still play. + ## + ## `Return` the number of channels allocated. + ## Never fails... but a high number of channels can segfault + ## if you run out of memory. We're talking REALLY high! + +proc querySpec*(frequency: ptr cint; format: ptr uint16; + channels: ptr cint): cint {.importc: "Mix_QuerySpec".} + ## Get the actual audio format in use by the opened audio device. + ## This may or may not match the parameters you passed to + ## `mixer.openAudio()`. + ## + ## `frequency` A pointer to an `int` where the frequency actually used + ## by the opened audio device will be stored. + ## + ## `format` A pointer to a `uint16` where the output format actually + ## being used by the audio device will be stored. + ## + ## `channels` A pointer to an `int` where the number of audio channels + ## will be stored. `2` will mean stereo, `1` will mean mono. + ## + ## `Return` `0` on error. + ## If the device was open the number of times it was opened will be returned. + ## The values of the arguments variables are not set on an error. + +proc loadWAV_RW*(src: RWopsPtr; freesrc: cint): ptr Chunk {. + importc: "Mix_LoadWAV_RW".} + ## Load src for use as a sample. + ## + ## This can load WAVE, AIFF, RIFF, OGG, and VOC formats. + ## Using `sdl.RWops` is not covered here, but they enable you to load from + ## almost any source. + ## + ## `src` The source `sdl.RWops` as a pointer. + ## The sample is loaded from this. + ## + ## `freesrc` A non-zero value mean is will automatically close/free + ## the `src` for you. + ## + ## `Note:` You must call `sdl.openAudio()` before this. + ## It must know the output characteristics so it can convert the sample + ## for playback, it does this conversion at load time. + ## + ## `Return` a pointer to the sample as a `mixer.chunk()`. + ## `nil` is returned on errors. template loadWAV*(file: untyped): untyped = loadWAV_RW(rwFromFile(file, "rb"), 1) proc loadMUS*(file: cstring): ptr Music {.importc: "Mix_LoadMUS".} -# Load a music file from an SDL_RWops object (Ogg and MikMod specific currently) -# Matt Campbell (matt@campbellhome.dhs.org) April 2000 + ## Load music file to use. + ## This can load WAVE, MOD, MIDI, OGG, MP3, FLAC, + ## and any file that you use a command to play with. + ## + ## `file` Name of music file to use. + ## + ## If you are using an external command to play the music, you must call + ## `mixer.setMusicCMD()` before this, otherwise the internal players + ## will be used. Alternatively, if you have set an external command up and + ## don't want to use it, you must call `mixer.setMusicCMD(nil)` + ## to use the built-in players again. + ## + ## `Return` a pointer to a `mixer.Music`. + ## `nil` is returned on errors. proc loadMUS_RW*(src: RWopsPtr; freesrc: cint): ptr Music {. importc: "Mix_LoadMUS_RW".} -# Load a music file from an SDL_RWops object assuming a specific format + ## Load a music file from an RWop object (Ogg and MikMod specific currently). + ## + ## Matt Campbell (matt@campbellhome.dhs.org) April 2000 + proc loadMUSType_RW*(src: RWopsPtr; `type`: MusicType; freesrc: cint): ptr Music {. importc: "Mix_LoadMUSType_RW".} -# Load a wave file of the mixer format from a memory buffer + ## Load a music file from an RWop object assuming a specific format. proc quickLoad_WAV*(mem: ptr uint8): ptr Chunk {.importc: "Mix_QuickLoad_WAV".} -# Load raw audio data of the mixer format from a memory buffer - -proc quickLoad_RAW*(mem: ptr uint8; len: uint32): ptr Chunk {.importc: "Mix_QuickLoad_RAW".} -# Free an audio chunk previously loaded + ## Load mem as a WAVE/RIFF file into a new sample. + ## + ## The WAVE in mem must be already in the output format. + ## It would be better to use `mixer.loadWAV_RW()` if you aren't sure. + ## + ## `mem` Memory buffer containing a WAVE file in output format. + ## + ## `Note:` This procedure does very little checking. + ## If the format mismatches the output format, + ## or if the buffer is not a WAVE, it will not return an error. + ## This is probably a dangerous procedure to use. + ## + ## `Return` a pointer to the sample as a `mixer.Chunk`. + ## `nil` is returned on errors. + +proc quickLoad_RAW*(mem: ptr uint8; len: uint32): ptr Chunk {. + importc: "Mix_QuickLoad_RAW".} + ## Load mem as a raw sample. + ## + ## The data in mem must be already in the output format. + ## If you aren't sure what you are doing, + ## this is not a good procedure for you! + ## + ## `mem` Memory buffer containing a WAVE file in output format. + ## + ## `Note:` This procedure does very little checking. + ## If the format mismatches the output format it will not return an error. + ## This is probably a dangerous procedure to use. + ## + ## `Return` a pointer to the sample as a `mixer.Chunk`. + ## `nil` is returned on errors, such as when out of memory. proc freeChunk*(chunk: ptr Chunk) {.importc: "Mix_FreeChunk".} + ## Free the memory used in `chunk`, and free `chunk` itself as well. + ## Do not use `chunk` after this without loading a new sample to it. + ## + ## `chunk` Pointer to the `mixer.Chunk` to free. + ## + ## `Note:` It's a bad idea to free a chunk that is still being played... + proc freeMusic*(music: ptr Music) {.importc: "Mix_FreeMusic".} -# Get a list of chunk/music decoders that this build of SDL_mixer provides. -# This list can change between builds AND runs of the program, if external -# libraries that add functionality become available. -# You must successfully call Mix_OpenAudio() before calling these functions. -# This API is only available in SDL_mixer 1.2.9 and later. -# -# // usage... -# int i; -# const int total = Mix_GetNumChunkDecoders(); -# for (i = 0; i < total; i++) -# printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i)); -# -# Appearing in this list doesn't promise your specific audio file will -# decode...but it's handy to know if you have, say, a functioning Timidity -# install. -# -# These return values are static, read-only data; do not modify or free it. -# The pointers remain valid until you call Mix_CloseAudio(). -# + ## Free the loaded `music`. + ## + ## `music` Pointer to `mixer.Music` to free. + ## + ## If `music` is playing it will be halted. + ## If `music` is fading out, then this procedure will wait (blocking) + ## until the fade out is complete. proc getNumChunkDecoders*(): cint {.importc: "Mix_GetNumChunkDecoders".} + ## Get a list of chunk/music decoders that this build of SDL_mixer provides. + ## + ## This list can change between builds AND runs of the program, if external + ## libraries that add functionality become available. + ## You must successfully call `openAudio()` + ## before calling these procedures. + ## This API is only available in SDL_mixer 1.2.9 and later. + ## + ## Usage: + ## + ## .. code-block:: nim + ## var i: cint + ## const total: cint = getNumChunkDecoders() + ## for i in 0..total-1: + ## echo "Supported chunk decoder: [$1]" % [getChunkDecoder(i)] + ## + ## Appearing in this list doesn't promise your specific audio file will + ## decode...but it's handy to know if you have, say, a functioning Timidity + ## install. + ## + ## These return values are static, read-only data; do not modify or free it. + ## The pointers remain valid until you call `closeAudio()`. + proc getChunkDecoder*(index: cint): cstring {.importc: "Mix_GetChunkDecoder".} + ## Get the name of the indexed sample chunk decoder. + ## You need to get the number of sample chunk decoders available using the + ## `mixer.getNumChunkDecoders()` procedure. + ## + ## `index` The index number of sample chunk decoder to get. + ## In the range from `0` to `mixer.getNumChunkDecoders()`-1, inclusive. + ## + ## `Return` the name of the indexed sample chunk decoder. + ## This string is owned by the SDL_mixer library, do not modify or free it. + ## It is valid until you call `mixer.closeAudio()` the final time. + proc getNumMusicDecoders*(): cint {.importc: "Mix_GetNumMusicDecoders".} + ## Get the number of music decoders available + ## from the `mixer.getMusicDecoder()` procedure. + ## + ## This number can be different for each run of a program, + ## due to the change in availability of shared libraries + ## that support each format. + ## + ## `Return` the number of music decoders available. + proc getMusicDecoder*(index: cint): cstring {.importc: "Mix_GetMusicDecoder".} -# Find out the music format of a mixer music, or the currently playing -# music, if 'music' is NULL. -# + ## Get the name of the `index`'ed music decoder. + ## You need to get the number of music decoders available using the + ## `mixer.getNumMusicDecoders()` procedure. + ## + ## `index` The index number of music decoder to get. + ## In the range from `0` to `mixer.getNumMusicDecoders()`-1, inclusive. + ## + ## `Return` the name of the `index`'ed music decoder. + ## This string is owned by the SDL_mixer library, do not modify or free it. + ## It is valid until you call `mixer.closeAudio()` the final time. proc getMusicType*(music: ptr Music): MusicType {.importc: "Mix_GetMusicType".} -# Set a function that is called after all mixing is performed. -# This can be used to provide real-time visual display of the audio stream -# or add a custom mixer filter for the stream data. -# - -proc setPostMix*(mix_func: proc (udata: pointer; stream: ptr uint8; - len: cint) {.cdecl.}; arg: pointer) {.importc: "Mix_SetPostMix".} -# Add your own music player or additional mixer function. -# If 'mix_func' is NULL, the default music player is re-enabled. -# + ## Find out the music format of a mixer music, or the currently playing + ## music, if `music` is `nil`. + ## + ## `music` The music to get the type of. + ## `nil` will get the currently playing music type. + ## + ## Tells you the file format encoding of the music. + ## This may be handy when used with `mixer.setMusicPosition()`, + ## and other music procedures that vary based on the type of music being + ## played. If you want to know the type of music currently being played, + ## pass in `nil` to `music`. + ## + ## `Return` the type of `music` or if `music` is `nil` then the + ## currently playing music type, otherwise `MUS_NONE` if no music is playing. + +proc setPostMix*( + mix_func: proc (udata: pointer; stream: ptr uint8; len: cint) {.cdecl.}; + arg: pointer) {.importc: "Mix_SetPostMix".} + ## Set a procedure that is called after all mixing is performed. + ## + ## `mix_func` The procedure pointer for the postmix processor. + ## `nil` unregisters the current postmixer. + ## + ## `arg` A pointer to data to pass into the `mix_func`'s `udata` + ## parameter. It is a good place to keep the state data for the processor, + ## especially if the processor is made to handle multiple channels at the + ## same time. + ## This may be `nil`, depending on the processor. + ## + ## This can be used to provide real-time visual display of the audio stream + ## or add a custom mixer filter for the stream data. + ## + ## You may just be reading the data and displaying it, or you may be + ## altering the stream to add an echo. Most processors also have state data + ## that they allocate as they are in use, this would be stored in the `arg` + ## pointer data space. This processor is never really finished, until the + ## audio device is closed, or you pass `nil` as the `mix_func`. + ## + ## There can only be one postmix procedure used at a time through this + ## method. Use `mixer.registerEffect(CHANNEL_POST, mix_func, nil, arg)` + ## to use multiple postmix processors. + ## + ## This postmix processor is run AFTER all the registered postmixers set up + ## by `mixer.registerEffect()`. proc hookMusic*(mix_func: proc (udata: pointer; stream: ptr uint8; len: cint) {. cdecl.}; arg: pointer) {.importc: "Mix_HookMusic".} -# Add your own callback when the music has finished playing. -# This callback is only called if the music finishes naturally. -# - -proc hookMusicFinished*(music_finished: proc () {.cdecl.}) {.importc: "Mix_HookMusicFinished".} -# Get a pointer to the user data for the current music hook + ## Add your own music player or additional mixer procedure. + ## + ## `mix_func` Procedure pointer to a music player mixer procedure. + ## `nil` will stop the use of the music player, returning the mixer to using + ## the internal music players like usual. + ## + ## `arg` This is passed to the `mix_func`'s udata parameter + ## when it is called. + ## + ## This sets up a custom music player procedure. The procedure will be called + ## with `arg` passed into the `udata` parameter when the `mix_func` is + ## called. The `stream` parameter passes in the audio stream buffer to be + ## filled with `len` bytes of music. + ## + ## The music player will then be called automatically when the mixer needs + ## it. Music playing will start as soon as this is called. + ## + ## All the music playing and stopping procedures have no effect on music + ## after this. Pause and resume will work. + ## + ## Using a custom music player and the internal music player is not possible, + ## the custom music player takes priority. To stop the custom music player + ## call `mixer.hookMusic(nil, nil)`. + ## + ## `Note:` NEVER call SDL_Mixer procedures, nor `sdl.lockAudio()`, + ## from a callback procedure. + +proc hookMusicFinished*(music_finished: proc () {.cdecl.}) {. + importc: "Mix_HookMusicFinished".} + ## Add your own callback for when the music has finished playing or when + ## it is stopped from a call to `mix.haltMusic()`. + ## + ## `music_finished` Procedure pointer to a `proc() {.cdecl.}`. + ## `nil` will remove the hook. + ## + ## This sets up a procedure to be called when music playback is halted. + ## Any time music stops, the music_finished procedure will be called. + ## Call with `nil` to remove the callback. + ## + ## `Note:` NEVER call SDL_Mixer procedures, nor `sdl.lockAudio()`, + ## from a callback procedure. proc getMusicHookData*(): pointer {.importc: "Mix_GetMusicHookData".} -# -# Add your own callback when a channel has finished playing. NULL -# to disable callback. The callback may be called from the mixer's audio -# callback or it could be called as a result of Mix_HaltChannel(), etc. -# do not call SDL_LockAudio() from this callback; you will either be -# inside the audio callback, or SDL_mixer will explicitly lock the audio -# before calling your callback. -# - -proc channelFinished*(channel_finished: proc (channel: cint) {.cdecl.}) {.importc: "Mix_ChannelFinished".} -# Special Effects API by ryan c. gordon. (icculus@icculus.org) + ## Get the `arg` passed into `mixer.hookMusic()`. + ## + ## `Return` the `arg` pointer. + +proc channelFinished*(channel_finished: proc (channel: cint) {.cdecl.}) {. + importc: "Mix_ChannelFinished".} + ## Add your own callback when a channel has finished playing. + ## + ## `channel_finished` Procedure to call when any channel finishes playback. + ## `nil` to disable callback. The callback may be called from the mixer's + ## audio callback or it could be called as a result of + ## `mixer.haltChannel()`, etc. + ## + ## `Note:` NEVER call SDL_Mixer procedures, nor `sdl.lockAudio()` + ## from a callback procedure. const MIX_CHANNEL_POST* = - 2 -# This is the format of a special effect callback: -# -# myeffect(int chan, void *stream, int len, void *udata); -# -# (chan) is the channel number that your effect is affecting. (stream) is -# the buffer of data to work upon. (len) is the size of (stream), and -# (udata) is a user-defined bit of data, which you pass as the last arg of -# Mix_RegisterEffect(), and is passed back unmolested to your callback. -# Your effect changes the contents of (stream) based on whatever parameters -# are significant, or just leaves it be, if you prefer. You can do whatever -# you like to the buffer, though, and it will continue in its changed state -# down the mixing pipeline, through any other effect functions, then finally -# to be mixed with the rest of the channels and music for the final output -# stream. -# -# DO NOT EVER call SDL_LockAudio() from your callback function! -# type Mix_EffectFunc_t* = proc (chan: cint; stream: pointer; len: cint; udata: pointer) {.cdecl.} - -# -# This is a callback that signifies that a channel has finished all its -# loops and has completed playback. This gets called if the buffer -# plays out normally, or if you call Mix_HaltChannel(), implicitly stop -# a channel via Mix_AllocateChannels(), or unregister a callback while -# it's still playing. -# -# DO NOT EVER call SDL_LockAudio() from your callback function! -# + ## This is the prototype for effect processing procedures. + ## + ## `chan` The channel number that this effect is effecting now. + ## `mixer.CHANNEL_POST` is passed in for post processing effects + ## over the final mix. + ## + ## `stream` The buffer containing the current sample to process. + ## + ## `len` The length of stream in bytes. + ## + ## `udata` User data pointer that was passed in + ## to `mixer.registerEffect()` when registering this + ## effect processor procedure. + ## + ## These procedures are used to apply effects processing on a sample chunk. + ## As a channel plays a sample, the registered effect procedures are + ## called. Each effect would then read and perhaps alter the `len` bytes + ## of `stream`. It may also be advantageous to keep the effect state in + ## the `udata`, with would be setup when registering the effect procedure + ## on a channel. + ## + ## Your effect changes the contents of `stream` based on whatever + ## parameters are significant, or just leaves it be, if you prefer. + ## You can do whatever you like to the buffer, though, and it will + ## continue in its changed state down the mixing pipeline, through + ## any other effect procedures, then finally to be mixed with the rest + ## of the channels and music for the final output stream. + ## + ## `DO NOT EVER` call `lockAudio()` from your callback procedure! type Mix_EffectDone_t* = proc (chan: cint; udata: pointer) {.cdecl.} + ## This is the prototype for effect processing procedures. + ## + ## `chan` The channel number that this effect is effecting now. + ## `mixer.CHANNEL_POST` is passed in for post processing effects + ## over the final mix. + ## + ## `udata` User data pointer that was passed in + ## to `mixer.registerEffect()` when registering this + ## effect processor procedure. + ## + ## This is a callback that signifies that a channel has finished all its + ## loops and has completed playback. This gets called if the buffer + ## plays out normally, or if you call `haltChannel()`, implicitly stop + ## a channel via `allocateChannels()`, or unregister a callback while + ## it's still playing. At that time the effects processing procedure may + ## want to reset some internal variables or free some memory. It should + ## free memory at least, because the processor could be freed after this + ## call. + ## + ## `DO NOT EVER` call `lockAudio()` from your callback procedure! -# Register a special effect function. At mixing time, the channel data is -# copied into a buffer and passed through each registered effect function. -# After it passes through all the functions, it is mixed into the final -# output stream. The copy to buffer is performed once, then each effect -# function performs on the output of the previous effect. Understand that -# this extra copy to a buffer is not performed if there are no effects -# registered for a given chunk, which saves CPU cycles, and any given -# effect will be extra cycles, too, so it is crucial that your code run -# fast. Also note that the data that your function is given is in the -# format of the sound device, and not the format you gave to Mix_OpenAudio(), -# although they may in reality be the same. This is an unfortunate but -# necessary speed concern. Use Mix_QuerySpec() to determine if you can -# handle the data before you register your effect, and take appropriate -# actions. -# You may also specify a callback (Mix_EffectDone_t) that is called when -# the channel finishes playing. This gives you a more fine-grained control -# than Mix_ChannelFinished(), in case you need to free effect-specific -# resources, etc. If you don't need this, you can specify NULL. -# You may set the callbacks before or after calling Mix_PlayChannel(). -# Things like Mix_SetPanning() are just internal special effect functions, -# so if you are using that, you've already incurred the overhead of a copy -# to a separate buffer, and that these effects will be in the queue with -# any functions you've registered. The list of registered effects for a -# channel is reset when a chunk finishes playing, so you need to explicitly -# set them with each call to Mix_PlayChannel*(). -# You may also register a special effect function that is to be run after -# final mixing occurs. The rules for these callbacks are identical to those -# in Mix_RegisterEffect, but they are run after all the channels and the -# music have been mixed into a single stream, whereas channel-specific -# effects run on a given channel before any other mixing occurs. These -# global effect callbacks are call "posteffects". Posteffects only have -# their Mix_EffectDone_t function called when they are unregistered (since -# the main output stream is never "done" in the same sense as a channel). -# You must unregister them manually when you've had enough. Your callback -# will be told that the channel being mixed is (MIX_CHANNEL_POST) if the -# processing is considered a posteffect. -# -# After all these effects have finished processing, the callback registered -# through Mix_SetPostMix() runs, and then the stream goes to the audio -# device. -# -# DO NOT EVER call SDL_LockAudio() from your callback function! -# -# returns zero if error (no such channel), nonzero if added. -# Error messages can be retrieved from Mix_GetError(). -# proc registerEffect*(chan: cint; f: Mix_EffectFunc_t; d: Mix_EffectDone_t; arg: pointer): cint {.importc: "Mix_RegisterEffect".} -# You may not need to call this explicitly, unless you need to stop an -# effect from processing in the middle of a chunk's playback. -# Posteffects are never implicitly unregistered as they are for channels, -# but they may be explicitly unregistered through this function by -# specifying MIX_CHANNEL_POST for a channel. -# returns zero if error (no such channel or effect), nonzero if removed. -# Error messages can be retrieved from Mix_GetError(). -# - -proc unregisterEffect*(channel: cint; f: Mix_EffectFunc_t): cint {.importc: "Mix_UnregisterEffect".} -# You may not need to call this explicitly, unless you need to stop all -# effects from processing in the middle of a chunk's playback. Note that -# this will also shut off some internal effect processing, since -# Mix_SetPanning() and others may use this API under the hood. This is -# called internally when a channel completes playback. -# Posteffects are never implicitly unregistered as they are for channels, -# but they may be explicitly unregistered through this function by -# specifying MIX_CHANNEL_POST for a channel. -# returns zero if error (no such channel), nonzero if all effects removed. -# Error messages can be retrieved from Mix_GetError(). -# + ## Register a special effect procedure. + ## + ## `chan` Channel number to register `f` and `d` on. + ## Use `mixer.CHANNEL_POST` to process the postmix stream. + ## + ## `f` The procedure pointer for the effects processor. + ## + ## `d` The procedure pointer for any cleanup routine to be called + ## when the channel is done playing a sample. + ## This may be `nil` for any processors that don't need to clean up + ## any memory or other dynamic data. + ## + ## `arg` A pointer to data to pass into the `f`'s and `d`'s `udata` + ## parameter. It is a good place to keep the state data for the processor, + ## especially if the processor is made to handle multiple channels + ## at the same time. + ## This may be `nil`, depending on the processor. + ## + ## Hook a processor procedure `f` into a channel for post processing + ## effects. You may just be reading the data and displaying it, or you may be + ## altering the stream to add an echo. Most processors also have state data + ## that they allocate as they are in use, this would be stored in the `arg` + ## pointer data space. When a processor is finished being used, any procedure + ## passed into `d` will be called, which is when your processor should + ## clean up the data in the `arg` data space. + ## + ## The effects are put into a linked list, and always appended to the end, + ## meaning they always work on previously registered effects output. Effects + ## may be added multiple times in a row. Effects are cumulative this way. + ## + ## At mixing time, the channel data is copied into a buffer and passed + ## through each registered effect procedure. After it passes through all the + ## procedures, it is mixed into the final output stream. The copy to buffer + ## is performed once, then each effect procedure performs on the output + ## of the previous effect. Understand that this extra copy to a buffer + ## is not performed if there are no effects registered for a given chunk, + ## which saves CPU cycles, and any given effect will be extra cycles, too, + ## so it is crucial that your code run fast. Also note that the data that + ## your procedure is given is in the format of the sound device, and not the + ## format you gave to `openAudio()`, although they may in reality be the + ## same. This is an unfortunate but necessary speed concern. Use + ## `querySpec()` to determine if you can handle the data before you + ## register your effect, and take appropriate actions. + ## + ## You may also specify a callback (`EffectDone_t`) that is called when + ## the channel finishes playing. This gives you a more fine-grained control + ## than `channelFinished()`, in case you need to free effect-specific + ## resources, etc. If you don't need this, you can specify `nil`. + ## + ## You may set the callbacks before or after calling `playChannel()`. + ## + ## Things like `setPanning()` are just internal special effect procedures, + ## so if you are using that, you've already incurred the overhead of a copy + ## to a separate buffer, and that these effects will be in the queue with + ## any procedures you've registered. The list of registered effects for a + ## channel is reset when a chunk finishes playing, so you need to explicitly + ## set them with each call to `playChannel()`. + ## + ## You may also register a special effect procedure that is to be run after + ## final mixing occurs. The rules for these callbacks are identical to those + ## in `registerEffect()`, but they are run after all the channels and the + ## music have been mixed into a single stream, whereas channel-specific + ## effects run on a given channel before any other mixing occurs. These + ## global effect callbacks are call "posteffects". Posteffects only have + ## their `EffectDone_t` proceudre called when they are unregistered (since + ## the main output stream is never "done" in the same sense as a channel). + ## You must unregister them manually when you've had enough. Your callback + ## will be told that the channel being mixed is (`CHANNEL_POST`) if the + ## processing is considered a posteffect. + ## + ## After all these effects have finished processing, the callback registered + ## through `setPostMix()` runs, and then the stream goes to the audio + ## device. + ## + ## `DO NOT EVER` call `lockAudio()` from your callback procedure! + ## + ## `Return` `0` if error (no such channel), nonzero if added. + ## + ## Error messages can be retrieved from `getError()`. + +proc unregisterEffect*(channel: cint; f: Mix_EffectFunc_t): cint {. + importc: "Mix_UnregisterEffect".} + ## Remove the oldest (first found) registered effect procedure `f` + ## from the effect list for `channel`. + ## + ## `channel` Channel number to remove `f` from as a post processor. + ## Use `mixer.CHANNEL_POST` for the postmix stream. + ## + ## `f` The procedure to remove from `channel`. + ## + ## This only removes the first found occurance of that procedure, so it may + ## need to be called multiple times if you added the same procedure multiple + ## times, just stop removing when `mixer.unregisterEffect()` returns an + ## error, to remove all occurances of `f` from a channel. + ## + ## If the `channel` is active the registered effect will have its + ## `mixer.EffectDone_t` procedure called, if it was specified in + ## `mixer.registerEffect()`. + ## + ## You may not need to call this explicitly, unless you need to stop an + ## effect from processing in the middle of a chunk's playback. + ## + ## Posteffects are never implicitly unregistered as they are for channels, + ## but they may be explicitly unregistered through this procedure by + ## specifying `CHANNEL_POST` for a channel. + ## + ## `Return` `0` if error (no such channel or effect), nonzero if removed. + ## + ## Error messages can be retrieved from `getError()`. + +proc unregisterAllEffects*(channel: cint): cint {. + importc: "Mix_UnregisterAllEffects".} + ## This removes all effects registered to `channel`. + ## + ## `channel` Channel to remove all effects from. + ## Use `mixer.CHANNEL_POST` for the postmix stream. + ## + ## If the `channel` is active, all the registered effects will have their + ## `mixer.EffectDone_t` procedures called, if they were specified in + ## `mixer.registerEffect()`. + ## + ## You may not need to call this explicitly, unless you need to stop all + ## effects from processing in the middle of a chunk's playback. Note that + ## this will also shut off some internal effect processing, since + ## `setPanning()` and others may use this API under the hood. This is + ## called internally when a channel completes playback. + ## + ## Posteffects are never implicitly unregistered as they are for channels, + ## but they may be explicitly unregistered through this procedure by + ## specifying `CHANNEL_POST` for a channel. + ## + ## `Return` `0` if error (no such channel), nonzero if all effects removed. + ## + ## Error messages can be retrieved from `getError()`. -proc unregisterAllEffects*(channel: cint): cint {.importc: "Mix_UnregisterAllEffects".} const MIX_EFFECTSMAXSPEED* = "MIX_EFFECTSMAXSPEED" - -# -# These are the internally-defined mixing effects. They use the same API that -# effects defined in the application use, but are provided here as a -# convenience. Some effects can reduce their quality or use more memory in -# the name of speed; to enable this, make sure the environment variable -# MIX_EFFECTSMAXSPEED (see above) is defined before you call -# Mix_OpenAudio(). -# -# Set the panning of a channel. The left and right channels are specified -# as integers between 0 and 255, quietest to loudest, respectively. -# -# Technically, this is just individual volume control for a sample with -# two (stereo) channels, so it can be used for more than just panning. -# If you want real panning, call it like this: -# -# Mix_SetPanning(channel, left, 255 - left); -# -# ...which isn't so hard. -# -# Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and -# the panning will be done to the final mixed stream before passing it on -# to the audio device. -# -# This uses the Mix_RegisterEffect() API internally, and returns without -# registering the effect function if the audio device is not configured -# for stereo output. Setting both (left) and (right) to 255 causes this -# effect to be unregistered, since that is the data's normal state. -# -# returns zero if error (no such channel or Mix_RegisterEffect() fails), -# nonzero if panning effect enabled. Note that an audio device in mono -# mode is a no-op, but this call will return successful in that case. -# Error messages can be retrieved from Mix_GetError(). -# - -proc setPanning*(channel: cint; left: uint8; right: uint8): cint {.importc: "Mix_SetPanning".} -# Set the position of a channel. (angle) is an integer from 0 to 360, that -# specifies the location of the sound in relation to the listener. (angle) -# will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260). -# Angle 0 is due north, and rotates clockwise as the value increases. -# For efficiency, the precision of this effect may be limited (angles 1 -# through 7 might all produce the same effect, 8 through 15 are equal, etc). -# (distance) is an integer between 0 and 255 that specifies the space -# between the sound and the listener. The larger the number, the further -# away the sound is. Using 255 does not guarantee that the channel will be -# culled from the mixing process or be completely silent. For efficiency, -# the precision of this effect may be limited (distance 0 through 5 might -# all produce the same effect, 6 through 10 are equal, etc). Setting (angle) -# and (distance) to 0 unregisters this effect, since the data would be -# unchanged. -# -# If you need more precise positional audio, consider using OpenAL for -# spatialized effects instead of SDL_mixer. This is only meant to be a -# basic effect for simple "3D" games. -# -# If the audio device is configured for mono output, then you won't get -# any effectiveness from the angle; however, distance attenuation on the -# channel will still occur. While this effect will function with stereo -# voices, it makes more sense to use voices with only one channel of sound, -# so when they are mixed through this effect, the positioning will sound -# correct. You can convert them to mono through SDL before giving them to -# the mixer in the first place if you like. -# -# Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and -# the positioning will be done to the final mixed stream before passing it -# on to the audio device. -# -# This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning(). -# -# returns zero if error (no such channel or Mix_RegisterEffect() fails), -# nonzero if position effect is enabled. -# Error messages can be retrieved from Mix_GetError(). -# - -proc setPosition*(channel: cint; angle: int16; distance: uint8): cint {.importc: "Mix_SetPosition".} -# Set the "distance" of a channel. (distance) is an integer from 0 to 255 -# that specifies the location of the sound in relation to the listener. -# Distance 0 is overlapping the listener, and 255 is as far away as possible -# A distance of 255 does not guarantee silence; in such a case, you might -# want to try changing the chunk's volume, or just cull the sample from the -# mixing process with Mix_HaltChannel(). -# For efficiency, the precision of this effect may be limited (distances 1 -# through 7 might all produce the same effect, 8 through 15 are equal, etc). -# (distance) is an integer between 0 and 255 that specifies the space -# between the sound and the listener. The larger the number, the further -# away the sound is. -# Setting (distance) to 0 unregisters this effect, since the data would be -# unchanged. -# If you need more precise positional audio, consider using OpenAL for -# spatialized effects instead of SDL_mixer. This is only meant to be a -# basic effect for simple "3D" games. -# -# Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and -# the distance attenuation will be done to the final mixed stream before -# passing it on to the audio device. -# -# This uses the Mix_RegisterEffect() API internally. -# -# returns zero if error (no such channel or Mix_RegisterEffect() fails), -# nonzero if position effect is enabled. -# Error messages can be retrieved from Mix_GetError(). -# - -proc setDistance*(channel: cint; distance: uint8): cint {.importc: "Mix_SetDistance".} -# -# !!! FIXME : Haven't implemented, since the effect goes past the -# end of the sound buffer. Will have to think about this. -# --ryan. -# + ## These are the internally-defined mixing effects. They use the same + ## API that effects defined in the application use, but are provided here + ## as a convenience. Some effects can reduce their quality or use more + ## memory in the name of speed; to enable this, make sure the environment + ## variable `EFFECTSMAXSPEED` (see above) is defined before you call + ## `openAudio()`. + +proc setPanning*(channel: cint; left: uint8; right: uint8): cint {. + importc: "Mix_SetPanning".} + ## Set the panning of a `channel`. + ## + ## `channel` Channel number to register this effect on. + ## Use `mixer.CHANNEL_POST` to process the postmix stream. + ## + ## `left` Volume for the left channel, + ## range is `0` (silence) to `255` (loud). + ## + ## `right` Volume for the right channel, + ## range is `0` (silence) to `255` (loud). + ## + ## This effect will only work on stereo audio. + ## Meaning you called `mixer.openAudio()` with `2` channels + ## (`mixer.DEFAULT_CHANNELS`). The easiest way to do true panning + ## is to call `mixer.setPanning(channel, left, 254 - left)` so that + ## the total volume is correct, if you consider the maximum volume to be + ## `127` per channel for center, or `254` max for left, this works, + ## but about halves the effective volume. + ## + ## This procedure registers the effect for you, + ## so don't try to `mixer.registerEffect()` it yourself. + ## + ## `Note:` Setting both left and right to `255` will unregister the effect + ## from channel. You cannot unregister it any other way, unless you use + ## `mixer.unregisterAllEffects()` on the channel. + ## + ## `Note:` Using this procedure on a mono audio device will not register + ## the effect, nor will it return an error status. + ## + ## Setting `channel` to `CHANNEL_POST` registers this as a posteffect, and + ## the panning will be done to the final mixed stream before passing it on + ## to the audio device. + ## + ## `Return` `0` if error (no such channel or `registerEffect()` fails), + ## nonzero if panning effect enabled. Note that an audio device in mono + ## mode is a no-op, but this call will return successful in that case. + ## + ## Error messages can be retrieved from `getError()`. + +proc setPosition*(channel: cint; angle: int16; distance: uint8): cint {. + importc: "Mix_SetPosition".} + ## Set the position of a `channel`. + ## + ## `channel` Channel number to register this effect on. + ## Use `mixer.CHANNEL_POST` to process the postmix stream. + ## + ## `angle` Direction in relation to forward from `0` to `360` degrees. + ## Larger angles will be reduced to this range using `angle mod 360`. + ## * `0` = directly in front. + ## * `90` = directly to the right. + ## * `180` = directly behind. + ## * `270` = directly to the left. + ## + ## So you can see it goes clockwise starting at directly in front. + ## This ends up being similar in effect to `mixer.setPanning()` + ## For efficiency, the precision of this effect may be limited + ## (angles `1` through `7` might all produce the same effect, + ## `8` through `15` are equal, etc). + ## + ## `distance` The distance from the listener, + ## from `0` (near/loud) to `255 (far/quiet). + ## This is the same as the `mixer.setDistance()` effect. + ## For efficiency, the precision of this effect may be limited + ## (distance `0` through `5` might all produce the same effect, + ## `6` through `10` are equal, etc). + ## + ## This effect emulates a simple 3D audio effect. It's not all that + ## realistic, but it can help improve some level of realism. By giving it + ## the `angle` and `distance` from the camera's point of view, + ## the effect pans and attenuates volumes. If you are looking for better + ## positional audio, using OpenAL is suggested. + ## + ## `Note:` Using angle and distance of `0`, will cause the effect to + ## unregister itself from `channel`. You cannot unregister it any other + ## way, unless you use `mixer.unregisterAllEffects()` + ## on the `channel`. + ## + ## If the audio device is configured for mono output, then you won't get + ## any effectiveness from the `angle`; however, distance attenuation on + ## the channel will still occur. While this effect will function with stereo + ## voices, it makes more sense to use voices with only one channel of sound, + ## so when they are mixed through this effect, the positioning will sound + ## correct. You can convert them to mono through SDL before giving them to + ## the mixer in the first place if you like. + ## + ## Setting `channel` to `mixer.CHANNEL_POST` registers this + ## as a posteffect, and the positioning will be done to the final mixed + ## stream before passing it on to the audio device. + ## + ## This is a convenience wrapper over `setDistance()` and `setPanning()`. + ## + ## `Return` `0` if error (no such channel or `registerEffect()` fails), + ## nonzero if position effect is enabled. + ## + ## Error messages can be retrieved from `getError()`. + +proc setDistance*(channel: cint; distance: uint8): cint {. + importc: "Mix_SetDistance".} + ## Set the `distance` of a `channel`. + ## + ## `channel` Channel number to register this effect on. + ## Use `mixer.CHANNEL_POST` to process the postmix stream. + ## + ## `distance` Specify the distance from the listener, + ## from `0` (close/loud) to `255` (far/quiet). A distance of `255` does + ## not guarantee silence; in such a case, you might want to try changing + ## the chunk's volume, or just cull the sample from the mixing process with + ## `mixer.haltChannel()`. + ## + ## This effect simulates a simple attenuation of volume due to distance. + ## The volume never quite reaches silence, even at max distance. + ## + ## `Note:` Using a distance of `0` will cause the effect to unregister + ## itself from `channel`. You cannot unregister it any other way, unless + ## you use `mixer.unregisterAllEffects()` on the `channel`. + ## + ## For efficiency, the precision of this effect may be limited + ## (distances `1` through `7` might all produce the same effect, + ## `8` through `15` are equal, etc). + ## + ## If you need more precise positional audio, consider using OpenAL for + ## spatialized effects instead of mixer. This is only meant to be a + ## basic effect for simple "3D" games. + ## + ## Setting `channel` to `mixer.CHANNEL_POST` registers this + ## as a posteffect, and the distance attenuation will be done to the final + ## mixed stream before passing it on to the audio device. + ## + ## This uses the `registerEffect()` API internally. + ## + ## `Return` `0` if error (no such channel or `mixer.registerEffect()` + ## fails), nonzero if position effect is enabled. + ## + ## Error messages can be retrieved from `getError()`. when false: - # Causes an echo effect to be mixed into a sound. (echo) is the amount - # of echo to mix. 0 is no echo, 255 is infinite (and probably not - # what you want). - # - # Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and - # the reverbing will be done to the final mixed stream before passing it on - # to the audio device. - # - # This uses the Mix_RegisterEffect() API internally. If you specify an echo - # of zero, the effect is unregistered, as the data is already in that state. - # - # returns zero if error (no such channel or Mix_RegisterEffect() fails), - # nonzero if reversing effect is enabled. - # Error messages can be retrieved from Mix_GetError(). - # - proc setReverb*(channel: cint; echo: uint8): cint {.importc: "Mix_SetReverb".} -# Causes a channel to reverse its stereo. This is handy if the user has his -# speakers hooked up backwards, or you would like to have a minor bit of -# psychedelia in your sound code. :) Calling this function with (flip) -# set to non-zero reverses the chunks's usual channels. If (flip) is zero, -# the effect is unregistered. -# -# This uses the Mix_RegisterEffect() API internally, and thus is probably -# more CPU intensive than having the user just plug in his speakers -# correctly. Mix_SetReverseStereo() returns without registering the effect -# function if the audio device is not configured for stereo output. -# -# If you specify MIX_CHANNEL_POST for (channel), then this the effect is used -# on the final mixed stream before sending it on to the audio device (a -# posteffect). -# -# returns zero if error (no such channel or Mix_RegisterEffect() fails), -# nonzero if reversing effect is enabled. Note that an audio device in mono -# mode is a no-op, but this call will return successful in that case. -# Error messages can be retrieved from Mix_GetError(). -# -proc setReverseStereo*(channel: cint; flip: cint): cint {.importc: "Mix_SetReverseStereo".} -# end of effects API. --ryan. -# Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate -# them dynamically to the next sample if requested with a -1 value below. -# Returns the number of reserved channels. -# + proc setReverb*(channel: cint; echo: uint8): cint {. + importc: "Mix_SetReverb".} + ## Causes an echo effect to be mixed into a sound. + ## + ## `echo` is the amount of echo to mix. + ## `0` is no echo, `255` is infinite (and probably not what you want). + ## + ## Setting `channel` to `CHANNEL_POST` registers this as a posteffect, + ## and the reverbing will be done to the final mixed stream before passing + ## it on to the audio device. + ## + ## This uses the `registerEffect()` API internally. + ## + ## If you specify an echo of zero, the effect is unregistered, + ## as the data is already in that state. + ## + ## `Returns` `0` if error (no such channel or `registerEffect()` + ## fails), nonzero if reversing effect is enabled. + ## + ## Error messages can be retrieved from `getError()`. + +proc setReverseStereo*(channel: cint; flip: cint): cint {. + importc: "Mix_SetReverseStereo".} + ## Simple reverse stereo, swaps left and right channel sound. + ## + ## `channel` Channel number to register this effect on. + ## Use `mixer.CHANNEL_POST` to process the postmix stream. + ## + ## `flip` Must be non-zero to work, + ## means nothing to the effect processor itself. + ## Set to `0` to unregister the effect from channel. + ## + ## Causes a `channel` to reverse its stereo. This is handy if the user has + ## his speakers hooked up backwards, or you would like to have a minor bit + ## of psychedelia in your sound code. :) + ## + ## Calling this procedure with `flip` set to non-zero reverses the chunks's + ## usual channels. If `flip` is zero, the effect is unregistered. + ## + ## This uses the `registerEffect()` API internally, and thus is probably + ## more CPU intensive than having the user just plug in his speakers + ## correctly. `setReverseStereo()` returns without registering the effect + ## procedure if the audio device is not configured for stereo output. + ## + ## If you specify `CHANNEL_POST` for `channel`, then this the effect is + ## used on the final mixed stream before sending it on to the audio device + ## (a posteffect). + ## + ## `Note:` Using a flip of `0`, will cause the effect to unregister itself + ## from `channel`. You cannot unregister it any other way, unless you use + ## `mixer.unregisterAllEffects()` on the `channel`. + ## + ## `Return` `0` if error (no such channel or `registerEffect()` fails), + ## nonzero if reversing effect is enabled. Note that an audio device in mono + ## mode is a no-op, but this call will return successful in that case. + ## + ## Error messages can be retrieved from `getError()`. proc reserveChannels*(num: cint): cint {.importc: "Mix_ReserveChannels".} -# Channel grouping functions -# Attach a tag to a channel. A tag can be assigned to several mixer -# channels, to form groups of channels. -# If 'tag' is -1, the tag is removed (actually -1 is the tag used to -# represent the group of all the channels). -# Returns true if everything was OK. -# + ## Reserve `num` channels from being used when playing samples when + ## passing in `-1` as a channel number to playback procedures. + ## The channels are reserved starting from channel `0` to `num`-1. + ## Passing in `0` will unreserve all channels. + ## Normally SDL_mixer starts without any channels reserved. + ## + ## `num` Number of channels to reserve from default mixing. + ## `0` removes all reservations. + ## + ## The following procedures are affected by this setting: + ## + ## * `mixer.playChannel()` + ## * `mixer.playChannelTimed()` + ## * `mixer.fadeInChannel()` + ## * `mixer.fadeInChannelTimed()` + ## + ## `Return` the number of channels reserved. + ## Never fails, but may return less channels than you ask for, + ## depending on the number of channels previously allocated. proc groupChannel*(which: cint; tag: cint): cint {.importc: "Mix_GroupChannel".} -# Assign several consecutive channels to a group - -proc groupChannels*(`from`: cint; to: cint; tag: cint): cint {.importc: "Mix_GroupChannels".} -# Finds the first available channel in a group of channels, -# returning -1 if none are available. -# + ## Add `which` channel to group tag, or reset it's group to the default + ## group tag (`-1`). + ## + ## `which` Channel number of channels to assign tag to. + ## + ## `tag` A group number. Any positive numbers (including zero). + ## `-1` is the default group. Use `-1` to remove a group tag essentially. + ## + ## `Return` `1` on success. + ## `0` is returned when the channel specified is invalid. + +proc groupChannels*(`from`: cint; to: cint; tag: cint): cint {. + importc: "Mix_GroupChannels".} + ## Add channels starting at `ch_from` up through `ch_to` to group tag, + ## or reset it's group to the default group tag (`-1`). + ## + ## `ch_from` First Channel number of channels to assign tag to. + ## Must be less or equal to `ch_to`. + ## + ## `ch_to` Last Channel number of channels to assign tag to. + ## Must be greater or equal to `ch_from`. + ## + ## `tag` A group number. Any positive numbers (including zero). + ## `-1` is the default group. Use `-1` to remove a group tag essentially. + ## + ## `Return` the number of tagged channels on success. + ## If that number is less than `ch_to` - `ch_from` + 1 + ## then some channels were no tagged because they didn't exist. proc groupAvailable*(tag: cint): cint {.importc: "Mix_GroupAvailable".} -# Returns the number of channels in a group. This is also a subtle -# way to get the total number of channels when 'tag' is -1 -# + ## Finds the first available (not playing) channel in a group `tag`. + ## + ## `tag` group number. Any positive numbers (including zero). + ## `-1` will search ALL channels. + ## + ## `Return` the channel found on success. + ## `-1` is returned when no channels in the group are available. proc groupCount*(tag: cint): cint {.importc: "Mix_GroupCount".} -# Finds the "oldest" sample playing in a group of channels + ## Count the number of channels in group `tag`. + ## + ## `tag` A group number. Any positive numbers (including zero). + ## `-1` will count ALL channels. + ## + ## `Return` the number of channels in a group. This procedure never fails. + ## This is also a subtle way to get the total number of channels + ## when `tag` is `-1`. proc groupOldest*(tag: cint): cint {.importc: "Mix_GroupOldest".} -# Finds the "most recent" (i.e. last) sample playing in a group of channels + ## Find the "oldest" sample playing in a group `tag`. + ## + ## `tag` A group number. Any positive numbers (including zero). + ## `-1` will search ALL channels. + ## + ## `Return` the channel found on success. + ## `-1` is returned when no channels in the group are playing + ## or the group is empty. proc groupNewer*(tag: cint): cint {.importc: "Mix_GroupNewer".} -# Play an audio chunk on a specific channel. -# If the specified channel is -1, play on the first free channel. -# If 'loops' is greater than zero, loop the sound that many times. -# If 'loops' is -1, loop inifinitely (~65000 times). -# The sound is played at most 'ticks' milliseconds. If -1, play forever. -# Returns which channel was used to play the sound. -# + ## Find the "most recent" (i.e. last) sample playing in a group `tag`. + ## + ## `tag` A group number. Any positive numbers (including zero). + ## `-1` will search ALL channels. + ## + ## `Return` the channel found on success. + ## `-1` is returned when no channels in the group are playing + ## or the group is empty. proc playChannelTimed*(channel: cint; chunk: ptr Chunk; loops: cint; - ticks: cint): cint {.importc: "Mix_PlayChannelTimed".} - -# The same as above, but the sound is played forever + ticks: cint): cint {.importc: "Mix_PlayChannelTimed".} + ## The same as `mixer.playChannel()`, + ## but the sound is played at most `ticks` milliseconds. + ## + ## `channel` Channel to play on, + ## or `-1` for the first free unreserved channel. + ## + ## `chunk` Sample to play. + ## + ## `loops` Number of loops, `-1` is infinite loops. + ## Passing `1` here plays the sample twice (1 loop). + ## + ## `ticks` Millisecond limit to play sample, at most. + ## If not enough loops or the sample chunk is not long enough, + ## then the sample may stop before this timeout occurs. + ## `-1` means play forever. + ## + ## If the sample is long enough and has enough loops then the sample will + ## stop after `ticks` milliseconds. + ## Otherwise this procedure is the same as `mixer.playChannel()`. + ## + ## `Return` the channel the sample is played on. + ## On any errors, `-1` is returned. template playChannel*(channel, chunk, loops: untyped): untyped = + ## Play chunk on channel, or if channel is `-1`, + ## pick the first free unreserved channel. + ## + ## `channel` Channel to play on, or `-1` + ## for the first free unreserved channel. + ## + ## `chunk` Sample to play. + ## + ## `loops` Number of loops, `-1` is infinite loops. + ## Passing `1` here plays the sample twice (1 loop). + ## + ## The sample will play for `loops` + 1 number of times, + ## unless stopped by halt, or fade out, or setting a new expiration time + ## of less time than it would have originally taken to play the loops, + ## or closing the mixer. + ## + ## `Note:` this just calls `mixer.playChannelTimed()` + ## with ticks set to `-1`. + ## + ## `Return` the channel the sample is played on. + ## On any errors, `-1` is returned. playChannelTimed(channel, chunk, loops, - 1) proc playMusic*(music: ptr Music; loops: cint): cint {.importc: "Mix_PlayMusic".} -# Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions + ## Play the loaded `music` `loops` times through from start to finish. + ## + ## `music` Pointer to `mixer.Music` to play. + ## + ## `loops` Number of times to play through the `music`. + ## `0` plays the music zero times. + ## `-1` plays the music forever (or as close as it can get to that). + ## + ## The previous music will be halted, or if fading out it waits (blocking) + ## for that to finish. + ## + ## `Return` `0` on success, or `-1` on errors. + +proc fadeInMusic*(music: ptr Music; loops: cint; ms: cint): cint {. + importc: "Mix_FadeInMusic".} + ## Fade in over `ms` milliseconds of time, the loaded `music`, + ## playing it `loops` times through from start to finish. + ## + ## `music` Pointer to `mixer.Music` to play. + ## + ## `loops` Number of times to play through the `music`. + ## `0` plays the music zero times. + ## `-1` plays the music forever (or as close as it can get to that). + ## + ## `ms` Milliseconds for the fade-in effect to complete. + ## + ## The fade in effect only applies to the first loop. + ## + ## Any previous music will be halted, or if it is fading out it will wait + ## (blocking) for the fade to complete. This procedure is the same as + ## `mixer.fadeInMusicPos(music, loops, ms, 0)`. + ## + ## `Return` `0` on success, or `-1` on errors. -proc fadeInMusic*(music: ptr Music; loops: cint; ms: cint): cint {.importc: "Mix_FadeInMusic".} proc fadeInMusicPos*(music: ptr Music; loops: cint; ms: cint; - position: cdouble): cint {.importc: "Mix_FadeInMusicPos".} + position: cdouble): cint {.importc: "Mix_FadeInMusicPos".} + ## Fade in over `ms` milliseconds of time, the loaded `music`, + ## playing it `loops` times through from start to finish. + ## + ## `music` Pointer to `mixer.Music` to play. + ## + ## `loops` Number of times to play through the music. + ## `0` plays the music zero times. + ## `-1` plays the music forever (or as close as it can get to that). + ## + ## `ms` Milliseconds for the fade-in effect to complete. + ## + ## `position` Posistion to play from, + ## see `mixer.setMusicPosition()` for meaning. + ## + ## The fade in effect only applies to the first loop. + ## + ## The first time the music is played, it posistion will be set to + ## `posistion`, which means different things for different types + ## of music files, see `mixer.setMusicPosition()` for more info + ## on that. + ## + ## Any previous music will be halted, or if it is fading out it will wait + ## (blocking) for the fade to complete. + ## + ## `Return` `0` on success, or `-1` on errors. + template fadeInChannel*(channel, chunk, loops, ms: untyped): untyped = + ## Play `chunk` on `channel`, or if `channel` is `-1`, + ## pick the first free unreserved channel. + ## + ## `channel` Channel to play on, + ## or `-1` for the first free unreserved channel. + ## + ## `chunk` Sample to play. + ## + ## `loops` Number of loops, `-1` is infinite loops. + ## Passing `1` here plays the sample twice (1 loop). + ## + ## `ms` Milliseconds of time that the fade-in effect should take + ## to go from silence to full volume. + ## + ## The channel volume starts at `0` and fades up to full volume over `ms` + ## milliseconds of time. + ## The sample may end before the fade-in is complete if it is too short + ## or doesn't have enough loops. + ## The sample will play for `loops` + 1 number of times, + ## unless stopped by halt, or fade out, or setting a new expiration time + ## of less time than it would have originally taken to play the loops, + ## or closing the mixer. + ## + ## `Note:` this just calls `mixer.fadeInChannelTimed()` + ## with ticks set to `-1`. + ## + ## `Return` the channel the sample is played on. + ## On any errors, `-1` is returned. fadeInChannelTimed(channel, chunk, loops, ms, - 1) proc fadeInChannelTimed*(channel: cint; chunk: ptr Chunk; loops: cint; - ms: cint; ticks: cint): cint {.importc: "Mix_FadeInChannelTimed".} -# Set the volume in the range of 0-128 of a specific channel or chunk. -# If the specified channel is -1, set volume for all channels. -# Returns the original volume. -# If the specified volume is -1, just return the current volume. -# + ms: cint; ticks: cint): cint {. + importc: "Mix_FadeInChannelTimed".} + ## The same as `mixer.fadeInChannel()`, + ## but the sound is played at most `ticks` milliseconds. + ## + ## `channel` Channel to play on, + ## or `-1` for the first free unreserved channel. + ## + ## `chunk` Sample to play. + ## + ## `loops` Number of loops, `-1` is infinite loops. + ## Passing `1` here plays the sample twice (1 loop). + ## + ## `ms` Milliseconds of time that the fade-in effect should take + ## to go from silence to full volume. + ## + ## `ticks` Millisecond limit to play sample, at most. + ## If not enough loops or the sample chunk is not long enough, + ## then the sample may stop before this timeout occurs. + ## `-1` means play forever. + ## + ## If the sample is long enough and has enough loops then the sample will + ## stop after `ticks` milliseconds. + ## Otherwise this procedures is the same as `mixer.fadeInChannel()`. + ## + ## `Return` the channel the sample is played on. + ## On any errors, `-1` is returned. proc volume*(channel: cint; volume: cint): cint {.importc: "Mix_Volume".} -proc volumeChunk*(chunk: ptr Chunk; volume: cint): cint {.importc: "Mix_VolumeChunk".} + ## Set the volume for any allocated channel. + ## + ## `channel` Channel to set mix volume for. + ## `-1` will set the volume for all allocated channels. + ## + ## `volume` The volume to use from `0` to `mixer.MAX_VOLUME` (128). + ## If greater than `mixer.MAX_VOLUME`, + ## then it will be set to `mixer.MAX_VOLUME`. + ## If less than `0` then the volume will not be set. + ## + ## If `channel` is `-1` then all channels at are set at once. + ## The `volume` is applied during the final mix, along with the sample + ## volume. So setting this volume to `64` will halve the output of all + ## samples played on the specified channel. + ## All channels default to a volume of `128`, which is the max. + ## Newly allocated channels will have the max volume set, so setting all + ## channels volumes does not affect subsequent channel allocations. + ## + ## `Return` current volume of the channel. + ## If channel is `-1`, the average volume is returned. + +proc volumeChunk*(chunk: ptr Chunk; volume: cint): cint {. + importc: "Mix_VolumeChunk".} + ## Set `chunk.volume` to `volume`. + ## + ## The volume setting will take effect when the chunk is used on a channel, + ## being mixed into the output. + ## + ## `chunk` Pointer to the `mixer.chunk` to set the volume in. + ## + ## `volume` The volume to use from `0` to `mixer.MAX_VOLUME` (128). + ## If greater than `mixer.MAX_VOLUME`, + ## then it will be set to `mixer.MAX_VOLUME`. + ## If less than `0` then `chunk.volume` will not be set. + ## + ## `Return` previous `chunk.volume` setting. + ## If you passed a negative value for `volume` then this volume is still + ## the current volume for the `chunk`. + proc volumeMusic*(volume: cint): cint {.importc: "Mix_VolumeMusic".} -# Halt playing of a particular channel + ## Set the volume to `volume`, if it is `0` or greater, + ## and return the previous volume setting. + ## + ## `volume` Music volume, from `0` to `mixer.MAX_VOLUME` (128). + ## Values greater than `mixer.MAX_VOLUME` + ## will use `mixer.MAX_VOLUME`. + ## `-1` does not set the volume, but does return the current volume setting. + ## + ## Setting the volume during a fade will not work, the faders use this + ## procedure to perform their effect! + ## + ## Setting volume while using an external music player set by + ## `mixer.setMusicCMD()` will have no effect, + ## and `mixer.getError()` will show the reason why not. + ## + ## `Return` the previous volume setting. proc haltChannel*(channel: cint): cint {.importc: "Mix_HaltChannel".} + ## Halt `channel` playback, or all channels if `-1` is passed in. + ## + ## `channel` Channel to stop playing, or `-1` for all channels. + ## + ## Any callback set by `mixer.channelFinished()` will be called. + ## + ## `Return` always returns zero. (kinda silly) + proc haltGroup*(tag: cint): cint {.importc: "Mix_HaltGroup".} -proc haltMusic*(): cint {.importc: "Mix_HaltMusic".} -# Change the expiration delay for a particular channel. -# The sample will stop playing after the 'ticks' milliseconds have elapsed, -# or remove the expiration if 'ticks' is -1 -# + ## Halt playback on all channels in group tag. + ## + ## `tag` Group to fade out. + ## `Note:` `-1` will NOT halt all channels. + ## Use `mixer.haltChannel(-1)` for that instead. + ## + ## Any callback set by `mixer.channelFinished()` will be called + ## once for each channel that stops. + ## + ## `Return` always returns zero. + ## (more silly than `mixer.haltChannel()`) -proc expireChannel*(channel: cint; ticks: cint): cint {.importc: "Mix_ExpireChannel".} -# Halt a channel, fading it out progressively till it's silent -# The ms parameter indicates the number of milliseconds the fading -# will take. -# +proc haltMusic*(): cint {.importc: "Mix_HaltMusic".} + ## Halt playback of music. + ## + ## This interrupts music fader effects. + ## + ## Any callback set by `mixer.hookMusicFinished()` will be called + ## when the music stops. + ## + ## `Return` always returns zero. + ## (even more silly than `mixer.haltGroup()`) + +proc expireChannel*(channel: cint; ticks: cint): cint {. + importc: "Mix_ExpireChannel".} + ## Halt `channel` playback, or all channels if `-1` is passed in, + ## after `ticks` milliseconds. + ## + ## `channel` Channel to stop playing, or `-1` for all channels. + ## + ## `ticks` Millisecons until channel(s) halt playback. + ## + ## Any callback set by `mixer.channelFinished()` will be called + ## when the channel expires. + ## + ## `Return` number of channels set to expire. + ## Whether or not they are active. + +proc fadeOutChannel*(which: cint; ms: cint): cint {. + importc: "Mix_FadeOutChannel".} + ## Gradually fade out `which` channel over `ms` milliseconds + ## starting from now. + ## + ## `channel` Channel to fade out, or `-1` to fade all channels out. + ## + ## `ms` Milliseconds of time that the fade-out effect should take + ## to go to silence, starting now. + ## + ## The channel will be halted after the fade out is completed. Only channels + ## that are playing are set to fade out, including paused channels. + ## + ## Any callback set by `mixer.channelFinished()` will be called + ## when the channel finishes fading out. + ## + ## `Return` the number of channels set to fade out. -proc fadeOutChannel*(which: cint; ms: cint): cint {.importc: "Mix_FadeOutChannel".} proc fadeOutGroup*(tag: cint; ms: cint): cint {.importc: "Mix_FadeOutGroup".} + ## Gradually fade out channels in group `tag` over `ms` milliseconds + ## starting from now. + ## + ## `tag` Group to fade out. + ## `Note:` `-1` will NOT fade all channels out. + ## Use `mixer.fadeOutChannel(-1)` for that instead. + ## + ## `ms` Milliseconds of time that the fade-out effect should take + ## to go to silence, starting now. + ## + ## The channels will be halted after the fade out is completed. + ## Only channels that are playing are set to fade out, including paused + ## channels. Any callback set by `mixer.channelFinished()` will be + ## called when each channel finishes fading out. + ## + ## `Return` the number of channels set to fade out. + proc fadeOutMusic*(ms: cint): cint {.importc: "Mix_FadeOutMusic".} -# Query the fading status of a channel + ## Gradually fade out the music over `ms` milliseconds starting from now. + ## + ## `ms` Milliseconds of time that the fade-out effect should take + ## to go to silence, starting now. + ## + ## The music will be halted after the fade out is completed. + ## Only when music is playing and not fading already are set to fade out, + ## including paused channels. + ## + ## Any callback set by `mixer.hookMusicFinished()` will be called + ## when the music finishes fading out. + ## + ## `Return` `1` on success, `0` on failure. proc fadingMusic*(): Fading {.importc: "Mix_FadingMusic".} + ## Tells you if music is fading in, out, or not at all. + ## + ## Does not tell you if the channel is playing anything, or paused, + ## so you'd need to test that separately. + ## + ## `Return` the fading status. Never returns an error. + proc fadingChannel*(which: cint): Fading {.importc: "Mix_FadingChannel".} -# Pause/Resume a particular channel + ## Tells you if `which` channel is fading in, out, or not. + ## Does not tell you if the channel is playing anything, or paused, + ## so you'd need to test that separately. + ## + ## `which` Channel to get the fade activity status from. + ## `-1` is not valid, and will probably crash the program. + ## + ## `Return` the fading status. Never returns an error. proc pause*(channel: cint) {.importc: "Mix_Pause".} + ## Pause `channel`, or all playing channels if `-1` is passed in. + ## You may still halt a paused channel. + ## + ## `channel` Channel to pause on, or `-1` for all channels. + ## + ## `Note:` Only channels which are actively playing will be paused. + proc resume*(channel: cint) {.importc: "Mix_Resume".} + ## Unpause `channel`, or all playing and paused channels + ## if `-1` is passed in. + ## + ## `channel` Channel to resume playing, or `-1` for all channels. + proc paused*(channel: cint): cint {.importc: "Mix_Paused".} + ## Tells you if `channel` is paused, or not. + ## + ## `channel` Channel to test whether it is paused or not. + ## `-1` will tell you how many channels are paused. + ## + ## `Note:` Does not check if the channel has been halted + ## after it was paused, which may seem a little weird. + ## + ## `Return` `0` if the channel is not paused. + ## Otherwise if you passed in `-1`, + ## the number of paused channels is returned. + ## If you passed in a specific channel, + ## then `1` is returned if it is paused. + # Pause/Resume the music stream proc pauseMusic*() {.importc: "Mix_PauseMusic".} + ## Pause the music playback. You may halt paused music. + ## + ## `Note:` Music can only be paused if it is actively playing. + proc resumeMusic*() {.importc: "Mix_ResumeMusic".} + ## Unpause the music. + ## This is safe to use on halted, paused, and already playing music. + proc rewindMusic*() {.importc: "Mix_RewindMusic".} -proc pausedMusic*(): cint {.importc: "Mix_PausedMusic".} -# Set the current position in the music stream. -# This returns 0 if successful, or -1 if it failed or isn't implemented. -# This function is only implemented for MOD music formats (set pattern -# order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set -# position in seconds), at the moment. -# + ## Rewind the music to the start. + ## This is safe to use on halted, paused, and already playing music. + ## + ## It is not useful to rewind the music immediately after starting playback, + ## because it starts at the beginning by default. + ## + ## This procedure only works for these streams: MOD, OGG, MP3, Native MIDI. -proc setMusicPosition*(position: cdouble): cint {.importc: "Mix_SetMusicPosition".} +proc pausedMusic*(): cint {.importc: "Mix_PausedMusic".} + ## Tells you if music is paused, or not. + ## + ## `Note:` Does not check if the music was been halted after it was paused, + ## which may seem a little weird. + ## + ## `Return` `0` if music is not paused. `1` if it is paused. + +proc setMusicPosition*(position: cdouble): cint {. + importc: "Mix_SetMusicPosition".} + ## Set the current `position` in the music stream. + ## + ## `position` Posistion to play from. + ## + ## The `position` takes different meanings for different music sources. + ## It only works on the music sources listed below. + ## + ## `MOD` + ## The `cdouble` is cast to `uint16` and used for a pattern + ## number in the module. Passing zero is similar to rewinding the song. + ## + ## `OGG` + ## Jumps to position seconds from the beginning of the song. + ## + ## `MP3` + ## Jumps to position seconds from the current position in the stream. + ## So you may want to call `mixer.rewindMusic()` before this. + ## Does not go in reverse. Negative values do nothing. + ## + ## This procedurre is only implemented for MOD music formats (set pattern + ## order number) and for OGG, FLAC, MP3_MAD, MPD_MPG and MODPLUG music + ## (set position in seconds), at the moment. + ## + ## `Return` `0` on success, + ## or `-1` if the codec doesn't support this procedure. -# Check the status of a specific channel. -# If the specified channel is -1, check all channels. -# proc playing*(channel: cint): cint {.importc: "Mix_Playing".} + ## Tells you if `channel` is playing, or not. + ## + ## `channel` Channel to test whether it is playing or not. + ## `-1` will tell you how many channels are playing. + ## + ## `Note:` Does not check if the channel has been paused. + ## + ## `Return` `0` if the channel is not playing. + ## Otherwise if you passed in `-1`, + ## the number of channels playing is returned. + ## If you passed in a specific channel, + ## then `1` is returned if it is playing. + proc playingMusic*(): cint {.importc: "Mix_PlayingMusic".} + ## Tells you if music is actively playing, or not. + ## + ## `Note:` Does not check if the channel has been paused. + ## + ## `Return` `0` if the music is not playing, or `1` if it is playing. -# Stop music and set external music playback command proc setMusicCMD*(command: cstring): cint {.importc: "Mix_SetMusicCMD".} -# Synchro value is set by MikMod from modules while playing + ## Stop music and set external music playback command. + ## + ## `command` System command to play the music. + ## Should be a complete command, as if typed in to the command line, + ## but it should expect the filename to be added as the last argument. + ## `nil` will turn off using an external command for music, + ## returning to the internal music playing functionality. + ## + ## Setup a command line music player to use to play music. + ## Any music playing will be halted. + ## + ## The music file to play is set by calling `mixer.loadMUS(filename)`, + ## and the filename is appended as the last argument on the commandline. + ## This allows you to reuse the music command to play multiple files. + ## + ## The command will be sent signals SIGTERM to halt, SIGSTOP to pause, + ## and SIGCONT to resume. The command program should react correctly + ## to those signals for it to function properly with mixer. + ## + ## `mixer.volumeMusic()` has no effect when using an external music + ## player, and `mixer.getError()` will have an error code set. + ## You should set the music volume in the music player's command if the music + ## player supports that. Looping music works, by calling the command again + ## when the previous music player process has ended. Playing music through a + ## command uses a forked process to execute the music command. + ## + ## To use the internal music players set the command to `nil`. + ## + ## `Note:` External music is not mixed by SDL_mixer, + ## so no post-processing hooks will be for music. + ## + ## `Note:` Playing music through an external command may not work + ## if the sound driver does not support multiple openings of the audio + ## device, since SDL_Mixer already has the audio device open for playing + ## samples through channels. + ## + ## `Note:` Commands are not totally portable, so be careful. + ## + ## `Return` `0` on success, or `-1` on any errors, + ## such as running out of memory. proc setSynchroValue*(value: cint): cint {.importc: "Mix_SetSynchroValue".} + ## Synchro value is set by MikMod from modules while playing. + proc getSynchroValue*(): cint {.importc: "Mix_GetSynchroValue".} -# Set/Get/Iterate SoundFonts paths to use by supported MIDI backends proc setSoundFonts*(paths: cstring): cint {. importc: "Mix_SetSoundFonts".} + ## Set SoundFonts paths to use by supported MIDI backends proc getSoundFonts*(): cstring {.importc: "Mix_GetSoundFonts".} + ## Get SoundFonts paths to use by supported MIDI backends proc eachSoundFont*(function: proc (a2: cstring; a3: pointer): cint {.cdecl.}; - data: pointer): cint {.importc: "Mix_EachSoundFont".} -# Get the Chunk currently associated with a mixer channel -# Returns NULL if it's an invalid channel, or there's no chunk associated. -# + data: pointer): cint {.importc: "Mix_EachSoundFont".} + ## Iterate SoundFonts paths to use by supported MIDI backends proc getChunk*(channel: cint): ptr Chunk {.importc: "Mix_GetChunk".} -# Close the mixer, halting all playing audio + ## Get the most recent sample chunk pointer played on `channel`. + ## This pointer may be currently playing, or just the last used. + ## + ## `channel` Channel to get the current `mixer.Chunk` playing. + ## `-1` is not valid, but will not crash the program. + ## + ## `Note:` The actual chunk may have been freed, + ## so this pointer may not be valid anymore. + ## + ## `Return` pointer to the `mixer.Chunk`. + ## `nil` is returned if the channel is not allocated, + ## or if the channel has not played any samples yet. proc closeAudio*() {.importc: "Mix_CloseAudio".} + ## Shutdown and cleanup the mixer API. + ## + ## After calling this all audio is stopped, the device is closed, + ## and the SDL_mixer procedures should not be used. You may, of course, + ## use `mixer.openAudio()` to start the functionality again. + ## + ## `Note:` This procedure doesn't do anything until you have called it + ## the same number of times that you called `mixer.openAudio()`. + ## You may use `mixer.querySpec()` to find out how many times + ## `mixer.closeAudio()` needs to be called before the device + ## is actually closed. + when not defined(SDL_Static): {.pop.} diff --git a/src/sdl2/net.nim b/src/sdl2/net.nim index a182f6c..e19a40c 100644 --- a/src/sdl2/net.nim +++ b/src/sdl2/net.nim @@ -1,5 +1,5 @@ # -# SDL_net: An example cross-platform network library for use with SDL +# net: An example cross-platform network library for use with SDL # Copyright (C) 1997-2013 Sam Lantinga # Copyright (C) 2012 Simeon Maxein # @@ -18,8 +18,20 @@ # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -# -# $Id$ + +## Cross-platform networking library. +## +## +## Network Byte Order +## ------------------ +## Also known as `Big-Endian`. Which means the most significant byte comes +## first in storage. Sparc and Motorola 68k based chips are MSB ordered. +## +## `Little-Endian` (LSB) is stored in the opposite order, with the least +## significant byte first in memory. Intel and AMD are two LSB machines. +## +## For network addresses, 1.2.3.4 is always stored as `{0x01 0x02 0x03 0x04}`. + import sdl2 when not defined(SDL_Static): @@ -34,234 +46,1078 @@ else: type IpAddress* = object + ## This type contains the information used + ## to form network connections and sockets. host*: uint32 # 32-bit IPv4 host address port*: uint16 # 16-bit protocol port TcpSocket* = pointer + ## This is an opaque data type used for TCP connections. + ## This is a pointer, and so it could be `nil` at times. + ## `nil` would indicate no socket has been established. const - INADDR_ANY* = 0x00000000 - INADDR_NONE* = 0xFFFFFFFF + INADDR_ANY* = 0x00000000 ## Used for listening on all network interfaces. + INADDR_NONE* = 0xFFFFFFFF ## Which has limited applications. INADDR_LOOPBACK* = 0x7F000001 INADDR_BROADCAST* = 0xFFFFFFFF -# The maximum channels on a a UDP socket + ## Used as destination when sending a message to all clients + ## on a subnet that allows broadcasts. + const SDLNET_MAX_UDPCHANNELS* = 32 -# The maximum addresses bound to a single UDP socket channel + ## The maximum channels on a a UDP socket const SDLNET_MAX_UDPADDRESSES* = 4 + ## The maximum addresses bound to a single UDP socket channel + type UDPsocket* = ptr object + ## This is an opaque data type used for UDP sockets. + ## This is a pointer, and so it could be `nil` at times. + ## `nil` would indicate no socket has been established. + UDPpacket* = object - channel*: cint # The src/dst channel of the packet - data*: ptr uint8 # The packet data - len*: cint # The length of the packet data - maxlen*: cint # The size of the data buffer - status*: cint # packet status after sending - address*: IpAddress # The source/dest address of an incoming/outgoing packet + ## `channel` The (software) channel number for this packet. + ## This can also be used as a priority value for the packet. + ## If no channel is assigned, the value is `-1`. + ## + ## `data` The data contained in this packet, this is the meat. + ## + ## `len` This is the meaningful length of the data in bytes. + ## + ## `maxlen` This is size of the data buffer, which may be larger + ## than the meaningful length. This is only used for packet creation + ## on the senders side. + ## + ## `status` This contains the number of bytes sent, or a `-1` on errors, + ## after sending. This is useless for a received packet. + ## + ## `address` This is the resolved `IPaddress` to be used when sending, + ## or it is the remote source of a received packet. + ## + ## This struct is used with UDPsockets to send and receive data. + ## It also helps keep track of a packets sending/receiving settings and + ## status. The channels concept helps prioritize, or segregate differring + ## types of data packets. + channel*: cint ## The src/dst channel of the packet + data*: ptr uint8 ## The packet data + len*: cint ## The length of the packet data + maxlen*: cint ## The size of the data buffer + status*: cint ## packet status after sending + address*: IpAddress + ## The source/dest address of an incoming/outgoing packet #********************************************************************* # Hooks for checking sockets for available data #********************************************************************* type SocketSet* = pointer -# Any network socket can be safely cast to this socket type + ## This is an opaque data type used for socket sets. + ## This is a pointer, and so it could be `nil` at times. + ## `nil` would indicate no socket set has been created. type GenericSocketObj* = object ready*: cint GenericSocket* = ptr GenericSocketObj + ## This data type is able to be used for both + ## `UDPsocket` and `TCPsocket` types. + ## + ## `ready` Non-zero when data is ready to be read, + ## or a server socket has a connection attempt ready to be accepted. + ## + ## After calling `net.checkSockets()`, if this socket is in + ## `net.socketSet()` used, the `ready` will be set according + ## to activity on the socket. This is the only real use for this type, + ## as it doesn't help you know what type of socket it is. when not defined(SDL_Static): {.push dynlib: LibName, callconv: cdecl.} -# This function gets the version of the dynamically linked SDL_net library. -# it should NOT be used to fill a version structure, instead you should -# use the SDL_NET_VERSION() macro. -# proc linkedVersion*(): ptr SDL_Version {.importc: "SDLNet_Linked_Version".} -# Initialize/Cleanup the network API -# SDL must be initialized before calls to functions in this library, -# because this library uses utility functions from the SDL library. -# + ## This procedure gets the version of the dynamically linked net library. + # TODO Add an equivalent `NET_VERSION` macro (version template ?) and this + # comment: + # It should NOT be used to fill a version structure, instead you should + # use the `version()` template. + proc init*(): cint {.importc: "SDLNet_Init".} + ## Initialize the network API. + ## + ## SDL must be initialized before calls to procedures in this library, + ## because this library uses utility procedures from the SDL library. + ## + ## `Return` `0` on success, `-1` on errors. + proc quit*() {.importc: "SDLNet_Quit".} + ## Shutdown and cleanup the network API. + ## + ## After calling this all sockets are closed, + ## and the net procedures should not be used. + ## You may, of course, use `net.init()` to use the functionality again. + #********************************************************************* # IPv4 hostname resolution API #********************************************************************* -# Resolve a host name and port to an IP address in network form. -# If the function succeeds, it will return 0. -# If the host couldn't be resolved, the host portion of the returned -# address will be INADDR_NONE, and the function will return -1. -# If 'host' is NULL, the resolved host will be set to INADDR_ANY. -# -proc resolveHost*(address: ptr IpAddress; host: cstring; port: uint16): cint {.importc: "SDLNet_ResolveHost".} -# Resolve an ip address to a host name in canonical form. -# If the ip couldn't be resolved, this function returns NULL, -# otherwise a pointer to a static buffer containing the hostname -# is returned. Note that this function is not thread-safe. -# +proc resolveHost*(address: ptr IpAddress; host: cstring; port: uint16): cint {. + importc: "SDLNet_ResolveHost".} + ## Resolve a host name and port to an IP address in network form. + ## + ## `address` points to the `IPaddress` that will be filled in. + ## It doesn't need to be set before calling this, + ## but it must be allocated in memory. + ## + ## `host` For connecting to a server, this is the hostname or IP + ## in a string. + ## + ## For becoming a server, this is `nil`. + ## + ## If you do use `nil`, all network interfaces would be listened to for + ## incoming connections, using the `INADDR_ANY` address. + ## + ## `port` For connecting to a server, this is the the servers listening + ## port number. + ## + ## For becoming a server, this is the port to listen on. + ## + ## If you are just doing Domain Name Resolution functions, this can be `0`. + ## + ## Resolve the string `host`, and fill in the `IPaddress` pointed to by + ## `address` with the resolved IP and the port number passed in through + ## `port`. + ## + ## This is the best way to fill in the `IPaddress` struct for later use. + ## This procedure does not actually open any sockets, it is used to prepare + ## the arguments for the socket opening procedures. + ## + ## `WARNING:` this procedure will put the `host` and `port` + ## into Network Byte Order into the `address` fields, so make sure + ## you pass in the data in your hosts byte order (normally not an issue). + ## + ## `Return` `0` on success. `-1` on errors, + ## plus `address.host` will be `INADDR_NONE`. + ## An error would likely be that the address could not be resolved. + ## + ## For a server listening on all interfaces, on port 1234: + ## + ## .. code-block:: nim + ## # create a server type IPaddress on port 1234 + ## var ipaddress: IPaddress + ## net.resolveHost(addr(ipaddress), nil, 1234) + ## + ## For a client connection to "host.domain.ext", at port 1234: + ## + ## .. code-block:: nim + ## # create an IPaddress for host name "host.domain.ext" on port 1234 + ## # this is used by a client + ## var ipaddress: IPaddress + ## net.resolveHost(addr(ipaddress), "host.domain.ext", 1234) + proc resolveIP*(ip: ptr IpAddress): cstring {.importc: "SDLNet_ResolveIP".} -# Get the addresses of network interfaces on this system. -# This returns the number of addresses saved in 'addresses' -# -proc getLocalAddresses*(addresses: ptr IpAddress; maxcount: cint): cint {.importc: "SDLNet_GetLocalAddresses".} + ## Resolve an ip address to a host name in canonical form. + ## + ## `address` points to the `IPaddress` that will be resolved + ## to a host name. The `address.port` is ignored. + ## + ## Resolve the IPv4 numeric address in `address.host`, + ## and return the hostname as a string. + ## + ## `Note` that this procedure is not thread-safe. + ## + ## `Return` a valid char pointer (`cstring`) on success. + ## The returned hostname will have host and domain, as in "host.domain.ext". + ## `nil` is returned on errors, such as when it's not able to resolve + ## the host name. The returned pointer is not to be freed. + ## Each time you call this procedure the previous pointer's data will change + ## to the new value, so you may have to copy it into a local buffer to keep + ## it around longer. + +proc getLocalAddresses*(addresses: ptr IpAddress; maxcount: cint): cint {. + importc: "SDLNet_GetLocalAddresses".} + ## Get the addresses of network interfaces on this system. + ## + ## `Return` the number of addresses saved in `addresses`. + #********************************************************************* # TCP network API #********************************************************************* -# Open a TCP network socket -# If ip.host is INADDR_NONE or INADDR_ANY, this creates a local server -# socket on the given port, otherwise a TCP connection to the remote -# host and port is attempted. The address passed in should already be -# swapped to network byte order (addresses returned from -# SDLNet_ResolveHost() are already in the correct form). -# The newly created socket is returned, or NULL if there was an error. -# proc tcpOpen*(ip: ptr IpAddress): TcpSocket {.importc: "SDLNet_TCP_Open".} -# Accept an incoming connection on the given server socket. -# The newly created socket is returned, or NULL if there was an error. -# + ## Open a TCP network socket. + ## + ## `ip` This points to the `IPaddress` that contains the resolved + ## IP address and port number to use. + ## + ## If `ip.host` is `INADDR_NONE` or `INADDR_ANY`, this creates a local + ## server socket on the given port, otherwise a TCP connection to the + ## remote host and port is attempted. The address passed in should already + ## be swapped to network byte order (addresses returned from + ## `resolveHost()` are already in the correct form). + ## + ## `Return` a valid `TCPsocket` on success, which indicates a successful + ## connection has been established, or a socket has been created that is + ## valid to accept incoming TCP connections. + ## `nil` is returned on errors, such as when it's not able to create + ## a socket, or it cannot connect to host and/or port contained in ip. + ## + ## .. code-block:: nim + ## # connect to localhost at port 9999 using TCP (client) + ## var + ## ip: IPaddress + ## tcpsock: TCPsocket + ## + ## if net.resolveHost(addr(ip), "localhost", 9999) == -1: + ## echo "net.resolveHost: ", net.getError() + ## quit(QuitFailure) + ## + ## tcpsock = net.tcpOpen(addr(ip)) + ## if tcpsock == nil: + ## echo "net.tcpOpen: ", net.getError() + ## quit(QuitFailure) + ## + ## .. code-block:: nim + ## # create a listening TCP socket on port 9999 (server) + ## var + ## ip: IPaddress + ## tcpsock: TCPsocket + ## + ## if net.resolveHost(addr(ip), nil, 9999) == -1: + ## echo "net.resolveHost: ", net.getError() + ## quit(QuitFailure) + ## + ## tcpsock = net.tcpOpen(addr(ip)) + ## if tcpsock == nil: + ## echo "net.tcpOpen: ", net.getError() + ## quit(QuitFailure) + proc tcpAccept*(server: TcpSocket): TcpSocket {.importc: "SDLNet_TCP_Accept".} -# Get the IP address of the remote system associated with the socket. -# If the socket is a server socket, this function returns NULL. -# -proc tcpGetPeerAddress*(sock: TcpSocket): ptr IpAddress {.importc: "SDLNet_TCP_GetPeerAddress".} -# Send 'len' bytes of 'data' over the non-server socket 'sock' -# This function returns the actual amount of data sent. If the return value -# is less than the amount of data sent, then either the remote connection was -# closed, or an unknown socket error occurred. -# -proc tcpSend*(sock: TcpSocket; data: pointer; len: cint): cint {.importc: "SDLNet_TCP_Send".} -# Receive up to 'maxlen' bytes of data over the non-server socket 'sock', -# and store them in the buffer pointed to by 'data'. -# This function returns the actual amount of data received. If the return -# value is less than or equal to zero, then either the remote connection was -# closed, or an unknown socket error occurred. -# -proc tcpRecv*(sock: TcpSocket; data: pointer; maxlen: cint): cint {.importc: "SDLNet_TCP_Recv".} -# Close a TCP network socket + ## Accept an incoming connection on the given `server` `TCPsocket`. + ## + ## `server` This is the server `TCPsocket` which was previously created + ## by `net.tcpOpen()`. + ## + ## Do not use this procedure on a connected socket. Server sockets are never + ## connected to a remote host. What you get back is a new `TCPsocket` that + ## is connected to the remote host. + ## + ## This is a non-blocking call, so if no connections are there to be + ## accepted, you will get a `nil` `TCPsocket` and the program will + ## continue going. + ## + ## `Return` a valid `TCPsocket` on success, which indicates a successful + ## connection has been established. `nil` is returned on errors, such as + ## when it's not able to create a socket, or it cannot finish connecting to + ## the originating host and port. There also may not be a connection attempt + ## in progress, so of course you cannot accept nothing, and you get a `nil` + ## in this case as well. + ## + ## .. code-block:: nim + ## # accept a connection coming in on server_tcpsock + ## var new_tcpsock: TCPsocket + ## + ## new_tcpsock = net.tcpAccept(server_tcpsock) + ## if new_tcpsock == nil: + ## echo "net.tcpAccept: ", net.getError() + ## else: + ## # communicate over new_tcpsock + +proc tcpGetPeerAddress*(sock: TcpSocket): ptr IpAddress {. + importc: "SDLNet_TCP_GetPeerAddress".} + ## Get the IP address of the remote system associated with the socket. + ## + ## `sock` This is a valid `TCPsocket`. + ## + ## Get the Peer's (the other side of the connection, the remote side, + ## not the local side) IP address and port number. + ## + ## `Return` an `IPaddress`. `nil` is returned on errors, + ## or when `sock` is a server socket. + ## + ## .. code-block:: nim + ## # get the remote IP and port + ## # var new_tcpsock: TCPsocket + ## var remote_ip: ptr IPaddress + ## + ## remote_ip = net.tcpGetPeerAddress(new_tcpsock) + ## if remote_ip == nil: + ## echo "net.tcpGetPeerAddress: ", net.getError() + ## echo "This may be a server socket." + ## else: + ## # print the info in IPaddress or something else... + +proc tcpSend*(sock: TcpSocket; data: pointer; len: cint): cint {. + importc: "SDLNet_TCP_Send".} + ## Send `len` bytes of `data` over the non-server socket `sock`. + ## + ## `sock` This is a valid, connected, `TCPsocket`. + ## + ## `data` This is a pointer to the data to send over `sock`. + ## + ## `len` This is the length (in bytes) of the `data`. + ## + ## Send `data` of length `len` over the socket `sock`. + ## This routine is not used for server sockets. + ## + ## `Return` the number of bytes sent. If the number returned is less than + ## `len`, then an error occured, such as the client disconnecting. + ## + ## .. code-block:: nim + ## # send a hello over sock + ## # var sock: TCPsocket + ## var + ## msg = ['H', 'e', 'l', 'l', 'o', '!'] + ## + ## if net.tcpSend(sock, addr(msg), msg.len) < msg.len: + ## echo "net.tcpSend: ", net.getError() + ## # it may be ood to disconnect sock because it is likely invalid now + +proc tcpRecv*(sock: TcpSocket; data: pointer; maxlen: cint): cint {. + importc: "SDLNet_TCP_Recv".} + ## Receive up to `maxlen` bytes of data over the non-server socket + ## `sock`, and store them in the buffer pointed to by `data`. + ## + ## `sock` This is a valid, connected, `TCPsocket`. + ## + ## `data` This is a pointer to the buffer that receives the data + ## from `sock`. + ## + ## `maxlen` This is the maximum length (in bytes) that will be read + ## into `data`. + ## + ## Receive data of `exactly` length `maxlen` bytes from the socket + ## `sock`, into the memory pointed to by `data`. + ## + ## This routine is not used for server sockets. + ## + ## Unless there is an error, or the connection is closed, the buffer will + ## read `maxlen` bytes. If you read more than is sent from the other end, + ## then it will wait until the full requested length is sent, or until the + ## connection is closed from the other end. + ## + ## You may have to read 1 byte at a time for some applications, for instance, + ## text applications where blocks of text are sent, but you want to read line + ## by line. In that case you may want to find the newline characters yourself + ## to break the lines up, instead of reading some inordinate amount of text + ## which may contain many lines, or not even a full line of text. + ## + ## `Return` the number of bytes received. If the number returned is + ## less than or equal to `0`, then an error occured, or the remote host + ## has closed the connection. + ## + ## .. code-block:: nim + ## # receive some text from sock + ## # var sock: TCPsocket + ## const + ## MaxLen = 1024 + ## var + ## msg: array[MaxLen, char] + ## + ## if net.tcpRecv(sock, addr(msg[0]), MaxLen) <= 0: + ## # an error may have occured, but sometimes you can just ignore it + ## # it may be good to disconnect sock because it is likely invalid now + ## + ## echo "Received: ", msg + proc tcpClose*(sock: TcpSocket) {.importc: "SDLNet_TCP_Close".} + ## Close a TCP network socket. + ## + ## `sock` A valid `TCPsocket`. + ## This can be a server or client type socket. + ## + ## This shutsdown, disconnects, and closes the `TCPsocket` sock. + ## + ## After this, you can be assured that this socket is not in use anymore. + ## You can reuse the `sock` variable after this to open a new connection + ## with `net.tcpOpen()`. Do not try to use any other procedures on + ## a closed socket, as it is now invalid. + ## + ## `Return` nothing, this always succeeds for all we need to know. + #********************************************************************* # UDP network API #********************************************************************* -# Allocate/resize/free a single UDP packet 'size' bytes long. -# The new packet is returned, or NULL if the function ran out of memory. -# proc allocPacket*(size: cint): ptr UDPpacket {.importc: "SDLNet_AllocPacket".} -proc resizePacket*(packet: ptr UDPpacket; newsize: cint): cint {.importc: "SDLNet_ResizePacket".} + ## Allocate a single UDP packet `size` bytes long. + ## + ## `size` Size, in bytes, of the data buffer to be allocated in the new + ## `UDPpacket`. Zero is invalid. + ## + ## Create (via malloc) a new `UDPpacket` with a data buffer + ## of `size` bytes. + ## The new packet should be freed using `net.freePacket()` when you are + ## done using it. + ## + ## `Return` a pointer to a new empty `UDPpacket`. + ## `nil` is returned on errors, such as out-of-memory. + ## + ## .. code-block:: nim + ## # create a new UDPpacket to hold 1024 bytes of data + ## var packet: ptr UDPpacket + ## + ## packet = net.allocPacket(1024) + ## if packet == nil: + ## echo "net.allocPacket: ", net.getError() + ## # perhaps do something else since you can't make this packet + ## else: + ## # do stuff with this new packet + ## # net.freePacket this packet when finished with it + +proc resizePacket*(packet: ptr UDPpacket; newsize: cint): cint {. + importc: "SDLNet_ResizePacket".} + ## Resize a single UDP packet `size` bytes long. + ## + ## `packet` A pointer to the `UDPpacket` to be resized. + ## + ## `size` The new desired size, in bytes, of the data buffer + ## to be allocated in the `UDPpacket`. + ## + ## Resize a `UDPpacket`'s data buffer to `size` bytes. The old data + ## buffer will not be retained, so the new buffer is invalid after this call. + ## + ## `Return` the new size of the data in the packet. + ## If the number returned is less than what you asked for, that's an error. + ## + ## .. code-block:: nim + ## # resize a UDPpacket to hold 2048 bytes of data + ## # var packet: ptr UDPpacket + ## var newsize: int + ## + ## newsize = net.resizePacket(packet, 2048) + ## if newsize < 2048: + ## echo "net.resizePacket: ", net.getError() + ## # perhaps do something else since you didn't get the buffer you wanted + ## else: + ## # do stuff with the resized packet + proc freePacket*(packet: ptr UDPpacket) {.importc: "SDLNet_FreePacket".} -# Allocate/Free a UDP packet vector (array of packets) of 'howmany' packets, -# each 'size' bytes long. -# A pointer to the first packet in the array is returned, or NULL if the -# function ran out of memory. -# -proc allocPacketV*(howmany: cint; size: cint): ptr ptr UDPpacket {.importc: "SDLNet_AllocPacketV".} + ## Free a single UDP packet. + ## + ## `packet` A pointer to the `UDPpacket` to be freed from memory. + ## + ## Free a `UDPpacket` from memory. + ## Do not use this `UDPpacket` after this procedure is called on it. + ## + ## `Return` nothing, this always succeeds. + ## + ## .. code-block:: nim + ## # free a UDPpacket + ## # var packet: ptr UDPpacket + ## + ## net.freePacket(packet) + ## packet = nil # just to help you know that it is freed + +proc allocPacketV*(howmany: cint; size: cint): ptr ptr UDPpacket {. + importc: "SDLNet_AllocPacketV".} + ## Allocate a UDP packet vector (array of packets) of `howmany` packets, + ## each `size` bytes long. + ## + ## `howmany` The number of UDPpackets to allocate. + ## + ## `size` Size, in bytes, of the data buffers to be allocated in the new + ## UDPpackets. Zero is invalid. + ## + ## Create (via malloc) a vector of new UDPpackets, each with data buffers of + ## `size` bytes. The new packet vector should be freed using + ## `net.freePacketV()` when you are done using it. The returned vector + ## is one entry longer than requested, for a terminating `nil`. + ## + ## `Return` a pointer to a new empty `UDPpacket` vector. + ## `nil` is returned on errors, such as out-of-memory. + ## + ## .. code-block:: nim + ## # create a new UDPpacket vector to hold 1024 bytes of data in 10 packets + ## var packetV: ptr ptr UDPpacket + ## + ## packetV = net.allocPacketV(10, 1024) + ## if packetV == nil: + ## echo "net.allocPacketV: ", net.getError() + ## # perhaps do something else since you can't make this packet + ## else: + ## # do stuff with this new packet vector + ## # net.freePacketV this packet vector when finished with it + proc freePacketV*(packetV: ptr ptr UDPpacket) {.importc: "SDLNet_FreePacketV".} -# Open a UDP network socket -# If 'port' is non-zero, the UDP socket is bound to a local port. -# The 'port' should be given in native byte order, but is used -# internally in network (big endian) byte order, in addresses, etc. -# This allows other systems to send to this socket via a known port. -# + ## Free a UDP packet vector (array of packets). + ## + ## `packetV` A pointer to the `UDPpacket` vector to be freed from memory. + ## + ## Free a `UDPpacket` vector from memory. Do not use this `UDPpacket` + ## vector, or any `UDPpacket` in it, after this procedure is called on it. + ## + ## `Return` nothing, this always succeeds. + ## + ## .. code-block:: nim + ## # free a UDPpacket vector + ## # var packetV: ptr ptr UDPpacket + ## + ## net.freePacketV(packetV) + ## packetV = nil # just to help you know that it is freed + proc udpOpen*(port: uint16): UDPsocket {.importc: "SDLNet_UDP_Open".} -# Set the percentage of simulated packet loss for packets sent on the socket. -# -proc udpSetPacketLoss*(sock: UDPsocket; percent: cint) {.importc: "SDLNet_UDP_SetPacketLoss".} -# Bind the address 'address' to the requested channel on the UDP socket. -# If the channel is -1, then the first unbound channel that has not yet -# been bound to the maximum number of addresses will be bound with -# the given address as it's primary address. -# If the channel is already bound, this new address will be added to the -# list of valid source addresses for packets arriving on the channel. -# If the channel is not already bound, then the address becomes the primary -# address, to which all outbound packets on the channel are sent. -# This function returns the channel which was bound, or -1 on error. -# -proc udpBind*(sock: UDPsocket; channel: cint; address: ptr IpAddress): cint {.importc: "SDLNet_UDP_Bind".} -# Unbind all addresses from the given channel + ## Open a UDP network socket. + ## + ## `port` This is the port number (in native byte order) on which to + ## receive UDP packets. Most servers will want to use a known port number + ## here so that clients can easily communicate with the server. + ## This can also be zero, which then opens an anonymous unused port number, + ## to most likely be used to send UDP packets from. + ## The `port` should be given in native byte order, but is used + ## internally in network (big endian) byte order, in addresses, etc. + ## This allows other systems to send to this socket via a known port. + ## + ## Open a socket to be used for UDP packet sending and/or receiving. + ## If a non-zero port is given it will be used, otherwise any open port + ## number will be used automatically. + ## + ## Unlike TCP sockets, this socket does not require a remote host IP to + ## connect to, this is because UDP ports are never actually connected like + ## TCP ports are. This socket is able to send and receive directly after + ## this simple creation. + ## + ## `Note` that below I say server, but clients may also open a specific + ## port, though it is prefered that a client be more flexible, given that + ## the port may be already allocated by another process, such as a server. + ## In such a case you will not be able to open the socket, and your program + ## will be stuck, so it is better to just use whatever port you are given by + ## using a specified port of zero. Then the client will always work. + ## The client can inform the server what port to talk back to, or the server + ## can just look at the source of the packets it is receiving to know where + ## to respond to. + ## + ## `Return` a valid `UDPsocket` on success. `nil` is returned on errors, + ## such as when it's not able to create a socket, or it cannot assign the + ## non-zero port as requested. + ## + ## .. code-block:: nim + ## # create a UDPsocket on port 6666 (server) + ## var udpsock: UDPsocket + ## + ## udpsock = net.udpOpen(6666) + ## if udpsock == nil: + ## echo "net.udpOpen: ", net.getError() + ## quit(QuitFailure) + ## + ## .. code-block:: nim + ## # create a UDPsocket on any available port (client) + ## var udpsock: UDPsocket + ## + ## udpsocket = net.udpOpen(0) + ## if udpsock == nil: + ## echo "net.udpOpen: ", net.getError() + ## quit(QuitFailure) + +proc udpSetPacketLoss*(sock: UDPsocket; percent: cint) {. + importc: "SDLNet_UDP_SetPacketLoss".} + ## Bind the address `address` to the requested channel on the UDP socket. + ## + ## `sock` the UDPsocket on which to assign the address. + ## + ## `channel` The channel to assign address to. + ## This should be less than `net.MAX_UDPCHANNELS`. + ## If `-1` is used, then the first unbound channel will be used, this should + ## only be used for incomming packet filtering, as it will find the first + ## channel with less than `SDLNET_MAX_UDPADDRESSES` assigned to it and use + ## that one. + ## If the `channel` is already bound, this new address will be added to + ## the list of valid source addresses for packets arriving on the channel. + ## If the `channel` is not already bound, then the address becomes the + ## primary address, to which all outbound packets on the channel are sent. + ## + ## `address` The resolved `IPaddress` to assign to the socket's channel. + ## The host and port are both used. It is not helpful to bind `0.0.0.0` + ## to a channel. + ## + ## Incoming packets are only allowed from bound addresses for the socket + ## channel. + ## All outgoing packets on that channel, regardless of the packets internal + ## address, will attempt to send once on each bound address on that channel. + ## You may assign up to `net.MAX_UDPADDRESSES` to each channel. + ## + ## `Return` the channel number that was bound. `-1` is returned on errors, + ## such as no free channels, or this channel has `net.MAX_UDPADDRESSES` + ## already assigned to it, or you have used a channel higher or equal to + ## `net.MAX_UDPCHANNELS`, or lower than `-1`. + ## + ## .. code-block:: nim + ## # Bind address to the first free channel + ## # var udpsock: UDPsocket + ## # var address: IPaddress + ## var channel: int + ## + ## channel = net.udpBind(udpsock, -1, address) + ## if channel == -1: + ## echo "net.udpBind: ", net.getError() + ## # do something because we failed to bind + +proc udpBind*(sock: UDPsocket; channel: cint; address: ptr IpAddress): cint {. + importc: "SDLNet_UDP_Bind".} + ## Bind the address `address` to the requested channel on the UDP socket. + ## + ## `sock` the UDPsocket on which to assign the address. + ## + ## `channel` The channel to assign address to. + ## This should be less than `net.MAX_UDPCHANNELS`. + ## If `-1` is used, then the first unbound channel will be used, this should + ## only be used for incomming packet filtering, as it will find the first + ## channel with less than `SDLNET_MAX_UDPADDRESSES` assigned to it and use + ## that one. + ## If the `channel` is already bound, this new address will be added to + ## the list of valid source addresses for packets arriving on the channel. + ## If the `channel` is not already bound, then the address becomes the + ## primary address, to which all outbound packets on the channel are sent. + ## + ## `address` The resolved `IPaddress` to assign to the socket's channel. + ## The host and port are both used. It is not helpful to bind `0.0.0.0` + ## to a channel. + ## + ## Incoming packets are only allowed from bound addresses for the socket + ## channel. + ## All outgoing packets on that channel, regardless of the packets internal + ## address, will attempt to send once on each bound address on that channel. + ## You may assign up to `net.MAX_UDPADDRESSES` to each channel. + ## + ## `Return` the channel number that was bound. `-1` is returned on errors, + ## such as no free channels, or this channel has `net.MAX_UDPADDRESSES` + ## already assigned to it, or you have used a channel higher or equal to + ## `net.MAX_UDPCHANNELS`, or lower than `-1`. + ## + ## .. code-block:: nim + ## # Bind address to the first free channel + ## # var udpsock: UDPsocket + ## # var address: IPaddress + ## var channel: int + ## + ## channel = net.udpBind(udpsock, -1, address) + ## if channel == -1: + ## echo "net.udpBind: ", net.getError() + ## # do something because we failed to bind + proc udpUnbind*(sock: UDPsocket; channel: cint) {.importc: "SDLNet_UDP_Unbind".} -# Get the primary IP address of the remote system associated with the -# socket and channel. If the channel is -1, then the primary IP port -# of the UDP socket is returned -- this is only meaningful for sockets -# opened with a specific port. -# If the channel is not bound and not -1, this function returns NULL. -# -proc udpGetPeerAddress*(sock: UDPsocket; channel: cint): ptr IpAddress {.importc: "SDLNet_UDP_GetPeerAddress".} -# Send a vector of packets to the the channels specified within the packet. -# If the channel specified in the packet is -1, the packet will be sent to -# the address in the 'src' member of the packet. -# Each packet will be updated with the status of the packet after it has -# been sent, -1 if the packet send failed. -# This function returns the number of packets sent. -# + ## Unbind all addresses from the given channel. + ## + ## `sock` A valid `UDPsocket` to unbind addresses from. + ## + ## `channel` The channel to unbind the addresses from in the `UDPsocket`. + ## + ## This removes all previously assigned (bound) addresses from a socket + ## channel. After this you may bind new addresses to the socket channel. + ## + ## `Return` nothing, this always succeeds. + ## + ## .. code-block:: nim + ## # unbind all addresses on the UDPsocket channel 0 + ## # var udpsock: UDPsocket + ## + ## net.udpUnbind(udpsock, 0) + +proc udpGetPeerAddress*(sock: UDPsocket; channel: cint): ptr IpAddress {. + importc: "SDLNet_UDP_GetPeerAddress".} + ## Get the primary IP address of the remote system associated with the + ## `socket` and `channel`. + ## + ## `sock` A valid `UDPsocket` that probably has an address assigned + ## to the channel. + ## + ## `channel` The channel to get the primary address from in the socket. + ## If the `channel` is `-1`, then the primary IP port of the UDP socket + ## is returned - this is only meaningful for sockets opened with a specific + ## port. + ## + ## Get the primary address assigned to this channel. Only the first bound address is returned. When channel is `-1`, get the port that this socket + ## is bound to on the local computer, this only means something if you + ## opened the socket with a specific port number. + ## Do not free the returned `IPaddress` pointer. + ## + ## `Return` a pointer to an `IPaddress`. + ## `nil` is returned for unbound channels and on any errors. + ## + ## .. code-block:: nim + ## # get the primary address bound to UDPsocket channel 0 + ## # var udpsock: UDPsocket + ## var address: ptr IPaddress + ## + ## address = net.udpGetPeerAddress(udpsock, 0) + ## if address == nil: + ## echo "net.udpGetPeerAddress: ", net.getError() + ## # do something because we failed to get the address + ## else: + ## # perhaps print out address.host and address.port + proc udpSendV*(sock: UDPsocket; packets: ptr ptr UDPpacket; npackets: cint): cint {.importc: "SDLNet_UDP_SendV".} -# Send a single packet to the specified channel. -# If the channel specified in the packet is -1, the packet will be sent to -# the address in the 'src' member of the packet. -# The packet will be updated with the status of the packet after it has -# been sent. -# This function returns 1 if the packet was sent, or 0 on error. -# -# NOTE: -# The maximum size of the packet is limited by the MTU (Maximum Transfer Unit) -# of the transport medium. It can be as low as 250 bytes for some PPP links, -# and as high as 1500 bytes for ethernet. -# -proc udpSend*(sock: UDPsocket; channel: cint; packet: ptr UDPpacket): cint {.importc: "SDLNet_UDP_Send".} -# Receive a vector of pending packets from the UDP socket. -# The returned packets contain the source address and the channel they arrived -# on. If they did not arrive on a bound channel, the the channel will be set -# to -1. -# The channels are checked in highest to lowest order, so if an address is -# bound to multiple channels, the highest channel with the source address -# bound will be returned. -# This function returns the number of packets read from the network, or -1 -# on error. This function does not block, so can return 0 packets pending. -# -proc udpRecvV*(sock: UDPsocket; packets: ptr ptr UDPpacket): cint {.importc: "SDLNet_UDP_RecvV".} -# Receive a single packet from the UDP socket. -# The returned packet contains the source address and the channel it arrived -# on. If it did not arrive on a bound channel, the the channel will be set -# to -1. -# The channels are checked in highest to lowest order, so if an address is -# bound to multiple channels, the highest channel with the source address -# bound will be returned. -# This function returns the number of packets read from the network, or -1 -# on error. This function does not block, so can return 0 packets pending. -# -proc udpRecv*(sock: UDPsocket; packet: ptr UDPpacket): cint {.importc: "SDLNet_UDP_Recv".} -# Close a UDP network socket + ## Send a vector of packets to the the channels specified within the packet. + ## + ## `sock` A valid `UDPsocket`. + ## + ## `packetV` The vector of packets to send. + ## + ## `npackets` number of packets in the `packetV` vector to send. + ## + ## Send `npackets` of `packetV` using the specified `sock` socket. + ## + ## Each packet is sent in the same way as in `net.udpSend()`. + ## + ## `Note:` Don't forget to set the length of the packets in the `len` + ## element of the `packets` you are sending! + ## + ## If the channel specified in the packet is `-1`, the packet will be sent + ## to the address in the `src` member of the `packet`. + ## + ## Each packet will be updated with the status of the packet after it has + ## been sent, `-1` if the packet send failed. + ## + ## `Return` the number of destinations sent to that worked, for each + ## packet in the vector, all summed up. `0` is returned on errors. + ## + ## .. code-block:: nim + ## # send a vector of 10 packets using UDPsocket + ## # var udpsock: UDPsocket + ## # var packetV: ptr ptr UDPpacket + ## var numsent: int + ## + ## numsent = net.udpSendV(udpsock, packetV, 10) + ## if numsent == 0: + ## echo "net.udpSendV: ", net.getError() + ## # do something because we failed to send + ## # this may just be because no addresses are bound to the channels... + + +proc udpSend*(sock: UDPsocket; channel: cint; packet: ptr UDPpacket): cint {. + importc: "SDLNet_UDP_Send".} + ## Send a single `packet` to the specified `channel`. + ## + ## `sock` A valid `UDPsocket`. + ## + ## `channel` What channel to sent packet on. + ## + ## `packet` The packet to send. + ## + ## Send `packet` using the specified socket `sock`, using the specified + ## `channel` or else the `packet`'s address. + ## + ## If `channel` is not `-1` then the packet is sent to all the `socket` + ## channels bound addresses. If socket `sock`'s channel is not bound to + ## any destinations, then the packet is not sent at all! + ## + ## If the channel is `-1`, then the `packet`'s address is used + ## as the destination. + ## + ## `Note:` Don't forget to set the length of the packet in the `len` + ## element of the `packet` you are sending! + ## + ## `Note:` The `packet.channel` will be set to the channel passed in to + ## this procedure. + ## + ## `Note:` The maximum size of the packet is limited by the MTU (Maximum + ## Transfer Unit) of the transport medium. It can be as low as `250` bytes + ## for some PPP links, and as high as `1500` bytes for ethernet. Beyond that + ## limit the packet will fragment, and make delivery more and more unreliable + ## as lost fragments cause the whole packet to be discarded. + ## + ## `Return` The number of destinations sent to that worked. + ## `0` is returned on errors. + ## + ## `Note` that since a channel can point to multiple destinations, there + ## should be just as many packets sent, so dont assume it will always return + ## `1` on success. Unfortunately there's no way to get the number of + ## destinations bound to a channel, so either you have to remember + ## the number bound, or just test for the zero return value indicating all + ## channels failed. + ## + ## .. code-block:: nim + ## # send a packet using a UDPsocket, + ## # using the packet's channel as the channel + ## # var udpsock: UDPsocket + ## # var packet: ptr UDPpacket + ## var numsent: int + ## + ## numsent = net.udpSend(udpsock, packet.channel, packet) + ## if numsent == 0: + ## echo "net.udpSend: ", net.getError() + ## # do something because we failed to send + ## # this may just be because no addresses are bound to the channel... + ## + ## Here's a way of sending one packet using it's internal channel setting. + ## This is actually what `net.udpSend()` ends up calling for you. + ## + ## .. code-block:: nim + ## # send a packet using a UDPsocket, + ## # using the packet's channel as the channel + ## # var udpsock: UDPsocket + ## # var packet: ptr UDPpacket + ## var numsent: int + ## + ## numsent = net.udpSendV(sock, addr(packet), 1) + ## if nusment == 0: + ## echo "net.udpSendV: ", net.getError() + ## # do something because we failed to send + ## # this may just be because no addresses are bound to the channel... + +proc udpRecvV*(sock: UDPsocket; packets: ptr ptr UDPpacket): cint {. + importc: "SDLNet_UDP_RecvV".} + ## Receive a vector of pending packets from the UDP socket. + ## + ## `sock` A valid `UDPsocket`. + ## + ## `packet` The packet to receive into. + ## + ## Receive into a packet vector on the specified socket `sock`. + ## + ## `packetV` is a `nil` terminated array. Packets will be received until + ## the `nil` is reached, or there are none ready to be received. + ## + ## This call is otherwise the same as `net.udpRecv()`. + ## + ## The returned packets contain the source address and the channel they + ## arrived on. If they did not arrive on a bound channel, the the channel + ## will be set to `-1`. + ## + ## The channels are checked in highest to lowest order, so if an address is + ## bound to multiple channels, the highest channel with the source address + ## bound will be returned. + ## + ## This procedure does not block, so can return `0` packets pending. + ## + ## `Return` the number of packets received. + ## `0` is returned when no packets are received. + ## `-1` is returned on errors. + ## + ## .. code-block:: nim + ## # try to receive some waiting udp packets + ## # var udpsock: UDPsocket + ## # var packetV: ptr ptr UDPpacket + ## var numrecv, i: int + ## + ## numrecv = net.udpRecvV(udpsock, addr(packetV) + ## if numrecv == -1: + ## # handle error, perhaps just print out the net.getError string. + ## + ## for i in 0..numrecv-1: + ## # do something with packetV[i] + +proc udpRecv*(sock: UDPsocket; packet: ptr UDPpacket): cint {. + importc: "SDLNet_UDP_Recv".} + ## Receive a single packet from the UDP socket. + ## + ## `sock` A valid `UDPsocket`. + ## + ## `packet` The packet to receive into. + ## + ## Receive a packet on the specified sock socket. + ## + ## The `packet` you pass in must have enough of a data size allocated for + ## the incoming packet data to fit into. This means you should have knowledge + ## of your size needs before trying to receive UDP packets. + ## The packet will have it's address set to the remote sender's address. + ## + ## The `socket`'s channels are checked in highest to lowest order, + ## so if an address is bound to multiple channels, the highest channel + ## with the source address bound will be retreived before the lower bound + ## channels. So, the packets channel will also be set to the highest numbered + ## channel that has the remote address and port assigned to it. Otherwise the + ## channel will `-1`, which you can filter out easily if you want to ignore + ## unbound source address. + ## + ## `Note` that the local and remote channel numbers do not have to, and + ## probably won't, match, as they are only local settings, they are not sent + ## in the packet. + ## + ## This is a non-blocking call, meaning if there's no data ready to be + ## received the procedure will return. + ## + ## `Return` `1` is returned when a packet is received. + ## `0` is returned when no packets are received. + ## `-1` is returned on errors. + ## + ## .. code-block:: nim + ## # try to receive a waiting udp packet + ## # var udpsock: UDPsocket + ## var + ## packet: UDPpacket + ## numrecv: int + ## + ## numrecv = net.udpRecv(udpsock, addr(packet)) + ## if numrecv > 0: + ## # do something with packet + proc udpClose*(sock: UDPsocket) {.importc: "SDLNet_UDP_Close".} + ## Close a UDP network socket. + ## + ## `sock` A valid `UDPsocket` to shutdown, close, and free. + ## + ## Shutdown, close, and free a `UDPsocket`. + ## Don't use the `UDPsocket` after calling this, except to open a new one. + ## + ## `Return` nothing, this always succeeds. + ## + ## .. code-block:: nim + ## # var udpsock: UDPsocket + ## + ## net.udpClose(udpsock) + ## udpsock = nil # this helps us know that this + ## # UDPsocket is not valid anymore -# Allocate a socket set for use with SDLNet_CheckSockets() -# This returns a socket set for up to 'maxsockets' sockets, or NULL if -# the function ran out of memory. -# -proc allocSocketSet*(maxsockets: cint): SocketSet {.importc: "SDLNet_AllocSocketSet".} -# Add a socket to a set of sockets to be checked for available data -proc addSocket*(set: SocketSet; sock: GenericSocket): cint {.importc: "SDLNet_AddSocket".} - -# Remove a socket from a set of sockets to be checked for available data -proc delSocket*(set: SocketSet; sock: GenericSocket): cint {.importc: "SDLNet_DelSocket".} - -# This function checks to see if data is available for reading on the -# given set of sockets. If 'timeout' is 0, it performs a quick poll, -# otherwise the function returns when either data is available for -# reading, or the timeout in milliseconds has elapsed, which ever occurs -# first. This function returns the number of sockets ready for reading, -# or -1 if there was an error with the select() system call. -# -proc checkSockets*(set: SocketSet; timeout: uint32): cint {.importc: "SDLNet_CheckSockets".} -# After calling CheckSockets(), you can use this function on a -# socket that was in the socket set, to find out if data is available -# for reading. -# +proc allocSocketSet*(maxsockets: cint): SocketSet {. + importc: "SDLNet_AllocSocketSet".} + ## Allocate a socket set for use with `net.checkSockets()`. + ## + ## `maxsockets` The maximum number of sockets you will want to watch. + ## + ## Create a socket set that will be able to watch up to maxsockets number + ## of sockets. The same socket set can be used for both UDP and TCP sockets. + ## + ## `Return` A new, empty, `SocketSet`. + ## `nil` is returned on errors, such as out-of-memory. + ## + ## .. code-block:: nim + ## # create a socket set to handle up to 16 sockets + ## var sset: SocketSet + ## + ## sset = net.allocSocketSet(16) + ## if sset == nil: + ## echo "net.allocSocketSet: ", net.getError() + ## quit(QuitFailure) # most of the time this is a major error, + ## # but do what you want + +proc addSocket*(set: SocketSet; sock: GenericSocket): cint {. + importc: "SDLNet_AddSocket".} + ## Add a socket to a set of sockets to be checked for available data. + ## + ## `set` The socket set to add this socket to. + ## + ## `sock` The socket to add to the socket set. + ## + ## Add a socket to a socket set that will be watched. + ## + ## TCP and UDP sockets should be added using the corrosponding template + ## (as in net.tcpAddSocket for a TCP socket). The generic socket + ## procedure will be called by the TCP and UDP templates. + ## Both TCP and UDP sockets may be added to the same socket set. + ## TCP clients and servers may all be in the same socket set. + ## There is no limitation on the sockets in the socket set, + ## other than they have been opened. + ## + ## `Return` the number of sockets used in the set on success. + ## `-1` is returned on errors. + ## + ## **See also:** + ## * `tcpAddSocket proc<#tcpAddSocket,SocketSet,TcpSocket>`_ + ## * `udpAddSocket proc<#udpAddSocket,SocketSet,UDPSocket>`_ + ## + ## .. code-block:: nim + ## # add two sockets to a socket set + ## # var sset: SocketSet + ## # var udpsock: UDPsocket + ## # var tcpsock: TCPsocket + ## var numused: int + ## + ## numused = net.udpAddSocket(sset, udpsock) + ## if numused == -1: + ## echo "net.addSocket: ", net.getError() + ## # perhaps you need to restart the set and make it bigger.. + ## + ## numused = net.udpAddSocket(sset, tcpsock) + ## if numused == -1: + ## echo "net.addSocket: ", net.getError() + ## # perhaps you need to restart the set and make it bigger... + +proc delSocket*(set: SocketSet; sock: GenericSocket): cint {. + importc: "SDLNet_DelSocket".} + ## Remove a socket from a set of sockets to be checked for available data. + ## + ## `sset` The socket set to remove this socket from. + ## + ## `sock` The socket to remove from the socket set. + ## + ## Remove a socket from a socket set. + ## + ## Use this before closing a socket that you are watching with a socket set. + ## This doesn't close the socket. Call the appropriate template for TCP or + ## UDP sockets. The generic socket procedure will be called by the TCP and + ## UDP templates. + ## + ## `Return` the number of sockets used in the set on success. + ## `-1` is returned on errors. + ## + ## **See also:** + ## * `tcpDelSocket proc<#tcpDelSocket,SocketSet,TcpSocket>`_ + ## * `udpDelSocket proc<#udpDelSocket,SocketSet,UdpSocket>`_ + ## + ## .. code-block:: nim + ## # remove two sockets from a socket set + ## # var sset: SocketSet + ## # udpsock: UDPsocket + ## # tcpsock: TCPsocket + ## var numused: int + ## + ## numused = net.udpDelSocket(sset, udpsock) + ## if numused == -1: + ## echo "net.delSocket: ", net.getError() + ## + ## numused = net.tcpDelSocket(sset, tcpsock) + ## if numused == -1: + ## echo "net.delSocket: ", net.getError() + ## # perhaps the socket is not in the set + +proc checkSockets*(set: SocketSet; timeout: uint32): cint {. + importc: "SDLNet_CheckSockets".} + ## This procedure checks to see if data is available for reading on the + ## given set of sockets. + ## + ## `set` The socket set to check. + ## + ## `timeout` The amount of time (in milliseconds). + ## `0` means no waiting. + ## `-1` means to wait over 49 days! (think about it) + ## + ## Check all sockets in the socket set for activity. If a non-zero + ## `timeout` is given then this procedure will wait for activity, + ## or else it will wait for `timeout` milliseconds. + ## + ## `Note:` "activity" also includes disconnections and other errors, + ## which would be determined by a failed read/write attempt. + ## + ## `Return` the number of sockets with activity. + ## `-1` is returned on errors, + ## and you may not get a meaningful error message. + ## `-1` is also returned for an empty set (nothing to check). + ## + ## .. code-block:: nim + ## # wait for up to 1 second for network activity + ## # var sset: SocketSet + ## var numready: int + ## + ## numready = net.checkSockets(sset, 1000) + ## if numready == -1: + ## echo "net.checkSockets: ", net.getError() + ## # most of the time this is a system error + ## else: + ## if numready > 0: + ## echo "There are ", numready, " sockets with activity!" + ## # check all sockets with net.socketReady + ## # and handle the active ones. -# Free a set of sockets allocated by SDL_NetAllocSocketSet() proc freeSocketSet*(set: SocketSet) {.importc: "SDLNet_FreeSocketSet".} + ## Free a set of sockets allocated by `allocSocketSet()`. + ## + ## `set` The socket set to free from memory. + ## + ## Free the socket set from memory. + ## + ## Do not reference the `set` after this call, + ## except to allocate a new one. + ## + ## `Return` nothing, this call always succeeds. + ## + ## .. code-block:: nim + ## # free a socket set + ## # var set: SocketSet + ## + ## net.freeSocketSet(set) + ## set = nil # this helps us remember that this set is not allocated + #********************************************************************* # Error reporting functions #********************************************************************* @@ -273,9 +1129,58 @@ proc getError*(): cstring {.importc: "SDLNet_GetError".} # Warning, some systems have data access alignment restrictions proc write16* (value: uint16, dest: pointer) {.importc: "SDLNet_Write16".} + ## Write a 16-bit value to network packet buffer. + ## + ## `value` The 16bit number to put into the area buffer. + ## + ## `area` The pointer into a data buffer, at which to put the number. + ## + ## Put the 16bit (a short on 32bit systems) value into the data buffer area + ## in network byte order. This helps avoid byte order differences between + ## two systems that are talking over the network. The value can be a signed + ## number, the unsigned parameter type doesn't affect the data. The area + ## pointer need not be at the beginning of a buffer, but must have at least + ## 2 bytes of space left, including the byte currently pointed at. + proc write32* (value: uint32, dest: pointer) {.importc: "SDLNet_Write32".} + ## Write a 32-bit value to network packet buffer. + ## + ## `value` The 32bit number to put into the area buffer. + ## + ## `area` The pointer into a data buffer, at which to put the number. + ## + ## Put the 32bit (a long on 32bit systems) value into the data buffer area + ## in network byte order. This helps avoid byte order differences between + ## two systems that are talking over the network. The value can be a signed + ## number, the unsigned parameter type doesn't affect the data. The area + ## pointer need not be at the beginning of a buffer, but must have at least + ## 4 bytes of space left, including the byte currently pointed at. + proc read16* (src: pointer): uint16 {.importc: "SDLNet_Read16".} + ## Read a 16-bit value from network packet buffer. + ## + ## `area` The pointer into a data buffer, at which to get the number from. + ## + ## Get a 16bit (a short on 32bit systems) value from the data buffer area + ## which is in network byte order. This helps avoid byte order differences + ## between two systems that are talking over the network. The returned value + ## can be a signed number, the unsigned parameter type doesn't affect the + ## data. The area pointer need not be at the beginning of a buffer, but must + ## have at least 2 bytes of space left, including the byte currently pointed + ## at. + proc read32* (src: pointer): uint32 {.importc: "SDLNet_Read32".} + ## Read a 32-bit value from network packet buffer. + ## + ## `area` The pointer into a data buffer, at which to get the number from. + ## + ## Get a 32bit (a long on 32bit systems) value from the data buffer area + ## which is in network byte order. This helps avoid byte order differences + ## between two systems that are talking over the network. The returned value + ## can be a signed number, the unsigned parameter type doesn't affect the + ## data. The area pointer need not be at the beginning of a buffer, but must + ## have at least 4 bytes of space left, including the byte currently pointed + ## at. when not defined(SDL_Static): {.pop.} @@ -293,9 +1198,55 @@ proc tcpDelSocket*(set: SocketSet; sock: TcpSocket): cint {.inline.} = proc udpDelSocket*(set: SocketSet; sock: UDPsocket): cint {.inline.} = delSocket(set, cast[GenericSocket](sock)) - -##define SDLNet_SocketReady(sock) _SDLNet_SocketReady((SDLNet_GenericSocket)(sock)) -#proc _SDLNet_SocketReady*(sock: SDLNet_GenericSocket): cint = -# #return (sock != NULL) && (sock->ready); proc socketReady* (sock: GenericSocket): bool = + ## Check whether a socket has been marked as active. + ## + ## `sock` The socket to check for activity. + ## Both `UDPsocket` and `TCPsocket` can be used with this procedure. + ## + ## This procedure should only be used on a socket in a socket set, + ## and that set has to have had `net.CheckSockets()` called upon it. + ## + ## `Return` non-zero for activity. `0` is returned for no activity. + ## + ## .. code-block:: nim + ## # wait forever for a connection attempt + ## # var sset: SocketSet + ## # var serversock, client: TCPsocket + ## var numready: int + ## + ## numready = net.checkSockets(sset, 1000) + ## if numready == -1: + ## echo "net.checkSockets: ", net.getError() + ## # most of the time this is a system error + ## elif numready > 0: + ## echo "There are ", numready, " sockets with activity!" + ## # check all sockets with net.socketReady + ## # and hanlde the active ones. + ## if net.socketReady(serversock): + ## client = net.tcpAccept(serversock) + ## if client: + ## # play with the client. + ## + ## To just quickly do network handling with no waiting, we do this. + ## + ## .. code-block:: nim + ## # check for, and handle UDP data + ## # var sset: SocketSet + ## # udpsock: UDPsocket + ## # packet: ptr UDPpacket + ## var numready, numpkts: int + ## + ## numready = net.checkSockets(sset, 0) + ## if numready == -1: + ## echo "net.checkSockets: ", net.getError() + ## # most of the time this is a system error + ## elif numready > 0: + ## echo "There are ", numready, " sockets with activity!" + ## # check all sockets with net.socketReady + ## # and handle the active ones. + ## if net.udpRecv(udpsock, addr(packet) + ## if numpkts > 0: + ## # process the packet. + not(sock.isNil) and sock.ready > 0 diff --git a/src/sdl2/private/keycodes.nim b/src/sdl2/private/keycodes.nim index 0ba8d21..26c350c 100644 --- a/src/sdl2/private/keycodes.nim +++ b/src/sdl2/private/keycodes.nim @@ -1,7 +1,15 @@ -## do not import this, it is included in sdl2.nim +# do not import this, it is included in sdl2.nim type Scancode* {.size: sizeof(cint).} = enum + ## The SDL keyboard scancode representation. + ## + ## Values of this type are used to represent keyboard keys, among other + ## places in the ``key.keysym.scancode`` field of the Event structure. + ## + ## The values in this enumeration are based on the USB usage page standard: + ## https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf + SDL_SCANCODE_UNKNOWN = 0, SDL_SCANCODE_A = 4, SDL_SCANCODE_B = 5, SDL_SCANCODE_C = 6, SDL_SCANCODE_D = 7, SDL_SCANCODE_E = 8, SDL_SCANCODE_F = 9, @@ -41,7 +49,7 @@ type SDL_SCANCODE_KP_5 = 93, SDL_SCANCODE_KP_6 = 94, SDL_SCANCODE_KP_7 = 95, SDL_SCANCODE_KP_8 = 96, SDL_SCANCODE_KP_9 = 97, SDL_SCANCODE_KP_0 = 98, SDL_SCANCODE_KP_PERIOD = 99, SDL_SCANCODE_NONUSBACKSLASH = 100, - SDL_SCANCODE_APPLICATION = 101, #*< windows contextual menu, compose + SDL_SCANCODE_APPLICATION = 101, ## windows contextual menu, compose SDL_SCANCODE_POWER = 102, SDL_SCANCODE_KP_EQUALS = 103, SDL_SCANCODE_F13 = 104, SDL_SCANCODE_F14 = 105, SDL_SCANCODE_F15 = 106, SDL_SCANCODE_F16 = 107, @@ -50,7 +58,7 @@ type SDL_SCANCODE_F23 = 114, SDL_SCANCODE_F24 = 115, SDL_SCANCODE_EXECUTE = 116, SDL_SCANCODE_HELP = 117, SDL_SCANCODE_MENU = 118, SDL_SCANCODE_SELECT = 119, - SDL_SCANCODE_STOP = 120, SDL_SCANCODE_AGAIN = 121, #*< redo + SDL_SCANCODE_STOP = 120, SDL_SCANCODE_AGAIN = 121, ## redo SDL_SCANCODE_UNDO = 122, SDL_SCANCODE_CUT = 123, SDL_SCANCODE_COPY = 124, SDL_SCANCODE_PASTE = 125, SDL_SCANCODE_FIND = 126, SDL_SCANCODE_MUTE = 127, SDL_SCANCODE_VOLUMEUP = 128, SDL_SCANCODE_VOLUMEDOWN = 129, @@ -59,15 +67,15 @@ type SDL_SCANCODE_INTERNATIONAL4 = 138, SDL_SCANCODE_INTERNATIONAL5 = 139, SDL_SCANCODE_INTERNATIONAL6 = 140, SDL_SCANCODE_INTERNATIONAL7 = 141, SDL_SCANCODE_INTERNATIONAL8 = 142, SDL_SCANCODE_INTERNATIONAL9 = 143, SDL_SCANCODE_LANG1 = 144, #*< Hangul/English toggle - SDL_SCANCODE_LANG2 = 145, #*< Hanja conversion - SDL_SCANCODE_LANG3 = 146, #*< Katakana - SDL_SCANCODE_LANG4 = 147, #*< Hiragana - SDL_SCANCODE_LANG5 = 148, #*< Zenkaku/Hankaku - SDL_SCANCODE_LANG6 = 149, #*< reserved - SDL_SCANCODE_LANG7 = 150, #*< reserved - SDL_SCANCODE_LANG8 = 151, #*< reserved - SDL_SCANCODE_LANG9 = 152, #*< reserved - SDL_SCANCODE_ALTERASE = 153, #*< Erase-Eaze + SDL_SCANCODE_LANG2 = 145, ## Hanja conversion + SDL_SCANCODE_LANG3 = 146, ## Katakana + SDL_SCANCODE_LANG4 = 147, ## Hiragana + SDL_SCANCODE_LANG5 = 148, ## Zenkaku/Hankaku + SDL_SCANCODE_LANG6 = 149, ## reserved + SDL_SCANCODE_LANG7 = 150, ## reserved + SDL_SCANCODE_LANG8 = 151, ## reserved + SDL_SCANCODE_LANG9 = 152, ## reserved + SDL_SCANCODE_ALTERASE = 153, ## Erase-Eaze SDL_SCANCODE_SYSREQ = 154, SDL_SCANCODE_CANCEL = 155, SDL_SCANCODE_CLEAR = 156, SDL_SCANCODE_PRIOR = 157, SDL_SCANCODE_RETURN2 = 158, SDL_SCANCODE_SEPARATOR = 159, @@ -97,9 +105,9 @@ type SDL_SCANCODE_KP_BINARY = 218, SDL_SCANCODE_KP_OCTAL = 219, SDL_SCANCODE_KP_DECIMAL = 220, SDL_SCANCODE_KP_HEXADECIMAL = 221, SDL_SCANCODE_LCTRL = 224, SDL_SCANCODE_LSHIFT = 225, SDL_SCANCODE_LALT = 226, #*< alt, option - SDL_SCANCODE_LGUI = 227, #*< windows, command (apple), meta + SDL_SCANCODE_LGUI = 227, ## windows, command (apple), meta SDL_SCANCODE_RCTRL = 228, SDL_SCANCODE_RSHIFT = 229, SDL_SCANCODE_RALT = 230, #*< alt gr, option - SDL_SCANCODE_RGUI = 231, #*< windows, command (apple), meta + SDL_SCANCODE_RGUI = 231, ## windows, command (apple), meta SDL_SCANCODE_MODE = 257, SDL_SCANCODE_AUDIONEXT = 258, SDL_SCANCODE_AUDIOPREV = 259, SDL_SCANCODE_AUDIOSTOP = 260, SDL_SCANCODE_AUDIOPLAY = 261, @@ -112,8 +120,8 @@ type SDL_SCANCODE_BRIGHTNESSDOWN = 275, SDL_SCANCODE_BRIGHTNESSUP = 276, SDL_SCANCODE_DISPLAYSWITCH = 277, SDL_SCANCODE_KBDILLUMTOGGLE = 278, SDL_SCANCODE_KBDILLUMDOWN = 279, SDL_SCANCODE_KBDILLUMUP = 280, SDL_SCANCODE_EJECT = 281, SDL_SCANCODE_SLEEP = 282, - SDL_NUM_SCANCODES = 512 #*< not a key, just marks the number of scancodes - # for array bounds + SDL_NUM_SCANCODES = 512 + ## not a key, just marks the number of scancodes for array bounds const SDLK_SCANCODE_MASK = 1 shl 30 template SDL_SCANCODE_TO_KEYCODE(some: ScanCode): untyped = (some.cint or SDLK_SCANCODE_MASK) @@ -181,15 +189,15 @@ const K_o*: cint = 'o'.cint K_p*: cint = 'p'.cint K_q*: cint = 'q'.cint - K_r*: cint = 'r'.cint - K_s*: cint = 's'.cint - K_t*: cint = 't'.cint - K_u*: cint = 'u'.cint - K_v*: cint = 'v'.cint - K_w*: cint = 'w'.cint - K_x*: cint = 'x'.cint - K_y*: cint = 'y'.cint - K_z*: cint = 'z'.cint + K_r*: cint = 'r'.cint + K_s*: cint = 's'.cint + K_t*: cint = 't'.cint + K_u*: cint = 'u'.cint + K_v*: cint = 'v'.cint + K_w*: cint = 'w'.cint + K_x*: cint = 'x'.cint + K_y*: cint = 'y'.cint + K_z*: cint = 'z'.cint K_DELETE*: cint = '\127'.cint K_CAPSLOCK*: cint = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK) diff --git a/src/sdl2/ttf.nim b/src/sdl2/ttf.nim index fbae363..23ee2c0 100644 --- a/src/sdl2/ttf.nim +++ b/src/sdl2/ttf.nim @@ -1,3 +1,10 @@ +## TrueType font rendering library. +## +## **Note:** +## In many places, ttf will say "glyph" when it means "code point." +## Unicode is hard, we learn as we go, and we apologize for adding to the +## confusion. + {.deadCodeElim: on.} when not defined(SDL_Static): @@ -14,54 +21,50 @@ import sdl2 type FontPtr* = ptr object{.pure.} - -# Set up for C function definitions, even when using C++ -# Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL -#/* -##define SDL_TTF_MAJOR_VERSION 2 -##define SDL_TTF_MINOR_VERSION 0 -##define SDL_TTF_PATCHLEVEL 12 -# -# This macro can be used to fill a version structure with the compile-time -# version of the SDL_ttf library. -# -##define SDL_TTF_VERSION(X) \ -#{ \ -# (X)->major = SDL_TTF_MAJOR_VERSION; \ -# (X)->minor = SDL_TTF_MINOR_VERSION; \ -# (X)->patch = SDL_TTF_PATCHLEVEL; \ -#} -# Backwards compatibility -##define TTF_MAJOR_VERSION SDL_TTF_MAJOR_VERSION -##define TTF_MINOR_VERSION SDL_TTF_MINOR_VERSION -#//#define TTF_PATCHLEVEL SDL_TTF_PATCHLEVEL -##define TTF_VERSION(X) SDL_TTF_VERSION(X) + ## The internal structure containing font information when not defined(SDL_Static): {.push callConv:cdecl, dynlib:LibName.} proc ttfLinkedVersion*(): ptr SDL_version {.importc: "TTF_Linked_Version".} + ## This procedure gets the version of the dynamically linked ttf library. + # TODO Add an equivalent of the `TTF_VERSION` macro (version template ?) + # and this comment: + # It should NOT be used to fill a version structure, instead you should + # use the `version()` template. + # ZERO WIDTH NO-BREAKSPACE (Unicode byte order mark) const UNICODE_BOM_NATIVE* = 0x0000FEFF UNICODE_BOM_SWAPPED* = 0x0000FFFE -# This function tells the library whether UNICODE text is generally -# byteswapped. A UNICODE BOM character in a string will override -# this setting for the remainder of that string. -# + proc ttfByteSwappedUnicode*(swapped: cint) {.importc: "TTF_ByteSwappedUNICODE".} + ## This procedure tells the library whether UNICODE text is generally + ## byteswapped. A UNICODE BOM character in a string will override + ## this setting for the remainder of that string. -# Initialize the TTF engine - returns 0 if successful, -1 on error proc ttfInit*(): SDL_Return {.importc: "TTF_Init", discardable.} -# Open a font file and create a font of the specified point size. -# Some .fon fonts will have several sizes embedded in the file, so the -# point size becomes the index of choosing which size. If the value -# is too high, the last indexed size will be the default. + ## Initialize the TTF engine. + ## + ## `Return` `0` if successful, `-1` on error. + proc openFont*(file: cstring; ptsize: cint): FontPtr {.importc: "TTF_OpenFont".} -proc openFontIndex*(file: cstring; ptsize: cint; index: clong): FontPtr {.importc: "TTF_OpenFontIndex".} -proc openFontRW*(src: ptr RWops; freesrc: cint; ptsize: cint): FontPtr {.importc: "TTF_OpenFontRW".} + ## Open a font file and create a font of the specified point size. + ## Some .fon fonts will have several sizes embedded in the file, so the + ## point size becomes the index of choosing which size. If the value + ## is too high, the last indexed size will be the default. + ## + ## **See also:** + ## * `openFontIndex proc<#openFontIndex,cstring,cint,clong>`_ + ## * `openFontRW proc<#openFontRW,ptr.RWops,cint,cint>`_ + ## * `openFontIndexRW proc<#openFontIndexRW,ptr.RWops,cint,cint,clong>`_ + +proc openFontIndex*(file: cstring; ptsize: cint; index: clong): FontPtr {. + importc: "TTF_OpenFontIndex".} +proc openFontRW*(src: ptr RWops; freesrc: cint; ptsize: cint): FontPtr {. + importc: "TTF_OpenFontRW".} proc openFontIndexRW*(src: ptr RWops; freesrc: cint; ptsize: cint; - index: clong): FontPtr {.importc: "TTF_OpenFontIndexRW".} + index: clong): FontPtr {.importc: "TTF_OpenFontIndexRW".} # Set and retrieve the font style const TTF_STYLE_NORMAL* = 0x00000000 @@ -69,6 +72,7 @@ const TTF_STYLE_ITALIC* = 0x00000002 TTF_STYLE_UNDERLINE* = 0x00000004 TTF_STYLE_STRIKETHROUGH* = 0x00000008 + proc getFontStyle*(font: FontPtr): cint {.importc: "TTF_GetFontStyle".} proc setFontStyle*(font: FontPtr; style: cint) {.importc: "TTF_SetFontStyle".} proc getFontOutline*(font: FontPtr): cint {.importc: "TTF_GetFontOutline".} @@ -81,40 +85,62 @@ const TTF_HINTING_MONO* = 2 TTF_HINTING_NONE* = 3 proc getFontHinting*(font: FontPtr): cint {.importc: "TTF_GetFontHinting".} + proc setFontHinting*(font: FontPtr; hinting: cint) {.importc: "TTF_SetFontHinting".} -# Get the total height of the font - usually equal to point size + proc fontHeight*(font: FontPtr): cint {.importc: "TTF_FontHeight".} -# Get the offset from the baseline to the top of the font -# This is a positive value, relative to the baseline. -# + ## Get the total height of the font - usually equal to point size. + proc fontAscent*(font: FontPtr): cint {.importc: "TTF_FontAscent".} -# Get the offset from the baseline to the bottom of the font -# This is a negative value, relative to the baseline. -# + ## Get the offset from the baseline to the top of the font. + ## + ## This is a positive value, relative to the baseline. + proc fontDescent*(font: FontPtr): cint {.importc: "TTF_FontDescent".} -# Get the recommended spacing between lines of text for this font + ## Get the offset from the baseline to the bottom of the font. + ## + ## This is a negative value, relative to the baseline. + proc fontLineSkip*(font: FontPtr): cint {.importc: "TTF_FontLineSkip".} -# Get/Set whether or not kerning is allowed for this font + ## Get the recommended spacing between lines of text for this font. + proc getFontKerning*(font: FontPtr): cint {.importc: "TTF_GetFontKerning".} + ## Get whether or not kerning is allowed for this font. + proc setFontKerning*(font: FontPtr; allowed: cint) {.importc: "TTF_SetFontKerning".} -# Get the number of faces of the font + ## Set whether or not kerning is allowed for this font. + proc fontFaces*(font: FontPtr): clong {.importc: "TTF_FontFaces".} -# Get the font face attributes, if any -proc fontFaceIsFixedWidth*(font: FontPtr): cint {.importc: "TTF_FontFaceIsFixedWidth".} + ## Get the number of faces of the font. + +proc fontFaceIsFixedWidth*(font: FontPtr): cint {. + importc: "TTF_FontFaceIsFixedWidth".} + ## Get the font face attributes, if any. + proc fontFaceFamilyName*(font: FontPtr): cstring {.importc: "TTF_FontFaceFamilyName".} proc fontFaceStyleName*(font: FontPtr): cstring {.importc: "TTF_FontFaceStyleName".} -# Check wether a glyph is provided by the font or not -proc glyphIsProvided*(font: FontPtr; ch: uint16): cint {.importc: "TTF_GlyphIsProvided".} -# Get the metrics (dimensions) of a glyph -# To understand what these metrics mean, here is a useful link: -# http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html -# + +proc glyphIsProvided*(font: FontPtr; ch: uint16): cint {. + importc: "TTF_GlyphIsProvided".} + ## Check wether a glyph is provided by the font or not. + proc glyphMetrics*(font: FontPtr; ch: uint16; minx: ptr cint; maxx: ptr cint; miny: ptr cint; maxy: ptr cint; advance: ptr cint): cint {.importc: "TTF_GlyphMetrics".} -# Get the dimensions of a rendered string of text + ## Get the metrics (dimensions) of a glyph. + ## + ## To understand what these metrics mean, here is a useful link: + ## + ## http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html + proc sizeText*(font: FontPtr; text: cstring; w: ptr cint; h: ptr cint): cint{. importc: "TTF_SizeText".} + ## Get the dimensions of a rendered string of text. + ## + ## **See also:** + ## * `sizeUtf8 proc<#sizeUtf8,FontPtr,cstring,ptr.cint,ptr.cint>`_ + ## * `sizeUnicode proc<#sizeUnicode,FontPtr,ptr.uint16,ptr.cint,ptr.cint>`_ + proc sizeUtf8*(font: FontPtr; text: cstring; w: ptr cint; h: ptr cint): cint{. importc: "TTF_SizeUTF8".} proc sizeUnicode*(font: FontPtr; text: ptr uint16; w, h: ptr cint): cint{. @@ -127,89 +153,122 @@ proc sizeUnicode*(font: FontPtr; text: ptr uint16; w, h: ptr cint): cint{. # proc renderTextSolid*(font: FontPtr; text: cstring; fg: Color): SurfacePtr{. importc: "TTF_RenderText_Solid".} + ## Create an 8-bit palettized surface and render the given text at + ## fast quality with the given font and color. The 0 pixel is the + ## colorkey, giving a transparent background, and the 1 pixel is set + ## to the text color. + ## + ## `Return` the new surface, or `nil` if there was an error. + ## + ## **See also:** + ## * `renderUtf8Solid proc<#renderUtf8Solid,FontPtr,cstring,Color>`_ + ## * `renderUnicodeSolid proc<#renderUnicodeSolid,FontPtr,ptr.uint16,Color>`_ + proc renderUtf8Solid*(font: FontPtr; text: cstring; fg: Color): SurfacePtr{. importc: "TTF_RenderUTF8_Solid".} proc renderUnicodeSolid*(font: FontPtr; text: ptr uint16; fg: Color): SurfacePtr {.importc: "TTF_RenderUNICODE_Solid".} -# Create an 8-bit palettized surface and render the given glyph at -# fast quality with the given font and color. The 0 pixel is the -# colorkey, giving a transparent background, and the 1 pixel is set -# to the text color. The glyph is rendered without any padding or -# centering in the X direction, and aligned normally in the Y direction. -# This function returns the new surface, or NULL if there was an error. -# + proc renderGlyphSolid*(font: FontPtr; ch: uint16; fg: Color): SurfacePtr {. importc: "TTF_RenderGlyph_Solid".} + ## Create an 8-bit palettized surface and render the given glyph at + ## fast quality with the given font and color. The 0 pixel is the + ## colorkey, giving a transparent background, and the 1 pixel is set + ## to the text color. + ## + ## The glyph is rendered without any padding or centering in the X + ## direction, and aligned normally in the Y direction. + ## + ## `Return` the new surface, or `nil` if there was an error. + +proc renderTextShaded*(font: FontPtr; text: cstring; + fg, bg: Color): SurfacePtr {.importc: "TTF_RenderText_Shaded".} + ## Create an 8-bit palettized surface and render the given text at + ## high quality with the given font and colors. The 0 pixel is background, + ## while other pixels have varying degrees of the foreground color. + ## + ## `Return` the new surface, or `nil` if there was an error. + ## + ## **See also:** + ## * `renderUtf8Shaded proc<#renderUtf8Shaded,FontPtr,cstring,Color,Color>`_ + ## * `renderUnicodeShaded proc<#renderUnicodeShaded,FontPtr,ptr.uint16,Color,Color>`_ -proc renderTextShaded*(font: FontPtr; text: cstring; fg, bg: Color): SurfacePtr {. - importc: "TTF_RenderText_Shaded".} proc renderUtf8Shaded*(font: FontPtr; text: cstring; fg, bg: Color): SurfacePtr {. importc: "TTF_RenderUTF8_Shaded".} proc renderUnicodeShaded*(font: FontPtr; text: ptr uint16; fg, bg: Color): SurfacePtr {.importc: "TTF_RenderUNICODE_Shaded".} -# Create an 8-bit palettized surface and render the given glyph at -# high quality with the given font and colors. The 0 pixel is background, -# while other pixels have varying degrees of the foreground color. -# The glyph is rendered without any padding or centering in the X -# direction, and aligned normally in the Y direction. -# This function returns the new surface, or NULL if there was an error. -# + proc renderGlyphShaded*(font: FontPtr; ch: uint16; fg, bg: Color): SurfacePtr {. importc: "TTF_RenderGlyph_Shaded".} -# Create a 32-bit ARGB surface and render the given text at high quality, -# using alpha blending to dither the font with the given color. -# This function returns the new surface, or NULL if there was an error. -# + ## Create an 8-bit palettized surface and render the given glyph at + ## high quality with the given font and colors. The 0 pixel is background, + ## while other pixels have varying degrees of the foreground color. + ## + ## The glyph is rendered without any padding or centering in the X + ## direction, and aligned normally in the Y direction. + ## + ## `Return` the new surface, or `nil` if there was an error. + proc renderTextBlended*(font: FontPtr; text: cstring; fg: Color): SurfacePtr {. importc: "TTF_RenderText_Blended".} + ## Create a 32-bit ARGB surface and render the given text at high quality, + ## using alpha blending to dither the font with the given color. + ## + ## `Return` the new surface, or `nil` if there was an error. + ## + ## **See also:** + ## * `renderUtf8Blended proc<#renderUtf8Blended,FontPtr,cstring,Color>`_ + ## * `renderUnicodeBlended proc<#renderUnicodeBlended,FontPtr,ptr.uint16,Color>`_ + proc renderUtf8Blended*(font: FontPtr; text: cstring; fg: Color): SurfacePtr {. importc: "TTF_RenderUTF8_Blended".} proc renderUnicodeBlended*(font: FontPtr; text: ptr uint16; fg: Color): SurfacePtr {.importc: "TTF_RenderUNICODE_Blended".} -# Create a 32-bit ARGB surface and render the given text at high quality, -# using alpha blending to dither the font with the given color. -# Text is wrapped to multiple lines on line endings and on word boundaries -# if it extends beyond wrapLength in pixels. -# This function returns the new surface, or NULL if there was an error. -# -proc renderTextBlendedWrapped*(font: FontPtr; text: cstring; fg: Color; wrapLength: uint32): - SurfacePtr {.importc: "TTF_RenderText_Blended_Wrapped".} + +proc renderTextBlendedWrapped*(font: FontPtr; text: cstring; fg: Color; + wrapLength: uint32): SurfacePtr {.importc: "TTF_RenderText_Blended_Wrapped".} + ## Create a 32-bit ARGB surface and render the given text at high quality, + ## using alpha blending to dither the font with the given color. + ## Text is wrapped to multiple lines on line endings and on word boundaries + ## if it extends beyond wrapLength in pixels. + ## + ## `Return` the new surface, or `nil` if there was an error. + ## + ## **See also:** + ## * `renderUtf8BlendedWrapped proc<#renderUtf8BlendedWrapped,FontPtr,cstring,Color,uint32>`_ + ## * `renderUnicodeBlendedWrapped proc<#renderUnicodeBlendedWrapped,FontPtr,ptr.uint16,Color,uint32>`_ + proc renderUtf8BlendedWrapped*(font: FontPtr; text: cstring; fg: Color; wrapLength: uint32): SurfacePtr {.importc: "TTF_RenderUTF8_Blended_Wrapped".} proc renderUnicodeBlendedWrapped*(font: FontPtr; text: ptr uint16; fg: Color; wrapLength: uint32): SurfacePtr {.importc: "TTF_RenderUNICODE_Blended_Wrapped".} -# Create a 32-bit ARGB surface and render the given glyph at high quality, -# using alpha blending to dither the font with the given color. -# The glyph is rendered without any padding or centering in the X -# direction, and aligned normally in the Y direction. -# This function returns the new surface, or NULL if there was an error. -# + proc renderGlyphBlended*(font: FontPtr; ch: uint16; fg: Color): SurfacePtr {. importc: "TTF_RenderGlyph_Blended".} + ## Create a 32-bit ARGB surface and render the given glyph at high quality, + ## using alpha blending to dither the font with the given color. + ## The glyph is rendered without any padding or centering in the X + ## direction, and aligned normally in the Y direction. + ## + ## `Return` the new surface, or `nil` if there was an error. -# -#/* Close an opened font file proc close*(font: FontPtr) {.importc: "TTF_CloseFont".} -# De-initialize the TTF engine + ## Close an opened font file. + proc ttfQuit*() {.importc: "TTF_Quit".} -# Check if the TTF engine is initialized + ## De-initialize the TTF engine. + proc ttfWasInit*(): bool {.importc: "TTF_WasInit".} -# Get the kerning size of two glyphs + ## Check if the TTF engine is initialized. + proc getFontKerningSize*(font: FontPtr; prev_index, indx: cint): cint {. importc: "TTF_GetFontKerningSize".} + ## Get the kerning size of two glyphs indices. when not defined(SDL_Static): {.pop.} -# For compatibility with previous versions, here are the old functions -##define TTF_RenderText(font, text, fg, bg) \ -# TTF_RenderText_Shaded(font, text, fg, bg) -##define TTF_RenderUTF8(font, text, fg, bg) \ -# TTF_RenderUTF8_Shaded(font, text, fg, bg) -##define TTF_RenderUNICODE(font, text, fg, bg) \ -# TTF_RenderUNICODE_Shaded(font, text, fg, bg) - -proc renderText*(font: FontPtr; text: cstring; - fg, bg: Color): SurfacePtr = renderTextShaded(font, text, fg, bg) +proc renderText*(font: FontPtr; text: cstring; fg, bg: Color): SurfacePtr = + renderTextShaded(font, text, fg, bg)