Wednesday, June 28, 2017

Mac Development : 2

Month Three : Week Four


        This week I encountered a big issue with the Mac of development that really brought development to a standstill. The issue is that in order to kick off the event loop for an application on Mac, you must call [NSApp run]. This function will begin to take in and process message coming into the window. However, the big kicked is that on Mac this is a blocking function, whereas on Windows and Mac the window can be created and its events handled on a separate thread without blocking. This meant that my OpenWindow function on Mac never returns because it calls [NSApp run] at the end to open the window and start the loop. Initially I figured I could just launch the window on a secondary thread, but the I got hit with the realization that any Cocoa function MUST be called on the main thread of the application no matter what. This is a big problem because the entire test suite resides on a secondary thread to begin with.


       The answer for this one was first to figure out what [NSApp run] really does. By looking directly at its source code I was able to discover it was simply getting the next message from the NSApp and sending to off and then updating the window. So, I created my own [NSApp run] equivalent that does the exact same this but breaks when the event queue is empty so the thread can continue running. However, this didn't fix the issue completely because getting the next event is a Cocoa function which must be ran on the main thread. Through a lot of research on this issue I finally found to separate ways to send a whole block of code to the main thread from any other thread. By using this method of code dispatching and my custom run function I was able to sufficiently mimic the functionality of the Windows and Linux side GWindow.

Mac Development

Month Three : Week Three


        These next two weeks are dedicated to developing the Mac implementation for GWindow. I was two days behind at the beginning of this week because of the issues I encountered with Linux and the bug we all fixed as a group. The main issue I ran into for Mac this week was the fact that the message Loop for Mac is handled very differently from Windows and Linux and  I was very unfamiliar with the Objective-C language I would need to use to complete the Mac side of GWindow.


       First I looked at the Mac side of the libraries that the other Gateware members had already made. Through this and some Cocoa documentation I figured out that the WndProc functions I created for the Windows and Linux side of the message loops for GWindow are handled by a custom object called a Responder or a Delegate in Mac. Essentially a delegate is like a listener that you attach to an object you'd like to receive events from (like a window). The delegate is then filled with overridden event catching functions like windowDidResize windowDidMove. Inside these functions is where I fill out my custom GWindow events and pass them along to my GWindow's listeners.

       However, just writing the delegate wasn't enough. Now I had to figure out how to connect them to my window which is being handled in a different file and even a different language. It turns out .mm and .cpp can be included directly into each other, and my GWindowDelegate was declared in the .mm with the class declaration and then assigned to my window with [window setDelegate:GWDelegate]. In the end, it took a a lot of official Cocoa documentation reading and testing things out in a separate testApp to get things to work correctly.

Linux Development : 2

Month Three : Week Two


        This week the main issue I ran into was dealing with the X11 window event system. The event loop is running on its own thread so it is hard to tell when a window call is going to be processed and have the changes made be visible to the user. This meant that an X11 function may be called successfully, but the Test-Suite would keep moving on to the next test before the function was completed, making the test-suite get off track and start failing.

        Like most operating systems, when an X11 event is sent  it enters a queue that processes messages one by one until the queue is empty. For the purposes of my library, I need the results of the functions I call to be in effect before the program continues on. Because this was not occurring I was experiencing very frustrating bugs that were not immediately obvious. For instance, when minimizing or moving a window or messing with its borders, the window would not react for several seconds but the function would return true because the action was successful, it just wasn't visible yet.

       By looking through some example code of other window handlers it became apparent that most X11 calls could be followed by XFlush() which will flush and process every message in the queue. By adding an XFlush() and sleep(1) after every X11 call that edits a window I was able to make sure that the functions were completing and actually changing the window before my program is allowed to move on, which resulted in successful tests.

Linux Development

Month Three : Week One

        This month is all about Linux and Mac development. The first week I decided to start with Linux because I am most familiar with it and was fairly confident I could deliver on time. The major issue I encountered was just the fact that X11 is rarely used by itself by an end-user, and because of this there is not a lot of useful documentation or example projects that display correct usage of many common window functions that I need to implement. Most posts tell me to not use raw X11 and to just use a toolkit, which does not help me at all because I am essentially trying to be the toolkit.

        The manner in which this issue manifested itself most often was when messing with the fullscreen functionality of the X11 window.  X11 has no easy to use fullscreen toggle or even a good way to check if the window is currently fullscreen. The most frustrating and time consuming way this would inhibit me is when I would manage to get the window fullscreen, nothing short of a user pressing the maximize button could get it out of fullscreen mode. Resizing, unmapping, taking the border off, nothing worked. Which essential meant if the window ever became fullscreen it would be impossible to restore it to its normal size through code. It took lots of trial and error to eventually discover that it is much easier to create a custom ClientMessage and fill that message with the information to set the window to fullscreen or out of fullscreen instead of trying to manually resize it. There is a massive list of properties that denote every attribute of an X11 window, and it is possible to peek and edit these properties by grabbing their ID's using Atoms and then putting them into a set or delete message and sending that off to the window with XSendEvent. Eventually I discovered that fullscreen mode on an X11 window is denoted by two properties being set on the window,  _NET_WM_STATE_MAXIMIZED_HORZ and _NET_WM_STATE_MAXIMIZED_VERT.

By grabbing these two properties and sending a property delete message to the window, I was able to get the window to exit fullscreen mode set itself to its proper internal size. Once I was able to get the window out of fullscreen it was trivial to do move and resize it.

Month #1 of Gateware research for mobile; Android Research

The great little green android man... little did I know that to work with this guy I had to assemble it first. Thanks to google and its Android Studio, at least it came with a manual.

Android is definitely not as user friendly as its competitor, especially since it's on its own world, and in this world, the language spoken is Java. Apparently google noticed this poor patched up robot dude and reworked him enough that now they have one of the best developer resources library I have ever seen.

After I got hold of these resources it was very easy to get a grasp of deployment in their environment, giving me a warm feel that if any questions arise (or android parts fall off) I'll have their resources waiting for me.

Month #1 of Gateware research for mobile; iOS Research

I joined the gateware team with the task of porting as many existing libraries as possible into iOS and Android, starting with iOS.

I've never gone too far into apple's development environment until now, and to be honest, I was very surprised to find a very organized and resourceful environment. It definitely had that apple feel of giving you as much as they can to help you, but this time, without abstracting the deeper layers of complexity that come with software, at least, not as much as they would like to. 

I also had to dive pretty deep into the world of Objective-C, and was amazed. Once you get used to it, it's easy to see the reasoning behind their choices of syntax and functionality. I was also surprised at how simple it is to combine it with C++, although thinking in low-levels, it shouldn't be that complicated given that they both are, in their raw form, C.

All in all, I have found new respect for apple after going through this experience, and am sure I will appreciate them even more in the near future.

Learning the Inner Workings of Audio Part 1: RESEARCH

For the past 48 hours, my life have been succumbed to study. I have been tasked with making a multi-platform Audio Engine for games, or simply a Audio Library whose focus will be for playing, loading, and editing sounds/music for games. To do this I will be using existing first party libraries to do the heavy lifting while the library I create will be able to reference those existing libraries when needed.

But enough about that, onto what I learned.

Generally, gaming audio files run on their own threads at run-time and usually sounds needed for a level are pre-loaded into memory prior to actually playing the file and unloaded when it is no longer needed. Have you ever noticed your game freezes but the background audio is still playing fine, this is the reason why.  One of the most commonly used file formats used in games is the .wav file due to its heavily documented and easy to read/write file format. This knowledge is needed since some api's such as XAudio2 doesn't actually handle loading the data itself but rather once the data is loaded, it accesses the necessary hardware to play that sound. This is not universally accepted as CoCos2d, another api designed specifically with games in mind, handles all the loading and playing of files itself.

Another common thing I found among different api's was the use of  Instancing and Asynchronous Callbacks. For sounds that may stay for the length of the game such as background music, an instance of sound kind of audio device is create which manages the audio specifically for the background music. A separate instance of an audio or several instances of an object might be used just to handle specific sound effects.  This way the BGM and sound effects can vary in volume and other things as the player wishes.  Callbacks are used mostly with streaming the audio so that huge music files aren't loaded into memory all at once and they are asynchronous as to not block the rest of the gameplay while its waiting for some feedback to play a sound

Well that's all for today, next time I'll be delving more into XAudio2 and how one loads and plays a sound with it. Until then, you can read up more on XAudio2 on MSDN.

In the meantime, You've activated my trap card! Goodbye!