FPL - A C99 Single-Header-File Platform Abstraction Library

Update
Finally i removed the requirement to link against user32.lib and shell32.lib - all the functions are dynamically loaded properly.
But you still have to link against kernel32.lib thou for calling LoadLibrary.

Also i changed the command line parsing to use "CommandLineToArgvW" instead of my implementation and fixed some critical bugs in other parts.

Including to that i added a working ffmpeg demo which i plan to make a simple player out of it - for testing all functions of the library ;)

v0.4.7 alpha:
  • Changed: [Win32] Load all user32 and shell32 functions dynamically
  • Changed: FPL_ENUM_AS_FLAGS_OPERATORS_INTERNAL requires a int type as well
  • Fixed: MemoryAlignedAllocate and MemoryAlignedFree was broken
  • Added: FPL_IS_ALIGNED macro

v0.4.6 alpha:
  • Fixed: [Win32] Crash when window is not set in the InitFlags but FPL_USE_WINDOW is set.

v0.4.5 alpha:
  • Changed: [Win32] Use CommandLineToArgvW for command line parsing

Edited by Finalspace on
Milestone Update!

I finally finished a huge milestone -> Audio playback! Hurray!
Also i extended the api a little bit and fixed some major bugs.
Now i can really start to focus on the next platform -> Linux X11/GLX/ALSA.

Last important note:

The asyncronous audio playback system is a stripped port from "mini_al.h" -> A awesome single header file library written by David Reid. So if you need more audio features than fpl provides, i recommend using "mini_al.h" directly.

Here is the full changelists:

## v0.5.0 beta:
- Added: [Win32] DirectSound playback support
- Added: Asyncronous audio playback

## v0.4.11 alpha:
- Fixed: [Win32] For now, load all user32 functions always, even when window is not used (This is to prepare for audio playback)
- Fixed: [Win32] ThreadStop was not releasing the thread handle
- Added: [Win32] ThreadWaitForAny
- Added: [Win32] SignalWaitForAll
- Added: [Win32] SignalWaitForAny
- Added: [Win32] SignalReset
- Added: FPL_NO_VIDEO
- Changed: ThreadWaitForSingle renamed to ThreadWaitForOne
- Changed: ThreadWaitForMultiple renamed to ThreadWaitForAll
- Changed: SignalWait renamed to SignalWaitForOne

## v0.4.10 alpha:
- Removed: Removed all _internal _INTERNAL postfixes from types, functions and macros
- Changed: Proper identitation for compiler directives based on context
- Added: [Win32] Dynamically loading ole32 functions (CoCreateInstance, CoInitializeEx, etc.)
- Fixed: [Win32] GetCursor was not using the dynamic loaded function
- Fixed: [Win32] Missing *Clipboard* dynamic functions

## v0.4.9 alpha:
- Removed: Removed all audio code for now
- Changed: A total cleanup of all internal stuff, so its much easier to add in new features

## v0.4.8 alpha:
- New: AtomicLoadU32, AtomicLoadU64, AtomicLoadS32, AtomicLoadS64, AtomicLoadPtr
- New: AtomicStoreU32, AtomicStoreU64, AtomicStoreS32, AtomicStoreS64, AtomicStorePtr
- New: AtomicExchangePtr, AtomicCompareAndExchangePtr, IsAtomicCompareAndExchangePtr
- New: [Win32] Implementation for AtomicLoadU32, AtomicLoadU64, AtomicLoadS32, AtomicLoadS64, AtomicLoadPtr
- New: [Win32] Implementation for AtomicStoreU32, AtomicStoreU64, AtomicStoreS32, AtomicStoreS64, AtomicStorePtr
- New: [Linux] Implementation for AtomicLoadU32, AtomicLoadU64, AtomicLoadS32, AtomicLoadS64, AtomicLoadPtr
- New: [Linux] Implementation for AtomicStoreU32, AtomicStoreU64, AtomicStoreS32, AtomicStoreS64, AtomicStorePtr
- New: [Win32] Loading of DirectSound (Prepare for audio output support)
- Draft: Added first audio output api
- Fixed: Threading context determination
- Fixed: [Win32] Fixed all thread implementations
- Fixed: [Win32] SetWindowLongPtrA does not exists on X86
- Fixed: [Win32] Missing call convention in SHGetFolderPathA and SHGetFolderPathW
- Changed: Improved header documentation (More examples, better descriptions, proper markdown syntax, etc.)
- Changed: All threading functions uses pointer instead of reference
- Changed: [Linux] Atomic* uses __sync instead of __atomic
- Changed: A bit of internal cleanup

Edited by Finalspace on
Update:
I added some useful audio functions and fixed some small bugs.
In addition i added a FFMPEG demo for testing out several features of the library, especially the multithreading and the audio system. At its current state the demo can already decode/render audio and video independently, including some caching of raw packets and decoded data. Works great, even though the ffmpeg api is a nightmare.

My main focus is get the ffmpeg to a usable state and then continue implementing the linux platform.

Also i decided to change the library a bit to not require C++/11 at all. Enum class and constexpr is nice, but there is no real reason to use that. So the next version will be C++/98 complaint.

Here is the full changelog for the latest version:

Changelog v0.5.1 beta:
  • New: audio::GetAudioNativeFormat()
  • New: audio::SetAudioClientReadCallback()
  • Fixed: InitFlags::Audio was never tested before InitAudio() was being called.
  • Changed: Renamed ThreadStop to ThreadDestroy


Edited by Finalspace on
Merry Christmas Update:

Merry Christmas everyone! Here comes the last FPL update for this year.

The library is now C++/98 complaint, therefore it does not need C++/11 anymore.
Also i added a few useful fields to the AudioDeviceFormat struct.

Oh and btw. i have rewritten the FFMPEG demo and it actually works now, including A/V sync. But there are still a lot of stuff to fix and improve.

My plans for the future is to finally implement the linux platform, but i expect this will not happen until next year, but who knows.

It would be nice if you can try it out and give me some feedback if it works for you or not.
Also if you have good ideas how to improve it, i am open (You can create a git issue as well as writing it here).

Here are the full changelog:

## v0.5.2 beta:
  • Changed: Library is now C++/98 complaint
  • Changed: The actual enum type for "flags" has no "s" at the end anymore.
  • Optimization: Changed some internal functions to "static inline"
  • Changed: Renamed audio::GetAudioNativeFormat to audio::GetAudioHardwareFormat
  • New: Added "periods", "bufferSizeInBytes", "bufferSizeInFrames" to AudioDeviceFormat

Edited by Finalspace on
I tried to replace the platform layer one of my application with FPL (just to test, I don't intend to use it permanently). It worked without major problem.

Compiling with VS2017:
- I got some warnings: "conditional expression is constant" is fpl_clearmem;
- warning on loose of precision while converting from uint32_t to WORD in the audio layer: wf.Format.wBitsPerSample = audio::GetAudioSampleSizeInBytes(audioSettings.desiredFormat.type) * 8;
- Some of the examples in the header aren't up to date. For example: VideoCompabilityProfile::ForwardCompability; => fpl::VideoCompabilityProfiles::Forward;

I didn't try to use inputs or audio so I don't know if that work.

A few things I prefer in my platform layer:
- If I press Alt + f4 I prefer to have a flag set that tells me the user wants to quit and let me handle how it will happen (this is probably doable in FPL but I didn't searched).
- For functions like GetWindowArea I would prefer passing pointers to my variable for FPL to fill them. GetWindowArea( uint32_t* width, uint32_t* height ); In addition GetWindowArea returns a WindowSize type which is just two integers. Unless it's used often I would prefer a generic vec2 type or passing two ints.

Maybe add a line that specify what compiler/linker flags are needed ?
If you generated the doxygen doc, is it uploaded somewhere ?
mrmixer
I tried to replace the platform layer one of my application with FPL (just to test, I don't intend to use it permanently). It worked without major problem.


Great, thats fine - just testing it out is all i want.

mrmixer

Compiling with VS2017:
- I got some warnings: "conditional expression is constant" is fpl_clearmem;
- warning on loose of precision while converting from uint32_t to WORD in the audio layer: wf.Format.wBitsPerSample = audio::GetAudioSampleSizeInBytes(audioSettings.desiredFormat.type) * 8;
- Some of the examples in the header aren't up to date. For example: VideoCompabilityProfile::ForwardCompability; => fpl::VideoCompabilityProfiles::Forward;


Yeah i need to fix those compiler warnings, i dont want to have any warnings at all. Also you are right, the examples needs to be updated as well.


mrmixer

I didn't try to use inputs or audio so I don't know if that work.


Its not that hard to use, but you need to handle the states yourself - fpl just provides you with all event messages. So a more advanced example using input will be added as well, like a simple platformer game or something.

mrmixer

A few things I prefer in my platform layer:
- If I press Alt + f4 I prefer to have a flag set that tells me the user wants to quit and let me handle how it will happen (this is probably doable in FPL but I didn't searched).
- For functions like GetWindowArea I would prefer passing pointers to my variable for FPL to fill them. GetWindowArea( uint32_t* width, uint32_t* height ); In addition GetWindowArea returns a WindowSize type which is just two integers. Unless it's used often I would prefer a generic vec2 type or passing two ints.


Yeah that alt+F4 is useful, firing a "exit" event in that case i would do.

Also regarding pointer arguments i will do that too, in addition to the already existing ones.
As a matter of fact, i would rather use the pointer ones by default and the return by value just calls the pointer one.

mrmixer

Maybe add a line that specify what compiler/linker flags are needed ?

If you generated the doxygen doc, is it uploaded somewhere ?


There is a small compiler guide in the documentation above in the source, but for win32 you basically does not need anything at all, because kernel32 is default linked in most win32 compilers.

About doxygen, right know its not uploaded anywhere yet, but i will do that. Keeping a recent one in the source directly would be fine right? I dont see a separate function in github for documentations...

Edited by Finalspace on
Small update

I fixed some doxygen statements and added the generated doxygen to the source.

## v0.5.2.1 beta:
  • Fixed: Corrected all doxygen statements to match new enum style or added missing exlamation marks.

Edited by Finalspace on
Important update:

Well switching to C++/98 was not that easy as i thought it to be - there are no standard int types, so i had to add one.
Now there shouldn´t be any C99 or C++11 code anymore.

But clang on win32 does still not compile :-(

## v0.5.3.0 beta:
  • Changed: Use custom int types because C++/98 has no default types unfortunatly
  • Fixed: Changed compiler detection order, because some non-MSVC compilers define _MSVC
  • Changed: Better C++/11 feature detection for optional nullptr and constexpr
Back to C++/11

Its embarrassing but i changed the library back to C++/11 and now its final.
Why? Because C++/11 is a good standard and it is supported in all modern compilers.

Here are the full changelog since last update:

## v0.5.6.0 beta:
- Changed: We are back to C++/11 and we will never going back to C++/98

## v0.5.5.1 beta:
- New[POSIX]: Implemented fpl::timings
- New[POSIX]: Implemented fpl::library
- New[POSIX]: Implemented fpl::threading::ThreadSleep
- Changed[POSIX]: Moved Linux fpl::console functions to Posix

## v0.5.5.0 beta:
- Changed: All internal handles are now unions now, so can have different sizes of handles
- Changed: Introduced POSIX platform and moved linux atomics into it

## v0.5.4.0 beta:
- Fixed: Some enum types was not using the namespace version
New years update:

I have done a tone since the last update, so i fixed some things, changed a lot - making it more robust.
Also i fully updated the doxygen style in the library to prepare for a full documentation.
But the FFMPEG demo got the most improvements, i have rewritten all the queues and added frame drop and seeking support.

Changelog:

## v0.5.7.0 beta:
- Changed: Total change of documentation style
- Changed: [Win32] ThreadMutex uses a critical section instead of a event
- Changed: [Win32] Include windows.h in the header, so we can define HANDLE, CRITICAL_SECTION in the api
- Changed: [Win32] Changed lots of functions to use conditions instead of asserts
- Changed: [Win32] Changed format specifiers to use either %d or %zu for integer types
- Changed: All Thread*Wait functions returns if the wait was successful or not in the same way Signal*Wait
- Changed: All ListFiles* functions uses reference instead of pointer
Starting year update

I added a few new functions to the api, fixed some bugs and improved some demos (especially the ffmpeg one - yeah i know this thing bugs me a lot...). Also i changed all code documentation to a javadoc/doxygen style to document every little detail.

But i still need some webspace for storing the docs. Right know i update the docs directly in the repo after i have done the commits for the change in version. Maybe i will get some small domain or something...

Anyway here is the full change log since last update.

Changelog

## v0.5.7.4 beta:
- Changed: Updated code documentation for all functions and types to doxygen/javadoc style
- Changed: SetFilePosition32 position is now int32_t instead of uint32_t to support negative positions as well
- Changed: Renamed desiredFormat to deviceFormat in AudioSettings
- Changed: [DirectSound] Use deviceID as GUID for the audio device
- new: Introduced AudioDeviceID
- New: Added deviceID field in AudioSettings
- New: Added audio::GetAudioDevices()
- New: Added strings::FormatString()

## v0.5.7.3 beta:
- Fixed: [Win32] Fixed SetWindowFullscreen was not working properly
- New: Introduced outputRect in VideoBackBuffer + Win32 implementation
- Changed: SetWindowFullscreen returns bool

## v0.5.7.2 beta:
- Added: Added new audio formats (AudioFormatType::F64, AudioFormatType::S64)

## v0.5.7.1 beta:
- Fixed: xInputSetState renamed to xInputGetState internally
- Added: Introduced InputSettings
- Added: [Win32] XInput controller detection is now limited to a fixed frequency, for improving performance (InputSettings.controllerDetectionFrequency)

Edited by Finalspace on
Fine update:

I updated the documentations a lot, with tutorials, examples, faq and all that stuff.
Also there was a few changes in the api and some bugfixes.

Stay tuned.

Here are the full changelog:

## v0.5.8.0 beta:
- Changed: SignalWaitFor* requires additional parameter for passing in the ThreadMutex reference (pthread compability)
- Changed: Signal* does not use const reference anymore (pthread compability)
- Changed: Updated documentation a ton
- Changed: Decreased MAX_ERRORSTATE_COUNT from 1024 to 256
- Changed: global__LastErrorState is a non-pointer global now
- Changed: Renamed GetPlatformLastError() to GetPlatformError()
- Changed: All array of objects parameters uses C++ array style -> int *arr[] instead of int **arr
- Fixed: MemoryAlignedFree() had wrong signature (void **) instead of (void *)
- Fixed: GetPlatformErrorCount() was not increasing when an empty error was pushed on for single error states
- Fixed: [Win32] InitPlatform() was not cleaning up the Win32State when the initialization failed
- Replaced: VideoCompabilityProfile is replaced by OpenGLCompabilityFlags (Only available with OpenGL)
- New: Added ClearPlatformErrors()
Documentation and improvements update

I finally finished the basic documentation, fixed some bugs and solidified the api a little bit.
Its best to update to this release as soon as possible!

This state of the documentation can be found here . I uploaded it to a friends webspace, so this link might change in the future.

It would be great if you look that up and see for youself if something important may be missing. Thanks!

Here is the changelog:

## v0.5.8.1 beta:
- Changed: KeyboardEventType::Char renamed to KeyboardEventType::CharInput
- Changed: Completed basic documentation
- Changed: Renamed VideoBackBuffer.stride to VideoBackBuffer.lineWidth
- Changed: Moved a few internal inline audio functions to the global audio namespace
- Fixed: [Win32] WM_CHAR was allowing unicode characters as well, which is wrong because it must be properly converted first.
- Fixed: Audio driver selection was buggy
- Added: pixelStride to fpl::video::VideoBackBuffer
- Added: fpl::window::ClearWindowEvents()
- Added: fpl::window::PushWindowEvent()
- Added: fpl::window::UpdateGameControllers()
- Added: fpl::audio::GetAudioBufferSizeInFrames()
- Added: fpl::audio::GetAudioDriverString()
- Added: fpl::audio::GetAudioFormatString()
- Added: fpl::audio::GetAudioSampleSizeInBytes()
- Added: fpl::audio::GetAudioFrameSizeInBytes()
- Added: fpl::audio::GetAudioBufferSizeInBytes()

Edited by Finalspace on
Refactoring for new platforms

I changed/moved the code a lot to make it more easier to add new platforms in the future.
Also i removed all the extra globals for storing api-functions and some states.
Lastly i decided to move out the documentation doxygen code into its own file, so the library get a bit smaller.

Oh and i updated the documentations on my friends server (Previous link).

Here is the changelog
## v0.5.9.0 beta:
- Changed: Moved documentation inside its own file "final_platform_layer.documentation"
- Changed: [Win32] Window creation uses CS_OWNDC always
- Changed: Refactoring of platform and non-platform code
- Changed: InitPlatform() and ReleasePlatform() is now platform independent

Edited by Finalspace on
Huge refactoring update:

I finally made video and window initialization the same way the audio system works. Now its much easier to add new video drivers or initialize new window systems, such as X11. Lastly i corrected some misdetection in arch/platform/compilers (ARM detection, C++ compilers only).

Here is the full changelog:

## v0.5.9.1 beta:
- Changed: MemoryInfos uses uint64_t instead of size_t
- Changed: Added BSD to platform detecton
- Changed: Architecture detection does not use _WIN64 or _WIN32 anymore
- Changed: fpl_api is now either fpl_platform_api or fpl_common_api
- Changed: Internal code refactoring
- Changed: Renamed VideoSettings driverType to driver
- Changed: Video initialization is now platform independent
- Changed: Window initialization is now platform independent
- Changed: Moved window::WindowFlip to video::VideoFlip
- Changed: [POSIX] Replaced file-io with POSIX open, read, write
- Changed: [Win32] Removed fpl_api from main entry point forward declararation
- Changed: [Win32] Moved main entry point inside the implementation block
- Fixed: Arm64 was misdetected as X64, this is now its own arch
- Fixed: GNUC and ICC are pure C-compilers, it makes no sense to detect such in a C++ library
- Fixed: [Linux][POSIX] Refactor init and release to match PlatformInitState and PlatformAppState
- Updated: Documentations updated
- New: [POSIX][X11][Linux] Added missing functions as not-implemented