added manyloc test suite; --path now relative to project dir if not absolute
This commit is contained in:
parent
4f09794be9
commit
75b508032b
51 changed files with 9286 additions and 5 deletions
1516
tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
Normal file
1516
tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
Normal file
File diff suppressed because it is too large
Load diff
614
tests/manyloc/keineschweine/dependencies/enet/enet.nim
Normal file
614
tests/manyloc/keineschweine/dependencies/enet/enet.nim
Normal file
|
|
@ -0,0 +1,614 @@
|
|||
discard """Copyright (c) 2002-2012 Lee Salzman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
"""
|
||||
when defined(Linux):
|
||||
const Lib = "libenet.so.1(|.0.3)"
|
||||
else:
|
||||
{.error: "Your platform has not been accounted for."}
|
||||
{.deadCodeElim: ON.}
|
||||
const
|
||||
ENET_VERSION_MAJOR* = 1
|
||||
ENET_VERSION_MINOR* = 3
|
||||
ENET_VERSION_PATCH* = 3
|
||||
template ENET_VERSION_CREATE(major, minor, patch: expr): expr =
|
||||
(((major) shl 16) or ((minor) shl 8) or (patch))
|
||||
|
||||
const
|
||||
ENET_VERSION* = ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR,
|
||||
ENET_VERSION_PATCH)
|
||||
type
|
||||
TVersion* = cuint
|
||||
TSocketType*{.size: sizeof(cint).} = enum
|
||||
ENET_SOCKET_TYPE_STREAM = 1, ENET_SOCKET_TYPE_DATAGRAM = 2
|
||||
TSocketWait*{.size: sizeof(cint).} = enum
|
||||
ENET_SOCKET_WAIT_NONE = 0, ENET_SOCKET_WAIT_SEND = (1 shl 0),
|
||||
ENET_SOCKET_WAIT_RECEIVE = (1 shl 1)
|
||||
TSocketOption*{.size: sizeof(cint).} = enum
|
||||
ENET_SOCKOPT_NONBLOCK = 1, ENET_SOCKOPT_BROADCAST = 2,
|
||||
ENET_SOCKOPT_RCVBUF = 3, ENET_SOCKOPT_SNDBUF = 4,
|
||||
ENET_SOCKOPT_REUSEADDR = 5
|
||||
const
|
||||
ENET_HOST_ANY* = 0
|
||||
ENET_HOST_BROADCAST* = 0xFFFFFFFF
|
||||
ENET_PORT_ANY* = 0
|
||||
|
||||
ENET_PROTOCOL_MINIMUM_MTU* = 576
|
||||
ENET_PROTOCOL_MAXIMUM_MTU* = 4096
|
||||
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS* = 32
|
||||
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE* = 4096
|
||||
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE* = 32768
|
||||
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT* = 1
|
||||
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT* = 255
|
||||
ENET_PROTOCOL_MAXIMUM_PEER_ID* = 0x00000FFF
|
||||
type
|
||||
PAddress* = ptr TAddress
|
||||
TAddress*{.pure, final.} = object
|
||||
host*: cuint
|
||||
port*: cushort
|
||||
|
||||
TPacketFlag*{.size: sizeof(cint).} = enum
|
||||
FlagReliable = (1 shl 0),
|
||||
FlagUnsequenced = (1 shl 1),
|
||||
NoAllocate = (1 shl 2),
|
||||
UnreliableFragment = (1 shl 3)
|
||||
|
||||
TENetListNode*{.pure, final.} = object
|
||||
next*: ptr T_ENetListNode
|
||||
previous*: ptr T_ENetListNode
|
||||
|
||||
PENetListIterator* = ptr TENetListNode
|
||||
TENetList*{.pure, final.} = object
|
||||
sentinel*: TENetListNode
|
||||
|
||||
T_ENetPacket*{.pure, final.} = object
|
||||
TPacketFreeCallback* = proc (a2: ptr T_ENetPacket){.cdecl.}
|
||||
|
||||
PPacket* = ptr TPacket
|
||||
TPacket*{.pure, final.} = object
|
||||
referenceCount: csize
|
||||
flags*: cint
|
||||
data*: cstring#ptr cuchar
|
||||
dataLength*: csize
|
||||
freeCallback*: TPacketFreeCallback
|
||||
|
||||
PAcknowledgement* = ptr TAcknowledgement
|
||||
TAcknowledgement*{.pure, final.} = object
|
||||
acknowledgementList*: TEnetListNode
|
||||
sentTime*: cuint
|
||||
command*: TEnetProtocol
|
||||
|
||||
POutgoingCommand* = ptr TOutgoingCommand
|
||||
TOutgoingCommand*{.pure, final.} = object
|
||||
outgoingCommandList*: TEnetListNode
|
||||
reliableSequenceNumber*: cushort
|
||||
unreliableSequenceNumber*: cushort
|
||||
sentTime*: cuint
|
||||
roundTripTimeout*: cuint
|
||||
roundTripTimeoutLimit*: cuint
|
||||
fragmentOffset*: cuint
|
||||
fragmentLength*: cushort
|
||||
sendAttempts*: cushort
|
||||
command*: TEnetProtocol
|
||||
packet*: PPacket
|
||||
|
||||
PIncomingCommand* = ptr TIncomingCommand
|
||||
TIncomingCommand*{.pure, final.} = object
|
||||
incomingCommandList*: TEnetListNode
|
||||
reliableSequenceNumber*: cushort
|
||||
unreliableSequenceNumber*: cushort
|
||||
command*: TEnetProtocol
|
||||
fragmentCount*: cuint
|
||||
fragmentsRemaining*: cuint
|
||||
fragments*: ptr cuint
|
||||
packet*: ptr TPacket
|
||||
|
||||
TPeerState*{.size: sizeof(cint).} = enum
|
||||
ENET_PEER_STATE_DISCONNECTED = 0, ENET_PEER_STATE_CONNECTING = 1,
|
||||
ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
|
||||
ENET_PEER_STATE_CONNECTION_PENDING = 3,
|
||||
ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, ENET_PEER_STATE_CONNECTED = 5,
|
||||
ENET_PEER_STATE_DISCONNECT_LATER = 6, ENET_PEER_STATE_DISCONNECTING = 7,
|
||||
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, ENET_PEER_STATE_ZOMBIE = 9
|
||||
|
||||
TENetProtocolCommand*{.size: sizeof(cint).} = enum
|
||||
ENET_PROTOCOL_COMMAND_NONE = 0, ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
|
||||
ENET_PROTOCOL_COMMAND_CONNECT = 2,
|
||||
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
|
||||
ENET_PROTOCOL_COMMAND_DISCONNECT = 4, ENET_PROTOCOL_COMMAND_PING = 5,
|
||||
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
|
||||
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
|
||||
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
|
||||
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
|
||||
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
|
||||
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
|
||||
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
|
||||
ENET_PROTOCOL_COMMAND_COUNT = 13, ENET_PROTOCOL_COMMAND_MASK = 0x0000000F
|
||||
TENetProtocolFlag*{.size: sizeof(cint).} = enum
|
||||
ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12,
|
||||
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 shl 6),
|
||||
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 shl 7),
|
||||
ENET_PROTOCOL_HEADER_SESSION_MASK = (3 shl 12),
|
||||
ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 shl 14),
|
||||
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 shl 15),
|
||||
ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED.cint or
|
||||
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME.cint
|
||||
|
||||
TENetProtocolHeader*{.pure, final.} = object
|
||||
peerID*: cushort
|
||||
sentTime*: cushort
|
||||
|
||||
TENetProtocolCommandHeader*{.pure, final.} = object
|
||||
command*: cuchar
|
||||
channelID*: cuchar
|
||||
reliableSequenceNumber*: cushort
|
||||
|
||||
TENetProtocolAcknowledge*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
receivedReliableSequenceNumber*: cushort
|
||||
receivedSentTime*: cushort
|
||||
|
||||
TENetProtocolConnect*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
outgoingPeerID*: cushort
|
||||
incomingSessionID*: cuchar
|
||||
outgoingSessionID*: cuchar
|
||||
mtu*: cuint
|
||||
windowSize*: cuint
|
||||
channelCount*: cuint
|
||||
incomingBandwidth*: cuint
|
||||
outgoingBandwidth*: cuint
|
||||
packetThrottleInterval*: cuint
|
||||
packetThrottleAcceleration*: cuint
|
||||
packetThrottleDeceleration*: cuint
|
||||
connectID*: cuint
|
||||
data*: cuint
|
||||
|
||||
TENetProtocolVerifyConnect*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
outgoingPeerID*: cushort
|
||||
incomingSessionID*: cuchar
|
||||
outgoingSessionID*: cuchar
|
||||
mtu*: cuint
|
||||
windowSize*: cuint
|
||||
channelCount*: cuint
|
||||
incomingBandwidth*: cuint
|
||||
outgoingBandwidth*: cuint
|
||||
packetThrottleInterval*: cuint
|
||||
packetThrottleAcceleration*: cuint
|
||||
packetThrottleDeceleration*: cuint
|
||||
connectID*: cuint
|
||||
|
||||
TENetProtocolBandwidthLimit*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
incomingBandwidth*: cuint
|
||||
outgoingBandwidth*: cuint
|
||||
|
||||
TENetProtocolThrottleConfigure*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
packetThrottleInterval*: cuint
|
||||
packetThrottleAcceleration*: cuint
|
||||
packetThrottleDeceleration*: cuint
|
||||
|
||||
TENetProtocolDisconnect*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
data*: cuint
|
||||
|
||||
TENetProtocolPing*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
|
||||
TENetProtocolSendReliable*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
dataLength*: cushort
|
||||
|
||||
TENetProtocolSendUnreliable*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
unreliableSequenceNumber*: cushort
|
||||
dataLength*: cushort
|
||||
|
||||
TENetProtocolSendUnsequenced*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
unsequencedGroup*: cushort
|
||||
dataLength*: cushort
|
||||
|
||||
TENetProtocolSendFragment*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
startSequenceNumber*: cushort
|
||||
dataLength*: cushort
|
||||
fragmentCount*: cuint
|
||||
fragmentNumber*: cuint
|
||||
totalLength*: cuint
|
||||
fragmentOffset*: cuint
|
||||
|
||||
## this is incomplete; need helper templates or something
|
||||
## ENetProtocol
|
||||
TENetProtocol*{.pure, final.} = object
|
||||
header*: TENetProtocolCommandHeader
|
||||
const
|
||||
ENET_BUFFER_MAXIMUM* = (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
|
||||
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024
|
||||
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024
|
||||
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000
|
||||
ENET_HOST_DEFAULT_MTU = 1400
|
||||
|
||||
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500
|
||||
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32
|
||||
ENET_PEER_PACKET_THROTTLE_SCALE = 32
|
||||
ENET_PEER_PACKET_THROTTLE_COUNTER = 7
|
||||
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2
|
||||
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2
|
||||
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000
|
||||
ENET_PEER_PACKET_LOSS_SCALE = (1 shl 16)
|
||||
ENET_PEER_PACKET_LOSS_INTERVAL = 10000
|
||||
ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024
|
||||
ENET_PEER_TIMEOUT_LIMIT = 32
|
||||
ENET_PEER_TIMEOUT_MINIMUM = 5000
|
||||
ENET_PEER_TIMEOUT_MAXIMUM = 30000
|
||||
ENET_PEER_PING_INTERVAL = 500
|
||||
ENET_PEER_UNSEQUENCED_WINDOWS = 64
|
||||
ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024
|
||||
ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32
|
||||
ENET_PEER_RELIABLE_WINDOWS = 16
|
||||
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000
|
||||
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
|
||||
|
||||
when defined(Linux):
|
||||
import posix
|
||||
const
|
||||
ENET_SOCKET_NULL*: cint = -1
|
||||
type
|
||||
TENetSocket* = cint
|
||||
PEnetBuffer* = ptr object
|
||||
TENetBuffer*{.pure, final.} = object
|
||||
data*: pointer
|
||||
dataLength*: csize
|
||||
TENetSocketSet* = Tfd_set
|
||||
## see if these are different on win32, if not then get rid of these
|
||||
template ENET_HOST_TO_NET_16*(value: expr): expr =
|
||||
(htons(value))
|
||||
template ENET_HOST_TO_NET_32*(value: expr): expr =
|
||||
(htonl(value))
|
||||
template ENET_NET_TO_HOST_16*(value: expr): expr =
|
||||
(ntohs(value))
|
||||
template ENET_NET_TO_HOST_32*(value: expr): expr =
|
||||
(ntohl(value))
|
||||
|
||||
template ENET_SOCKETSET_EMPTY*(sockset: expr): expr =
|
||||
FD_ZERO(addr((sockset)))
|
||||
template ENET_SOCKETSET_ADD*(sockset, socket: expr): expr =
|
||||
FD_SET(socket, addr((sockset)))
|
||||
template ENET_SOCKETSET_REMOVE*(sockset, socket: expr): expr =
|
||||
FD_CLEAR(socket, addr((sockset)))
|
||||
template ENET_SOCKETSET_CHECK*(sockset, socket: expr): expr =
|
||||
FD_ISSET(socket, addr((sockset)))
|
||||
|
||||
when defined(Windows):
|
||||
## put the content of win32.h in here
|
||||
|
||||
|
||||
type
|
||||
PChannel* = ptr TChannel
|
||||
TChannel*{.pure, final.} = object
|
||||
outgoingReliableSequenceNumber*: cushort
|
||||
outgoingUnreliableSequenceNumber*: cushort
|
||||
usedReliableWindows*: cushort
|
||||
reliableWindows*: array[0..ENET_PEER_RELIABLE_WINDOWS - 1, cushort]
|
||||
incomingReliableSequenceNumber*: cushort
|
||||
incomingUnreliableSequenceNumber*: cushort
|
||||
incomingReliableCommands*: TENetList
|
||||
incomingUnreliableCommands*: TENetList
|
||||
|
||||
PPeer* = ptr TPeer
|
||||
TPeer*{.pure, final.} = object
|
||||
dispatchList*: TEnetListNode
|
||||
host*: ptr THost
|
||||
outgoingPeerID*: cushort
|
||||
incomingPeerID*: cushort
|
||||
connectID*: cuint
|
||||
outgoingSessionID*: cuchar
|
||||
incomingSessionID*: cuchar
|
||||
address*: TAddress
|
||||
data*: pointer
|
||||
state*: TPeerState
|
||||
channels*: PChannel
|
||||
channelCount*: csize
|
||||
incomingBandwidth*: cuint
|
||||
outgoingBandwidth*: cuint
|
||||
incomingBandwidthThrottleEpoch*: cuint
|
||||
outgoingBandwidthThrottleEpoch*: cuint
|
||||
incomingDataTotal*: cuint
|
||||
outgoingDataTotal*: cuint
|
||||
lastSendTime*: cuint
|
||||
lastReceiveTime*: cuint
|
||||
nextTimeout*: cuint
|
||||
earliestTimeout*: cuint
|
||||
packetLossEpoch*: cuint
|
||||
packetsSent*: cuint
|
||||
packetsLost*: cuint
|
||||
packetLoss*: cuint
|
||||
packetLossVariance*: cuint
|
||||
packetThrottle*: cuint
|
||||
packetThrottleLimit*: cuint
|
||||
packetThrottleCounter*: cuint
|
||||
packetThrottleEpoch*: cuint
|
||||
packetThrottleAcceleration*: cuint
|
||||
packetThrottleDeceleration*: cuint
|
||||
packetThrottleInterval*: cuint
|
||||
lastRoundTripTime*: cuint
|
||||
lowestRoundTripTime*: cuint
|
||||
lastRoundTripTimeVariance*: cuint
|
||||
highestRoundTripTimeVariance*: cuint
|
||||
roundTripTime*: cuint
|
||||
roundTripTimeVariance*: cuint
|
||||
mtu*: cuint
|
||||
windowSize*: cuint
|
||||
reliableDataInTransit*: cuint
|
||||
outgoingReliableSequenceNumber*: cushort
|
||||
acknowledgements*: TENetList
|
||||
sentReliableCommands*: TENetList
|
||||
sentUnreliableCommands*: TENetList
|
||||
outgoingReliableCommands*: TENetList
|
||||
outgoingUnreliableCommands*: TENetList
|
||||
dispatchedCommands*: TENetList
|
||||
needsDispatch*: cint
|
||||
incomingUnsequencedGroup*: cushort
|
||||
outgoingUnsequencedGroup*: cushort
|
||||
unsequencedWindow*: array[0..ENET_PEER_UNSEQUENCED_WINDOW_SIZE div 32 - 1,
|
||||
cuint]
|
||||
eventData*: cuint
|
||||
|
||||
PCompressor* = ptr TCompressor
|
||||
TCompressor*{.pure, final.} = object
|
||||
context*: pointer
|
||||
compress*: proc (context: pointer; inBuffers: ptr TEnetBuffer;
|
||||
inBufferCount: csize; inLimit: csize;
|
||||
outData: ptr cuchar; outLimit: csize): csize{.cdecl.}
|
||||
decompress*: proc (context: pointer; inData: ptr cuchar; inLimit: csize;
|
||||
outData: ptr cuchar; outLimit: csize): csize{.cdecl.}
|
||||
destroy*: proc (context: pointer){.cdecl.}
|
||||
|
||||
TChecksumCallback* = proc (buffers: ptr TEnetBuffer; bufferCount: csize): cuint{.
|
||||
cdecl.}
|
||||
|
||||
PHost* = ptr THost
|
||||
THost*{.pure, final.} = object
|
||||
socket*: TEnetSocket
|
||||
address*: TAddress
|
||||
incomingBandwidth*: cuint
|
||||
outgoingBandwidth*: cuint
|
||||
bandwidthThrottleEpoch*: cuint
|
||||
mtu*: cuint
|
||||
randomSeed*: cuint
|
||||
recalculateBandwidthLimits*: cint
|
||||
peers*: ptr TPeer
|
||||
peerCount*: csize
|
||||
channelLimit*: csize
|
||||
serviceTime*: cuint
|
||||
dispatchQueue*: TEnetList
|
||||
continueSending*: cint
|
||||
packetSize*: csize
|
||||
headerFlags*: cushort
|
||||
commands*: array[0..ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS - 1,
|
||||
TEnetProtocol]
|
||||
commandCount*: csize
|
||||
buffers*: array[0..ENET_BUFFER_MAXIMUM - 1, TEnetBuffer]
|
||||
bufferCount*: csize
|
||||
checksum*: TChecksumCallback
|
||||
compressor*: TCompressor
|
||||
packetData*: array[0..ENET_PROTOCOL_MAXIMUM_MTU - 1,
|
||||
array[0..2 - 1, cuchar]]
|
||||
receivedAddress*: TAddress
|
||||
receivedData*: ptr cuchar
|
||||
receivedDataLength*: csize
|
||||
totalSentData*: cuint
|
||||
totalSentPackets*: cuint
|
||||
totalReceivedData*: cuint
|
||||
totalReceivedPackets*: cuint
|
||||
|
||||
TEventType*{.size: sizeof(cint).} = enum
|
||||
EvtNone = 0, EvtConnect = 1,
|
||||
EvtDisconnect = 2, EvtReceive = 3
|
||||
PEvent* = ptr TEvent
|
||||
TEvent*{.pure, final.} = object
|
||||
kind*: TEventType
|
||||
peer*: ptr TPeer
|
||||
channelID*: cuchar
|
||||
data*: cuint
|
||||
packet*: ptr TPacket
|
||||
|
||||
TENetCallbacks*{.pure, final.} = object
|
||||
malloc*: proc (size: csize): pointer{.cdecl.}
|
||||
free*: proc (memory: pointer){.cdecl.}
|
||||
no_memory*: proc (){.cdecl.}
|
||||
|
||||
{.push callConv:cdecl.}
|
||||
proc enet_malloc*(a2: csize): pointer{.
|
||||
importc: "enet_malloc", dynlib: Lib.}
|
||||
proc enet_free*(a2: pointer){.
|
||||
importc: "enet_free", dynlib: Lib.}
|
||||
|
||||
proc enetInit*(): cint{.
|
||||
importc: "enet_initialize", dynlib: Lib.}
|
||||
proc enetInit*(version: TVersion; inits: ptr TENetCallbacks): cint{.
|
||||
importc: "enet_initialize_with_callbacks", dynlib: Lib.}
|
||||
proc enetDeinit*(){.
|
||||
importc: "enet_deinitialize", dynlib: Lib.}
|
||||
proc enet_time_get*(): cuint{.
|
||||
importc: "enet_time_get", dynlib: Lib.}
|
||||
proc enet_time_set*(a2: cuint){.
|
||||
importc: "enet_time_set", dynlib: Lib.}
|
||||
|
||||
#enet docs are pretty lacking, i'm not sure what the names of these arguments should be
|
||||
proc createSocket*(kind: TSocketType): TEnetSocket{.
|
||||
importc: "enet_socket_create", dynlib: Lib.}
|
||||
proc bindTo*(socket: TEnetSocket; address: var TAddress): cint{.
|
||||
importc: "enet_socket_bind", dynlib: Lib.}
|
||||
proc bindTo*(socket: TEnetSocket; address: ptr TAddress): cint{.
|
||||
importc: "enet_socket_bind", dynlib: Lib.}
|
||||
proc listen*(socket: TEnetSocket; a3: cint): cint{.
|
||||
importc: "enet_socket_listen", dynlib: Lib.}
|
||||
proc accept*(socket: TEnetSocket; address: var TAddress): TEnetSocket{.
|
||||
importc: "enet_socket_accept", dynlib: Lib.}
|
||||
proc accept*(socket: TEnetSocket; address: ptr TAddress): TEnetSocket{.
|
||||
importc: "enet_socket_accept", dynlib: Lib.}
|
||||
proc connect*(socket: TEnetSocket; address: var TAddress): cint{.
|
||||
importc: "enet_socket_connect", dynlib: Lib.}
|
||||
proc connect*(socket: TEnetSocket; address: ptr TAddress): cint{.
|
||||
importc: "enet_socket_connect", dynlib: Lib.}
|
||||
proc send*(socket: TEnetSocket; address: var TAddress; buffer: ptr TEnetBuffer; size: csize): cint{.
|
||||
importc: "enet_socket_send", dynlib: Lib.}
|
||||
proc send*(socket: TEnetSocket; address: ptr TAddress; buffer: ptr TEnetBuffer; size: csize): cint{.
|
||||
importc: "enet_socket_send", dynlib: Lib.}
|
||||
proc receive*(socket: TEnetSocket; address: var TAddress;
|
||||
buffer: ptr TEnetBuffer; size: csize): cint{.
|
||||
importc: "enet_socket_receive", dynlib: Lib.}
|
||||
proc receive*(socket: TEnetSocket; address: ptr TAddress;
|
||||
buffer: ptr TEnetBuffer; size: csize): cint{.
|
||||
importc: "enet_socket_receive", dynlib: Lib.}
|
||||
proc wait*(socket: TEnetSocket; a3: ptr cuint; a4: cuint): cint{.
|
||||
importc: "enet_socket_wait", dynlib: Lib.}
|
||||
proc setOption*(socket: TEnetSocket; a3: TSocketOption; a4: cint): cint{.
|
||||
importc: "enet_socket_set_option", dynlib: Lib.}
|
||||
proc destroy*(socket: TEnetSocket){.
|
||||
importc: "enet_socket_destroy", dynlib: Lib.}
|
||||
proc select*(socket: TEnetSocket; a3: ptr TENetSocketSet;
|
||||
a4: ptr TENetSocketSet; a5: cuint): cint{.
|
||||
importc: "enet_socketset_select", dynlib: Lib.}
|
||||
|
||||
proc setHost*(address: PAddress; hostName: cstring): cint{.
|
||||
importc: "enet_address_set_host", dynlib: Lib.}
|
||||
proc setHost*(address: var TAddress; hostName: cstring): cint{.
|
||||
importc: "enet_address_set_host", dynlib: Lib.}
|
||||
proc getHostIP*(address: var TAddress; hostName: cstring; nameLength: csize): cint{.
|
||||
importc: "enet_address_get_host_ip", dynlib: Lib.}
|
||||
proc getHost*(address: var TAddress; hostName: cstring; nameLength: csize): cint{.
|
||||
importc: "enet_address_get_host", dynlib: Lib.}
|
||||
|
||||
## Call the above two funcs but trim the result string
|
||||
proc getHostIP*(address: var TAddress; hostName: var string; nameLength: csize): cint{.inline.} =
|
||||
hostName.setLen nameLength
|
||||
result = getHostIP(address, cstring(hostName), nameLength)
|
||||
if result == 0:
|
||||
hostName.setLen(len(cstring(hostName)))
|
||||
proc getHost*(address: var TAddress; hostName: var string; nameLength: csize): cint{.inline.} =
|
||||
hostName.setLen nameLength
|
||||
result = getHost(address, cstring(hostName), nameLength)
|
||||
if result == 0:
|
||||
hostName.setLen(len(cstring(hostName)))
|
||||
|
||||
proc createPacket*(data: pointer; len: csize; flag: TPacketFlag): PPacket{.
|
||||
importc: "enet_packet_create", dynlib: Lib.}
|
||||
proc destroy*(packet: PPacket){.
|
||||
importc: "enet_packet_destroy", dynlib: Lib.}
|
||||
proc resize*(packet: PPacket; dataLength: csize): cint{.
|
||||
importc: "enet_packet_resize", dynlib: Lib.}
|
||||
|
||||
proc crc32*(buffers: ptr TEnetBuffer; bufferCount: csize): cuint{.
|
||||
importc: "enet_crc32", dynlib: Lib.}
|
||||
|
||||
proc createHost*(address: ptr TAddress; maxConnections, maxChannels: csize; downSpeed, upSpeed: cuint): PHost{.
|
||||
importc: "enet_host_create", dynlib: Lib.}
|
||||
proc createHost*(address: var TAddress; maxConnections, maxChannels: csize; downSpeed, upSpeed: cuint): PHost{.
|
||||
importc: "enet_host_create", dynlib: Lib.}
|
||||
proc destroy*(host: PHost){.
|
||||
importc: "enet_host_destroy", dynlib: Lib.}
|
||||
proc connect*(host: PHost; address: ptr TAddress; channelCount: csize; data: cuint): PPeer{.
|
||||
importc: "enet_host_connect", dynlib: Lib.}
|
||||
proc connect*(host: PHost; address: var TAddress; channelCount: csize; data: cuint): PPeer{.
|
||||
importc: "enet_host_connect", dynlib: Lib.}
|
||||
|
||||
proc checkEvents*(host: PHost; event: var TEvent): cint{.
|
||||
importc: "enet_host_check_events", dynlib: Lib.}
|
||||
proc checkEvents*(host: PHost; event: ptr TEvent): cint{.
|
||||
importc: "enet_host_check_events", dynlib: Lib.}
|
||||
proc hostService*(host: PHost; event: var TEvent; timeout: cuint): cint{.
|
||||
importc: "enet_host_service", dynlib: Lib.}
|
||||
proc hostService*(host: PHost; event: ptr TEvent; timeout: cuint): cint{.
|
||||
importc: "enet_host_service", dynlib: Lib.}
|
||||
proc flush*(host: PHost){.
|
||||
importc: "enet_host_flush", dynlib: Lib.}
|
||||
proc broadcast*(host: PHost; channelID: cuchar; packet: PPacket){.
|
||||
importc: "enet_host_broadcast", dynlib: Lib.}
|
||||
proc compress*(host: PHost; compressor: PCompressor){.
|
||||
importc: "enet_host_compress", dynlib: Lib.}
|
||||
proc compressWithRangeCoder*(host: PHost): cint{.
|
||||
importc: "enet_host_compress_with_range_coder", dynlib: Lib.}
|
||||
proc channelLimit*(host: PHost; channelLimit: csize){.
|
||||
importc: "enet_host_channel_limit", dynlib: Lib.}
|
||||
proc bandwidthLimit*(host: PHost; incoming, outgoing: cuint){.
|
||||
importc: "enet_host_bandwidth_limit", dynlib: Lib.}
|
||||
proc bandwidthThrottle*(host: PHost){.
|
||||
importc: "enet_host_bandwidth_throttle", dynlib: Lib.}
|
||||
|
||||
|
||||
proc send*(peer: PPeer; channel: cuchar; packet: PPacket): cint{.
|
||||
importc: "enet_peer_send", dynlib: Lib.}
|
||||
proc receive*(peer: PPeer; channelID: ptr cuchar): PPacket{.
|
||||
importc: "enet_peer_receive", dynlib: Lib.}
|
||||
proc ping*(peer: PPeer){.
|
||||
importc: "enet_peer_ping", dynlib: Lib.}
|
||||
proc reset*(peer: PPeer){.
|
||||
importc: "enet_peer_reset", dynlib: Lib.}
|
||||
proc disconnect*(peer: PPeer; a3: cuint){.
|
||||
importc: "enet_peer_disconnect", dynlib: Lib.}
|
||||
proc disconnectNow*(peer: PPeer; a3: cuint){.
|
||||
importc: "enet_peer_disconnect_now", dynlib: Lib.}
|
||||
proc disconnectLater*(peer: PPeer; a3: cuint){.
|
||||
importc: "enet_peer_disconnect_later", dynlib: Lib.}
|
||||
proc throttleConfigure*(peer: PPeer; interval, acceleration, deceleration: cuint){.
|
||||
importc: "enet_peer_throttle_configure", dynlib: Lib.}
|
||||
proc throttle*(peer: PPeer; rtt: cuint): cint{.
|
||||
importc: "enet_peer_throttle", dynlib: Lib.}
|
||||
proc resetQueues*(peer: PPeer){.
|
||||
importc: "enet_peer_reset_queues", dynlib: Lib.}
|
||||
proc setupOutgoingCommand*(peer: PPeer; outgoingCommand: POutgoingCommand){.
|
||||
importc: "enet_peer_setup_outgoing_command", dynlib: Lib.}
|
||||
|
||||
proc queueOutgoingCommand*(peer: PPeer; command: ptr TEnetProtocol;
|
||||
packet: PPacket; offset: cuint; length: cushort): POutgoingCommand{.
|
||||
importc: "enet_peer_queue_outgoing_command", dynlib: Lib.}
|
||||
proc queueIncomingCommand*(peer: PPeer; command: ptr TEnetProtocol;
|
||||
packet: PPacket; fragmentCount: cuint): PIncomingCommand{.
|
||||
importc: "enet_peer_queue_incoming_command", dynlib: Lib.}
|
||||
proc queueAcknowledgement*(peer: PPeer; command: ptr TEnetProtocol;
|
||||
sentTime: cushort): PAcknowledgement{.
|
||||
importc: "enet_peer_queue_acknowledgement", dynlib: Lib.}
|
||||
proc dispatchIncomingUnreliableCommands*(peer: PPeer; channel: PChannel){.
|
||||
importc: "enet_peer_dispatch_incoming_unreliable_commands", dynlib: Lib.}
|
||||
proc dispatchIncomingReliableCommands*(peer: PPeer; channel: PChannel){.
|
||||
importc: "enet_peer_dispatch_incoming_reliable_commands", dynlib: Lib.}
|
||||
|
||||
proc createRangeCoder*(): pointer{.
|
||||
importc: "enet_range_coder_create", dynlib: Lib.}
|
||||
proc rangeCoderDestroy*(context: pointer){.
|
||||
importc: "enet_range_coder_destroy", dynlib: Lib.}
|
||||
proc rangeCoderCompress*(context: pointer; inBuffers: PEnetBuffer; inLimit,
|
||||
bufferCount: csize; outData: cstring; outLimit: csize): csize{.
|
||||
importc: "enet_range_coder_compress", dynlib: Lib.}
|
||||
proc rangeCoderDecompress*(context: pointer; inData: cstring; inLimit: csize;
|
||||
outData: cstring; outLimit: csize): csize{.
|
||||
importc: "enet_range_coder_decompress", dynlib: Lib.}
|
||||
proc protocolCommandSize*(commandNumber: cuchar): csize{.
|
||||
importc: "enet_protocol_command_size", dynlib: Lib.}
|
||||
|
||||
{.pop.}
|
||||
|
||||
from hashes import `!$`, `!&`, THash, hash
|
||||
proc hash*(x: TAddress): THash {.nimcall, noSideEffect.} =
|
||||
result = !$(hash(x.host.int32) !& hash(x.port.int16))
|
||||
|
||||
49
tests/manyloc/keineschweine/dependencies/enet/testclient.nim
Normal file
49
tests/manyloc/keineschweine/dependencies/enet/testclient.nim
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import enet, strutils
|
||||
|
||||
if enetInit() != 0:
|
||||
quit "Could not initialize ENet"
|
||||
var
|
||||
address: enet.TAddress
|
||||
event: TEvent
|
||||
peer: PPeer
|
||||
client: PHost
|
||||
|
||||
client = createHost(nil, 1, 2, 0, 0)
|
||||
if client == nil:
|
||||
quit "Could not create client!"
|
||||
|
||||
if setHost(addr address, "localhost") != 0:
|
||||
quit "Could not set host"
|
||||
address.port = 8024
|
||||
|
||||
peer = client.connect(addr address, 2, 0)
|
||||
if peer == nil:
|
||||
quit "No available peers"
|
||||
|
||||
block:
|
||||
var bConnected = false
|
||||
while not bConnected:
|
||||
if client.hostService(event, 5000) > 0 and event.kind == EvtConnect:
|
||||
echo "Connected"
|
||||
bConnected = true
|
||||
else:
|
||||
echo "Connection failed"
|
||||
quit 0
|
||||
|
||||
var runServer = true
|
||||
while client.hostService(event, 1000) >= 0 and runServer:
|
||||
case event.kind
|
||||
of EvtReceive:
|
||||
echo "Recvd ($1) $2 ".format(
|
||||
event.packet.dataLength,
|
||||
event.packet.data)
|
||||
of EvtDisconnect:
|
||||
echo "Disconnected"
|
||||
event.peer.data = nil
|
||||
runServer = false
|
||||
of EvtNone: discard
|
||||
else:
|
||||
echo repr(event)
|
||||
|
||||
|
||||
client.destroy()
|
||||
45
tests/manyloc/keineschweine/dependencies/enet/testserver.nim
Normal file
45
tests/manyloc/keineschweine/dependencies/enet/testserver.nim
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import enet, strutils
|
||||
var
|
||||
address: enet.TAddress
|
||||
server: PHost
|
||||
event: TEvent
|
||||
|
||||
if enetInit() != 0:
|
||||
quit "Could not initialize ENet"
|
||||
|
||||
address.host = EnetHostAny
|
||||
address.port = 8024
|
||||
|
||||
server = enet.createHost(
|
||||
addr address, 32, 2, 0, 0)
|
||||
if server == nil:
|
||||
quit "Could not create the server!"
|
||||
|
||||
while server.hostService(addr event, 2500) >= 0:
|
||||
case event.kind
|
||||
of EvtConnect:
|
||||
echo "New client from $1:$2".format(event.peer.address.host, event.peer.address.port)
|
||||
|
||||
var
|
||||
msg = "hello"
|
||||
resp = createPacket(cstring(msg), msg.len + 1, FlagReliable)
|
||||
|
||||
if event.peer.send(0.cuchar, resp) < 0:
|
||||
echo "FAILED"
|
||||
else:
|
||||
echo "Replied"
|
||||
of EvtReceive:
|
||||
echo "Recvd ($1) $2 ".format(
|
||||
event.packet.dataLength,
|
||||
event.packet.data)
|
||||
|
||||
destroy(event.packet)
|
||||
|
||||
of EvtDisconnect:
|
||||
echo "Disconnected"
|
||||
event.peer.data = nil
|
||||
else:
|
||||
discard
|
||||
|
||||
server.destroy()
|
||||
enetDeinit()
|
||||
295
tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim
Normal file
295
tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
import macros, macro_dsl, streams, streams_enh
|
||||
from strutils import format
|
||||
|
||||
template newLenName(): stmt {.immediate.} =
|
||||
let lenName {.inject.} = ^("len"& $lenNames)
|
||||
inc(lenNames)
|
||||
|
||||
template defPacketImports*(): stmt {.immediate, dirty.} =
|
||||
import macros, macro_dsl, streams, streams_enh
|
||||
from strutils import format
|
||||
|
||||
proc `$`*[T](x: seq[T]): string =
|
||||
result = "[seq len="
|
||||
result.add($x.len)
|
||||
result.add ':'
|
||||
for i in 0.. <len(x):
|
||||
result.add " "
|
||||
result.add($x[i])
|
||||
result.add ']'
|
||||
|
||||
macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
|
||||
result = newNimNode(nnkStmtList)
|
||||
let
|
||||
typeName = quoted2ident(typeNameN)
|
||||
packetID = ^"p"
|
||||
streamID = ^"s"
|
||||
var
|
||||
constructorParams = newNimNode(nnkFormalParams).und(typeName)
|
||||
constructor = newNimNode(nnkProcDef).und(
|
||||
postfix(^("new"& $typeName.ident), "*"),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
constructorParams,
|
||||
emptyNode(),
|
||||
emptyNode())
|
||||
pack = newNimNode(nnkProcDef).und(
|
||||
postfix(^"pack", "*"),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(
|
||||
emptyNode(), # : void
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
packetID, # p: var typeName
|
||||
newNimNode(nnkVarTy).und(typeName),
|
||||
emptyNode()),
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
streamID, # s: PStream
|
||||
^"PStream",
|
||||
newNimNode(nnkNilLit))),
|
||||
emptyNode(),
|
||||
emptyNode())
|
||||
read = newNimNode(nnkProcDef).und(
|
||||
newIdentNode("read"& $typeName.ident).postfix("*"),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(
|
||||
typeName, #result type
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
streamID, # s: PStream = nil
|
||||
^"PStream",
|
||||
newNimNode(nnkNilLit))),
|
||||
emptyNode(),
|
||||
emptyNode())
|
||||
constructorBody = newNimNode(nnkStmtList)
|
||||
packBody = newNimNode(nnkStmtList)
|
||||
readBody = newNimNode(nnkStmtList)
|
||||
lenNames = 0
|
||||
for i in 0.. typeFields.len - 1:
|
||||
let
|
||||
name = typeFields[i][0]
|
||||
dotName = packetID.dot(name)
|
||||
resName = newIdentNode(!"result").dot(name)
|
||||
case typeFields[i][1].kind
|
||||
of nnkBracketExpr: #ex: paddedstring[32, '\0'], array[range, type]
|
||||
case $typeFields[i][1][0].ident
|
||||
of "paddedstring":
|
||||
let length = typeFields[i][1][1]
|
||||
let padChar = typeFields[i][1][2]
|
||||
packBody.add(newCall(
|
||||
"writePaddedStr", streamID, dotName, length, padChar))
|
||||
## result.name = readPaddedStr(s, length, char)
|
||||
readBody.add(resName := newCall(
|
||||
"readPaddedStr", streamID, length, padChar))
|
||||
## make the type a string
|
||||
typeFields[i] = newNimNode(nnkIdentDefs).und(
|
||||
name,
|
||||
^"string",
|
||||
newNimNode(nnkEmpty))
|
||||
of "array":
|
||||
readBody.add(
|
||||
newNimNode(nnkDiscardStmt).und(
|
||||
newCall("readData", streamID, newNimNode(nnkAddr).und(resName), newCall("sizeof", resName))))
|
||||
packBody.add(
|
||||
newCall("writeData", streamID, newNimNode(nnkAddr).und(dotName), newCall("sizeof", dotName)))
|
||||
of "seq":
|
||||
## let lenX = readInt16(s)
|
||||
newLenName()
|
||||
let
|
||||
item = ^"item" ## item name in our iterators
|
||||
seqType = typeFields[i][1][1] ## type of seq
|
||||
readName = newIdentNode("read"& $seqType.ident)
|
||||
readBody.add(newNimNode(nnkLetSection).und(
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
lenName,
|
||||
newNimNode(nnkEmpty),
|
||||
newCall("readInt16", streamID))))
|
||||
readBody.add( ## result.name = @[]
|
||||
resName := ("@".prefix(newNimNode(nnkBracket))),
|
||||
newNimNode(nnkForStmt).und( ## for item in 1..len:
|
||||
item,
|
||||
infix(1.lit, "..", lenName),
|
||||
newNimNode(nnkStmtList).und(
|
||||
newCall( ## add(result.name, unpack[seqType](stream))
|
||||
"add", resName, newNimNode(nnkCall).und(readName, streamID)
|
||||
) ) ) )
|
||||
packbody.add(
|
||||
newNimNode(nnkVarSection).und(newNimNode(nnkIdentDefs).und(
|
||||
lenName, ## var lenName = int16(len(p.name))
|
||||
newIdentNode("int16"),
|
||||
newCall("int16", newCall("len", dotName)))),
|
||||
newCall("writeData", streamID, newNimNode(nnkAddr).und(lenName), 2.lit),
|
||||
newNimNode(nnkForStmt).und( ## for item in 0..length - 1: pack(p.name[item], stream)
|
||||
item,
|
||||
infix(0.lit, "..", infix(lenName, "-", 1.lit)),
|
||||
newNimNode(nnkStmtList).und(
|
||||
newCall("echo", item, ": ".lit),
|
||||
newCall("pack", dotName[item], streamID))))
|
||||
#set the default value to @[] (new sequence)
|
||||
typeFields[i][2] = "@".prefix(newNimNode(nnkBracket))
|
||||
else:
|
||||
error("Unknown type: "& treeRepr(typeFields[i]))
|
||||
of nnkIdent: ##normal type
|
||||
case $typeFields[i][1].ident
|
||||
of "string": # length encoded string
|
||||
packBody.add(newCall("writeLEStr", streamID, dotName))
|
||||
readBody.add(resName := newCall("readLEStr", streamID))
|
||||
of "int8", "int16", "int32", "float32", "float64", "char", "bool":
|
||||
packBody.add(newCall(
|
||||
"writeData", streamID, newNimNode(nnkAddr).und(dotName), newCall("sizeof", dotName)))
|
||||
readBody.add(resName := newCall("read"& $typeFields[i][1].ident, streamID))
|
||||
else: ## hopefully the type you specified was another defpacket() type
|
||||
packBody.add(newCall("pack", dotName, streamID))
|
||||
readBody.add(resName := newCall("read"& $typeFields[i][1].ident, streamID))
|
||||
else:
|
||||
error("I dont know what to do with: "& treerepr(typeFields[i]))
|
||||
|
||||
var
|
||||
toStringFunc = newNimNode(nnkProcDef).und(
|
||||
newNimNode(nnkPostfix).und(
|
||||
^"*",
|
||||
newNimNode(nnkAccQuoted).und(^"$")),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(
|
||||
^"string",
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
packetID, # p: typeName
|
||||
typeName,
|
||||
emptyNode())),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkStmtList).und(#[6]
|
||||
newNimNode(nnkAsgn).und(
|
||||
^"result", ## result =
|
||||
newNimNode(nnkCall).und(#[6][0][1]
|
||||
^"format", ## format
|
||||
emptyNode())))) ## "[TypeName $1 $2]"
|
||||
formatStr = "["& $typeName.ident
|
||||
|
||||
const emptyFields = {nnkEmpty, nnkNilLit}
|
||||
var objFields = newNimNode(nnkRecList)
|
||||
for i in 0.. < len(typeFields):
|
||||
let fname = typeFields[i][0]
|
||||
constructorParams.add(newNimNode(nnkIdentDefs).und(
|
||||
fname,
|
||||
typeFields[i][1],
|
||||
typeFields[i][2]))
|
||||
constructorBody.add((^"result").dot(fname) := fname)
|
||||
#export the name
|
||||
typeFields[i][0] = fname.postfix("*")
|
||||
if not(typeFields[i][2].kind in emptyFields):
|
||||
## empty the type default for the type def
|
||||
typeFields[i][2] = newNimNode(nnkEmpty)
|
||||
objFields.add(typeFields[i])
|
||||
toStringFunc[6][0][1].add(
|
||||
prefix("$", packetID.dot(fname)))
|
||||
formatStr.add " $"
|
||||
formatStr.add($(i + 1))
|
||||
|
||||
formatStr.add ']'
|
||||
toStringFunc[6][0][1][1] = formatStr.lit()
|
||||
|
||||
result.add(
|
||||
newNimNode(nnkTypeSection).und(
|
||||
newNimNode(nnkTypeDef).und(
|
||||
typeName.postfix("*"),
|
||||
newNimNode(nnkEmpty),
|
||||
newNimNode(nnkObjectTy).und(
|
||||
newNimNode(nnkEmpty), #not sure what this is
|
||||
newNimNode(nnkEmpty), #parent: OfInherit(Ident(!"SomeObj"))
|
||||
objFields))))
|
||||
result.add(constructor.und(constructorBody))
|
||||
result.add(pack.und(packBody))
|
||||
result.add(read.und(readBody))
|
||||
result.add(toStringFunc)
|
||||
when defined(GenPacketShowOutput):
|
||||
echo(repr(result))
|
||||
|
||||
proc `->`(a: string, b: string): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkIdentDefs).und(^a, ^b, newNimNode(nnkEmpty))
|
||||
proc `->`(a: string, b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkIdentDefs).und(^a, b, newNimNode(nnkEmpty))
|
||||
proc `->`(a, b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
a[2] = b
|
||||
result = a
|
||||
|
||||
proc newProc*(name: string, params: varargs[PNimrodNode], resultType: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkProcDef).und(
|
||||
^name,
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(resultType),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkStmtList))
|
||||
result[3].add(params)
|
||||
macro forwardPacket*(typeName: expr, underlyingType: typedesc): stmt {.immediate.} =
|
||||
result = newNimNode(nnkStmtList).und(
|
||||
newProc(
|
||||
"read"& $typeName.ident,
|
||||
["s" -> "PStream" -> newNimNode(nnkNilLit)],
|
||||
typeName),
|
||||
newProc(
|
||||
"pack",
|
||||
[ "p" -> newNimNode(nnkVarTy).und(typeName),
|
||||
"s" -> "PStream" -> newNimNode(nnkNilLit)],
|
||||
emptyNode()))
|
||||
result[0][6].add(newNimNode(nnkDiscardStmt).und(
|
||||
newCall(
|
||||
"readData", ^"s", newNimNode(nnkAddr).und(^"result"), newCall("sizeof", ^"result")
|
||||
)))
|
||||
result[1][6].add(
|
||||
newCall(
|
||||
"writeData", ^"s", newNimNode(nnkAddr).und(^"p"), newCall(
|
||||
"sizeof", ^"p")))
|
||||
when defined(GenPacketShowOutput):
|
||||
echo(repr(result))
|
||||
|
||||
template forwardPacketT*(typeName: expr): stmt {.dirty, immediate.} =
|
||||
proc `read typeName`*(s: PStream): typeName =
|
||||
discard readData(s, addr result, sizeof(result))
|
||||
proc `pack typeName`*(p: var typeName; s: PStream) =
|
||||
writeData(s, addr p, sizeof(p))
|
||||
|
||||
when isMainModule:
|
||||
type
|
||||
SomeEnum = enum
|
||||
A = 0'i8,
|
||||
B, C
|
||||
forwardPacket(SomeEnum, int8)
|
||||
|
||||
|
||||
defPacket(Foo, tuple[x: array[0..4, int8]])
|
||||
var f = newFoo([4'i8, 3'i8, 2'i8, 1'i8, 0'i8])
|
||||
var s2 = newStringStream("")
|
||||
f.pack(s2)
|
||||
assert s2.data == "\4\3\2\1\0"
|
||||
|
||||
var s = newStringStream()
|
||||
s.flushImpl = proc(s: PStream) =
|
||||
var z = PStringStream(s)
|
||||
z.setPosition(0)
|
||||
z.data.setLen(0)
|
||||
|
||||
|
||||
s.setPosition(0)
|
||||
s.data.setLen(0)
|
||||
var o = B
|
||||
o.pack(s)
|
||||
o = A
|
||||
o.pack(s)
|
||||
o = C
|
||||
o.pack(s)
|
||||
assert s.data == "\1\0\2"
|
||||
s.flush
|
||||
|
||||
defPacket(Y, tuple[z: int8])
|
||||
proc `$`(z: Y): string = result = "Y("& $z.z &")"
|
||||
defPacket(TestPkt, tuple[x: seq[Y]])
|
||||
var test = newTestPkt()
|
||||
test.x.add([newY(5), newY(4), newY(3), newY(2), newY(1)])
|
||||
for itm in test.x:
|
||||
echo(itm)
|
||||
test.pack(s)
|
||||
echo(repr(s.data))
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
import macros, macro_dsl, estreams
|
||||
from strutils import format
|
||||
|
||||
template newLenName(): stmt {.immediate.} =
|
||||
let lenName {.inject.} = ^("len"& $lenNames)
|
||||
inc(lenNames)
|
||||
|
||||
template defPacketImports*(): stmt {.immediate, dirty.} =
|
||||
import macros, macro_dsl, estreams
|
||||
from strutils import format
|
||||
|
||||
proc `$`*[T](x: seq[T]): string =
|
||||
result = "[seq len="
|
||||
result.add($x.len)
|
||||
result.add ':'
|
||||
for i in 0.. <len(x):
|
||||
result.add " "
|
||||
result.add($x[i])
|
||||
result.add ']'
|
||||
|
||||
macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
|
||||
result = newNimNode(nnkStmtList)
|
||||
let
|
||||
typeName = quoted2ident(typeNameN)
|
||||
packetID = ^"p"
|
||||
streamID = ^"s"
|
||||
var
|
||||
constructorParams = newNimNode(nnkFormalParams).und(typeName)
|
||||
constructor = newNimNode(nnkProcDef).und(
|
||||
postfix(^("new"& $typeName.ident), "*"),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
constructorParams,
|
||||
emptyNode(),
|
||||
emptyNode())
|
||||
pack = newNimNode(nnkProcDef).und(
|
||||
postfix(^"pack", "*"),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(
|
||||
emptyNode(), # : void
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
streamID, # s: PBuffer
|
||||
^"PBuffer",
|
||||
newNimNode(nnkNilLit)),
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
packetID, # p: var typeName
|
||||
newNimNode(nnkVarTy).und(typeName),
|
||||
emptyNode())),
|
||||
emptyNode(),
|
||||
emptyNode())
|
||||
read = newNimNode(nnkProcDef).und(
|
||||
newIdentNode("read"& $typeName.ident).postfix("*"),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(
|
||||
typeName, #result type
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
streamID, # s: PBuffer = nil
|
||||
^"PBuffer",
|
||||
newNimNode(nnkNilLit))),
|
||||
emptyNode(),
|
||||
emptyNode())
|
||||
constructorBody = newNimNode(nnkStmtList)
|
||||
packBody = newNimNode(nnkStmtList)
|
||||
readBody = newNimNode(nnkStmtList)
|
||||
lenNames = 0
|
||||
for i in 0.. typeFields.len - 1:
|
||||
let
|
||||
name = typeFields[i][0]
|
||||
dotName = packetID.dot(name)
|
||||
resName = newIdentNode(!"result").dot(name)
|
||||
case typeFields[i][1].kind
|
||||
of nnkBracketExpr: #ex: paddedstring[32, '\0'], array[range, type]
|
||||
case $typeFields[i][1][0].ident
|
||||
of "seq":
|
||||
## let lenX = readInt16(s)
|
||||
newLenName()
|
||||
let
|
||||
item = ^"item" ## item name in our iterators
|
||||
seqType = typeFields[i][1][1] ## type of seq
|
||||
readName = newIdentNode("read"& $seqType.ident)
|
||||
readBody.add(newNimNode(nnkLetSection).und(
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
lenName,
|
||||
newNimNode(nnkEmpty),
|
||||
newCall("readInt16", streamID))))
|
||||
readBody.add( ## result.name = @[]
|
||||
resName := ("@".prefix(newNimNode(nnkBracket))),
|
||||
newNimNode(nnkForStmt).und( ## for item in 1..len:
|
||||
item,
|
||||
infix(1.lit, "..", lenName),
|
||||
newNimNode(nnkStmtList).und(
|
||||
newCall( ## add(result.name, unpack[seqType](stream))
|
||||
"add", resName, newNimNode(nnkCall).und(readName, streamID)
|
||||
) ) ) )
|
||||
packbody.add(
|
||||
newNimNode(nnkVarSection).und(newNimNode(nnkIdentDefs).und(
|
||||
lenName, ## var lenName = int16(len(p.name))
|
||||
newIdentNode("int16"),
|
||||
newCall("int16", newCall("len", dotName)))),
|
||||
newCall("writeBE", streamID, lenName),
|
||||
newNimNode(nnkForStmt).und( ## for item in 0..length - 1: pack(p.name[item], stream)
|
||||
item,
|
||||
infix(0.lit, "..", infix(lenName, "-", 1.lit)),
|
||||
newNimNode(nnkStmtList).und(
|
||||
newCall("echo", item, ": ".lit),
|
||||
newCall("pack", streamID, dotName[item]))))
|
||||
#set the default value to @[] (new sequence)
|
||||
typeFields[i][2] = "@".prefix(newNimNode(nnkBracket))
|
||||
else:
|
||||
error("Unknown type: "& treeRepr(typeFields[i]))
|
||||
of nnkIdent: ##normal type
|
||||
case $typeFields[i][1].ident
|
||||
of "string": # length encoded string
|
||||
packBody.add(newCall("write", streamID, dotName))
|
||||
readBody.add(resName := newCall("readStr", streamID))
|
||||
of "int8", "int16", "int32", "float32", "float64", "char", "bool":
|
||||
packBody.add(newCall(
|
||||
"writeBE", streamID, dotName))
|
||||
readBody.add(resName := newCall("read"& $typeFields[i][1].ident, streamID))
|
||||
else: ## hopefully the type you specified was another defpacket() type
|
||||
packBody.add(newCall("pack", streamID, dotName))
|
||||
readBody.add(resName := newCall("read"& $typeFields[i][1].ident, streamID))
|
||||
else:
|
||||
error("I dont know what to do with: "& treerepr(typeFields[i]))
|
||||
|
||||
var
|
||||
toStringFunc = newNimNode(nnkProcDef).und(
|
||||
newNimNode(nnkPostfix).und(
|
||||
^"*",
|
||||
newNimNode(nnkAccQuoted).und(^"$")),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(
|
||||
^"string",
|
||||
newNimNode(nnkIdentDefs).und(
|
||||
packetID, # p: typeName
|
||||
typeName,
|
||||
emptyNode())),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkStmtList).und(#[6]
|
||||
newNimNode(nnkAsgn).und(
|
||||
^"result", ## result =
|
||||
newNimNode(nnkCall).und(#[6][0][1]
|
||||
^"format", ## format
|
||||
emptyNode())))) ## "[TypeName $1 $2]"
|
||||
formatStr = "["& $typeName.ident
|
||||
|
||||
const emptyFields = {nnkEmpty, nnkNilLit}
|
||||
var objFields = newNimNode(nnkRecList)
|
||||
for i in 0.. < len(typeFields):
|
||||
let fname = typeFields[i][0]
|
||||
constructorParams.add(newNimNode(nnkIdentDefs).und(
|
||||
fname,
|
||||
typeFields[i][1],
|
||||
typeFields[i][2]))
|
||||
constructorBody.add((^"result").dot(fname) := fname)
|
||||
#export the name
|
||||
typeFields[i][0] = fname.postfix("*")
|
||||
if not(typeFields[i][2].kind in emptyFields):
|
||||
## empty the type default for the type def
|
||||
typeFields[i][2] = newNimNode(nnkEmpty)
|
||||
objFields.add(typeFields[i])
|
||||
toStringFunc[6][0][1].add(
|
||||
prefix("$", packetID.dot(fname)))
|
||||
formatStr.add " $"
|
||||
formatStr.add($(i + 1))
|
||||
|
||||
formatStr.add ']'
|
||||
toStringFunc[6][0][1][1] = formatStr.lit()
|
||||
|
||||
result.add(
|
||||
newNimNode(nnkTypeSection).und(
|
||||
newNimNode(nnkTypeDef).und(
|
||||
typeName.postfix("*"),
|
||||
newNimNode(nnkEmpty),
|
||||
newNimNode(nnkObjectTy).und(
|
||||
newNimNode(nnkEmpty), #not sure what this is
|
||||
newNimNode(nnkEmpty), #parent: OfInherit(Ident(!"SomeObj"))
|
||||
objFields))))
|
||||
result.add(constructor.und(constructorBody))
|
||||
result.add(pack.und(packBody))
|
||||
result.add(read.und(readBody))
|
||||
result.add(toStringFunc)
|
||||
when defined(GenPacketShowOutput):
|
||||
echo(repr(result))
|
||||
|
||||
proc newProc*(name: PNimrodNode; params: varargs[PNimrodNode]; resultType: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkProcDef).und(
|
||||
name,
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkFormalParams).und(resultType),
|
||||
emptyNode(),
|
||||
emptyNode(),
|
||||
newNimNode(nnkStmtList))
|
||||
result[3].add(params)
|
||||
|
||||
proc body*(procNode: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
assert procNode.kind == nnkProcDef and procNode[6].kind == nnkStmtList
|
||||
result = procNode[6]
|
||||
|
||||
proc iddefs*(a, b: string; c: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkIdentDefs).und(^a, ^b, c)
|
||||
proc iddefs*(a: string; b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkIdentDefs).und(^a, b, emptyNode())
|
||||
proc varTy*(a: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkVarTy).und(a)
|
||||
|
||||
macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} =
|
||||
var
|
||||
packetID = ^"p"
|
||||
streamID = ^"s"
|
||||
result = newNimNode(nnkStmtList).und(
|
||||
newProc(
|
||||
(^("read"& $typeName.ident)).postfix("*"),
|
||||
[ iddefs("s", "PBuffer", newNimNode(nnkNilLit)) ],
|
||||
typeName),
|
||||
newProc(
|
||||
(^"pack").postfix("*"),
|
||||
[ iddefs("s", "PBuffer", newNimNode(nnkNilLit)),
|
||||
iddefs("p", varTy(typeName)) ],
|
||||
emptyNode()))
|
||||
var
|
||||
readBody = result[0][6]
|
||||
packBody = result[1][6]
|
||||
resName = ^"result"
|
||||
|
||||
case underlyingType.kind
|
||||
of nnkBracketExpr:
|
||||
case $underlyingType[0].ident
|
||||
of "array":
|
||||
for i in underlyingType[1][1].intval.int .. underlyingType[1][2].intval.int:
|
||||
readBody.add(
|
||||
newCall("read", ^"s", resName[lit(i)]))
|
||||
packBody.add(
|
||||
newCall("writeBE", ^"s", packetID[lit(i)]))
|
||||
else:
|
||||
echo "Unknown type: ", repr(underlyingtype)
|
||||
else:
|
||||
echo "unknown type:", repr(underlyingtype)
|
||||
echo(repr(result))
|
||||
|
||||
template forwardPacketT*(typeName: expr; underlyingType: expr): stmt {.dirty, immediate.} =
|
||||
proc `read typeName`*(buffer: PBuffer): typeName =
|
||||
#discard readData(s, addr result, sizeof(result))
|
||||
var res: underlyingType
|
||||
buffer.read(res)
|
||||
result = typeName(res)
|
||||
proc `pack`*(buffer: PBuffer; ord: var typeName) =
|
||||
#writeData(s, addr p, sizeof(p))
|
||||
buffer.write(underlyingType(ord))
|
||||
|
||||
when isMainModule:
|
||||
type
|
||||
SomeEnum = enum
|
||||
A = 0'i8,
|
||||
B, C
|
||||
forwardPacket(SomeEnum, int8)
|
||||
|
||||
|
||||
defPacket(Foo, tuple[x: array[0..4, int8]])
|
||||
var f = newFoo([4'i8, 3'i8, 2'i8, 1'i8, 0'i8])
|
||||
var s2 = newStringStream("")
|
||||
f.pack(s2)
|
||||
assert s2.data == "\4\3\2\1\0"
|
||||
|
||||
var s = newStringStream()
|
||||
s.flushImpl = proc(s: PStream) =
|
||||
var z = PStringStream(s)
|
||||
z.setPosition(0)
|
||||
z.data.setLen(0)
|
||||
|
||||
|
||||
s.setPosition(0)
|
||||
s.data.setLen(0)
|
||||
var o = B
|
||||
o.pack(s)
|
||||
o = A
|
||||
o.pack(s)
|
||||
o = C
|
||||
o.pack(s)
|
||||
assert s.data == "\1\0\2"
|
||||
s.flush
|
||||
|
||||
defPacket(Y, tuple[z: int8])
|
||||
proc `$`(z: Y): string = result = "Y("& $z.z &")"
|
||||
defPacket(TestPkt, tuple[x: seq[Y]])
|
||||
var test = newTestPkt()
|
||||
test.x.add([newY(5), newY(4), newY(3), newY(2), newY(1)])
|
||||
for itm in test.x:
|
||||
echo(itm)
|
||||
test.pack(s)
|
||||
echo(repr(s.data))
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import macros
|
||||
{.deadCodeElim: on.}
|
||||
#Inline macro.add() to allow for easier nesting
|
||||
proc und*(a: PNimrodNode; b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
a.add(b)
|
||||
result = a
|
||||
proc und*(a: PNimrodNode; b: varargs[PNimrodNode]): PNimrodNode {.compileTime.} =
|
||||
a.add(b)
|
||||
result = a
|
||||
|
||||
proc `^`*(a: string): PNimrodNode {.compileTime.} =
|
||||
## new ident node
|
||||
result = newIdentNode(!a)
|
||||
proc `[]`*(a, b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## new bracket expression: node[node] not to be confused with node[indx]
|
||||
result = newNimNode(nnkBracketExpr).und(a, b)
|
||||
proc `:=`*(left, right: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## new Asgn node: left = right
|
||||
result = newNimNode(nnkAsgn).und(left, right)
|
||||
|
||||
proc lit*(a: string): PNimrodNode {.compileTime.} =
|
||||
result = newStrLitNode(a)
|
||||
proc lit*(a: int): PNimrodNode {.compileTime.} =
|
||||
result = newIntLitNode(a)
|
||||
proc lit*(a: float): PNimrodNode {.compileTime.} =
|
||||
result = newFloatLitNode(a)
|
||||
proc lit*(a: char): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkCharLit)
|
||||
result.intval = a.ord
|
||||
|
||||
proc emptyNode*(): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkEmpty)
|
||||
|
||||
proc dot*(left, right: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkDotExpr).und(left, right)
|
||||
proc postfix*(a: PNimrodNode, b: string): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkPostfix).und(newIdentNode(!b), a)
|
||||
proc prefix*(a: string, b: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
result = newNimNode(nnkPrefix).und(newIdentNode(!a), b)
|
||||
|
||||
proc infix*(a, b, c: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## 5.infix("+", 10) ## => 5 + 10
|
||||
result = newNimNode(nnkInfix).und(b, a, c)
|
||||
proc infix*(a: PNimrodNode; b: string; c: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
## Infix operation: infix(5, "+", 10) ## =>
|
||||
result = newNimNode(nnkInfix).und(newIdentNode(b), a, c)
|
||||
|
||||
proc quoted2ident*(a: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
if a.kind != nnkAccQuoted:
|
||||
return a
|
||||
var pname = ""
|
||||
for piece in 0..a.len - 1:
|
||||
pname.add($a[piece].ident)
|
||||
result = ^pname
|
||||
|
||||
|
||||
macro `?`(a: expr): expr =
|
||||
## Character literal ?A #=> 'A'
|
||||
result = ($a[1].ident)[0].lit
|
||||
## echo(?F,?a,?t,?t,?y)
|
||||
|
||||
when isMainModule:
|
||||
macro foo(x: stmt): stmt =
|
||||
result = newNimNode(nnkStmtList)
|
||||
result.add(newNimNode(nnkCall).und(!!"echo", "Hello thar".lit))
|
||||
result.add(newCall("echo", lit("3 * 45 = "), (3.lit.infix("*", 45.lit))))
|
||||
let stmtlist = x[1]
|
||||
for i in countdown(len(stmtlist)-1, 0):
|
||||
result.add(stmtlist[i])
|
||||
foo:
|
||||
echo y, " * 2 = ", y * 2
|
||||
let y = 320
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import streams
|
||||
from strutils import repeatChar
|
||||
|
||||
proc readPaddedStr*(s: PStream, length: int, padChar = '\0'): TaintedString =
|
||||
var lastChr = length
|
||||
result = s.readStr(length)
|
||||
while lastChr >= 0 and result[lastChr - 1] == padChar: dec(lastChr)
|
||||
result.setLen(lastChr)
|
||||
|
||||
proc writePaddedStr*(s: PStream, str: string, length: int, padChar = '\0') =
|
||||
if str.len < length:
|
||||
s.write(str)
|
||||
s.write(repeatChar(length - str.len, padChar))
|
||||
elif str.len > length:
|
||||
s.write(str.substr(0, length - 1))
|
||||
else:
|
||||
s.write(str)
|
||||
|
||||
proc readLEStr*(s: PStream): TaintedString =
|
||||
var len = s.readInt16()
|
||||
result = s.readStr(len)
|
||||
|
||||
proc writeLEStr*(s: PStream, str: string) =
|
||||
s.write(str.len.int16)
|
||||
s.write(str)
|
||||
|
||||
when isMainModule:
|
||||
var testStream = newStringStream()
|
||||
|
||||
testStream.writeLEStr("Hello")
|
||||
doAssert testStream.data == "\5\0Hello"
|
||||
|
||||
testStream.setPosition 0
|
||||
var res = testStream.readLEStr()
|
||||
doAssert res == "Hello"
|
||||
|
||||
testStream.setPosition 0
|
||||
testStream.writePaddedStr("Sup", 10)
|
||||
echo(repr(testStream), testStream.data.len)
|
||||
doAssert testStream.data == "Sup"&repeatChar(7, '\0')
|
||||
|
||||
testStream.setPosition 0
|
||||
res = testStream.readPaddedStr(10)
|
||||
doAssert res == "Sup"
|
||||
|
||||
testStream.close()
|
||||
|
||||
83
tests/manyloc/keineschweine/dependencies/nake/nake.nim
Normal file
83
tests/manyloc/keineschweine/dependencies/nake/nake.nim
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
discard """
|
||||
DO AS THOU WILST PUBLIC LICENSE
|
||||
|
||||
Whoever should stumble upon this document is henceforth and forever
|
||||
entitled to DO AS THOU WILST with aforementioned document and the
|
||||
contents thereof.
|
||||
|
||||
As said in the Olde Country, `Keepe it Gangster'."""
|
||||
|
||||
import strutils, parseopt, tables, os
|
||||
|
||||
type
|
||||
PTask* = ref object
|
||||
desc*: string
|
||||
action*: TTaskFunction
|
||||
TTaskFunction* = proc() {.closure.}
|
||||
var
|
||||
tasks* = initTable[string, PTask](16)
|
||||
|
||||
proc newTask*(desc: string; action: TTaskFunction): PTask
|
||||
proc runTask*(name: string) {.inline.}
|
||||
proc shell*(cmd: varargs[string, `$`]): int {.discardable.}
|
||||
proc cd*(dir: string) {.inline.}
|
||||
|
||||
template nakeImports*(): stmt {.immediate.} =
|
||||
import tables, parseopt, strutils, os
|
||||
|
||||
template task*(name: string; description: string; body: stmt): stmt {.dirty, immediate.} =
|
||||
block:
|
||||
var t = newTask(description, proc() {.closure.} =
|
||||
body)
|
||||
tasks[name] = t
|
||||
|
||||
proc newTask*(desc: string; action: TTaskFunction): PTask =
|
||||
new(result)
|
||||
result.desc = desc
|
||||
result.action = action
|
||||
proc runTask*(name: string) = tasks[name].action()
|
||||
|
||||
proc shell*(cmd: varargs[string, `$`]): int =
|
||||
result = execShellCmd(cmd.join(" "))
|
||||
proc cd*(dir: string) = setCurrentDir(dir)
|
||||
template withDir*(dir: string; body: stmt): stmt =
|
||||
## temporary cd
|
||||
## withDir "foo":
|
||||
## # inside foo
|
||||
## #back to last dir
|
||||
var curDir = getCurrentDir()
|
||||
cd(dir)
|
||||
body
|
||||
cd(curDir)
|
||||
|
||||
when isMainModule:
|
||||
if not existsFile("nakefile.nim"):
|
||||
echo "No nakefile.nim found. Current working dir is ", getCurrentDir()
|
||||
quit 1
|
||||
var args = ""
|
||||
for i in 1..paramCount():
|
||||
args.add paramStr(i)
|
||||
args.add " "
|
||||
quit(shell("nimrod", "c", "-r", "nakefile.nim", args))
|
||||
else:
|
||||
addQuitProc(proc() {.noconv.} =
|
||||
var
|
||||
task: string
|
||||
printTaskList: bool
|
||||
for kind, key, val in getOpt():
|
||||
case kind
|
||||
of cmdLongOption, cmdShortOption:
|
||||
case key.tolower
|
||||
of "tasks", "t":
|
||||
printTaskList = true
|
||||
else:
|
||||
echo "Unknown option: ", key, ": ", val
|
||||
of cmdArgument:
|
||||
task = key
|
||||
else: nil
|
||||
if printTaskList or task.isNil or not(tasks.hasKey(task)):
|
||||
echo "Available tasks:"
|
||||
for name, task in pairs(tasks):
|
||||
echo name, " - ", task.desc
|
||||
quit 0
|
||||
tasks[task].action())
|
||||
23
tests/manyloc/keineschweine/dependencies/nake/nakefile.nim
Normal file
23
tests/manyloc/keineschweine/dependencies/nake/nakefile.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import nake
|
||||
nakeImports
|
||||
|
||||
task "install", "compile and install nake binary":
|
||||
if shell("nimrod", "c", "nake") == 0:
|
||||
let path = getEnv("PATH").split(PathSep)
|
||||
for index, dir in pairs(path):
|
||||
echo " ", index, ". ", dir
|
||||
echo "Where to install nake binary? (quit with ^C or quit or exit)"
|
||||
let ans = stdin.readLine().toLower
|
||||
var index = 0
|
||||
case ans
|
||||
of "q", "quit", "x", "exit":
|
||||
quit 0
|
||||
else:
|
||||
index = parseInt(ans)
|
||||
if index > path.len or index < 0:
|
||||
echo "Invalid index."
|
||||
quit 1
|
||||
moveFile "nake", path[index]/"nake"
|
||||
echo "Great success!"
|
||||
|
||||
|
||||
13
tests/manyloc/keineschweine/dependencies/sfml/README.md
Normal file
13
tests/manyloc/keineschweine/dependencies/sfml/README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
sfml-nimrod
|
||||
===========
|
||||
|
||||
Nimrod binding of SFML 2.0
|
||||
|
||||
This is only tested for Linux at the moment
|
||||
|
||||
### What is needed for Windows / OS X?
|
||||
|
||||
* The library names need filling in
|
||||
* TWindowHandle is handled differently on those platforms
|
||||
|
||||
I believe that is it
|
||||
1115
tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
Normal file
1115
tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
Normal file
File diff suppressed because it is too large
Load diff
899
tests/manyloc/keineschweine/dependencies/sfml/sfml_audio.nim
Normal file
899
tests/manyloc/keineschweine/dependencies/sfml/sfml_audio.nim
Normal file
|
|
@ -0,0 +1,899 @@
|
|||
import
|
||||
sfml
|
||||
const
|
||||
Lib = "libcsfml-audio.so.2.0"
|
||||
type
|
||||
PMusic* = ptr TMusic
|
||||
TMusic* {.pure, final.} = object
|
||||
PSound* = ptr TSound
|
||||
TSound* {.pure, final.} = object
|
||||
PSoundBuffer* = ptr TSoundBuffer
|
||||
TSoundBuffer* {.pure, final.} = object
|
||||
PSoundBufferRecorder* = ptr TSoundBufferRecorder
|
||||
TSoundBufferRecorder* {.pure, final.} = object
|
||||
PSoundRecorder* = ptr TSoundRecorder
|
||||
TSoundRecorder* {.pure, final.} = object
|
||||
PSoundStream* = ptr TSoundStream
|
||||
TSoundStream* {.pure, final.} = object
|
||||
TSoundStatus* {.size: sizeof(cint).} = enum
|
||||
Stopped, Paused, Playing
|
||||
|
||||
proc newMusic*(filename: cstring): PMusic {.
|
||||
cdecl, importc: "sfMusic_createFromFile", dynlib: Lib.}
|
||||
proc newMusic*(data: pointer, size: cint): PMusic {.
|
||||
cdecl, importc: "sfMusic_createFromMemory", dynlib: Lib.}
|
||||
proc newMusic*(stream: PInputStream): PMusic {.
|
||||
cdecl, importc: "sfMusic_createFromStream", dynlib: Lib.}
|
||||
proc destroy*(music: PMusic) {.
|
||||
cdecl, importc: "sfMusic_destroy", dynlib: Lib.}
|
||||
proc setLoop*(music: PMusic, loop: bool) {.
|
||||
cdecl, importc: "sfMusic_setLoop", dynlib: Lib.}
|
||||
proc getLoop*(music: PMusic): bool {.
|
||||
cdecl, importc: "sfMusic_getLoop", dynlib: Lib.}
|
||||
proc getDuration*(music: PMusic): TTime {.
|
||||
cdecl, importc: "sfMusic_getDuration", dynlib: Lib.}
|
||||
proc play*(music: PMusic) {.
|
||||
cdecl, importc: "sfMusic_play", dynlib: Lib.}
|
||||
proc pause*(music: PMusic) {.
|
||||
cdecl, importc: "sfMusic_pause", dynlib: Lib.}
|
||||
proc stop*(music: PMusic) {.
|
||||
cdecl, importc: "sfMusic_stop", dynlib: Lib.}
|
||||
proc getChannelCount*(music: PMusic): cint {.
|
||||
cdecl, importc: "sfMusic_getChannelCount", dynlib: Lib.}
|
||||
proc getSampleRate*(music: PMusic): cint {.
|
||||
cdecl, importc: "sfMusic_getSampleRate", dynlib: Lib.}
|
||||
proc getStatus*(music: PMusic): TSoundStatus {.
|
||||
cdecl, importc: "sfMusic_getStatus", dynlib: Lib.}
|
||||
proc getPlayingOffset*(music: PMusic): TTime {.
|
||||
cdecl, importc: "sfMusic_getPlayingOffset", dynlib: Lib.}
|
||||
proc setPitch*(music: PMusic, pitch: cfloat) {.
|
||||
cdecl, importc: "sfMusic_setPitch", dynlib: Lib.}
|
||||
proc setVolume*(music: PMusic, volume: float) {.
|
||||
cdecl, importc: "sfMusic_setVolume", dynlib: Lib.}
|
||||
proc setPosition*(music: PMusic, position: TVector3f) {.
|
||||
cdecl, importc: "sfMusic_setPosition", dynlib: Lib.}
|
||||
proc setRelativeToListener*(music: PMusic, relative: bool) {.
|
||||
cdecl, importc: "sfMusic_setRelativeToListener", dynlib: Lib.}
|
||||
proc setMinDistance*(music: PMusic, distance: cfloat) {.
|
||||
cdecl, importc: "sfMusic_setMinDistance", dynlib: Lib.}
|
||||
proc setAttenuation*(music: PMusic, attenuation: cfloat) {.
|
||||
cdecl, importc: "sfMusic_setAttenuation", dynlib: Lib.}
|
||||
proc setPlayingOffset*(music: PMusic, time: TTime) {.
|
||||
cdecl, importc: "sfMusic_setPlayingOffset", dynlib: Lib.}
|
||||
proc getPitch*(music: PMusic): cfloat {.
|
||||
cdecl, importc: "sfMusic_getPitch", dynlib: Lib.}
|
||||
proc getVolume*(music: PMusic): cfloat {.
|
||||
cdecl, importc: "sfMusic_getVolume", dynlib: Lib.}
|
||||
proc getPosition*(music: PMusic): TVector3f {.
|
||||
cdecl, importc: "sfMusic_getPosition", dynlib: Lib.}
|
||||
proc isRelativeToListener*(music: PMusic): bool {.
|
||||
cdecl, importc: "sfMusic_isRelativeToListener", dynlib: Lib.}
|
||||
proc getMinDistance*(music: PMusic): cfloat {.
|
||||
cdecl, importc: "sfMusic_isRelativeToListener", dynlib: Lib.}
|
||||
proc getAttenuation*(music: PMusic): cfloat {.
|
||||
cdecl, importc: "sfMusic_isRelativeToListener", dynlib: Lib.}
|
||||
|
||||
#/ \brief Create a new sound
|
||||
proc newSound*(): PSound{.
|
||||
cdecl, importc: "sfSound_create", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound by copying an existing one
|
||||
#/
|
||||
#/ \param sound Sound to copy
|
||||
#/
|
||||
#/ \return A new sfSound object which is a copy of \a sound
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc copy*(sound: PSound): PSound{.
|
||||
cdecl, importc: "sfSound_copy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Destroy a sound
|
||||
proc destroy*(sound: PSound){.
|
||||
cdecl, importc: "sfSound_destroy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Start or resume playing a sound
|
||||
#/
|
||||
#/ This function starts the sound if it was stopped, resumes
|
||||
#/ it if it was paused, and restarts it from beginning if it
|
||||
#/ was it already playing.
|
||||
#/ This function uses its own thread so that it doesn't block
|
||||
#/ the rest of the program while the sound is played.
|
||||
proc play*(sound: PSound){.
|
||||
cdecl, importc: "sfSound_play", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ This function pauses the sound if it was playing,
|
||||
#/ otherwise (sound already paused or stopped) it has no effect.
|
||||
proc pause*(sound: PSound){.
|
||||
cdecl, importc: "sfSound_pause", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ This function stops the sound if it was playing or paused,
|
||||
#/ and does nothing if it was already stopped.
|
||||
#/ It also resets the playing position (unlike sfSound_pause).
|
||||
proc stop*(sound: PSound){.
|
||||
cdecl, importc: "sfSound_stop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ It is important to note that the sound buffer is not copied,
|
||||
#/ thus the sfSoundBuffer object must remain alive as long
|
||||
#/ as it is attached to the sound.
|
||||
proc setBuffer*(sound: PSound; buffer: PSoundBuffer){.
|
||||
cdecl, importc: "sfSound_setBuffer", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the audio buffer attached to a sound
|
||||
proc getBuffer*(sound: PSound): PSoundBuffer{.
|
||||
cdecl, importc: "sfSound_getBuffer", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set whether or not a sound should loop after reaching the end
|
||||
#/
|
||||
#/ If set, the sound will restart from beginning after
|
||||
#/ reaching the end and so on, until it is stopped or
|
||||
#/ sfSound_setLoop(sound, sfFalse) is called.
|
||||
#/ The default looping state for sounds is false.
|
||||
proc setLoop*(sound: PSound; loop: bool){.
|
||||
cdecl, importc: "sfSound_setLoop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Tell whether or not a soud is in loop mode
|
||||
proc getLoop*(sound: PSound): bool {.
|
||||
cdecl, importc: "sfSound_getLoop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current status of a sound (stopped, paused, playing)
|
||||
proc getStatus*(sound: PSound): TSoundStatus{.
|
||||
cdecl, importc: "sfSound_getStatus", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the pitch of a sound
|
||||
#/
|
||||
#/ The pitch represents the perceived fundamental frequency
|
||||
#/ of a sound; thus you can make a sound more acute or grave
|
||||
#/ by changing its pitch. A side effect of changing the pitch
|
||||
#/ is to modify the playing speed of the sound as well.
|
||||
#/ The default value for the pitch is 1.
|
||||
proc setPitch*(sound: PSound; pitch: cfloat){.
|
||||
cdecl, importc: "sfSound_setPitch", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the volume of a sound
|
||||
#/
|
||||
#/ The volume is a value between 0 (mute) and 100 (full volume).
|
||||
#/ The default value for the volume is 100.
|
||||
proc setVolume*(sound: PSound; volume: cfloat){.
|
||||
cdecl, importc: "sfSound_setVolume", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the 3D position of a sound in the audio scene
|
||||
#/
|
||||
#/ Only sounds with one channel (mono sounds) can be
|
||||
#/ spatialized.
|
||||
#/ The default position of a sound is (0, 0, 0).
|
||||
proc setPosition*(sound: PSound; position: TVector3f){.
|
||||
cdecl, importc: "sfSound_setPosition", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Make the sound's position relative to the listener or absolute
|
||||
#/
|
||||
#/ Making a sound relative to the listener will ensure that it will always
|
||||
#/ be played the same way regardless the position of the listener.
|
||||
#/ This can be useful for non-spatialized sounds, sounds that are
|
||||
#/ produced by the listener, or sounds attached to it.
|
||||
#/ The default value is false (position is absolute).
|
||||
proc setRelativeToListener*(sound: PSound; relative: bool){.
|
||||
cdecl, importc: "sfSound_setRelativeToListener", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the minimum distance of a sound
|
||||
#/
|
||||
#/ The "minimum distance" of a sound is the maximum
|
||||
#/ distance at which it is heard at its maximum volume. Further
|
||||
#/ than the minimum distance, it will start to fade out according
|
||||
#/ to its attenuation factor. A value of 0 ("inside the head
|
||||
#/ of the listener") is an invalid value and is forbidden.
|
||||
#/ The default value of the minimum distance is 1.
|
||||
proc setMinDistance*(sound: PSound; distance: cfloat){.
|
||||
cdecl, importc: "sfSound_setMinDistance", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the attenuation factor of a sound
|
||||
#/
|
||||
#/ The attenuation is a multiplicative factor which makes
|
||||
#/ the sound more or less loud according to its distance
|
||||
#/ from the listener. An attenuation of 0 will produce a
|
||||
#/ non-attenuated sound, i.e. its volume will always be the same
|
||||
#/ whether it is heard from near or from far. On the other hand,
|
||||
#/ an attenuation value such as 100 will make the sound fade out
|
||||
#/ very quickly as it gets further from the listener.
|
||||
#/ The default value of the attenuation is 1.
|
||||
proc setAttenuation*(sound: PSound; attenuation: cfloat){.
|
||||
cdecl, importc: "sfSound_setAttenuation", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Change the current playing position of a sound
|
||||
#/
|
||||
#/ The playing position can be changed when the sound is
|
||||
#/ either paused or playing.
|
||||
proc setPlayingOffset*(sound: PSound; timeOffset: sfml.TTime){.
|
||||
cdecl, importc: "sfSound_setPlayingOffset", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the pitch of a sound
|
||||
proc getPitch*(sound: PSound): cfloat{.
|
||||
cdecl, importc: "sfSound_getPitch", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the volume of a sound
|
||||
proc getVolume*(sound: PSound): cfloat{.
|
||||
cdecl, importc: "sfSound_getVolume", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the 3D position of a sound in the audio scene
|
||||
proc getPosition*(sound: PSound): TVector3f{.
|
||||
cdecl, importc: "sfSound_getPosition", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Tell whether a sound's position is relative to the
|
||||
#/ listener or is absolute
|
||||
proc isRelativeToListener*(sound: PSound): bool{.
|
||||
cdecl, importc: "sfSound_isRelativeToListener", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the minimum distance of a sound
|
||||
proc getMinDistance*(sound: PSound): cfloat{.
|
||||
cdecl, importc: "sfSound_getMinDistance", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the attenuation factor of a sound
|
||||
proc getAttenuation*(sound: PSound): cfloat{.
|
||||
cdecl, importc: "sfSound_getAttenuation", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current playing position of a sound
|
||||
proc getPlayingOffset*(sound: PSound): TTime{.
|
||||
cdecl, importc: "sfSound_getPlayingOffset", dynlib: Lib.}
|
||||
|
||||
#//////////////////////////////////////////////////////////
|
||||
# Headers
|
||||
#//////////////////////////////////////////////////////////
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound buffer and load it from a file
|
||||
#/
|
||||
#/ Here is a complete list of all the supported audio formats:
|
||||
#/ ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
|
||||
#/ w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
|
||||
#/
|
||||
#/ \param filename Path of the sound file to load
|
||||
#/
|
||||
#/ \return A new sfSoundBuffer object (NULL if failed)
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc newSoundBuffer*(filename: cstring): PSoundBuffer{.
|
||||
cdecl, importc: "sfSoundBuffer_createFromFile", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound buffer and load it from a file in memory
|
||||
#/
|
||||
#/ Here is a complete list of all the supported audio formats:
|
||||
#/ ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
|
||||
#/ w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
|
||||
#/
|
||||
#/ \param data Pointer to the file data in memory
|
||||
#/ \param sizeInBytes Size of the data to load, in bytes
|
||||
#/
|
||||
#/ \return A new sfSoundBuffer object (NULL if failed)
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc newSoundBuffer*(data: pointer; sizeInBytes: cint): PSoundBuffer{.
|
||||
cdecl, importc: "sfSoundBuffer_createFromMemory", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound buffer and load it from a custom stream
|
||||
#/
|
||||
#/ Here is a complete list of all the supported audio formats:
|
||||
#/ ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
|
||||
#/ w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
|
||||
#/
|
||||
#/ \param stream Source stream to read from
|
||||
#/
|
||||
#/ \return A new sfSoundBuffer object (NULL if failed)
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc newSoundBuffer*(stream: PInputStream): PSoundBuffer{.
|
||||
cdecl, importc: "sfSoundBuffer_createFromStream", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound buffer and load it from an array of samples in memory
|
||||
#/
|
||||
#/ The assumed format of the audio samples is 16 bits signed integer
|
||||
#/ (sfInt16).
|
||||
#/
|
||||
#/ \param samples Pointer to the array of samples in memory
|
||||
#/ \param sampleCount Number of samples in the array
|
||||
#/ \param channelCount Number of channels (1 = mono, 2 = stereo, ...)
|
||||
#/ \param sampleRate Sample rate (number of samples to play per second)
|
||||
#/
|
||||
#/ \return A new sfSoundBuffer object (NULL if failed)
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc createFromSamples*(samples: ptr int16; sampleCount: cuint;
|
||||
channelCount: cuint; sampleRate: cuint): PSoundBuffer{.
|
||||
cdecl, importc: "sfSoundBuffer_createFromSamples", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound buffer by copying an existing one
|
||||
#/
|
||||
#/ \param soundBuffer Sound buffer to copy
|
||||
#/
|
||||
#/ \return A new sfSoundBuffer object which is a copy of \a soundBuffer
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc copy*(soundBuffer: PSoundBuffer): PSoundBuffer{.
|
||||
cdecl, importc: "sfSoundBuffer_copy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Destroy a sound buffer
|
||||
#/
|
||||
#/ \param soundBuffer Sound buffer to destroy
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc destroy*(soundBuffer: PSoundBuffer){.
|
||||
cdecl, importc: "sfSoundBuffer_destroy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Save a sound buffer to an audio file
|
||||
#/
|
||||
#/ Here is a complete list of all the supported audio formats:
|
||||
#/ ogg, wav, flac, aiff, au, raw, paf, svx, nist, voc, ircam,
|
||||
#/ w64, mat4, mat5 pvf, htk, sds, avr, sd2, caf, wve, mpc2k, rf64.
|
||||
#/
|
||||
#/ \param soundBuffer Sound buffer object
|
||||
#/ \param filename Path of the sound file to write
|
||||
#/
|
||||
#/ \return sfTrue if saving succeeded, sfFalse if it failed
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc saveToFile*(soundBuffer: PSoundBuffer; filename: cstring): bool {.
|
||||
cdecl, importc: "sfSoundBuffer_saveToFile", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the array of audio samples stored in a sound buffer
|
||||
#/
|
||||
#/ The format of the returned samples is 16 bits signed integer
|
||||
#/ (sfInt16). The total number of samples in this array
|
||||
#/ is given by the sfSoundBuffer_getSampleCount function.
|
||||
#/
|
||||
#/ \param soundBuffer Sound buffer object
|
||||
#/
|
||||
#/ \return Read-only pointer to the array of sound samples
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc sfSoundBuffer_getSamples*(soundBuffer: PSoundBuffer): ptr Int16{.
|
||||
cdecl, importc: "sfSoundBuffer_getSamples", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the number of samples stored in a sound buffer
|
||||
#/
|
||||
#/ The array of samples can be accessed with the
|
||||
#/ sfSoundBuffer_getSamples function.
|
||||
proc getSampleCount*(soundBuffer: PSoundBuffer): cint{.
|
||||
cdecl, importc: "sfSoundBuffer_getSampleCount", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the sample rate of a sound buffer
|
||||
#/
|
||||
#/ The sample rate is the number of samples played per second.
|
||||
#/ The higher, the better the quality (for example, 44100
|
||||
#/ samples/s is CD quality).
|
||||
proc getSampleRate*(soundBuffer: PSoundBuffer): cuint{.
|
||||
cdecl, importc: "sfSoundBuffer_getSampleRate", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the number of channels used by a sound buffer
|
||||
#/
|
||||
#/ If the sound is mono then the number of channels will
|
||||
#/ be 1, 2 for stereo, etc.
|
||||
proc getChannelCount*(soundBuffer: PSoundBuffer): cuint{.
|
||||
cdecl, importc: "sfSoundBuffer_getChannelCount", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the total duration of a sound buffer
|
||||
#/
|
||||
#/ \param soundBuffer Sound buffer object
|
||||
#/
|
||||
#/ \return Sound duration
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getDuration*(soundBuffer: PSoundBuffer): TTime{.
|
||||
cdecl, importc: "sfSoundBuffer_getDuration", dynlib: Lib.}
|
||||
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Change the global volume of all the sounds and musics
|
||||
#/
|
||||
#/ The volume is a number between 0 and 100; it is combined with
|
||||
#/ the individual volume of each sound / music.
|
||||
#/ The default value for the volume is 100 (maximum).
|
||||
#/
|
||||
#/ \param volume New global volume, in the range [0, 100]
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc listenerSetGlobalVolume*(volume: cfloat){.
|
||||
cdecl, importc: "sfListener_setGlobalVolume", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current value of the global volume
|
||||
#/
|
||||
#/ \return Current global volume, in the range [0, 100]
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc listenerGetGlobalVolume*(): cfloat{.
|
||||
cdecl, importc: "sfListener_getGlobalVolume", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the position of the listener in the scene
|
||||
#/
|
||||
#/ The default listener's position is (0, 0, 0).
|
||||
#/
|
||||
#/ \param position New position of the listener
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc listenerSetPosition*(position: TVector3f){.
|
||||
cdecl, importc: "sfListener_setPosition", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current position of the listener in the scene
|
||||
#/
|
||||
#/ \return The listener's position
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc listenerGetPosition*(): TVector3f{.
|
||||
cdecl, importc: "sfListener_getPosition", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the orientation of the listener in the scene
|
||||
#/
|
||||
#/ The orientation defines the 3D axes of the listener
|
||||
#/ (left, up, front) in the scene. The orientation vector
|
||||
#/ doesn't have to be normalized.
|
||||
#/ The default listener's orientation is (0, 0, -1).
|
||||
#/
|
||||
#/ \param position New direction of the listener
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc listenerSetDirection*(orientation: TVector3f){.
|
||||
cdecl, importc: "sfListener_setDirection", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current orientation of the listener in the scene
|
||||
#/
|
||||
#/ \return The listener's direction
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc listenerGetDirection*(): TVector3f{.
|
||||
cdecl, importc: "sfListener_getDirection", dynlib: Lib.}
|
||||
|
||||
type
|
||||
TSoundRecorderStartCallback* = proc (a2: pointer): bool {.cdecl.}
|
||||
#/< Type of the callback used when starting a capture
|
||||
TSoundRecorderProcessCallback* = proc(a2: ptr int16; a3: cuint;
|
||||
a4: pointer): bool {.cdecl.}
|
||||
#/< Type of the callback used to process audio data
|
||||
TSoundRecorderStopCallback* = proc (a2: pointer){.cdecl.}
|
||||
#/< Type of the callback used when stopping a capture
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Construct a new sound recorder from callback functions
|
||||
#/
|
||||
#/ \param onStart Callback function which will be called when a new capture starts (can be NULL)
|
||||
#/ \param onProcess Callback function which will be called each time there's audio data to process
|
||||
#/ \param onStop Callback function which will be called when the current capture stops (can be NULL)
|
||||
#/ \param userData Data to pass to the callback function (can be NULL)
|
||||
#/
|
||||
#/ \return A new sfSoundRecorder object (NULL if failed)
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc newSoundRecorder*(onStart: TSoundRecorderStartCallback;
|
||||
onProcess: TSoundRecorderProcessCallback;
|
||||
onStop: TSoundRecorderStopCallback;
|
||||
userData: pointer = nil): PSoundRecorder{.
|
||||
cdecl, importc: "sfSoundRecorder_create", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Destroy a sound recorder
|
||||
#/
|
||||
#/ \param soundRecorder Sound recorder to destroy
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc destroy*(soundRecorder: PSoundRecorder){.
|
||||
cdecl, importc: "sfSoundRecorder_destroy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Start the capture of a sound recorder
|
||||
#/
|
||||
#/ The \a sampleRate parameter defines the number of audio samples
|
||||
#/ captured per second. The higher, the better the quality
|
||||
#/ (for example, 44100 samples/sec is CD quality).
|
||||
#/ This function uses its own thread so that it doesn't block
|
||||
#/ the rest of the program while the capture runs.
|
||||
#/ Please note that only one capture can happen at the same time.
|
||||
#/
|
||||
#/ \param soundRecorder Sound recorder object
|
||||
#/ \param sampleRate Desired capture rate, in number of samples per second
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc start*(soundRecorder: PSoundRecorder; sampleRate: cuint){.
|
||||
cdecl, importc: "sfSoundRecorder_start", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Stop the capture of a sound recorder
|
||||
#/
|
||||
#/ \param soundRecorder Sound recorder object
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc stop*(soundRecorder: PSoundRecorder){.
|
||||
cdecl, importc: "sfSoundRecorder_stop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the sample rate of a sound recorder
|
||||
#/
|
||||
#/ The sample rate defines the number of audio samples
|
||||
#/ captured per second. The higher, the better the quality
|
||||
#/ (for example, 44100 samples/sec is CD quality).
|
||||
#/
|
||||
#/ \param soundRecorder Sound recorder object
|
||||
#/
|
||||
#/ \return Sample rate, in samples per second
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getSampleRate*(soundRecorder: PSoundRecorder): cuint{.
|
||||
cdecl, importc: "sfSoundRecorder_getSampleRate", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Check if the system supports audio capture
|
||||
#/
|
||||
#/ This function should always be called before using
|
||||
#/ the audio capture features. If it returns false, then
|
||||
#/ any attempt to use sfSoundRecorder will fail.
|
||||
#/
|
||||
#/ \return sfTrue if audio capture is supported, sfFalse otherwise
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc soundRecorderIsAvailable*(): bool {.
|
||||
cdecl, importc: "sfSoundRecorder_isAvailable", dynlib: Lib.}
|
||||
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound buffer recorder
|
||||
#/
|
||||
#/ \return A new sfSoundBufferRecorder object (NULL if failed)
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc newSoundBufferRecorder*(): PSoundBufferRecorder{.
|
||||
cdecl, importc: "sfSoundBufferRecorder_create", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Destroy a sound buffer recorder
|
||||
#/
|
||||
#/ \param soundBufferRecorder Sound buffer recorder to destroy
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc destroy*(soundBufferRecorder: PSoundBufferRecorder){.
|
||||
cdecl, importc: "sfSoundBufferRecorder_destroy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Start the capture of a sound recorder recorder
|
||||
#/
|
||||
#/ The \a sampleRate parameter defines the number of audio samples
|
||||
#/ captured per second. The higher, the better the quality
|
||||
#/ (for example, 44100 samples/sec is CD quality).
|
||||
#/ This function uses its own thread so that it doesn't block
|
||||
#/ the rest of the program while the capture runs.
|
||||
#/ Please note that only one capture can happen at the same time.
|
||||
#/
|
||||
#/ \param soundBufferRecorder Sound buffer recorder object
|
||||
#/ \param sampleRate Desired capture rate, in number of samples per second
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc start*(soundBufferRecorder: PSoundBufferRecorder; sampleRate: cuint){.
|
||||
cdecl, importc: "sfSoundBufferRecorder_start", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Stop the capture of a sound recorder
|
||||
#/
|
||||
#/ \param soundBufferRecorder Sound buffer recorder object
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc stop*(soundBufferRecorder: PSoundBufferRecorder){.
|
||||
cdecl, importc: "sfSoundBufferRecorder_stop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the sample rate of a sound buffer recorder
|
||||
#/
|
||||
#/ The sample rate defines the number of audio samples
|
||||
#/ captured per second. The higher, the better the quality
|
||||
#/ (for example, 44100 samples/sec is CD quality).
|
||||
#/
|
||||
#/ \param soundBufferRecorder Sound buffer recorder object
|
||||
#/
|
||||
#/ \return Sample rate, in samples per second
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getSampleRate*(soundBufferRecorder: PSoundBufferRecorder): cuint{.
|
||||
cdecl, importc: "sfSoundBufferRecorder_getSampleRate", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the sound buffer containing the captured audio data
|
||||
#/
|
||||
#/ The sound buffer is valid only after the capture has ended.
|
||||
#/ This function provides a read-only access to the internal
|
||||
#/ sound buffer, but it can be copied if you need to
|
||||
#/ make any modification to it.
|
||||
#/
|
||||
#/ \param soundBufferRecorder Sound buffer recorder object
|
||||
#/
|
||||
#/ \return Read-only access to the sound buffer
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getBuffer*(soundBufferRecorder: PSoundBufferRecorder): PSoundBuffer{.
|
||||
cdecl, importc: "sfSoundBufferRecorder_getBuffer", dynlib: Lib.}
|
||||
|
||||
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief defines the data to fill by the OnGetData callback
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
type
|
||||
PSoundStreamChunk* = ptr TSoundStreamChunk
|
||||
TSoundStreamChunk*{.pure, final.} = object
|
||||
samples*: ptr int16 #/< Pointer to the audio samples
|
||||
sampleCount*: cuint #/< Number of samples pointed by Samples
|
||||
|
||||
TSoundStreamGetDataCallback* = proc (a2: PSoundStreamChunk;
|
||||
a3: pointer): bool{.cdecl.}
|
||||
#/< Type of the callback used to get a sound stream data
|
||||
TSoundStreamSeekCallback* = proc (a2: TTime; a3: pointer){.cdecl.}
|
||||
#/< Type of the callback used to seek in a sound stream
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Create a new sound stream
|
||||
#/
|
||||
#/ \param onGetData Function called when the stream needs more data (can't be NULL)
|
||||
#/ \param onSeek Function called when the stream seeks (can't be NULL)
|
||||
#/ \param channelCount Number of channels to use (1 = mono, 2 = stereo)
|
||||
#/ \param sampleRate Sample rate of the sound (44100 = CD quality)
|
||||
#/ \param userData Data to pass to the callback functions
|
||||
#/
|
||||
#/ \return A new sfSoundStream object
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc create*(onGetData: TSoundStreamGetDataCallback; onSeek: TSoundStreamSeekCallback;
|
||||
channelCount: cuint; sampleRate: cuint; userData: pointer): PSoundStream{.
|
||||
cdecl, importc: "sfSoundStream_create", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Destroy a sound stream
|
||||
#/
|
||||
#/ \param soundStream Sound stream to destroy
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc destroy*(soundStream: PSoundStream){.
|
||||
cdecl, importc: "sfSoundStream_destroy", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Start or resume playing a sound stream
|
||||
#/
|
||||
#/ This function starts the stream if it was stopped, resumes
|
||||
#/ it if it was paused, and restarts it from beginning if it
|
||||
#/ was it already playing.
|
||||
#/ This function uses its own thread so that it doesn't block
|
||||
#/ the rest of the program while the music is played.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc play*(soundStream: PSoundStream){.
|
||||
cdecl, importc: "sfSoundStream_play", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Pause a sound stream
|
||||
#/
|
||||
#/ This function pauses the stream if it was playing,
|
||||
#/ otherwise (stream already paused or stopped) it has no effect.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc pause*(soundStream: PSoundStream){.
|
||||
cdecl, importc: "sfSoundStream_pause", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Stop playing a sound stream
|
||||
#/
|
||||
#/ This function stops the stream if it was playing or paused,
|
||||
#/ and does nothing if it was already stopped.
|
||||
#/ It also resets the playing position (unlike sfSoundStream_pause).
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc stop*(soundStream: PSoundStream){.
|
||||
cdecl, importc: "sfSoundStream_stop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current status of a sound stream (stopped, paused, playing)
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Current status
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getStatus*(soundStream: PSoundStream): TSoundStatus{.
|
||||
cdecl, importc: "sfSoundStream_getStatus", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Return the number of channels of a sound stream
|
||||
#/
|
||||
#/ 1 channel means a mono sound, 2 means stereo, etc.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Number of channels
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getChannelCount*(soundStream: PSoundStream): cuint{.
|
||||
cdecl, importc: "sfSoundStream_getChannelCount", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the sample rate of a sound stream
|
||||
#/
|
||||
#/ The sample rate is the number of audio samples played per
|
||||
#/ second. The higher, the better the quality.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Sample rate, in number of samples per second
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getSampleRate*(soundStream: PSoundStream): cuint{.
|
||||
cdecl, importc: "sfSoundStream_getSampleRate", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the pitch of a sound stream
|
||||
#/
|
||||
#/ The pitch represents the perceived fundamental frequency
|
||||
#/ of a sound; thus you can make a stream more acute or grave
|
||||
#/ by changing its pitch. A side effect of changing the pitch
|
||||
#/ is to modify the playing speed of the stream as well.
|
||||
#/ The default value for the pitch is 1.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param pitch New pitch to apply to the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setPitch*(soundStream: PSoundStream; pitch: cfloat){.
|
||||
cdecl, importc: "sfSoundStream_setPitch", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the volume of a sound stream
|
||||
#/
|
||||
#/ The volume is a value between 0 (mute) and 100 (full volume).
|
||||
#/ The default value for the volume is 100.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param volume Volume of the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setVolume*(soundStream: PSoundStream; volume: cfloat){.
|
||||
cdecl, importc: "sfSoundStream_setVolume", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the 3D position of a sound stream in the audio scene
|
||||
#/
|
||||
#/ Only streams with one channel (mono streams) can be
|
||||
#/ spatialized.
|
||||
#/ The default position of a stream is (0, 0, 0).
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param position Position of the stream in the scene
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setPosition*(soundStream: PSoundStream; position: TVector3f){.
|
||||
cdecl, importc: "sfSoundStream_setPosition", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Make a sound stream's position relative to the listener or absolute
|
||||
#/
|
||||
#/ Making a stream relative to the listener will ensure that it will always
|
||||
#/ be played the same way regardless the position of the listener.
|
||||
#/ This can be useful for non-spatialized streams, streams that are
|
||||
#/ produced by the listener, or streams attached to it.
|
||||
#/ The default value is false (position is absolute).
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param relative sfTrue to set the position relative, sfFalse to set it absolute
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setRelativeToListener*(soundStream: PSoundStream; relative: bool){.
|
||||
cdecl, importc: "sfSoundStream_setRelativeToListener", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the minimum distance of a sound stream
|
||||
#/
|
||||
#/ The "minimum distance" of a stream is the maximum
|
||||
#/ distance at which it is heard at its maximum volume. Further
|
||||
#/ than the minimum distance, it will start to fade out according
|
||||
#/ to its attenuation factor. A value of 0 ("inside the head
|
||||
#/ of the listener") is an invalid value and is forbidden.
|
||||
#/ The default value of the minimum distance is 1.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param distance New minimum distance of the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setMinDistance*(soundStream: PSoundStream; distance: cfloat){.
|
||||
cdecl, importc: "sfSoundStream_setMinDistance", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set the attenuation factor of a sound stream
|
||||
#/
|
||||
#/ The attenuation is a multiplicative factor which makes
|
||||
#/ the stream more or less loud according to its distance
|
||||
#/ from the listener. An attenuation of 0 will produce a
|
||||
#/ non-attenuated stream, i.e. its volume will always be the same
|
||||
#/ whether it is heard from near or from far. On the other hand,
|
||||
#/ an attenuation value such as 100 will make the stream fade out
|
||||
#/ very quickly as it gets further from the listener.
|
||||
#/ The default value of the attenuation is 1.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param attenuation New attenuation factor of the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setAttenuation*(soundStream: PSoundStream; attenuation: cfloat){.
|
||||
cdecl, importc: "sfSoundStream_setAttenuation", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Change the current playing position of a sound stream
|
||||
#/
|
||||
#/ The playing position can be changed when the stream is
|
||||
#/ either paused or playing.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param timeOffset New playing position
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setPlayingOffset*(soundStream: PSoundStream; timeOffset: TTime){.
|
||||
cdecl, importc: "sfSoundStream_setPlayingOffset", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Set whether or not a sound stream should loop after reaching the end
|
||||
#/
|
||||
#/ If set, the stream will restart from beginning after
|
||||
#/ reaching the end and so on, until it is stopped or
|
||||
#/ sfSoundStream_setLoop(stream, sfFalse) is called.
|
||||
#/ The default looping state for sound streams is false.
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/ \param loop sfTrue to play in loop, sfFalse to play once
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc setLoop*(soundStream: PSoundStream; loop: bool){.
|
||||
cdecl, importc: "sfSoundStream_setLoop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the pitch of a sound stream
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Pitch of the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getPitch*(soundStream: PSoundStream): cfloat{.
|
||||
cdecl, importc: "sfSoundStream_getPitch", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the volume of a sound stream
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Volume of the stream, in the range [0, 100]
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getVolume*(soundStream: PSoundStream): cfloat{.
|
||||
cdecl, importc: "sfSoundStream_getVolume", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the 3D position of a sound stream in the audio scene
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Position of the stream in the world
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getPosition*(soundStream: PSoundStream): TVector3f{.
|
||||
cdecl, importc: "sfSoundStream_getPosition", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Tell whether a sound stream's position is relative to the
|
||||
#/ listener or is absolute
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return sfTrue if the position is relative, sfFalse if it's absolute
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc isRelativeToListener*(soundStream: PSoundStream): bool{.
|
||||
cdecl, importc: "sfSoundStream_isRelativeToListener", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the minimum distance of a sound stream
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Minimum distance of the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getMinDistance*(soundStream: PSoundStream): cfloat{.
|
||||
cdecl, importc: "sfSoundStream_getMinDistance", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the attenuation factor of a sound stream
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Attenuation factor of the stream
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getAttenuation*(soundStream: PSoundStream): cfloat{.
|
||||
cdecl, importc: "sfSoundStream_getAttenuation", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Tell whether or not a sound stream is in loop mode
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return sfTrue if the music is looping, sfFalse otherwise
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getLoop*(soundStream: PSoundStream): bool{.
|
||||
cdecl, importc: "sfSoundStream_getLoop", dynlib: Lib.}
|
||||
#//////////////////////////////////////////////////////////
|
||||
#/ \brief Get the current playing position of a sound stream
|
||||
#/
|
||||
#/ \param soundStream Sound stream object
|
||||
#/
|
||||
#/ \return Current playing position
|
||||
#/
|
||||
#//////////////////////////////////////////////////////////
|
||||
proc getPlayingOffset*(soundStream: PSoundStream): TTime{.
|
||||
cdecl, importc: "sfSoundStream_getPlayingOffset", dynlib: Lib.}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import sfml
|
||||
{.deadCodeElim: on.}
|
||||
let
|
||||
Black*: TColor = color(0, 0, 0)
|
||||
White*: TColor = color(255, 255, 255)
|
||||
Red*: TColor = color(255, 0, 0)
|
||||
Green*: TColor = color(0, 255, 0)
|
||||
Blue*: TColor = color(0, 0, 255)
|
||||
Yellow*: TColor = color(255, 255, 0)
|
||||
Magenta*: TColor = color(255, 0, 255)
|
||||
Cyan*: TColor = color(0, 255, 255)
|
||||
Transparent*: TColor = color(0, 0, 0, 0)
|
||||
Gray* = color(84, 84, 84)
|
||||
RoyalBlue* = color(65, 105, 225)
|
||||
##todo: define more colors lul
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
import sfml, math, strutils
|
||||
{.deadCodeElim: on.}
|
||||
Loading…
Add table
Add a link
Reference in a new issue