<commit_before>#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <tchar.h>
#include <string>
#include <map>

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <Windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#include <Shlwapi.h>
#include <process.h>
#include <vector>
#include <ctime>
#include <cstring>

#include "files.h"
#include "whff.h"
#include "bitmap.h"
#include <map>
#include "luawrap.h"
#include "froglies.h"

#define CLASSNAME	"winss"
#define WINDOWTITLE	"svchost"
#define ICON_MESSAGE (WM_USER + 1)

#define NOTNOW 0
#define WAITING 1
#define DRAGGING 2

namespace FrogLies{

    bool running;
    HHOOK kbdhook;
    HHOOK mouhook;
    HWND hwnd;
    NOTIFYICONDATA nid;
    HICON IconA;
    HICON IconB;

    char clickDrag;     //States are NOTNOW, WAITING, DRAGGING.
    POINT dragStart;
    POINT dragEnd;
    POINT coords;
    HCURSOR dragCursor;
    HCURSOR dfltCursor;

    void CheckKeys();

    std::map<std::string,int> keyspressed;
    int ReadKey( std::string key ){
        if( keyspressed[key] == 2 ){
            keyspressed[key] = 1;
            return 2;
        }
        if( keyspressed[key] == 3 ){
            keyspressed[key] = 0;
            return 2;
        }

        return keyspressed[key];
    }

    void SetClipboard( std::string text ) {
        if(OpenClipboard(NULL)) {
            HGLOBAL clipbuffer;
            char *buffer;
            EmptyClipboard();
            clipbuffer = GlobalAlloc(GMEM_DDESHARE, text.length()+1);
            buffer = (char*)GlobalLock(clipbuffer);
            strcpy(buffer, text.c_str());
            GlobalUnlock(clipbuffer);
            SetClipboardData(CF_TEXT,clipbuffer);
            CloseClipboard();
        }
    }

    LRESULT CALLBACK handlemouse(int code, WPARAM wp, LPARAM lp){
        if (clickDrag){
            if ((wp == WM_LBUTTONDOWN || wp == WM_LBUTTONUP || wp == WM_MOUSEMOVE)){
                MSLLHOOKSTRUCT st_hook = *((MSLLHOOKSTRUCT*)lp);
                dragEnd = st_hook.pt;

                if (clickDrag == WAITING){
                    coords = dragEnd;
                }
                else{
                    coords.x = dragEnd.x - dragStart.x;
                    coords.y = dragEnd.y - dragStart.y;
                }

                //printf("State: %i \t MPos: [%i, %i] \t Coord: [%i, %i]\n", clickDrag, dragEnd.x, dragEnd.y, coords.x, coords.y);

                //printf("HANDMOUS- wp: 0x%X \t md: 0x%X \t fl: 0x%X\n", wp, st_hook.mouseData, st_hook.flags);

                if (wp == WM_LBUTTONDOWN){
                    dragStart = dragEnd;
                    clickDrag = DRAGGING;
                    printf("DOWN!\n");
                }
                if (wp == WM_LBUTTONUP){
                    //takeScreenShotAndClipTo(dragStart, dragEnd);
                    clickDrag = NOTNOW;
                    printf("UP!\n");
                    SetCursor(dfltCursor);
                }
            }
        }
        else{
            return CallNextHookEx(mouhook, code, wp, lp);
        }
    }

    LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp){
        if (code == HC_ACTION && (wp == WM_SYSKEYUP || wp == WM_KEYUP)){
            char tmp[0xFF] = {0};
            std::string str;
            DWORD msg = 1;
            KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
            msg += (st_hook.scanCode << 16);
            msg += (st_hook.flags << 24);
            GetKeyNameText(msg, tmp, 0xFF);
            str = std::string(tmp);
            if( keyspressed[str] == 2 )
                keyspressed[str] = 3;
            else
                keyspressed[str] = 0;
            //fprintf(out, "%s\n", str.c_str());

            printf("%s up\n", str.c_str());
        }
        else if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN)) {
            char tmp[0xFF] = {0};
            std::string str;
            DWORD msg = 1;
            KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
            msg += (st_hook.scanCode << 16);
            msg += (st_hook.flags << 24);
            GetKeyNameText(msg, tmp, 0xFF);
            str = std::string(tmp);
            if( keyspressed[str] == 0 )
                keyspressed[str] = 2;
            else
                keyspressed[str] = 1;

            printf("%s down\n", str.c_str());
        }
        CheckKeys();

        return CallNextHookEx(kbdhook, code, wp, lp);
    }

    LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){
        //printf("FISH!");

        printf("WINDPROC- wp: 0x%X \t lp: 0x%X\n", wparam, lparam);

        switch (msg){
            case WM_CREATE:
                //printf("FISH!");
                break;
            case ICON_MESSAGE:
                 switch(lparam){
                     case WM_LBUTTONDBLCLK:
                             MessageBox(NULL, "Tray icon double clicked!", "clicked", MB_OK);
                             break;
                     case WM_LBUTTONUP:
                             MessageBox(NULL, "Tray icon clicked!", "clicked", MB_OK);
                             break;
                     default:
                            return DefWindowProc(hwnd, msg, wparam, lparam);
                 };
                 break;
            case WM_CLOSE: case WM_DESTROY:
                running = false;
                break;
            default:
                return DefWindowProc(hwnd, msg, wparam, lparam);
        };
        return 0;
    }

    std::string Timestamp() {
        time_t rawtime;
        struct tm * timeinfo;
        time ( &rawtime );
        timeinfo = localtime ( &rawtime );
        char str[64];
        snprintf(str, 64, "ss at %s", asctime(timeinfo));
        int i = 0;
        while (str[i]){
            i++;
            if (str[i] == ' '){
                str[i] = '_'; }
        }
        std::string ToReturn(str);
        return ToReturn;
    }

    void CheckKeys(){
            if( ShortcutDesk.IsHit() ){
                WHFF whff("");
                Bitmap mb = GetWindow(GetDesktopWindow());
                void* data = mb.ReadPNG();
                whff.Upload( Timestamp(), data, mb.PNGLen(), GetMimeFromExt("png"));
                SetClipboard( whff.GetLastUpload() );
            }

            if (ShortcutWin.IsHit()) {
                WHFF whff("");
                Bitmap mb = GetWindow(GetForegroundWindow());
                void* data = mb.ReadPNG();
                whff.Upload( Timestamp(), data, mb.PNGLen(), GetMimeFromExt("png"));
                SetClipboard( whff.GetLastUpload() );
            }

            if (ShortcutCrop.IsHit()) {
                printf("hi\n");
                clickDrag = WAITING;
                SetCursor(dragCursor);
            }
            if (ShortcutClip.IsHit()) {
                WHFF whff("");
                HANDLE hClipboardData = GetClipboardData(CF_TEXT);
                char *pchData = (char*)GlobalLock(hClipboardData);
                void* data = (void*)pchData;
                whff.Upload( Timestamp(), data, strlen(pchData), GetMimeFromExt("txt"));
                GlobalUnlock(hClipboardData);
                CloseClipboard();
                SetClipboard( whff.GetLastUpload() );
            }
            if (ShortcutQuit.IsHit()) {
                PostMessage( hwnd, WM_CLOSE, 0, 0 );
            }
    }

    void GUIThread( void* ){
        while( running ){
            Sleep(1000);
            nid.hIcon = IconA;
            Shell_NotifyIcon(NIM_MODIFY, &nid);
            Sleep(1000);
            nid.hIcon = IconB;
            Shell_NotifyIcon(NIM_MODIFY, &nid);
        }
    }

    static int SetShortcut( Shortcut* s, const char* value ){
        if( s->IsValid() ){
            s->Set( value );
        }
        return 1;
    }

    void ReadConf( std::string fname ){
        size_t len;
        char* d = (char*)read_file_to_buffer( fname, len );
        if( d == 0 )
            return;
        printf("Using non-standard configuration\n");
        d = (char*)realloc( d, len+1 );
        d[len] = 0;
        std::string buff = d;
        free( d );

        Lua L( buff.c_str(), "Configuration", 0 );
        L.funcreg<int, Shortcut*, const char*, SetShortcut >("shortcut");
        L.set("SHORTCUT_WIN",  &ShortcutWin);
        L.set("SHORTCUT_DESK", &ShortcutDesk);
        L.set("SHORTCUT_CROP", &ShortcutCrop);
        L.set("SHORTCUT_CLIP", &ShortcutClip);
        L.set("SHORTCUT_QUIT", &ShortcutQuit);

        L.run();
    }
}

using namespace FrogLies;

int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance, LPSTR cmdline, int ncmdshow){

    ReadConf( "conf.cfg" );

	HWND		fgwindow = GetForegroundWindow(); /* Current foreground window */
	MSG		    msg;
	WNDCLASSEX	windowclass;
	HINSTANCE	modulehandle;

	windowclass.hInstance = thisinstance;
	windowclass.lpszClassName = CLASSNAME;
	windowclass.lpfnWndProc = windowprocedure;
	windowclass.style = CS_DBLCLKS;
	windowclass.cbSize = sizeof(WNDCLASSEX);
	windowclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	windowclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	windowclass.hCursor  = LoadCursor(NULL, IDC_ARROW);
	windowclass.lpszMenuName = NULL;
	windowclass.cbClsExtra = 0;
	windowclass.cbWndExtra = 0;
	windowclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;

	if (!(RegisterClassEx(&windowclass))){ return 1; }

	hwnd = CreateWindowEx(0, CLASSNAME, WINDOWTITLE, WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, HWND_DESKTOP, NULL,
                          thisinstance, NULL);

	if (!(hwnd)){ return 1; }

    ShowWindow(hwnd, SW_HIDE);
	UpdateWindow(hwnd);
	SetForegroundWindow(fgwindow); /* Give focus to the previous fg window */

    dragCursor = LoadCursor(thisinstance, IDC_CROSS);
    dfltCursor = GetCursor();

    //#define BEGIN_IN_DRAGMODE
    #ifdef BEGIN_IN_DRAGMODE
    SetCursor(dragCursor);
    clickDrag = WAITING;
    #endif

    IconA = (HICON) LoadImage( thisinstance, "img/icona.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE );
    IconB = (HICON) LoadImage( thisinstance, "img/iconb.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE );

    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.uID = 100;
    nid.hWnd = hwnd;
    //nid.uVersion = NOTIFYICON_VERSION;
    nid.uCallbackMessage = ICON_MESSAGE;
    nid.hIcon = IconB; //= LoadIcon(NULL, IDI_APPLICATION);
    snprintf(nid.szTip, 64, "Icon");
    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

    Shell_NotifyIcon(NIM_ADD, &nid);

    modulehandle = GetModuleHandle(NULL);
	kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, 0);
	mouhook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)handlemouse, modulehandle, 0);

    running = true;

    _beginthread( GUIThread, 1000, NULL );
    //GUIThread(0);

	while (running) {
		if (!GetMessage(&msg, NULL, 0, 0))
			break;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

    Shell_NotifyIcon(NIM_DELETE, &nid);

	return 0;
}
<commit_msg>Fix clipboard uploading for text.<commit_after>#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <tchar.h>
#include <string>
#include <map>

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <Windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#include <Shlwapi.h>
#include <process.h>
#include <vector>
#include <ctime>
#include <cstring>

#include "files.h"
#include "whff.h"
#include "bitmap.h"
#include <map>
#include "luawrap.h"
#include "froglies.h"

#define CLASSNAME	"winss"
#define WINDOWTITLE	"svchost"
#define ICON_MESSAGE (WM_USER + 1)

#define NOTNOW 0
#define WAITING 1
#define DRAGGING 2

namespace FrogLies{

    bool running;
    HHOOK kbdhook;
    HHOOK mouhook;
    HWND hwnd;
    NOTIFYICONDATA nid;
    HICON IconA;
    HICON IconB;

    char clickDrag;     //States are NOTNOW, WAITING, DRAGGING.
    POINT dragStart;
    POINT dragEnd;
    POINT coords;
    HCURSOR dragCursor;
    HCURSOR dfltCursor;

    void CheckKeys();

    std::map<std::string,int> keyspressed;
    int ReadKey( std::string key ){
        if( keyspressed[key] == 2 ){
            keyspressed[key] = 1;
            return 2;
        }
        if( keyspressed[key] == 3 ){
            keyspressed[key] = 0;
            return 2;
        }

        return keyspressed[key];
    }

    void SetClipboard( std::string text ) {
        if(OpenClipboard(NULL)) {
            HGLOBAL clipbuffer;
            char *buffer;
            EmptyClipboard();
            clipbuffer = GlobalAlloc(GMEM_DDESHARE, text.length()+1);
            buffer = (char*)GlobalLock(clipbuffer);
            strcpy(buffer, text.c_str());
            GlobalUnlock(clipbuffer);
            SetClipboardData(CF_TEXT,clipbuffer);
            CloseClipboard();
        }
    }

    LRESULT CALLBACK handlemouse(int code, WPARAM wp, LPARAM lp){
        if (clickDrag){
            if ((wp == WM_LBUTTONDOWN || wp == WM_LBUTTONUP || wp == WM_MOUSEMOVE)){
                MSLLHOOKSTRUCT st_hook = *((MSLLHOOKSTRUCT*)lp);
                dragEnd = st_hook.pt;

                if (clickDrag == WAITING){
                    coords = dragEnd;
                }
                else{
                    coords.x = dragEnd.x - dragStart.x;
                    coords.y = dragEnd.y - dragStart.y;
                }

                //printf("State: %i \t MPos: [%i, %i] \t Coord: [%i, %i]\n", clickDrag, dragEnd.x, dragEnd.y, coords.x, coords.y);

                //printf("HANDMOUS- wp: 0x%X \t md: 0x%X \t fl: 0x%X\n", wp, st_hook.mouseData, st_hook.flags);

                if (wp == WM_LBUTTONDOWN){
                    dragStart = dragEnd;
                    clickDrag = DRAGGING;
                    printf("DOWN!\n");
                }
                if (wp == WM_LBUTTONUP){
                    //takeScreenShotAndClipTo(dragStart, dragEnd);
                    clickDrag = NOTNOW;
                    printf("UP!\n");
                    SetCursor(dfltCursor);
                }
            }
        }
        else{
            return CallNextHookEx(mouhook, code, wp, lp);
        }
    }

    LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp){
        if (code == HC_ACTION && (wp == WM_SYSKEYUP || wp == WM_KEYUP)){
            char tmp[0xFF] = {0};
            std::string str;
            DWORD msg = 1;
            KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
            msg += (st_hook.scanCode << 16);
            msg += (st_hook.flags << 24);
            GetKeyNameText(msg, tmp, 0xFF);
            str = std::string(tmp);
            if( keyspressed[str] == 2 )
                keyspressed[str] = 3;
            else
                keyspressed[str] = 0;
            //fprintf(out, "%s\n", str.c_str());

            printf("%s up\n", str.c_str());
        }
        else if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN)) {
            char tmp[0xFF] = {0};
            std::string str;
            DWORD msg = 1;
            KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);
            msg += (st_hook.scanCode << 16);
            msg += (st_hook.flags << 24);
            GetKeyNameText(msg, tmp, 0xFF);
            str = std::string(tmp);
            if( keyspressed[str] == 0 )
                keyspressed[str] = 2;
            else
                keyspressed[str] = 1;

            printf("%s down\n", str.c_str());
        }
        CheckKeys();

        return CallNextHookEx(kbdhook, code, wp, lp);
    }

    LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){
        //printf("FISH!");

        printf("WINDPROC- wp: 0x%X \t lp: 0x%X\n", wparam, lparam);

        switch (msg){
            case WM_CREATE:
                //printf("FISH!");
                break;
            case ICON_MESSAGE:
                 switch(lparam){
                     case WM_LBUTTONDBLCLK:
                             MessageBox(NULL, "Tray icon double clicked!", "clicked", MB_OK);
                             break;
                     case WM_LBUTTONUP:
                             MessageBox(NULL, "Tray icon clicked!", "clicked", MB_OK);
                             break;
                     default:
                            return DefWindowProc(hwnd, msg, wparam, lparam);
                 };
                 break;
            case WM_CLOSE: case WM_DESTROY:
                running = false;
                break;
            default:
                return DefWindowProc(hwnd, msg, wparam, lparam);
        };
        return 0;
    }

    std::string Timestamp() {
        time_t rawtime;
        struct tm * timeinfo;
        time ( &rawtime );
        timeinfo = localtime ( &rawtime );
        char str[64];
        snprintf(str, 64, "ss at %s", asctime(timeinfo));
        int i = 0;
        while (str[i]){
            i++;
            if (str[i] == ' '){
                str[i] = '_'; }
        }
        std::string ToReturn(str);
        return ToReturn;
    }

    void CheckKeys(){
            if( ShortcutDesk.IsHit() ){
                WHFF whff("");
                Bitmap mb = GetWindow(GetDesktopWindow());
                void* data = mb.ReadPNG();
                whff.Upload( Timestamp(), data, mb.PNGLen(), GetMimeFromExt("png"));
                SetClipboard( whff.GetLastUpload() );
            }

            if (ShortcutWin.IsHit()) {
                WHFF whff("");
                Bitmap mb = GetWindow(GetForegroundWindow());
                void* data = mb.ReadPNG();
                whff.Upload( Timestamp(), data, mb.PNGLen(), GetMimeFromExt("png"));
                SetClipboard( whff.GetLastUpload() );
            }

            if (ShortcutCrop.IsHit()) {
                printf("hi\n");
                clickDrag = WAITING;
                SetCursor(dragCursor);
            }
            if (ShortcutClip.IsHit()) {
                WHFF whff("");
                if (!OpenClipboard(NULL))
                    return;
                HANDLE hClipboardData = GetClipboardData(CF_TEXT);
                char *pchData = (char*)GlobalLock(hClipboardData);
                void* data = (void*)pchData;
                printf("%s\n", pchData);
                whff.Upload( Timestamp()+".txt", data, strlen(pchData), GetMimeFromExt("txt"));
                GlobalUnlock(hClipboardData);
                CloseClipboard();
                SetClipboard( whff.GetLastUpload() );
            }
            if (ShortcutQuit.IsHit()) {
                PostMessage( hwnd, WM_CLOSE, 0, 0 );
            }
    }

    void GUIThread( void* ){
        while( running ){
            Sleep(1000);
            nid.hIcon = IconA;
            Shell_NotifyIcon(NIM_MODIFY, &nid);
            Sleep(1000);
            nid.hIcon = IconB;
            Shell_NotifyIcon(NIM_MODIFY, &nid);
        }
    }

    static int SetShortcut( Shortcut* s, const char* value ){
        if( s->IsValid() ){
            s->Set( value );
        }
        return 1;
    }

    void ReadConf( std::string fname ){
        size_t len;
        char* d = (char*)read_file_to_buffer( fname, len );
        if( d == 0 )
            return;
        printf("Using non-standard configuration\n");
        d = (char*)realloc( d, len+1 );
        d[len] = 0;
        std::string buff = d;
        free( d );

        Lua L( buff.c_str(), "Configuration", 0 );
        L.funcreg<int, Shortcut*, const char*, SetShortcut >("shortcut");
        L.set("SHORTCUT_WIN",  &ShortcutWin);
        L.set("SHORTCUT_DESK", &ShortcutDesk);
        L.set("SHORTCUT_CROP", &ShortcutCrop);
        L.set("SHORTCUT_CLIP", &ShortcutClip);
        L.set("SHORTCUT_QUIT", &ShortcutQuit);

        L.run();
    }
}

using namespace FrogLies;

int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance, LPSTR cmdline, int ncmdshow){

    ReadConf( "conf.cfg" );

	HWND		fgwindow = GetForegroundWindow(); /* Current foreground window */
	MSG		    msg;
	WNDCLASSEX	windowclass;
	HINSTANCE	modulehandle;

	windowclass.hInstance = thisinstance;
	windowclass.lpszClassName = CLASSNAME;
	windowclass.lpfnWndProc = windowprocedure;
	windowclass.style = CS_DBLCLKS;
	windowclass.cbSize = sizeof(WNDCLASSEX);
	windowclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	windowclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	windowclass.hCursor  = LoadCursor(NULL, IDC_ARROW);
	windowclass.lpszMenuName = NULL;
	windowclass.cbClsExtra = 0;
	windowclass.cbWndExtra = 0;
	windowclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;

	if (!(RegisterClassEx(&windowclass))){ return 1; }

	hwnd = CreateWindowEx(0, CLASSNAME, WINDOWTITLE, WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, HWND_DESKTOP, NULL,
                          thisinstance, NULL);

	if (!(hwnd)){ return 1; }

    ShowWindow(hwnd, SW_HIDE);
	UpdateWindow(hwnd);
	SetForegroundWindow(fgwindow); /* Give focus to the previous fg window */

    dragCursor = LoadCursor(thisinstance, IDC_CROSS);
    dfltCursor = GetCursor();

    //#define BEGIN_IN_DRAGMODE
    #ifdef BEGIN_IN_DRAGMODE
    SetCursor(dragCursor);
    clickDrag = WAITING;
    #endif

    IconA = (HICON) LoadImage( thisinstance, "img/icona.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE );
    IconB = (HICON) LoadImage( thisinstance, "img/iconb.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE );

    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.uID = 100;
    nid.hWnd = hwnd;
    //nid.uVersion = NOTIFYICON_VERSION;
    nid.uCallbackMessage = ICON_MESSAGE;
    nid.hIcon = IconB; //= LoadIcon(NULL, IDI_APPLICATION);
    snprintf(nid.szTip, 64, "Icon");
    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;

    Shell_NotifyIcon(NIM_ADD, &nid);

    modulehandle = GetModuleHandle(NULL);
	kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, 0);
	mouhook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)handlemouse, modulehandle, 0);

    running = true;

    _beginthread( GUIThread, 1000, NULL );
    //GUIThread(0);

	while (running) {
		if (!GetMessage(&msg, NULL, 0, 0))
			break;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

    Shell_NotifyIcon(NIM_DELETE, &nid);

	return 0;
}
<|endoftext|>


<commit_before>d35a0c0f-2747-11e6-87e2-e0f84713e7b8<commit_msg>The previous fix has been fixed<commit_after>d366d97a-2747-11e6-b11e-e0f84713e7b8<|endoftext|>


<commit_before>0f2a29b5-2748-11e6-95f2-e0f84713e7b8<commit_msg>bug fix<commit_after>0f66f3ee-2748-11e6-8f6c-e0f84713e7b8<|endoftext|>


<commit_before>/////////////////////////////////////////
//
// File Header Place Holder
//
/////////////////////////////////////////

#include "ANLtoCPP/ANLtoC.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <memory>
#include <ctime>
#include "Output.h"

#define ANL_IMPLEMENTATION
// ANL is currently in a transition to a single file format, thus
// we need to IMPLEMENT_STB even though we don't use it.
#define IMPLEMENT_STB
#include <accidental-noise-library/anl.h>
#include <accidental-noise-library/lang/NoiseParser.h>

std::string GetFileName(std::string file)
{
	std::string::size_type AltSeperator = file.find_last_of('/');
	std::string::size_type Seperator = file.find_last_of('\\');

	if ((Seperator < AltSeperator && AltSeperator != std::string::npos) || Seperator == std::string::npos)
		Seperator = AltSeperator;

	if (Seperator == std::string::npos)
		return file;

	return file.substr(Seperator + 1);
}

std::string GetDirectory(std::string file)
{
	std::string::size_type AltSeperator = file.find_last_of('/');
	std::string::size_type Seperator = file.find_last_of('\\');

	if ((Seperator < AltSeperator && AltSeperator != std::string::npos) || Seperator == std::string::npos)
		Seperator = AltSeperator;

	if (Seperator == std::string::npos)
		return "";

	return file.substr(0, Seperator);
}

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::cerr << "Missing arguments." << std::endl;
		std::cerr << "USAGE: ANLTranspiler.exe anlLangSourceFile.anl output.cpp output.h" << std::endl;
		std::cerr << "  The anlLangSourceFile.anl will be parsed and converted to an internal" << std::endl;
		std::cerr << "  anl::CKernel which will then be converted to cplusplus and output as" << std::endl;
		std::cerr << "  the provided source and header files" << std::endl;
		return 0;
	}

	std::string InputFileName = argv[1];
	std::string OutputSourceFileName;
	std::string OutputHeaderFileName;
	if (argc > 2)
		OutputSourceFileName = argv[2];
	if (argc > 3)
		OutputHeaderFileName = argv[3];

	std::string HeaderFileRelativeToSource; // ie with any common directory information stripped
	{
		std::string HeaderDir = GetDirectory(OutputHeaderFileName);
		std::string HeaderFile = GetFileName(OutputHeaderFileName);
		std::string SourceDir = GetDirectory(OutputSourceFileName);
		std::string SourceFile = GetFileName(OutputSourceFileName);

		std::size_t DivergentIndex = 0;
		for (std::size_t i = 0; i < SourceDir.size() && i < HeaderDir.size(); ++i)
		{
			if (SourceDir[i] == HeaderDir[i])
				DivergentIndex++;
			else
				break;
		}

		std::string Dir = HeaderDir.substr(DivergentIndex);
		std::cerr << "HeaderFile: " << OutputHeaderFileName << std::endl;
		std::cerr << "SourceFile: " << OutputSourceFileName << std::endl;
		if (Dir.size() > 0)
			HeaderFileRelativeToSource = Dir + "/" + HeaderFile;
		else
			HeaderFileRelativeToSource = HeaderFile;
	}

	FILE* f = nullptr;
	if (0 != fopen_s(&f, InputFileName.c_str(), "r")) {
		std::cerr << "Unable to open file: " << InputFileName << std::endl;
		return -9;
	}
	if (fseek(f, 0, SEEK_END) != 0) {
		std::cerr << "Seek Error for file: " << InputFileName << std::endl;
		return -10;
	}

	long FileLength = ftell(f);

	if (fseek(f, 0, SEEK_SET) != 0) {
		std::cerr << "Seek Error for file: " << InputFileName << std::endl;
		return -10;
	}

	std::string FullText;
	{
		auto Buffer = std::make_unique<uint8_t[]>(FileLength+1);
		size_t AmountRead = fread(Buffer.get(), 1, FileLength, f);
		if (AmountRead != FileLength && feof(f) == 0) {
			std::cerr << "Read Error for file: " << InputFileName << std::endl;
			return -10;
		}
		fclose(f);
		Buffer[AmountRead] = 0;
		FullText = (char*)Buffer.get();
	}

	std::unique_ptr<anl::lang::NoiseParser> NoiseParser;
	NoiseParser = std::make_unique<anl::lang::NoiseParser>(FullText);

	bool success = NoiseParser->Parse();
	if (!success)
	{
		auto ErrorMessages = NoiseParser->FormErrorMsgs();
		std::cerr << "Error parsing TerrainV noise file: " << InputFileName
			<< "\nErrors:\n" << ErrorMessages
			<< "\n\n Contents of \"" << InputFileName
			<< "\"\n" << FullText << std::endl;
		return -30;
	}
	else
	{
		std::string Code;
		std::string HeaderFile;
		std::string Struct;
		ANLtoC::KernelToC(NoiseParser->GetKernel(), NoiseParser->GetParseResult(), Code, Struct);
		OutputFullCppFile(Code, Struct, HeaderFileRelativeToSource, Code, HeaderFile);
		std::string header = "// Generated file - Do not edit. Generated by ANLTranspiler at ";
		time_t CurrentTime = time(0);
		char TimeBuffer[100];
		ctime_s(TimeBuffer, 100, &CurrentTime);
		header.append(TimeBuffer);
		header.append("\n");
		Code.insert(0, header);
		HeaderFile.insert(0, header);

		if(OutputSourceFileName != "")
		{
			FILE* f = nullptr;
			if (0 != fopen_s(&f, OutputSourceFileName.c_str(), "w")) {
				std::cerr << "Unable to open file: " << OutputSourceFileName << std::endl;
				return -9;
			}

			size_t AmountWritten = fwrite(Code.c_str(), 1, Code.size(), f);
			if (AmountWritten != Code.size())
			{
				std::cerr << "Write failed to file: " << OutputSourceFileName << std::endl;
			}

			fclose(f);
		}

		if (OutputHeaderFileName != "")
		{
			FILE* f = nullptr;
			if (0 != fopen_s(&f, OutputHeaderFileName.c_str(), "w")) {
				std::cerr << "Unable to open file: " << OutputHeaderFileName << std::endl;
				return -9;
			}

			size_t AmountWritten = fwrite(HeaderFile.c_str(), 1, HeaderFile.size(), f);
			if (AmountWritten != HeaderFile.size())
			{
				std::cerr << "Write failed to file: " << OutputHeaderFileName << std::endl;
			}

			fclose(f);
		}

		anl::CNoiseExecutor vm(NoiseParser->GetKernel());
		double VMResult = vm.evaluateScalar(0.5, 0.5, NoiseParser->GetParseResult());
	}

	return 0;
}
<commit_msg>Removed necessary output to stderr<commit_after>/////////////////////////////////////////
//
// File Header Place Holder
//
/////////////////////////////////////////

#include "ANLtoCPP/ANLtoC.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <memory>
#include <ctime>
#include "Output.h"

#define ANL_IMPLEMENTATION
// ANL is currently in a transition to a single file format, thus
// we need to IMPLEMENT_STB even though we don't use it.
#define IMPLEMENT_STB
#include <accidental-noise-library/anl.h>
#include <accidental-noise-library/lang/NoiseParser.h>

std::string GetFileName(std::string file)
{
	std::string::size_type AltSeperator = file.find_last_of('/');
	std::string::size_type Seperator = file.find_last_of('\\');

	if ((Seperator < AltSeperator && AltSeperator != std::string::npos) || Seperator == std::string::npos)
		Seperator = AltSeperator;

	if (Seperator == std::string::npos)
		return file;

	return file.substr(Seperator + 1);
}

std::string GetDirectory(std::string file)
{
	std::string::size_type AltSeperator = file.find_last_of('/');
	std::string::size_type Seperator = file.find_last_of('\\');

	if ((Seperator < AltSeperator && AltSeperator != std::string::npos) || Seperator == std::string::npos)
		Seperator = AltSeperator;

	if (Seperator == std::string::npos)
		return "";

	return file.substr(0, Seperator);
}

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::cerr << "Missing arguments." << std::endl;
		std::cerr << "USAGE: ANLTranspiler.exe anlLangSourceFile.anl output.cpp output.h" << std::endl;
		std::cerr << "  The anlLangSourceFile.anl will be parsed and converted to an internal" << std::endl;
		std::cerr << "  anl::CKernel which will then be converted to cplusplus and output as" << std::endl;
		std::cerr << "  the provided source and header files" << std::endl;
		return 0;
	}

	std::string InputFileName = argv[1];
	std::string OutputSourceFileName;
	std::string OutputHeaderFileName;
	if (argc > 2)
		OutputSourceFileName = argv[2];
	if (argc > 3)
		OutputHeaderFileName = argv[3];

	std::string HeaderFileRelativeToSource; // ie with any common directory information stripped
	{
		std::string HeaderDir = GetDirectory(OutputHeaderFileName);
		std::string HeaderFile = GetFileName(OutputHeaderFileName);
		std::string SourceDir = GetDirectory(OutputSourceFileName);
		std::string SourceFile = GetFileName(OutputSourceFileName);

		std::size_t DivergentIndex = 0;
		for (std::size_t i = 0; i < SourceDir.size() && i < HeaderDir.size(); ++i)
		{
			if (SourceDir[i] == HeaderDir[i])
				DivergentIndex++;
			else
				break;
		}

		std::string Dir = HeaderDir.substr(DivergentIndex);

		if (Dir.size() > 0)
			HeaderFileRelativeToSource = Dir + "/" + HeaderFile;
		else
			HeaderFileRelativeToSource = HeaderFile;
	}

	FILE* f = nullptr;
	if (0 != fopen_s(&f, InputFileName.c_str(), "r")) {
		std::cerr << "Unable to open file: " << InputFileName << std::endl;
		return -9;
	}
	if (fseek(f, 0, SEEK_END) != 0) {
		std::cerr << "Seek Error for file: " << InputFileName << std::endl;
		return -10;
	}

	long FileLength = ftell(f);

	if (fseek(f, 0, SEEK_SET) != 0) {
		std::cerr << "Seek Error for file: " << InputFileName << std::endl;
		return -10;
	}

	std::string FullText;
	{
		auto Buffer = std::make_unique<uint8_t[]>(FileLength+1);
		size_t AmountRead = fread(Buffer.get(), 1, FileLength, f);
		if (AmountRead != FileLength && feof(f) == 0) {
			std::cerr << "Read Error for file: " << InputFileName << std::endl;
			return -10;
		}
		fclose(f);
		Buffer[AmountRead] = 0;
		FullText = (char*)Buffer.get();
	}

	std::unique_ptr<anl::lang::NoiseParser> NoiseParser;
	NoiseParser = std::make_unique<anl::lang::NoiseParser>(FullText);

	bool success = NoiseParser->Parse();
	if (!success)
	{
		auto ErrorMessages = NoiseParser->FormErrorMsgs();
		std::cerr << "Error parsing TerrainV noise file: " << InputFileName
			<< "\nErrors:\n" << ErrorMessages
			<< "\n\n Contents of \"" << InputFileName
			<< "\"\n" << FullText << std::endl;
		return -30;
	}
	else
	{
		std::string Code;
		std::string HeaderFile;
		std::string Struct;
		ANLtoC::KernelToC(NoiseParser->GetKernel(), NoiseParser->GetParseResult(), Code, Struct);
		OutputFullCppFile(Code, Struct, HeaderFileRelativeToSource, Code, HeaderFile);
		std::string header = "// Generated file - Do not edit. Generated by ANLTranspiler at ";
		time_t CurrentTime = time(0);
		char TimeBuffer[100];
		ctime_s(TimeBuffer, 100, &CurrentTime);
		header.append(TimeBuffer);
		header.append("\n");
		Code.insert(0, header);
		HeaderFile.insert(0, header);

		if(OutputSourceFileName != "")
		{
			FILE* f = nullptr;
			if (0 != fopen_s(&f, OutputSourceFileName.c_str(), "w")) {
				std::cerr << "Unable to open file: " << OutputSourceFileName << std::endl;
				return -9;
			}

			size_t AmountWritten = fwrite(Code.c_str(), 1, Code.size(), f);
			if (AmountWritten != Code.size())
			{
				std::cerr << "Write failed to file: " << OutputSourceFileName << std::endl;
			}

			fclose(f);
		}

		if (OutputHeaderFileName != "")
		{
			FILE* f = nullptr;
			if (0 != fopen_s(&f, OutputHeaderFileName.c_str(), "w")) {
				std::cerr << "Unable to open file: " << OutputHeaderFileName << std::endl;
				return -9;
			}

			size_t AmountWritten = fwrite(HeaderFile.c_str(), 1, HeaderFile.size(), f);
			if (AmountWritten != HeaderFile.size())
			{
				std::cerr << "Write failed to file: " << OutputHeaderFileName << std::endl;
			}

			fclose(f);
		}

		anl::CNoiseExecutor vm(NoiseParser->GetKernel());
		double VMResult = vm.evaluateScalar(0.5, 0.5, NoiseParser->GetParseResult());
	}

	return 0;
}
<|endoftext|>


<commit_before>d491915c-2747-11e6-b97a-e0f84713e7b8<commit_msg>Does anyone even read these anymore???<commit_after>d4b7bef3-2747-11e6-b029-e0f84713e7b8<|endoftext|>


<commit_before>/*
* HMAC
* (C) 1999-2007,2014 Jack Lloyd
*     2007 Yves Jerschow
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/hmac.h>

namespace Botan {

/*
* Update a HMAC Calculation
*/
void HMAC::add_data(const uint8_t input[], size_t length)
   {
   verify_key_set(m_ikey.empty() == false);
   m_hash->update(input, length);
   }

/*
* Finalize a HMAC Calculation
*/
void HMAC::final_result(uint8_t mac[])
   {
   verify_key_set(m_okey.empty() == false);
   m_hash->final(mac);
   m_hash->update(m_okey);
   m_hash->update(mac, m_hash_output_length);
   m_hash->final(mac);
   m_hash->update(m_ikey);
   }

Key_Length_Specification HMAC::key_spec() const
   {
   // Support very long lengths for things like PBKDF2 and the TLS PRF
   return Key_Length_Specification(0, 4096);
   }

size_t HMAC::output_length() const
   {
   return m_hash_output_length;
   }

/*
* HMAC Key Schedule
*/
void HMAC::key_schedule(const uint8_t key[], size_t length)
   {
   const uint8_t ipad = 0x36;
   const uint8_t opad = 0x5C;

   m_hash->clear();

   m_ikey.resize(m_hash_block_size);
   set_mem(m_ikey.data(), m_hash_block_size, ipad);

   m_okey.resize(m_hash_block_size);
   set_mem(m_okey.data(), m_hash_block_size, opad);

   if(length > m_hash_block_size)
      {
      m_hash->update(key, length);
      m_hash->final(m_ikey.data());

      xor_buf(m_okey.data(), m_ikey.data(), m_hash_output_length);

      for(size_t i = 0; i != m_hash_output_length; ++i)
         {
         m_ikey[i] ^= ipad;
         }
      }
   else
      {
      xor_buf(m_ikey, key, length);
      xor_buf(m_okey, key, length);
      }

   m_hash->update(m_ikey);
   }

/*
* Clear memory of sensitive data
*/
void HMAC::clear()
   {
   m_hash->clear();
   zap(m_ikey);
   zap(m_okey);
   }

/*
* Return the name of this type
*/
std::string HMAC::name() const
   {
   return "HMAC(" + m_hash->name() + ")";
   }

/*
* Return a clone of this object
*/
MessageAuthenticationCode* HMAC::clone() const
   {
   return new HMAC(m_hash->clone());
   }

/*
* HMAC Constructor
*/
HMAC::HMAC(HashFunction* hash) :
   m_hash(hash),
   m_hash_output_length(m_hash->output_length()),
   m_hash_block_size(m_hash->hash_block_size())
   {
   BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length,
                   "HMAC is not compatible with this hash function");
   }

}
<commit_msg>Attempt to avoid leaking the HMAC key length<commit_after>/*
* HMAC
* (C) 1999-2007,2014,2020 Jack Lloyd
*     2007 Yves Jerschow
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/hmac.h>
#include <botan/internal/ct_utils.h>

namespace Botan {

/*
* Update a HMAC Calculation
*/
void HMAC::add_data(const uint8_t input[], size_t length)
   {
   verify_key_set(m_ikey.empty() == false);
   m_hash->update(input, length);
   }

/*
* Finalize a HMAC Calculation
*/
void HMAC::final_result(uint8_t mac[])
   {
   verify_key_set(m_okey.empty() == false);
   m_hash->final(mac);
   m_hash->update(m_okey);
   m_hash->update(mac, m_hash_output_length);
   m_hash->final(mac);
   m_hash->update(m_ikey);
   }

Key_Length_Specification HMAC::key_spec() const
   {
   // Support very long lengths for things like PBKDF2 and the TLS PRF
   return Key_Length_Specification(0, 4096);
   }

size_t HMAC::output_length() const
   {
   return m_hash_output_length;
   }

/*
* HMAC Key Schedule
*/
void HMAC::key_schedule(const uint8_t key[], size_t length)
   {
   const uint8_t ipad = 0x36;
   const uint8_t opad = 0x5C;

   m_hash->clear();

   m_ikey.resize(m_hash_block_size);
   m_okey.resize(m_hash_block_size);

   clear_mem(m_ikey.data(), m_ikey.size());
   clear_mem(m_okey.data(), m_okey.size());

   /*
   * Sometimes the HMAC key length itself is sensitive, as with PBKDF2 where it
   * reveals the length of the passphrase. Make some attempt to hide this to
   * side channels. Clearly if the secret is longer than the block size then the
   * branch to hash first reveals that. In addition, counting the number of
   * compression functions executed reveals the size at the granularity of the
   * hash function's block size.
   *
   * The greater concern is for smaller keys; being able to detect when a
   * passphrase is say 4 bytes may assist choosing weaker targets. Even though
   * the loop bounds are constant, we can only actually read key[0..length] so
   * it doesn't seem possible to make this computation truly constant time.
   *
   * We don't mind leaking if the length is exactly zero since that's
   * trivial to simply check.
   */

   if(length > m_hash_block_size)
      {
      m_hash->update(key, length);
      m_hash->final(m_ikey.data());
      }
   else if(length > 0)
      {
      for(size_t i = 0, i_mod_length = 0; i != m_hash_block_size; ++i)
         {
         /*
         access key[i % length] but avoiding division due to variable
         time computation on some processors.
         */
         auto needs_reduction = CT::Mask<size_t>::is_lte(length, i_mod_length);
         i_mod_length = needs_reduction.select(0, i_mod_length);
         const uint8_t kb = key[i_mod_length];

         auto in_range = CT::Mask<size_t>::is_lt(i, length);
         m_ikey[i] = static_cast<uint8_t>(in_range.if_set_return(kb));
         i_mod_length += 1;
         }
      }

   for(size_t i = 0; i != m_hash_block_size; ++i)
      {
      m_ikey[i] ^= ipad;
      m_okey[i] = m_ikey[i] ^ ipad ^ opad;
      }

   m_hash->update(m_ikey);
   }

/*
* Clear memory of sensitive data
*/
void HMAC::clear()
   {
   m_hash->clear();
   zap(m_ikey);
   zap(m_okey);
   }

/*
* Return the name of this type
*/
std::string HMAC::name() const
   {
   return "HMAC(" + m_hash->name() + ")";
   }

/*
* Return a clone of this object
*/
MessageAuthenticationCode* HMAC::clone() const
   {
   return new HMAC(m_hash->clone());
   }

/*
* HMAC Constructor
*/
HMAC::HMAC(HashFunction* hash) :
   m_hash(hash),
   m_hash_output_length(m_hash->output_length()),
   m_hash_block_size(m_hash->hash_block_size())
   {
   BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length,
                   "HMAC is not compatible with this hash function");
   }

}
<|endoftext|>


<commit_before>fdb693f8-ad5a-11e7-8a49-ac87a332f658<commit_msg>I am finally done<commit_after>fe64914c-ad5a-11e7-878a-ac87a332f658<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <SFML/Graphics.hpp>
#include "GUI-SFML.hpp"

typedef std::chrono::high_resolution_clock CLOCK;

void determineFpsAndDeltaTime(sf::Text &txtStatFPS, float &dt,
        float &averageFpsTime, float &fpsInSec, int &fpsCnt,
        int &averageFpsInOneSec,
        CLOCK::time_point &timePoint1);

int main()
{
    unsigned int windowWidth{ 1280 };
    unsigned int windowHeight{ 720 };
    sf::RenderWindow window(sf::VideoMode{ windowWidth, windowHeight }, "GUI-SFML");

    sf::Font font;
    if (!font.loadFromFile("assets/fonts/LiberationSans-Regular.ttf"))
    {
        std::cout << "Error by loading Font" << std::endl;
    }

    sf::Text txtStatFPS;
    txtStatFPS.setFont(font);
    txtStatFPS.setCharacterSize(12);
    txtStatFPS.setFillColor(sf::Color::Black);
    float dt{ 0.f };
    float averageFpsTime{ 0.f };
    float fpsInSec{ 0.f };
    int fpsCnt{ 0 };
    int averageFpsInOneSec{ 0 };
    CLOCK::time_point timePoint1{ CLOCK::now() };

    gsf::GUIEnvironment guiEnvironment{ window };
    gsf::TextWidget::Ptr textWidget{
        gsf::TextWidget::create("IM A TEXT\nTESTA\nTESTB\nTESTC\nS", font) };
    //textWidget->centerOrigin();
    textWidget->setBackgroundColor(sf::Color{ 192, 192, 192 });
    textWidget->setCharacterSize(60);
    textWidget->setPosition(windowWidth / 2.f + 100.f, windowHeight / 2.f - 330.f);
    guiEnvironment.addWidget(std::move(textWidget));

    std::unique_ptr<gsf::ProgressWidget> progressWidget{
        std::make_unique<gsf::ProgressWidget>(260, 40) };
    progressWidget->setPosition(460, 460);
    progressWidget->setProgress(50);
    progressWidget->setOnLeftClickListener([](gsf::Widget *widget, sf::Vector2f pos)
            {
                std::cout << "Clicked Progress \n";
            });
    guiEnvironment.addWidget(std::move(progressWidget));

    std::unique_ptr<gsf::ScrollableWidget> scrollableWidget{
        std::make_unique<gsf::ScrollableWidget>(300, 200) };
    scrollableWidget->setBackgroundColor(sf::Color{ 162, 162, 162 });

    std::unique_ptr<gsf::VerticalLayout> layout{
        std::make_unique<gsf::VerticalLayout>() };
    layout->enableAutoDetermineWidth();
    layout->setOutlineThickness(8.f);
    layout->setOutlineColor(sf::Color::Yellow);

    for (int i{ 0 }; i != 6; i++)
    {
        /*
        std::string textString{ "Text Num " + std::to_string(i) };
        std::unique_ptr<gsf::TextWidget> text{ std::make_unique<gsf::TextWidget>
                (textString, font, 40, sf::Color::White) };
        if (i % 2 == 0)
        {
            text->setBackgroundColor(sf::Color{ 192, 192, 192 });
        }
        else
        {
            text->setBackgroundColor(sf::Color{ 128, 128, 128 });
        }
        std::function<void(gsf::Widget*, sf::Vector2f)> leftClickListener =
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
        {
            gsf::TextWidget *textWidget = static_cast<gsf::TextWidget*>(widget);
            std::cout << "TextWidget: Left Mouse Button Clicked. Text: "
                << textWidget->getText().toAnsiString() << std::endl;
        };
        text->setOnLeftClickListener(leftClickListener);

        layout->attachChild(std::move(text));
        */
        gsf::ProgressWidget::Ptr prog{ gsf::ProgressWidget::create(360.f, 40.f) };
        if (i % 2 == 0)
        {
            prog->setOutlineColor(sf::Color::Red);
        }
        else
        {
            prog->setOutlineColor(sf::Color::Blue);
        }
        layout->attachChild(std::move(prog));
    }

    scrollableWidget->attachChild(std::move(layout));

    std::unique_ptr<gsf::WindowWidget> windowWidget{
        std::make_unique<gsf::WindowWidget>(
                scrollableWidget->getGlobalBounds().width,
                scrollableWidget->getGlobalBounds().height, L"", font) };
    windowWidget->setPosition(200.f , 200.f);
    //windowWidget->setBackgroundColor(sf::Color::White);
    windowWidget->attachChild(std::move(scrollableWidget));
    windowWidget->setIsVisible(true);
    guiEnvironment.addWidget(std::move(windowWidget));

    std::unique_ptr<gsf::WindowWidget> windowWidget2{
        std::make_unique<gsf::WindowWidget>(300.f, 360.f, L"", font) };
    windowWidget2->setPosition(240.f , 40.f);
    //windowWidget2->setBackgroundColor(sf::Color::Red);
    //windowWidget2->setTopBarFillColor(sf::Color::Green);
    //windowWidget2->setCloseButtonFillColor(sf::Color::Blue);
    windowWidget2->setWindowTitle(L"Test");
    //windowWidget2->setWindowTitleColor(sf::Color::Red);
    guiEnvironment.addWidget(std::move(windowWidget2));

    std::unique_ptr<gsf::WindowWidget> windowWidget3{
        std::make_unique<gsf::WindowWidget>
            (300.f, 360.f, L"Test Window TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT", font) };
    windowWidget3->setPosition(300.f , 60.f);
    //windowWidget3->setOutlineThickness(12.f);
    //windowWidget3->setOutlineColor(sf::Color::White);
    //windowWidget3->setBackgroundColor(sf::Color::Blue);
    guiEnvironment.addWidget(std::move(windowWidget3));

    // BUTTON TEST
    std::unique_ptr<gsf::TextButtonWidget> buttonWidget{
        std::make_unique<gsf::TextButtonWidget>
            (200.f, 80.f, L"CABBBBBTTTTTTTTTTTTTTTTTTTTTTClick me", font) };
    buttonWidget->setPosition(240.f , 360.f);
    buttonWidget->setOnLeftClickListener(
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
            {
                std::cout << "Button Left Click\n";

            });
    buttonWidget->setOnRightClickListener(
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
            {
                std::cout << "Button Right Click\n";

            });
    buttonWidget->setOnMiddleClickListener(
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
            {
                std::cout << "Button Middle Click\n";

            });
    guiEnvironment.addWidget(std::move(buttonWidget));

    // SCROLLBAR TEST
    std::unique_ptr<gsf::ScrollableWidget> scrollableWidget3{
        std::make_unique<gsf::ScrollableWidget>(300, 200) };
    scrollableWidget3->setPosition(820.f, 420.f);
    scrollableWidget3->setBackgroundColor(sf::Color{ 128,  128, 128 });

    std::unique_ptr<gsf::VerticalLayout> layout4{
        std::make_unique<gsf::VerticalLayout>() };
    layout4->enableAutoDetermineWidth();
    layout4->setBackgroundColor(sf::Color::Cyan);

    for (int i{0}; i != 10; i++)
    {
        std::string textString{ "Text Text Text Text Text Text Text Num "
            + std::to_string(i) };
        std::unique_ptr<gsf::TextWidget> text{
            std::make_unique<gsf::TextWidget>
                (textString, font, 40, sf::Color::White) };
        if (i % 2 == 0)
        {
            text->setBackgroundColor(sf::Color::Green);
        }
        else
        {
            text->setBackgroundColor(sf::Color::Magenta);
        }
        std::function<void(gsf::Widget*, sf::Vector2f)> leftClickListener =
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
        {
            gsf::TextWidget *textWidget = static_cast<gsf::TextWidget*>(widget);
            std::cout << "TextWidget: Left Mouse Button Clicked. Text: "
                << textWidget->getText().toAnsiString() << std::endl;
        };
        text->setOnLeftClickListener(leftClickListener);
        //text->setBackgroundColor(sf::Color::Red);
        layout4->attachChild(std::move(text));
    }
    scrollableWidget3->attachChild(std::move(layout4));
    guiEnvironment.addWidget(std::move(scrollableWidget3));

    std::unique_ptr<gsf::TextInputWidget> textInput1{
        std::make_unique<gsf::TextInputWidget>(300.f, 60.f, font) };
    textInput1->setPosition(320.f, 520.f);
    textInput1->setBackgroundColor(sf::Color::White);
    textInput1->setIsHorizontalScrollEnabled(false);
    textInput1->setText(L"Test Text HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH :)");
    textInput1->setWhiteListChars(L"0123456789");
    guiEnvironment.addWidget(std::move(textInput1));

    // Console Widget
    std::unique_ptr<gsf::ConsoleWidget> console1{
        std::make_unique<gsf::ConsoleWidget>(500.f, 200.f, font) };
    console1->setPosition(700.f, 200.f);
    console1->setOnCommandEnteredListener(
            [] (gsf::Widget *widget, std::wstring inputText)
            {
                std::wcout << "CommandEnteredListener command: " << inputText
                    << std::endl;
                gsf::ConsoleWidget *consoleWidget{
                    static_cast<gsf::ConsoleWidget*>(widget) };
                consoleWidget->addTextToDisplay(L"OK");
            }
    );
    guiEnvironment.addWidget(std::move(console1));

    // CheckBoxWidget
    std::unique_ptr<gsf::CheckBoxWidget> checkBox1{
        std::make_unique<gsf::CheckBoxWidget>(60, 60.f) };
    checkBox1->setPosition(10.f, 620.f);
    guiEnvironment.addWidget(std::move(checkBox1));

    // ComboBoxWidget
    gsf::ComboBoxWidget::Ptr comboBox{
        gsf::ComboBoxWidget::create(80.f, 20.f, font) };
    comboBox->setPosition(120.f, 620.f);
    comboBox->addElement(L"Entry One");
    comboBox->addElement(L"Entry Two");
    comboBox->addElement(L"Entry Three");
    comboBox->addElement(L"Entry Four");
    comboBox->addElement(L"Entry Five");
    comboBox->addElement(L"Entry LAST");
    guiEnvironment.addWidget(std::move(comboBox));

    // ListBoxWidget
    gsf::ListBoxWidget::Ptr listBox{
        gsf::ListBoxWidget::create(80.f, 100.f, font) };
    listBox->setOnElementSelectedListener([](gsf::Widget* widget, int index)
    {
        gsf::ListBoxWidget *widgetList{ static_cast<gsf::ListBoxWidget*>(widget) };
        std::wstring content{ widgetList->getElement(index) };
        std::cout << "Index selected: " << index << std::endl;
    });
    listBox->setPosition(320.f, 590.f);
    listBox->addElement(L"Entry One");
    listBox->addElement(L"Entry Two");
    listBox->addElement(L"Entry Three");
    listBox->addElement(L"Entry Four");
    listBox->addElement(L"Entry Five");
    listBox->addElement(L"Entry Six");
    listBox->addElement(L"Entry Seven");
    listBox->addElement(L"Entry Eight");
    listBox->addElement(L"Entry Nine");
    listBox->addElement(L"Entry Ten");
    listBox->addElement(L"Entry Eleven");
    //guiEnvironment.addWidget(std::move(listBox));

    while (window.isOpen())
    {
        determineFpsAndDeltaTime(txtStatFPS, dt, averageFpsTime, fpsInSec, fpsCnt,
            averageFpsInOneSec, timePoint1);
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
            else if (event.type == sf::Event::Resized)
            {
                /*
                std::cout << "new width: " << event.size.width << std::endl;
                std::cout << "new height: " << event.size.height << std::endl;
                sf::View currentView{ window.getView() };
                sf::FloatRect currentViewport{ currentView.getViewport() };
                std::cout << "ViewSize: width: " << currentView.getSize().x
                    << " height: " << currentView.getSize().y
                    << "\n Viewport: left: " << currentViewport.left << " top: "
                    << currentViewport.top << " width: " << currentViewport.width
                    << " height: " << currentViewport.height
                    << "\n-------------------------------------------\n";
                sf::FloatRect newRect( 0, 0, event.size.width, event.size.height );
                sf::View newView(newRect);
                //window.setView(newView);
                */
            }
            guiEnvironment.handleEvent(event);
        }
        guiEnvironment.update(dt);

        window.clear(sf::Color::White);
        window.draw(guiEnvironment);
        window.draw(txtStatFPS);
        window.display();
    }

    return 0;
}

void determineFpsAndDeltaTime(sf::Text &txtStatFPS, float &dt,
        float &averageFpsTime, float &fpsInSec, int &fpsCnt,
        int &averageFpsInOneSec,
        CLOCK::time_point &timePoint1)
{
    CLOCK::time_point timePoint2{ CLOCK::now() };
    std::chrono::duration<float> timeSpan{ timePoint2 - timePoint1 };
    timePoint1 = CLOCK::now();
    // Get deltaTime as float in seconds
    dt = std::chrono::duration_cast<std::chrono::duration<float,std::ratio<1>>>
        (timeSpan).count();
    float fps{ 1.f / dt };

    averageFpsTime += dt;
    fpsInSec += fps;
    fpsCnt++;
    if (averageFpsTime >= 1.f)
    {
        averageFpsInOneSec = fpsInSec / fpsCnt;
        averageFpsTime = 0.f;
        fpsInSec = 0.f;
        fpsCnt = 0;
    }

    txtStatFPS.setString("FPS: " + std::to_string(averageFpsInOneSec) + " ("
            + std::to_string(fps) + ")");
}
<commit_msg>Clean up<commit_after>#include <chrono>
#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <SFML/Graphics.hpp>
#include "GUI-SFML.hpp"

typedef std::chrono::high_resolution_clock CLOCK;

void determineFpsAndDeltaTime(sf::Text &txtStatFPS, float &dt,
        float &averageFpsTime, float &fpsInSec, int &fpsCnt,
        int &averageFpsInOneSec,
        CLOCK::time_point &timePoint1);

int main()
{
    unsigned int windowWidth{ 1280 };
    unsigned int windowHeight{ 720 };
    sf::RenderWindow window(sf::VideoMode{ windowWidth, windowHeight }, "GUI-SFML");

    sf::Font font;
    if (!font.loadFromFile("assets/fonts/LiberationSans-Regular.ttf"))
    {
        std::cout << "Error by loading Font" << std::endl;
    }

    sf::Text txtStatFPS;
    txtStatFPS.setFont(font);
    txtStatFPS.setCharacterSize(12);
    txtStatFPS.setFillColor(sf::Color::Black);
    float dt{ 0.f };
    float averageFpsTime{ 0.f };
    float fpsInSec{ 0.f };
    int fpsCnt{ 0 };
    int averageFpsInOneSec{ 0 };
    CLOCK::time_point timePoint1{ CLOCK::now() };

    gsf::GUIEnvironment guiEnvironment{ window };
    gsf::TextWidget::Ptr textWidget{
        gsf::TextWidget::create("IM A TEXT\nTESTA\nTESTB\nTESTC\nS", font) };
    //textWidget->centerOrigin();
    textWidget->setBackgroundColor(sf::Color{ 192, 192, 192 });
    textWidget->setCharacterSize(60);
    textWidget->setPosition(windowWidth / 2.f + 100.f, windowHeight / 2.f - 330.f);
    guiEnvironment.addWidget(std::move(textWidget));

    std::unique_ptr<gsf::ProgressWidget> progressWidget{
        std::make_unique<gsf::ProgressWidget>(260, 40) };
    progressWidget->setPosition(460, 460);
    progressWidget->setProgress(50);
    progressWidget->setOnLeftClickListener([](gsf::Widget *widget, sf::Vector2f pos)
            {
                std::cout << "Clicked Progress \n";
            });
    guiEnvironment.addWidget(std::move(progressWidget));

    std::unique_ptr<gsf::ScrollableWidget> scrollableWidget{
        std::make_unique<gsf::ScrollableWidget>(300, 200) };
    scrollableWidget->setBackgroundColor(sf::Color{ 162, 162, 162 });

    std::unique_ptr<gsf::VerticalLayout> layout{
        std::make_unique<gsf::VerticalLayout>() };
    layout->enableAutoDetermineWidth();
    layout->setOutlineThickness(8.f);
    layout->setOutlineColor(sf::Color::Yellow);

    for (int i{ 0 }; i != 6; i++)
    {
        /*
        std::string textString{ "Text Num " + std::to_string(i) };
        std::unique_ptr<gsf::TextWidget> text{ std::make_unique<gsf::TextWidget>
                (textString, font, 40, sf::Color::White) };
        if (i % 2 == 0)
        {
            text->setBackgroundColor(sf::Color{ 192, 192, 192 });
        }
        else
        {
            text->setBackgroundColor(sf::Color{ 128, 128, 128 });
        }
        std::function<void(gsf::Widget*, sf::Vector2f)> leftClickListener =
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
        {
            gsf::TextWidget *textWidget = static_cast<gsf::TextWidget*>(widget);
            std::cout << "TextWidget: Left Mouse Button Clicked. Text: "
                << textWidget->getText().toAnsiString() << std::endl;
        };
        text->setOnLeftClickListener(leftClickListener);

        layout->attachChild(std::move(text));
        */
        gsf::ProgressWidget::Ptr prog{ gsf::ProgressWidget::create(360.f, 40.f) };
        if (i % 2 == 0)
        {
            prog->setOutlineColor(sf::Color::Red);
        }
        else
        {
            prog->setOutlineColor(sf::Color::Blue);
        }
        layout->attachChild(std::move(prog));
    }

    scrollableWidget->attachChild(std::move(layout));

    std::unique_ptr<gsf::WindowWidget> windowWidget{
        std::make_unique<gsf::WindowWidget>(
                scrollableWidget->getGlobalBounds().width,
                scrollableWidget->getGlobalBounds().height, L"", font) };
    windowWidget->setPosition(200.f , 200.f);
    //windowWidget->setBackgroundColor(sf::Color::White);
    windowWidget->attachChild(std::move(scrollableWidget));
    windowWidget->setIsVisible(true);
    guiEnvironment.addWidget(std::move(windowWidget));

    std::unique_ptr<gsf::WindowWidget> windowWidget2{
        std::make_unique<gsf::WindowWidget>(300.f, 360.f, L"", font) };
    windowWidget2->setPosition(240.f , 40.f);
    //windowWidget2->setBackgroundColor(sf::Color::Red);
    //windowWidget2->setTopBarFillColor(sf::Color::Green);
    //windowWidget2->setCloseButtonFillColor(sf::Color::Blue);
    windowWidget2->setWindowTitle(L"Test");
    //windowWidget2->setWindowTitleColor(sf::Color::Red);
    guiEnvironment.addWidget(std::move(windowWidget2));

    std::unique_ptr<gsf::WindowWidget> windowWidget3{
        std::make_unique<gsf::WindowWidget>
            (300.f, 360.f, L"Test Window TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT", font) };
    windowWidget3->setPosition(300.f , 60.f);
    //windowWidget3->setOutlineThickness(12.f);
    //windowWidget3->setOutlineColor(sf::Color::White);
    //windowWidget3->setBackgroundColor(sf::Color::Blue);
    guiEnvironment.addWidget(std::move(windowWidget3));

    // BUTTON TEST
    std::unique_ptr<gsf::TextButtonWidget> buttonWidget{
        std::make_unique<gsf::TextButtonWidget>
            (200.f, 80.f, L"CABBBBBTTTTTTTTTTTTTTTTTTTTTTClick me", font) };
    buttonWidget->setPosition(240.f , 360.f);
    buttonWidget->setOnLeftClickListener(
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
            {
                std::cout << "Button Left Click\n";

            });
    buttonWidget->setOnRightClickListener(
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
            {
                std::cout << "Button Right Click\n";

            });
    buttonWidget->setOnMiddleClickListener(
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
            {
                std::cout << "Button Middle Click\n";

            });
    guiEnvironment.addWidget(std::move(buttonWidget));

    // SCROLLBAR TEST
    std::unique_ptr<gsf::ScrollableWidget> scrollableWidget3{
        std::make_unique<gsf::ScrollableWidget>(300, 200) };
    scrollableWidget3->setPosition(820.f, 420.f);
    scrollableWidget3->setBackgroundColor(sf::Color{ 128,  128, 128 });

    std::unique_ptr<gsf::VerticalLayout> layout4{
        std::make_unique<gsf::VerticalLayout>() };
    layout4->enableAutoDetermineWidth();
    layout4->setBackgroundColor(sf::Color::Cyan);

    for (int i{0}; i != 10; i++)
    {
        std::string textString{ "Text Text Text Text Text Text Text Num "
            + std::to_string(i) };
        std::unique_ptr<gsf::TextWidget> text{
            std::make_unique<gsf::TextWidget>
                (textString, font, 40, sf::Color::White) };
        if (i % 2 == 0)
        {
            text->setBackgroundColor(sf::Color::Green);
        }
        else
        {
            text->setBackgroundColor(sf::Color::Magenta);
        }
        std::function<void(gsf::Widget*, sf::Vector2f)> leftClickListener =
            [] (gsf::Widget* widget, sf::Vector2f mousePos)
        {
            gsf::TextWidget *textWidget = static_cast<gsf::TextWidget*>(widget);
            std::cout << "TextWidget: Left Mouse Button Clicked. Text: "
                << textWidget->getText().toAnsiString() << std::endl;
        };
        text->setOnLeftClickListener(leftClickListener);
        //text->setBackgroundColor(sf::Color::Red);
        layout4->attachChild(std::move(text));
    }
    scrollableWidget3->attachChild(std::move(layout4));
    guiEnvironment.addWidget(std::move(scrollableWidget3));

    std::unique_ptr<gsf::TextInputWidget> textInput1{
        std::make_unique<gsf::TextInputWidget>(300.f, 60.f, font) };
    textInput1->setPosition(320.f, 520.f);
    textInput1->setBackgroundColor(sf::Color::White);
    textInput1->setIsHorizontalScrollEnabled(false);
    textInput1->setText(L"Test Text HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH :)");
    textInput1->setWhiteListChars(L"0123456789");
    guiEnvironment.addWidget(std::move(textInput1));

    // Console Widget
    std::unique_ptr<gsf::ConsoleWidget> console1{
        std::make_unique<gsf::ConsoleWidget>(500.f, 200.f, font) };
    console1->setPosition(700.f, 200.f);
    console1->setOnCommandEnteredListener(
            [] (gsf::Widget *widget, std::wstring inputText)
            {
                std::wcout << "CommandEnteredListener command: " << inputText
                    << std::endl;
                gsf::ConsoleWidget *consoleWidget{
                    static_cast<gsf::ConsoleWidget*>(widget) };
                consoleWidget->addTextToDisplay(L"OK");
            }
    );
    guiEnvironment.addWidget(std::move(console1));

    // CheckBoxWidget
    std::unique_ptr<gsf::CheckBoxWidget> checkBox1{
        std::make_unique<gsf::CheckBoxWidget>(60, 60.f) };
    checkBox1->setPosition(10.f, 620.f);
    guiEnvironment.addWidget(std::move(checkBox1));

    // ComboBoxWidget
    gsf::ComboBoxWidget::Ptr comboBox{
        gsf::ComboBoxWidget::create(80.f, 20.f, font) };
    comboBox->setPosition(120.f, 620.f);
    comboBox->addElement(L"Entry One");
    comboBox->addElement(L"Entry Two");
    comboBox->addElement(L"Entry Three");
    comboBox->addElement(L"Entry Four");
    comboBox->addElement(L"Entry Five");
    comboBox->addElement(L"Entry LAST");
    guiEnvironment.addWidget(std::move(comboBox));

    // ListBoxWidget
    gsf::ListBoxWidget::Ptr listBox{
        gsf::ListBoxWidget::create(80.f, 100.f, font) };
    listBox->setOnElementSelectedListener([](gsf::Widget* widget, int index)
    {
        gsf::ListBoxWidget *widgetList{ static_cast<gsf::ListBoxWidget*>(widget) };
        std::wstring content{ widgetList->getElement(index) };
        std::cout << "Index selected: " << index << std::endl;
    });
    listBox->setPosition(320.f, 590.f);
    listBox->addElement(L"Entry One");
    listBox->addElement(L"Entry Two");
    listBox->addElement(L"Entry Three");
    listBox->addElement(L"Entry Four");
    listBox->addElement(L"Entry Five");
    listBox->addElement(L"Entry Six");
    listBox->addElement(L"Entry Seven");
    listBox->addElement(L"Entry Eight");
    listBox->addElement(L"Entry Nine");
    listBox->addElement(L"Entry Ten");
    listBox->addElement(L"Entry Eleven");
    guiEnvironment.addWidget(std::move(listBox));

    while (window.isOpen())
    {
        determineFpsAndDeltaTime(txtStatFPS, dt, averageFpsTime, fpsInSec, fpsCnt,
            averageFpsInOneSec, timePoint1);
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
            else if (event.type == sf::Event::Resized)
            {
                /*
                std::cout << "new width: " << event.size.width << std::endl;
                std::cout << "new height: " << event.size.height << std::endl;
                sf::View currentView{ window.getView() };
                sf::FloatRect currentViewport{ currentView.getViewport() };
                std::cout << "ViewSize: width: " << currentView.getSize().x
                    << " height: " << currentView.getSize().y
                    << "\n Viewport: left: " << currentViewport.left << " top: "
                    << currentViewport.top << " width: " << currentViewport.width
                    << " height: " << currentViewport.height
                    << "\n-------------------------------------------\n";
                sf::FloatRect newRect( 0, 0, event.size.width, event.size.height );
                sf::View newView(newRect);
                //window.setView(newView);
                */
            }
            guiEnvironment.handleEvent(event);
        }
        guiEnvironment.update(dt);

        window.clear(sf::Color::White);
        window.draw(guiEnvironment);
        window.draw(txtStatFPS);
        window.display();
    }

    return 0;
}

void determineFpsAndDeltaTime(sf::Text &txtStatFPS, float &dt,
        float &averageFpsTime, float &fpsInSec, int &fpsCnt,
        int &averageFpsInOneSec,
        CLOCK::time_point &timePoint1)
{
    CLOCK::time_point timePoint2{ CLOCK::now() };
    std::chrono::duration<float> timeSpan{ timePoint2 - timePoint1 };
    timePoint1 = CLOCK::now();
    // Get deltaTime as float in seconds
    dt = std::chrono::duration_cast<std::chrono::duration<float,std::ratio<1>>>
        (timeSpan).count();
    float fps{ 1.f / dt };

    averageFpsTime += dt;
    fpsInSec += fps;
    fpsCnt++;
    if (averageFpsTime >= 1.f)
    {
        averageFpsInOneSec = fpsInSec / fpsCnt;
        averageFpsTime = 0.f;
        fpsInSec = 0.f;
        fpsCnt = 0;
    }

    txtStatFPS.setString("FPS: " + std::to_string(averageFpsInOneSec) + " ("
            + std::to_string(fps) + ")");
}
<|endoftext|>


<commit_before>#include <sndfile.h>
#include <iostream>
#include <string>
#include <vector>
#include <boost/program_options.hpp>

#include "utilities.hpp"

namespace po = boost::program_options;

int main(int argc, char **argv) {
    std::string inputFilename = "";
    std::string outputFilename = "";
    int blockSize = 1024;
    float minDb = -45;
    float targetDb = -20;
    int windowSize = 20;
    bool limiter = true;
    float limiterRelease = 0.0006;
    int limiterAttack = 1024;
    bool checkSilence = false;

    po::options_description prettyDesc("Options"); // this version doesn't include the positional arguments
    prettyDesc.add_options()
        ("help", "Show this help information")
        ("target,t", po::value<float>(&targetDb)->required(), "Set target dB level")
        ("silence,s", po::value<float>(&minDb)->default_value(-45.0), "Minimum dB value for audio content, anything below this is considered silence.")
        ("check-silence", "Skips dynamics processing and cuts out silence from the output file. Use to test the silence level.")
        ("window,w", po::value<int>(&windowSize)->default_value(20), "Window size for smoothing volume changes.")
        ("block-size", po::value<int>(&blockSize)->default_value(1024), "Block size for calculating RMS values.")
        ("limiter-attack", po::value<int>(&limiterAttack)->default_value(1024), "Limiter attack time in samples.")
        ("limiter-release", po::value<float>(&limiterRelease)->default_value(0.0006), "Limiter release time in dB/sample.")
        ("limiter-disable", "Disable the limiter completely - may cause clipping.")
    ;
    po::options_description desc("Options"); // this one is actually used to parse, don't use required()
    desc.add_options()
        ("help", "Show this help information")
        ("input-file", po::value<std::string>(&inputFilename))
        ("output-file", po::value<std::string>(&outputFilename))
        ("target,t", po::value<float>(&targetDb), "Set target dB level")
        ("silence,s", po::value<float>(&minDb)->default_value(-45.0), "Minimum dB value for audio content, anything below this is considered silence.")
        ("check-silence", "Skips dynamics processing and cuts out silence from the output file. Use to test the silence level.")
        ("window,w", po::value<int>(&windowSize)->default_value(20), "Window size for smoothing volume changes.")
        ("block-size", po::value<int>(&blockSize)->default_value(1024), "Block size for calculating RMS values.")
        ("limiter-attack", po::value<int>(&limiterAttack)->default_value(1024), "Limiter attack time in samples.")
        ("limiter-release", po::value<float>(&limiterRelease)->default_value(0.0006), "Limiter release time in dB/sample.")
        ("disable-limiter", "Disable the limiter completely - may cause clipping.")
    ;
    po::positional_options_description p;
    p.add("input-file", 1).add("output-file", 1);

    po::variables_map vm;
    try {
        po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
        po::notify(vm);
    } catch(std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
        return 1;
    }

    if (vm.count("help")) {
        std::cout << "Usage: " << argv[0] << " input.wav output.wav OPTIONS" << std::endl << std::endl;
        std::cout << prettyDesc << std::endl;
        return 1;
    }

    // do we have the required values?
    if (!vm.count("input-file") || !vm.count("output-file")) {
        std::cout << "The input and output filenames are required." << std::endl;
        return 1;
    }
    if (vm.count("check-silence")) {
        checkSilence = true;
    }
    if (!vm.count("target") && !checkSilence) {
        std::cout << "The target dB level (-t, --target)is required." << std::endl;
        return 1;
    }
    if (vm.count("disable-limiter")) {
        limiter = false;
    }
    // check that everything's within a valid range
    if (blockSize < 32) {
        std::cout << "Block size must be >= 32." << std::endl;
        return 1;
    }
    if (minDb >= 0) {
        std::cout << "Silence level must be < 0 dB." << std::endl;
        return 1;
    }
    if (targetDb >= 0) {
        std::cout << "Target level must be < 0 dB." << std::endl;
        return 1;
    }
    if (windowSize < 1) {
        std::cout << "Window size must be >= 1." << std::endl;
        return 1;
    }
    if (limiterRelease <= 0) {
        std::cout << "Limiter release must be > 0." << std::endl;
        return 1;
    }
    if (limiterAttack < 1) {
        std::cout << "Limiter attack must be > 0." << std::endl;
        return 1;
    }

    SF_INFO info;
    info.format = 0;
    SNDFILE* infile = sf_open(inputFilename.c_str(), SFM_READ, &info);

    if (!infile) {
        std::cout << "Error opening input file: " << sf_strerror(NULL) << std::endl;
        return 1;
    }

    SNDFILE *outfile = NULL;
    if (checkSilence) {
        SF_INFO outinfo;
        outinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
        outinfo.samplerate = info.samplerate;
        outinfo.channels = info.channels;
        outfile = sf_open(outputFilename.c_str(), SFM_WRITE, &outinfo);

        if (!outfile) {
            std::cout << "Error opening output file: " << sf_strerror(NULL) << std::endl;
            sf_close(infile);
            return 1;
        }
    }

    // the file was opened, let's calculate some RMS!
    std::cout << "Calculating RMS values..." << std::endl;
    std::vector<float> rmsBlocks;
    sf_count_t frames;
    float *data = new float[blockSize * info.channels];
    do {
        frames = sf_readf_float(infile, data, blockSize);
        //std::cout << samples << std::endl;
        float rms = calculateRMS(data, frames * info.channels);
        float rmsDb = VtoDB(rms);
        rmsBlocks.push_back(rmsDb);
        if (checkSilence && rmsDb > minDb) {
            sf_writef_float(outfile, data, frames);
        }
    } while (frames == blockSize);
    std::cout << rmsBlocks.size() << " RMS blocks calculated." << std::endl;
    delete[] data;

    if (checkSilence) {
        std::cout << "Done." << std::endl;

        sf_close(infile);
        sf_close(outfile);
        return 0;
    }

    // use a ring buffer to calculate a moving average over the RMS blocks
    int ringBufferSize = windowSize * 2 + 1;
    float ringBuffer[ringBufferSize];
    for (int i=0; i<ringBufferSize; i++) {
        ringBuffer[i] = -1000.0;
    }
    int ringBufferPos = 0;
    std::vector<float>::size_type currentBlock = 0;
    // start filling the ring buffer
    for (int i=0; i<windowSize; i++) {
        if (currentBlock < rmsBlocks.size()) {
            ringBuffer[ringBufferPos] = rmsBlocks[currentBlock];
        } else {
            ringBuffer[ringBufferPos] = -1000.0;
        }
        currentBlock++;
        ringBufferPos++;
    }
    // go through all of our blocks
    std::cout << "Calculating gain points..." << std::endl;
    std::vector<gainPoint> gainPoints;
    int minAverageBlocks = windowSize * 1.5;
    for (std::vector<float>::size_type i=0; i<rmsBlocks.size(); i++) {
        if (currentBlock < rmsBlocks.size()) {
            ringBuffer[ringBufferPos] = rmsBlocks[currentBlock];
        } else {
            ringBuffer[ringBufferPos] = -1000.0;
        }
        currentBlock++;
        ringBufferPos++;
        if (ringBufferPos >= ringBufferSize) ringBufferPos = 0;
        // calculate the average RMS if we have enough blocks that aren't silent
        int numBlocks = 0;
        float rms = 0;
        for (int j=0; j<ringBufferSize; j++) {
            if (ringBuffer[j] > minDb) {
                numBlocks++;
                rms += ringBuffer[j];
            }
        }
        if (numBlocks > minAverageBlocks) {
            rms = rms / (float)numBlocks;
            float gain = targetDb - rms;
            gainPoint gp;
            gp.gain = gain;
            gp.position = (i * blockSize) + (blockSize / 2);
            gainPoints.push_back(gp);
        }
    }
    std::cout << gainPoints.size() << " gain points calculated." << std::endl;
    if (gainPoints.size() == 0) {
        std::cout << "Error: no gain points found, nothing to do." << std::endl;
        sf_close(infile);
        return 1;
    }

    SF_INFO outinfo;
    outinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    outinfo.samplerate = info.samplerate;
    outinfo.channels = info.channels;
    outfile = sf_open(outputFilename.c_str(), SFM_WRITE, &outinfo);

    if (!outfile) {
        std::cout << "Error opening output file: " << sf_strerror(NULL) << std::endl;
        sf_close(infile);
        return 1;
    }

    // now we go through the file and apply the gain!
    float limiterGain = 0.0;
    std::cout << "Applying gain..." << std::endl;
    int processSize = 1024;
    if (limiter && limiterAttack > processSize) processSize = limiterAttack;
    data = new float[processSize * info.channels];
    float *oldData = new float[processSize * info.channels];
    sf_count_t oldFrames;
    sf_seek(infile, 0, SEEK_SET);
    sf_count_t currentFrame = 0;
    sf_count_t clipped = 0;
    int currentPerc = 0;
    int blockNum = 0;
    int totalBlocks = info.frames / processSize;
    gainPoint firstGainPoint = gainPoints[0];
    gainPoint lastGainPoint = gainPoints[gainPoints.size() - 1];
    int currentGainPointNumber = 0;
    gainPoint currentGainPoint = firstGainPoint;
    gainPoint nextGainPoint;
    if (gainPoints.size() > 1) nextGainPoint = gainPoints[1];
    do {
        // flip the buffers and read new data
        float *temp = oldData;
        data = oldData;
        oldData = temp;
        oldFrames = frames;
        frames = sf_readf_float(infile, data, processSize);
        for (sf_count_t i=0; i<frames; i++) {
            // calculate the gain
            float gain = 0.0;
            if (currentFrame <= firstGainPoint.position) {
                gain = firstGainPoint.gain;
            } else if (currentFrame >= lastGainPoint.position) {
                gain = lastGainPoint.gain;
            } else {
                // interpolate between gain points
                if (currentFrame >= nextGainPoint.position) {
                    currentGainPointNumber++;
                    currentGainPoint = gainPoints[currentGainPointNumber];
                    nextGainPoint = gainPoints[currentGainPointNumber + 1];
                }
                float pos = (float)(currentFrame - currentGainPoint.position) / (float)(nextGainPoint.position - currentGainPoint.position);
                gain = ((1.0f - pos) * currentGainPoint.gain) + (pos * nextGainPoint.gain);
            }
            //float gain = interpolateGain(gainPoints, currentFrame);
            if (limiter) gain += limiterGain;
            float gainMult = DBtoV(gain);
            // apply the gain
            float highestValue = 0.0;
            for (int j=0; j<info.channels; j++) {
                float sample = data[i * info.channels + j];
                sample = sample * gainMult;
                if (!limiter && sample > 1.0) clipped++;
                if (sample > highestValue) highestValue = sample;
                data[i * info.channels + j] = sample;
            }
            if (highestValue > 1.0 && limiter) {
                // kick the limiter in
                highestValue += .001;
                float additionalLimiterGain = -VtoDB(highestValue);
                limiterGain += additionalLimiterGain;
                // and drop the attack frames down
                for (int attack=0; attack<limiterAttack; attack++) {
                    int frame = i - attack;
                    float gain = additionalLimiterGain * ((float)(limiterAttack - attack) / (float)limiterAttack);
                    float mult = DBtoV(gain);
                    if (frame >= 0) {
                        for (int j=0; j<info.channels; j++) {
                            data[frame * info.channels + j] *= mult;
                        }
                    } else {
                        int oldFrame = frame + oldFrames;
                        for (int j=0; j<info.channels; j++) {
                            oldData[oldFrame * info.channels + j] *= mult;
                        }
                    }
                }
                // and drop our current frame down
                for (int j=0; j<info.channels; j++) {
                    data[i * info.channels + j] /= highestValue;
                }

            }
            currentFrame++;
            limiterGain += limiterRelease;
            if (limiterGain > 0) limiterGain = 0;
        }
        // write the frames to the new file
        if (blockNum > 0) sf_writef_float(outfile, oldData, oldFrames);
        blockNum++;
        if (totalBlocks > 0) {
            int thisPerc = (blockNum * 100) / totalBlocks;
            if (thisPerc > currentPerc) {
                currentPerc = thisPerc;
                std::cout << currentPerc << "% done" << std::endl;
            }
        }
    } while (frames == processSize);
    sf_writef_float(outfile, data, frames);
    if (clipped) std::cout << "WARNING: " << clipped << " samples clipped and limiter disabled" << std::endl;

    std::cout << "Done." << std::endl;

    sf_close(infile);
    sf_close(outfile);

    return 0;
}
<commit_msg>added gain information<commit_after>#include <sndfile.h>
#include <iostream>
#include <string>
#include <vector>
#include <boost/program_options.hpp>

#include "utilities.hpp"

namespace po = boost::program_options;

int main(int argc, char **argv) {
    std::string inputFilename = "";
    std::string outputFilename = "";
    int blockSize = 1024;
    float minDb = -45;
    float targetDb = -20;
    int windowSize = 20;
    bool limiter = true;
    float limiterRelease = 0.0006;
    int limiterAttack = 1024;
    bool checkSilence = false;

    po::options_description prettyDesc("Options"); // this version doesn't include the positional arguments
    prettyDesc.add_options()
        ("help", "Show this help information")
        ("target,t", po::value<float>(&targetDb)->required(), "Set target dB level")
        ("silence,s", po::value<float>(&minDb)->default_value(-45.0), "Minimum dB value for audio content, anything below this is considered silence.")
        ("check-silence", "Skips dynamics processing and cuts out silence from the output file. Use to test the silence level.")
        ("window,w", po::value<int>(&windowSize)->default_value(20), "Window size for smoothing volume changes.")
        ("block-size", po::value<int>(&blockSize)->default_value(1024), "Block size for calculating RMS values.")
        ("limiter-attack", po::value<int>(&limiterAttack)->default_value(1024), "Limiter attack time in samples.")
        ("limiter-release", po::value<float>(&limiterRelease)->default_value(0.0006), "Limiter release time in dB/sample.")
        ("limiter-disable", "Disable the limiter completely - may cause clipping.")
    ;
    po::options_description desc("Options"); // this one is actually used to parse, don't use required()
    desc.add_options()
        ("help", "Show this help information")
        ("input-file", po::value<std::string>(&inputFilename))
        ("output-file", po::value<std::string>(&outputFilename))
        ("target,t", po::value<float>(&targetDb), "Set target dB level")
        ("silence,s", po::value<float>(&minDb)->default_value(-45.0), "Minimum dB value for audio content, anything below this is considered silence.")
        ("check-silence", "Skips dynamics processing and cuts out silence from the output file. Use to test the silence level.")
        ("window,w", po::value<int>(&windowSize)->default_value(20), "Window size for smoothing volume changes.")
        ("block-size", po::value<int>(&blockSize)->default_value(1024), "Block size for calculating RMS values.")
        ("limiter-attack", po::value<int>(&limiterAttack)->default_value(1024), "Limiter attack time in samples.")
        ("limiter-release", po::value<float>(&limiterRelease)->default_value(0.0006), "Limiter release time in dB/sample.")
        ("disable-limiter", "Disable the limiter completely - may cause clipping.")
    ;
    po::positional_options_description p;
    p.add("input-file", 1).add("output-file", 1);

    po::variables_map vm;
    try {
        po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
        po::notify(vm);
    } catch(std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
        return 1;
    }

    if (vm.count("help")) {
        std::cout << "Usage: " << argv[0] << " input.wav output.wav OPTIONS" << std::endl << std::endl;
        std::cout << prettyDesc << std::endl;
        return 1;
    }

    // do we have the required values?
    if (!vm.count("input-file") || !vm.count("output-file")) {
        std::cout << "The input and output filenames are required." << std::endl;
        return 1;
    }
    if (vm.count("check-silence")) {
        checkSilence = true;
    }
    if (!vm.count("target") && !checkSilence) {
        std::cout << "The target dB level (-t, --target)is required." << std::endl;
        return 1;
    }
    if (vm.count("disable-limiter")) {
        limiter = false;
    }
    // check that everything's within a valid range
    if (blockSize < 32) {
        std::cout << "Block size must be >= 32." << std::endl;
        return 1;
    }
    if (minDb >= 0) {
        std::cout << "Silence level must be < 0 dB." << std::endl;
        return 1;
    }
    if (targetDb >= 0) {
        std::cout << "Target level must be < 0 dB." << std::endl;
        return 1;
    }
    if (windowSize < 1) {
        std::cout << "Window size must be >= 1." << std::endl;
        return 1;
    }
    if (limiterRelease <= 0) {
        std::cout << "Limiter release must be > 0." << std::endl;
        return 1;
    }
    if (limiterAttack < 1) {
        std::cout << "Limiter attack must be > 0." << std::endl;
        return 1;
    }

    SF_INFO info;
    info.format = 0;
    SNDFILE* infile = sf_open(inputFilename.c_str(), SFM_READ, &info);

    if (!infile) {
        std::cout << "Error opening input file: " << sf_strerror(NULL) << std::endl;
        return 1;
    }

    SNDFILE *outfile = NULL;
    if (checkSilence) {
        SF_INFO outinfo;
        outinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
        outinfo.samplerate = info.samplerate;
        outinfo.channels = info.channels;
        outfile = sf_open(outputFilename.c_str(), SFM_WRITE, &outinfo);

        if (!outfile) {
            std::cout << "Error opening output file: " << sf_strerror(NULL) << std::endl;
            sf_close(infile);
            return 1;
        }
    }

    // the file was opened, let's calculate some RMS!
    std::cout << "Calculating RMS values..." << std::endl;
    std::vector<float> rmsBlocks;
    sf_count_t frames;
    float *data = new float[blockSize * info.channels];
    do {
        frames = sf_readf_float(infile, data, blockSize);
        //std::cout << samples << std::endl;
        float rms = calculateRMS(data, frames * info.channels);
        float rmsDb = VtoDB(rms);
        rmsBlocks.push_back(rmsDb);
        if (checkSilence && rmsDb > minDb) {
            sf_writef_float(outfile, data, frames);
        }
    } while (frames == blockSize);
    std::cout << rmsBlocks.size() << " RMS blocks calculated." << std::endl;
    delete[] data;

    if (checkSilence) {
        std::cout << "Done." << std::endl;

        sf_close(infile);
        sf_close(outfile);
        return 0;
    }

    // use a ring buffer to calculate a moving average over the RMS blocks
    int ringBufferSize = windowSize * 2 + 1;
    float ringBuffer[ringBufferSize];
    for (int i=0; i<ringBufferSize; i++) {
        ringBuffer[i] = -1000.0;
    }
    int ringBufferPos = 0;
    std::vector<float>::size_type currentBlock = 0;
    // start filling the ring buffer
    for (int i=0; i<windowSize; i++) {
        if (currentBlock < rmsBlocks.size()) {
            ringBuffer[ringBufferPos] = rmsBlocks[currentBlock];
        } else {
            ringBuffer[ringBufferPos] = -1000.0;
        }
        currentBlock++;
        ringBufferPos++;
    }
    // go through all of our blocks
    std::cout << "Calculating gain points..." << std::endl;
    std::vector<gainPoint> gainPoints;
    int minAverageBlocks = windowSize * 1.5;
    float maximumGain = 0;
    float minimumGain = 0;
    for (std::vector<float>::size_type i=0; i<rmsBlocks.size(); i++) {
        if (currentBlock < rmsBlocks.size()) {
            ringBuffer[ringBufferPos] = rmsBlocks[currentBlock];
        } else {
            ringBuffer[ringBufferPos] = -1000.0;
        }
        currentBlock++;
        ringBufferPos++;
        if (ringBufferPos >= ringBufferSize) ringBufferPos = 0;
        // calculate the average RMS if we have enough blocks that aren't silent
        int numBlocks = 0;
        float rms = 0;
        for (int j=0; j<ringBufferSize; j++) {
            if (ringBuffer[j] > minDb) {
                numBlocks++;
                rms += ringBuffer[j];
            }
        }
        if (numBlocks > minAverageBlocks) {
            rms = rms / (float)numBlocks;
            float gain = targetDb - rms;
            gainPoint gp;
            gp.gain = gain;
            gp.position = (i * blockSize) + (blockSize / 2);
            gainPoints.push_back(gp);
            if (gainPoints.size() == 1 || gain > maximumGain) maximumGain = gain;
            if (gainPoints.size() == 1 || gain < minimumGain) minimumGain = gain;
        }
    }
    std::cout << gainPoints.size() << " gain points calculated." << std::endl;
    if (gainPoints.size() == 0) {
        std::cout << "Error: no gain points found, nothing to do." << std::endl;
        sf_close(infile);
        return 1;
    }
    std::cout << "Minimum gain: " << minimumGain << " dB." << std::endl;
    std::cout << "Maximum gain: " << maximumGain << " dB." << std::endl;

    SF_INFO outinfo;
    outinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    outinfo.samplerate = info.samplerate;
    outinfo.channels = info.channels;
    outfile = sf_open(outputFilename.c_str(), SFM_WRITE, &outinfo);

    if (!outfile) {
        std::cout << "Error opening output file: " << sf_strerror(NULL) << std::endl;
        sf_close(infile);
        return 1;
    }

    // now we go through the file and apply the gain!
    float limiterGain = 0.0;
    std::cout << "Applying gain..." << std::endl;
    int processSize = 1024;
    if (limiter && limiterAttack > processSize) processSize = limiterAttack;
    data = new float[processSize * info.channels];
    float *oldData = new float[processSize * info.channels];
    sf_count_t oldFrames;
    sf_seek(infile, 0, SEEK_SET);
    sf_count_t currentFrame = 0;
    sf_count_t clipped = 0;
    int currentPerc = 0;
    int blockNum = 0;
    int totalBlocks = info.frames / processSize;
    gainPoint firstGainPoint = gainPoints[0];
    gainPoint lastGainPoint = gainPoints[gainPoints.size() - 1];
    int currentGainPointNumber = 0;
    gainPoint currentGainPoint = firstGainPoint;
    gainPoint nextGainPoint;
    if (gainPoints.size() > 1) nextGainPoint = gainPoints[1];
    do {
        // flip the buffers and read new data
        float *temp = oldData;
        data = oldData;
        oldData = temp;
        oldFrames = frames;
        frames = sf_readf_float(infile, data, processSize);
        for (sf_count_t i=0; i<frames; i++) {
            // calculate the gain
            float gain = 0.0;
            if (currentFrame <= firstGainPoint.position) {
                gain = firstGainPoint.gain;
            } else if (currentFrame >= lastGainPoint.position) {
                gain = lastGainPoint.gain;
            } else {
                // interpolate between gain points
                if (currentFrame >= nextGainPoint.position) {
                    currentGainPointNumber++;
                    currentGainPoint = gainPoints[currentGainPointNumber];
                    nextGainPoint = gainPoints[currentGainPointNumber + 1];
                }
                float pos = (float)(currentFrame - currentGainPoint.position) / (float)(nextGainPoint.position - currentGainPoint.position);
                gain = ((1.0f - pos) * currentGainPoint.gain) + (pos * nextGainPoint.gain);
            }
            //float gain = interpolateGain(gainPoints, currentFrame);
            if (limiter) gain += limiterGain;
            float gainMult = DBtoV(gain);
            // apply the gain
            float highestValue = 0.0;
            for (int j=0; j<info.channels; j++) {
                float sample = data[i * info.channels + j];
                sample = sample * gainMult;
                if (!limiter && sample > 1.0) clipped++;
                if (sample > highestValue) highestValue = sample;
                data[i * info.channels + j] = sample;
            }
            if (highestValue > 1.0 && limiter) {
                // kick the limiter in
                highestValue += .001;
                float additionalLimiterGain = -VtoDB(highestValue);
                limiterGain += additionalLimiterGain;
                // and drop the attack frames down
                for (int attack=0; attack<limiterAttack; attack++) {
                    int frame = i - attack;
                    float gain = additionalLimiterGain * ((float)(limiterAttack - attack) / (float)limiterAttack);
                    float mult = DBtoV(gain);
                    if (frame >= 0) {
                        for (int j=0; j<info.channels; j++) {
                            data[frame * info.channels + j] *= mult;
                        }
                    } else {
                        int oldFrame = frame + oldFrames;
                        for (int j=0; j<info.channels; j++) {
                            oldData[oldFrame * info.channels + j] *= mult;
                        }
                    }
                }
                // and drop our current frame down
                for (int j=0; j<info.channels; j++) {
                    data[i * info.channels + j] /= highestValue;
                }

            }
            currentFrame++;
            limiterGain += limiterRelease;
            if (limiterGain > 0) limiterGain = 0;
        }
        // write the frames to the new file
        if (blockNum > 0) sf_writef_float(outfile, oldData, oldFrames);
        blockNum++;
        if (totalBlocks > 0) {
            int thisPerc = (blockNum * 100) / totalBlocks;
            if (thisPerc > currentPerc) {
                currentPerc = thisPerc;
                std::cout << currentPerc << "% done" << std::endl;
            }
        }
    } while (frames == processSize);
    sf_writef_float(outfile, data, frames);
    if (clipped) std::cout << "WARNING: " << clipped << " samples clipped and limiter disabled" << std::endl;

    std::cout << "Done." << std::endl;

    sf_close(infile);
    sf_close(outfile);

    return 0;
}
<|endoftext|>


<commit_before>6567e7ca-2749-11e6-8b20-e0f84713e7b8<commit_msg>Fix that bug where things didn't work but now they should<commit_after>65785fba-2749-11e6-a589-e0f84713e7b8<|endoftext|>


<commit_before>4baf4c42-ad5d-11e7-9c7d-ac87a332f658<commit_msg>bug fix<commit_after>4c3df26b-ad5d-11e7-8b4c-ac87a332f658<|endoftext|>


<commit_before>715e8a5c-2749-11e6-9794-e0f84713e7b8<commit_msg>I hope I am done<commit_after>716e4e0f-2749-11e6-abb0-e0f84713e7b8<|endoftext|>


<commit_before>4fbb257a-ad5d-11e7-b173-ac87a332f658<commit_msg>Did a thing<commit_after>508faf47-ad5d-11e7-af2e-ac87a332f658<|endoftext|>