C client: Simplify audio/http API

This commit is contained in:
UnknownShadow200 2018-08-29 00:33:27 +10:00
parent cac5978407
commit e0e0326a98
16 changed files with 149 additions and 139 deletions

View File

@ -39,19 +39,20 @@ namespace SharpWave {
Play(); Play();
} }
bool BufferBlock(AudioChunk tmp, AudioFormat fmt, IEnumerator<AudioChunk> chunks) { bool BufferBlock(int i, AudioChunk tmp, int size, IEnumerator<AudioChunk> chunks) {
// decode up to around a second
int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short);
tmp.Length = 0; tmp.Length = 0;
bool end = false;
while (tmp.Length < secondSize) { while (tmp.Length < size) {
if (!chunks.MoveNext()) return true; if (!chunks.MoveNext()) { end = true; break; }
AudioChunk src = chunks.Current; AudioChunk src = chunks.Current;
Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length); Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length);
tmp.Length += src.Length; tmp.Length += src.Length;
} }
return false;
BufferData(i, tmp);
return end;
} }
public void PlayStreaming(Stream stream) { public void PlayStreaming(Stream stream) {
@ -64,19 +65,19 @@ namespace SharpWave {
// largest possible vorbis frame decodes to blocksize1 samples // largest possible vorbis frame decodes to blocksize1 samples
// so we may end up decoding slightly over a second of audio // so we may end up decoding slightly over a second of audio
int chunkSize = (fmt.SampleRate + 8192) * fmt.Channels * sizeof(short); int chunkSize = (fmt.SampleRate + 8192) * fmt.Channels * sizeof(short);
int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short);
byte[][] data = new byte[NumBuffers][]; byte[][] data = new byte[NumBuffers][];
for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; } for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; }
bool reachedEnd = false; bool end = false;
for (int i = 0; i < NumBuffers && !reachedEnd; i++) { for (int i = 0; i < NumBuffers && !end; i++) {
tmp.Data = data[i]; tmp.Data = data[i];
reachedEnd = BufferBlock(tmp, fmt, chunks); end = BufferBlock(i, tmp, secondSize, chunks);
BufferData(i, tmp);
} }
Play(); Play();
for (; !reachedEnd;) { for (; !end;) {
int next = -1; int next = -1;
for (int i = 0; i < NumBuffers; i++) { for (int i = 0; i < NumBuffers; i++) {
if (IsCompleted(i)) { next = i; break; } if (IsCompleted(i)) { next = i; break; }
@ -86,8 +87,7 @@ namespace SharpWave {
if (pendingStop) break; if (pendingStop) break;
tmp.Data = data[next]; tmp.Data = data[next];
reachedEnd = BufferBlock(tmp, fmt, chunks); end = BufferBlock(next, tmp, secondSize, chunks);
BufferData(next, tmp);
} }
while (!IsFinished()) { Thread.Sleep(10); } while (!IsFinished()) { Thread.Sleep(10); }

View File

@ -82,8 +82,8 @@ static void AsyncDownloader_Add(String* url, bool priority, String* id, UInt8 ty
Mutex_Lock(async_pendingMutex); Mutex_Lock(async_pendingMutex);
{ {
struct AsyncRequest req = { 0 }; struct AsyncRequest req = { 0 };
String reqUrl = String_FromArray(req.URL); String_Set(&reqUrl, url); String reqUrl = String_FromArray(req.URL); String_Copy(&reqUrl, url);
String reqID = String_FromArray(req.ID); String_Set(&reqID, id); String reqID = String_FromArray(req.ID); String_Copy(&reqID, id);
req.RequestType = type; req.RequestType = type;
Platform_Log2("Adding %s (type %b)", &reqUrl, &type); Platform_Log2("Adding %s (type %b)", &reqUrl, &type);
@ -92,7 +92,7 @@ static void AsyncDownloader_Add(String* url, bool priority, String* id, UInt8 ty
req.LastModified = *lastModified; req.LastModified = *lastModified;
} }
if (etag) { if (etag) {
String reqEtag = String_FromArray(req.Etag); String_Set(&reqEtag, etag); String reqEtag = String_FromArray(req.Etag); String_Copy(&reqEtag, etag);
} }
/* request.Data = data; TODO: Implement this. do we need to copy or expect caller to malloc it? */ /* request.Data = data; TODO: Implement this. do we need to copy or expect caller to malloc it? */
@ -112,7 +112,7 @@ void AsyncDownloader_GetSkin(STRING_PURE String* id, STRING_PURE String* skinNam
String url = String_FromArray(urlBuffer); String url = String_FromArray(urlBuffer);
if (Utils_IsUrlPrefix(skinName, 0)) { if (Utils_IsUrlPrefix(skinName, 0)) {
String_Set(&url, skinName); String_Copy(&url, skinName);
} else { } else {
String_AppendString(&url, &async_skinServer); String_AppendString(&url, &async_skinServer);
String_AppendColorless(&url, skinName); String_AppendColorless(&url, skinName);
@ -192,43 +192,20 @@ bool AsyncDownloader_GetCurrent(struct AsyncRequest* request, Int32* progress) {
static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) { static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
String url = String_FromRawArray(request->URL); String url = String_FromRawArray(request->URL);
Platform_Log2("Downloading from %s (type %b)", &url, &request->RequestType); Platform_Log2("Downloading from %s (type %b)", &url, &request->RequestType);
struct Stopwatch stopwatch; UInt32 elapsedMS; struct Stopwatch stopwatch;
void* handle;
ReturnCode res;
Stopwatch_Start(&stopwatch); Stopwatch_Start(&stopwatch);
res = Http_MakeRequest(request, &handle); ReturnCode res = Http_Do(request, &async_curProgress);
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000; UInt32 elapsed = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
Platform_Log2("HTTP make request: ret code %i, in %i ms", &res, &elapsedMS);
if (res) return;
async_curProgress = ASYNC_PROGRESS_FETCHING_DATA;
UInt32 size = 0;
Stopwatch_Start(&stopwatch);
res = Http_GetRequestHeaders(request, handle, &size);
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
UInt32 status = request->StatusCode; UInt32 status = request->StatusCode;
Platform_Log3("HTTP get headers: ret code %i (http %i), in %i ms", &res, &status, &elapsedMS); Platform_Log3("HTTP: return code %i (http %i), in %i ms", &res, &status, &elapsed);
if (res || request->StatusCode != 200) { if (request->ResultData) {
Http_FreeRequest(handle); return; UInt32 size = request->ResultSize;
UInt64 addr = (UInt64)request->ResultData;
Platform_Log2("HTTP returned data: %i bytes at %x", &size, &addr);
} }
void* data = NULL;
if (request->RequestType != REQUEST_TYPE_CONTENT_LENGTH) {
Stopwatch_Start(&stopwatch);
res = Http_GetRequestData(request, handle, &data, size, &async_curProgress);
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
Platform_Log3("HTTP get data: ret code %i (size %i), in %i ms", &res, &size, &elapsedMS);
}
Http_FreeRequest(handle);
if (res) return;
UInt64 addr = (UInt64)data;
Platform_Log2("OK I got the DATA! %i bytes at %x", &size, &addr);
request->ResultData = data;
request->ResultSize = size;
} }
static void AsyncDownloader_CompleteResult(struct AsyncRequest* request) { static void AsyncDownloader_CompleteResult(struct AsyncRequest* request) {

View File

@ -148,7 +148,7 @@ static void Soundboard_Init(struct Soundboard* board, STRING_PURE String* boardN
group = &board->Groups[board->Count++]; group = &board->Groups[board->Count++];
group->Name = String_ClearedArray(group->NameBuffer); group->Name = String_ClearedArray(group->NameBuffer);
String_Set(&group->Name, &name); String_Copy(&group->Name, &name);
} }
if (group->Count == Array_Elems(group->Sounds)) { if (group->Count == Array_Elems(group->Sounds)) {
@ -211,7 +211,8 @@ static void Sounds_PlayRaw(struct SoundOutput* output, struct Sound* snd, struct
} }
} }
Audio_PlayData(output->Handle, 0, buffer, snd->DataSize); Audio_BufferData(output->Handle, 0, buffer, snd->DataSize);
Audio_Play(output->Handle);
/* TODO: handle errors here */ /* TODO: handle errors here */
} }
@ -320,6 +321,23 @@ void* music_thread;
void* music_waitable; void* music_waitable;
volatile bool music_pendingStop; volatile bool music_pendingStop;
static ReturnCode Music_BufferBlock(Int32 i, Int16* data, Int32 maxSamples, struct VorbisState* ctx) {
Int32 samples = 0;
ReturnCode res = 0;
while (samples < maxSamples) {
res = Vorbis_DecodeFrame(ctx);
if (res) break;
Int16* cur = &data[samples];
samples += Vorbis_OutputFrame(ctx, cur);
}
if (Game_MusicVolume < 100) { Volume_Mix16(data, samples, Game_MusicVolume); }
Audio_BufferData(music_out, i, data, samples * sizeof(Int16));
return res;
}
static ReturnCode Music_PlayOgg(struct Stream* source) { static ReturnCode Music_PlayOgg(struct Stream* source) {
UInt8 buffer[OGG_BUFFER_SIZE]; UInt8 buffer[OGG_BUFFER_SIZE];
struct Stream stream; struct Stream stream;
@ -338,12 +356,19 @@ static ReturnCode Music_PlayOgg(struct Stream* source) {
/* largest possible vorbis frame decodes to blocksize1 * channels samples */ /* largest possible vorbis frame decodes to blocksize1 * channels samples */
/* so we may end up decoding slightly over a second of audio */ /* so we may end up decoding slightly over a second of audio */
Int32 chunkSize = fmt.Channels * (fmt.SampleRate + vorbis.BlockSizes[1]); Int32 i, chunkSize = fmt.Channels * (fmt.SampleRate + vorbis.BlockSizes[1]);
Int32 samplesPerSecond = fmt.Channels * fmt.SampleRate; Int32 samplesPerSecond = fmt.Channels * fmt.SampleRate;
Int16* data = Mem_Alloc(chunkSize * AUDIO_MAX_CHUNKS, sizeof(Int16), "Ogg - final PCM output"); Int16* data = Mem_Alloc(chunkSize * AUDIO_MAX_CHUNKS, sizeof(Int16), "Ogg - final PCM output");
/* fill up with some samples before playing */
for (i = 0; i < AUDIO_MAX_CHUNKS && !res; i++) {
Int16* base = data + (chunkSize * i);
res = Music_BufferBlock(i, base, samplesPerSecond, &vorbis);
}
Audio_Play(music_out);
for (;;) { for (;;) {
Int32 i, next = -1; Int32 next = -1;
for (i = 0; i < AUDIO_MAX_CHUNKS; i++) { for (i = 0; i < AUDIO_MAX_CHUNKS; i++) {
if (Audio_IsCompleted(music_out, i)) { next = i; break; } if (Audio_IsCompleted(music_out, i)) { next = i; break; }
} }
@ -351,20 +376,8 @@ static ReturnCode Music_PlayOgg(struct Stream* source) {
if (next == -1) { Thread_Sleep(10); continue; } if (next == -1) { Thread_Sleep(10); continue; }
if (music_pendingStop) break; if (music_pendingStop) break;
/* decode up to around a second */
Int16* base = data + (chunkSize * next); Int16* base = data + (chunkSize * next);
Int32 samples = 0; res = Music_BufferBlock(next, base, samplesPerSecond, &vorbis);
while (samples < samplesPerSecond) {
res = Vorbis_DecodeFrame(&vorbis);
if (res) break;
Int16* cur = &base[samples];
samples += Vorbis_OutputFrame(&vorbis, cur);
}
if (Game_MusicVolume < 100) { Volume_Mix16(base, samples, Game_MusicVolume); }
Audio_PlayData(music_out, next, base, samples * sizeof(Int16));
/* need to specially handle last bit of audio */ /* need to specially handle last bit of audio */
if (res) break; if (res) break;
} }

View File

@ -116,7 +116,7 @@ void Game_GetDefaultTexturePack(STRING_TRANSIENT String* texPack) {
} }
void Game_SetDefaultTexturePack(STRING_PURE String* texPack) { void Game_SetDefaultTexturePack(STRING_PURE String* texPack) {
String_Set(&game_defTexPack, texPack); String_Copy(&game_defTexPack, texPack);
Options_Set(OPT_DEFAULT_TEX_PACK, texPack); Options_Set(OPT_DEFAULT_TEX_PACK, texPack);
} }

View File

@ -1307,7 +1307,7 @@ static void SaveLevelScreen_DoSave(struct GuiElem* elem, struct GuiElem* widget,
String warnMsg = String_FromConst("Saving.."); String warnMsg = String_FromConst("Saving..");
SaveLevelScreen_MakeDesc(screen, &warnMsg); SaveLevelScreen_MakeDesc(screen, &warnMsg);
String_Set(&screen->TextPath, &path); String_Copy(&screen->TextPath, &path);
SaveLevelScreen_RemoveOverwrites(screen); SaveLevelScreen_RemoveOverwrites(screen);
} }
} }
@ -1495,7 +1495,7 @@ static void FontListScreen_EntryClick(struct GuiElem* elem, struct GuiElem* w) {
String fontName = ListScreen_UNSAFE_GetCur(screen, w); String fontName = ListScreen_UNSAFE_GetCur(screen, w);
if (String_CaselessEqualsConst(&fontName, LIST_SCREEN_EMPTY)) return; if (String_CaselessEqualsConst(&fontName, LIST_SCREEN_EMPTY)) return;
String_Set(&Game_FontName, &fontName); String_Copy(&Game_FontName, &fontName);
Options_Set(OPT_FONT_NAME, &fontName); Options_Set(OPT_FONT_NAME, &fontName);
Int32 cur = screen->CurrentIndex; Int32 cur = screen->CurrentIndex;
@ -2494,14 +2494,14 @@ static void GraphicsOptionsScreen_SetMipmaps(STRING_PURE String* v) {
Gfx_Mipmaps = Menu_SetBool(v, OPT_MIPMAPS); Gfx_Mipmaps = Menu_SetBool(v, OPT_MIPMAPS);
char urlBuffer[STRING_SIZE]; char urlBuffer[STRING_SIZE];
String url = String_FromArray(urlBuffer); String url = String_FromArray(urlBuffer);
String_Set(&url, &World_TextureUrl); String_Copy(&url, &World_TextureUrl);
/* always force a reload from cache */ /* always force a reload from cache */
World_TextureUrl.length = 0; World_TextureUrl.length = 0;
String_AppendConst(&World_TextureUrl, "~`#$_^*()@"); String_AppendConst(&World_TextureUrl, "~`#$_^*()@");
TexturePack_ExtractCurrent(&url); TexturePack_ExtractCurrent(&url);
String_Set(&World_TextureUrl, &url); String_Copy(&World_TextureUrl, &url);
} }
static void GraphicsOptionsScreen_ContextRecreated(void* obj) { static void GraphicsOptionsScreen_ContextRecreated(void* obj) {
@ -3237,7 +3237,7 @@ struct Screen* UrlWarningOverlay_MakeInstance(STRING_PURE String* url) {
Array_Elems(widgets), UrlWarningOverlay_ContextRecreated); Array_Elems(widgets), UrlWarningOverlay_ContextRecreated);
String dstUrl = String_FromArray(screen->__UrlBuffer); String dstUrl = String_FromArray(screen->__UrlBuffer);
String_Set(&dstUrl, url); String_Copy(&dstUrl, url);
screen->Url = dstUrl; screen->Url = dstUrl;
Overlay_UseVTABLE((struct MenuScreen*)screen, &WarningOverlay_VTABLE); Overlay_UseVTABLE((struct MenuScreen*)screen, &WarningOverlay_VTABLE);
@ -3294,7 +3294,7 @@ struct Screen* ConfirmDenyOverlay_MakeInstance(STRING_PURE String* url, bool alw
Array_Elems(widgets), ConfirmDenyOverlay_ContextRecreated); Array_Elems(widgets), ConfirmDenyOverlay_ContextRecreated);
String dstUrl = String_FromArray(screen->__UrlBuffer); String dstUrl = String_FromArray(screen->__UrlBuffer);
String_Set(&dstUrl, url); String_Copy(&dstUrl, url);
screen->Url = dstUrl; screen->Url = dstUrl;
screen->AlwaysDeny = alwaysDeny; screen->AlwaysDeny = alwaysDeny;

View File

@ -222,7 +222,7 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) {
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
Window_ProcessEvents(); Window_ProcessEvents();
if (clipboard_paste_text.length) { if (clipboard_paste_text.length) {
String_Set(value, &clipboard_paste_text); String_Copy(value, &clipboard_paste_text);
return; return;
} else { } else {
Thread_Sleep(100); Thread_Sleep(100);
@ -231,7 +231,7 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) {
} }
void Window_SetClipboardText(STRING_PURE String* value) { void Window_SetClipboardText(STRING_PURE String* value) {
String_Set(&clipboard_paste_text, value); String_Copy(&clipboard_paste_text, value);
XSetSelectionOwner(win_display, xa_clipboard, win_handle, 0); XSetSelectionOwner(win_display, xa_clipboard, win_handle, 0);
} }

View File

@ -102,8 +102,8 @@ static void Handlers_CheckName(EntityID id, STRING_TRANSIENT String* displayName
String nameNoCols = String_FromArray(nameNoColsBuffer); String nameNoCols = String_FromArray(nameNoColsBuffer);
String_AppendColorless(&nameNoCols, displayName); String_AppendColorless(&nameNoCols, displayName);
if (!String_Equals(&nameNoCols, &Game_Username)) { String_Set(displayName, &Game_Username); } if (!String_Equals(&nameNoCols, &Game_Username)) { String_Copy(displayName, &Game_Username); }
if (!skinName->length) { String_Set(skinName, &Game_Username); } if (!skinName->length) { String_Copy(skinName, &Game_Username); }
} }
static void Classic_ReadAbsoluteLocation(UInt8* data, EntityID id, bool interpolate); static void Classic_ReadAbsoluteLocation(UInt8* data, EntityID id, bool interpolate);
@ -125,9 +125,9 @@ static void Handlers_AddEntity(UInt8* data, EntityID id, STRING_TRANSIENT String
p->FetchedSkin = false; p->FetchedSkin = false;
String player_name = String_ClearedArray(p->DisplayNameRaw); String player_name = String_ClearedArray(p->DisplayNameRaw);
String_Set(&player_name, displayName); String_Copy(&player_name, displayName);
String player_skin = String_ClearedArray(p->SkinNameRaw); String player_skin = String_ClearedArray(p->SkinNameRaw);
String_Set(&player_skin, skinName); String_Copy(&player_skin, skinName);
Player_UpdateName((struct Player*)p); Player_UpdateName((struct Player*)p);
} }
@ -381,7 +381,7 @@ static void Classic_Handshake(UInt8* data) {
struct HacksComp* hacks = &LocalPlayer_Instance.Hacks; struct HacksComp* hacks = &LocalPlayer_Instance.Hacks;
HacksComp_SetUserType(hacks, *data, !cpe_blockPerms); HacksComp_SetUserType(hacks, *data, !cpe_blockPerms);
String_Set(&hacks->HacksFlags, &ServerConnection_ServerName); String_Copy(&hacks->HacksFlags, &ServerConnection_ServerName);
String_AppendString(&hacks->HacksFlags, &ServerConnection_ServerMOTD); String_AppendString(&hacks->HacksFlags, &ServerConnection_ServerMOTD);
HacksComp_UpdateState(hacks); HacksComp_UpdateState(hacks);
} }

View File

@ -862,28 +862,33 @@ ReturnCode Socket_Select(SocketPtr socket, Int32 selectMode, bool* success) {
*#########################################################################################################################*/ *#########################################################################################################################*/
#if CC_BUILD_WIN #if CC_BUILD_WIN
HINTERNET hInternet; HINTERNET hInternet;
/* TODO: Test last modified and etag even work */
#define FLAG_STATUS HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER
#define FLAG_LENGTH HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER
#define FLAG_LASTMOD HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME
void Http_Init(void) { void Http_Init(void) {
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */ /* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
hInternet = InternetOpenA(PROGRAM_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); hInternet = InternetOpenA(PROGRAM_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet) ErrorHandler_FailWithCode(GetLastError(), "Failed to init WinINet"); if (!hInternet) ErrorHandler_FailWithCode(GetLastError(), "Failed to init WinINet");
} }
ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle) { static ReturnCode Http_Make(struct AsyncRequest* req, HINTERNET* handle) {
String url = String_FromRawArray(request->URL); String url = String_FromRawArray(req->URL);
char headersBuffer[STRING_SIZE * 2]; char headersBuffer[STRING_SIZE * 2];
String headers = String_MakeNull(); String headers = String_MakeNull();
/* https://stackoverflow.com/questions/25308488/c-wininet-custom-http-headers */ /* https://stackoverflow.com/questions/25308488/c-wininet-custom-http-headers */
if (request->Etag[0] || request->LastModified.Year) { if (req->Etag[0] || req->LastModified.Year) {
headers = String_ClearedArray(headersBuffer); headers = String_ClearedArray(headersBuffer);
if (request->LastModified.Year) { if (req->LastModified.Year) {
String_AppendConst(&headers, "If-Modified-Since: "); String_AppendConst(&headers, "If-Modified-Since: ");
DateTime_HttpDate(&request->LastModified, &headers); DateTime_HttpDate(&req->LastModified, &headers);
String_AppendConst(&headers, "\r\n"); String_AppendConst(&headers, "\r\n");
} }
if (request->Etag[0]) { if (req->Etag[0]) {
String etag = String_FromRawArray(request->Etag); String etag = String_FromRawArray(req->Etag);
String_AppendConst(&headers, "If-None-Match: "); String_AppendConst(&headers, "If-None-Match: ");
String_AppendString(&headers, &etag); String_AppendString(&headers, &etag);
String_AppendConst(&headers, "\r\n"); String_AppendConst(&headers, "\r\n");
@ -896,39 +901,38 @@ ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle) {
return Win_Return(*handle); return Win_Return(*handle);
} }
/* TODO: Test last modified and etag even work */ static ReturnCode Http_GetHeaders(struct AsyncRequest* req, HINTERNET handle) {
#define Http_Query(flags, result) HttpQueryInfoA(handle, flags, result, &bufferLen, NULL) DWORD len;
ReturnCode Http_GetRequestHeaders(struct AsyncRequest* request, void* handle, UInt32* size) {
DWORD bufferLen;
UInt32 status; UInt32 status;
bufferLen = sizeof(DWORD); len = sizeof(DWORD);
if (!Http_Query(HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status)) return GetLastError(); if (!HttpQueryInfoA(handle, FLAG_STATUS, &status, &len, NULL)) return GetLastError();
request->StatusCode = status; req->StatusCode = status;
bufferLen = sizeof(DWORD); len = sizeof(DWORD);
if (!Http_Query(HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, size)) return GetLastError(); if (!HttpQueryInfoA(handle, FLAG_LENGTH, &req->ResultSize, &len, NULL)) return GetLastError();
SYSTEMTIME lastModified; SYSTEMTIME time;
bufferLen = sizeof(SYSTEMTIME); len = sizeof(SYSTEMTIME);
if (Http_Query(HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &lastModified)) { if (HttpQueryInfoA(handle, FLAG_LASTMOD, &time, &len, NULL)) {
Platform_FromSysTime(&request->LastModified, &lastModified); Platform_FromSysTime(&req->LastModified, &time);
} }
String etag = String_ClearedArray(request->Etag); String etag = String_ClearedArray(req->Etag);
bufferLen = etag.capacity; len = etag.capacity;
Http_Query(HTTP_QUERY_ETAG, etag.buffer); HttpQueryInfoA(handle, HTTP_QUERY_ETAG, etag.buffer, &len, NULL);
return 0; return 0;
} }
ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void** data, UInt32 size, volatile Int32* progress) { static ReturnCode Http_GetData(struct AsyncRequest* req, HINTERNET handle, volatile Int32* progress) {
if (!size) return ERROR_NOT_SUPPORTED; UInt32 size = req->ResultSize;
if (size) return ERROR_NOT_SUPPORTED;
*progress = 0; *progress = 0;
UInt8* buffer = Mem_Alloc(size, sizeof(UInt8), "http get data"); UInt8* buffer = Mem_Alloc(size, sizeof(UInt8), "http get data");
UInt32 left = size, read, totalRead = 0; UInt32 left = size, read, totalRead = 0;
*data = buffer; req->ResultData = buffer;
while (left) { while (left) {
UInt32 toRead = left, avail = 0; UInt32 toRead = left, avail = 0;
@ -949,7 +953,23 @@ ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void*
return 0; return 0;
} }
ReturnCode Http_FreeRequest(void* handle) { return Win_Return(InternetCloseHandle(handle)); } ReturnCode Http_Do(struct AsyncRequest* req, volatile Int32* progress) {
HINTERNET handle;
ReturnCode res = Http_Make(req, &handle);
if (res) return res;
*progress = ASYNC_PROGRESS_FETCHING_DATA;
res = Http_GetHeaders(req, handle);
if (res) { InternetCloseHandle(handle); return res; }
if (req->RequestType != REQUEST_TYPE_CONTENT_LENGTH && req->StatusCode == 200) {
res = Http_GetData(req, handle, progress);
if (res) { InternetCloseHandle(handle); return res; }
}
return Win_Return(InternetCloseHandle(handle));
}
ReturnCode Http_Free(void) { return Win_Return(InternetCloseHandle(hInternet)); } ReturnCode Http_Free(void) { return Win_Return(InternetCloseHandle(hInternet)); }
#elif CC_BUILD_NIX #elif CC_BUILD_NIX
void Http_Init(void) { } void Http_Init(void) { }
@ -1028,7 +1048,7 @@ void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format) {
ctx->Format = *format; ctx->Format = *format;
} }
void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize) { void Audio_BufferData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize) {
struct AudioContext* ctx = &Audio_Contexts[handle]; struct AudioContext* ctx = &Audio_Contexts[handle];
WAVEHDR* hdr = &ctx->Headers[idx]; WAVEHDR* hdr = &ctx->Headers[idx];
Mem_Set(hdr, 0, sizeof(WAVEHDR)); Mem_Set(hdr, 0, sizeof(WAVEHDR));
@ -1043,6 +1063,8 @@ void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize)
ErrorHandler_CheckOrFail(result, "Audio - write header"); ErrorHandler_CheckOrFail(result, "Audio - write header");
} }
void Audio_Play(AudioHandle handle) { }
bool Audio_IsCompleted(AudioHandle handle, Int32 idx) { bool Audio_IsCompleted(AudioHandle handle, Int32 idx) {
struct AudioContext* ctx = &Audio_Contexts[handle]; struct AudioContext* ctx = &Audio_Contexts[handle];
WAVEHDR* hdr = &ctx->Headers[idx]; WAVEHDR* hdr = &ctx->Headers[idx];

View File

@ -80,15 +80,15 @@ void Thread_Join(void* handle);
void Thread_FreeHandle(void* handle); void Thread_FreeHandle(void* handle);
void* Mutex_Create(void); void* Mutex_Create(void);
void Mutex_Free(void* handle); void Mutex_Free(void* handle);
void Mutex_Lock(void* handle); void Mutex_Lock(void* handle);
void Mutex_Unlock(void* handle); void Mutex_Unlock(void* handle);
void* Waitable_Create(void); void* Waitable_Create(void);
void Waitable_Free(void* handle); void Waitable_Free(void* handle);
void Waitable_Signal(void* handle); void Waitable_Signal(void* handle);
void Waitable_Wait(void* handle); void Waitable_Wait(void* handle);
void Waitable_WaitFor(void* handle, UInt32 milliseconds); void Waitable_WaitFor(void* handle, UInt32 milliseconds);
void Font_GetNames(StringsBuffer* buffer); void Font_GetNames(StringsBuffer* buffer);
void Font_Make(struct FontDesc* desc, STRING_PURE String* fontName, UInt16 size, UInt16 style); void Font_Make(struct FontDesc* desc, STRING_PURE String* fontName, UInt16 size, UInt16 style);
@ -110,10 +110,7 @@ ReturnCode Socket_Close(SocketPtr socket);
ReturnCode Socket_Select(SocketPtr socket, Int32 selectMode, bool* success); ReturnCode Socket_Select(SocketPtr socket, Int32 selectMode, bool* success);
void Http_Init(void); void Http_Init(void);
ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle); ReturnCode Http_Do(struct AsyncRequest* req, volatile Int32* progress);
ReturnCode Http_GetRequestHeaders(struct AsyncRequest* request, void* handle, UInt32* size);
ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void** data, UInt32 size, volatile Int32* progress);
ReturnCode Http_FreeRequest(void* handle);
ReturnCode Http_Free(void); ReturnCode Http_Free(void);
#define AUDIO_MAX_CHUNKS 4 #define AUDIO_MAX_CHUNKS 4
@ -126,7 +123,8 @@ void Audio_Free(AudioHandle handle);
struct AudioFormat* Audio_GetFormat(AudioHandle handle); struct AudioFormat* Audio_GetFormat(AudioHandle handle);
void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format); void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format);
void Audio_SetVolume(AudioHandle handle, Real32 volume); void Audio_SetVolume(AudioHandle handle, Real32 volume);
void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize); void Audio_BufferData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize);
void Audio_Play(AudioHandle handle);
bool Audio_IsCompleted(AudioHandle handle, Int32 idx); bool Audio_IsCompleted(AudioHandle handle, Int32 idx);
bool Audio_IsFinished(AudioHandle handle); bool Audio_IsFinished(AudioHandle handle);
#endif #endif

View File

@ -92,7 +92,7 @@ int main(void) {
String title = String_FromConst(PROGRAM_APP_NAME); String title = String_FromConst(PROGRAM_APP_NAME);
String rawArgs = Platform_GetCommandLineArgs(); String rawArgs = Platform_GetCommandLineArgs();
/* NOTE: Make sure to comment this out before pushing a commit */ /* NOTE: Make sure to comment this out before pushing a commit */
rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565"); //rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565");
String args[5]; Int32 argsCount = Array_Elems(args); String args[5]; Int32 argsCount = Array_Elems(args);
String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount); String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount);
@ -100,14 +100,14 @@ int main(void) {
if (argsCount == 1) { if (argsCount == 1) {
String name = args[0]; String name = args[0];
if (!name.length) name = String_FromReadonly("Singleplayer"); if (!name.length) name = String_FromReadonly("Singleplayer");
String_Set(&Game_Username, &name); String_Copy(&Game_Username, &name);
} else if (argsCount < 4) { } else if (argsCount < 4) {
Platform_LogConst("ClassiCube.exe is only the raw client. You must either use the launcher or provide command line arguments to start the client."); Platform_LogConst("ClassiCube.exe is only the raw client. You must either use the launcher or provide command line arguments to start the client.");
return 1; return 1;
} else { } else {
String_Set(&Game_Username, &args[0]); String_Copy(&Game_Username, &args[0]);
String_Set(&Game_Mppass, &args[1]); String_Copy(&Game_Mppass, &args[1]);
String_Set(&Game_IPAddress, &args[2]); String_Copy(&Game_IPAddress, &args[2]);
UInt8 ip[4]; UInt8 ip[4];
if (!Utils_ParseIP(&args[2], ip)) { if (!Utils_ParseIP(&args[2], ip)) {

View File

@ -743,7 +743,7 @@ static void ChatScreen_OpenInput(struct ChatScreen* screen, STRING_PURE String*
ChatScreen_SetHandlesAllInput(screen, true); ChatScreen_SetHandlesAllInput(screen, true);
Key_KeyRepeat = true; Key_KeyRepeat = true;
String_Set(&screen->Input.Base.Text, initialText); String_Copy(&screen->Input.Base.Text, initialText);
Elem_Recreate(&screen->Input.Base); Elem_Recreate(&screen->Input.Base);
} }
@ -1071,7 +1071,7 @@ static void ChatScreen_ChatReceived(void* obj, String* msg, Int32 type) {
static void ChatScreen_ContextLost(void* obj) { static void ChatScreen_ContextLost(void* obj) {
struct ChatScreen* screen = (struct ChatScreen*)obj; struct ChatScreen* screen = (struct ChatScreen*)obj;
if (screen->HandlesAllInput) { if (screen->HandlesAllInput) {
String_Set(&screen->ChatInInputStr, &screen->Input.Base.Text); String_Copy(&screen->ChatInInputStr, &screen->Input.Base.Text);
Gui_CalcCursorVisible(); Gui_CalcCursorVisible();
} }

View File

@ -321,8 +321,8 @@ static void MPConnection_TickConnect(void) {
} }
static void MPConnection_BeginConnect(void) { static void MPConnection_BeginConnect(void) {
Socket_Create(&net_socket);
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged); Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
Socket_Create(&net_socket);
ServerConnection_Disconnected = false; ServerConnection_Disconnected = false;
Socket_SetBlocking(net_socket, false); Socket_SetBlocking(net_socket, false);

View File

@ -49,9 +49,9 @@ void String_StripCols(STRING_TRANSIENT String* str) {
} }
} }
void String_Set(STRING_TRANSIENT String* str, STRING_PURE String* value) { void String_Copy(STRING_TRANSIENT String* dst, STRING_PURE String* src) {
str->length = 0; dst->length = 0;
String_AppendString(str, value); String_AppendString(dst, src);
} }
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length) { String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length) {
@ -684,7 +684,7 @@ void StringsBuffer_Clear(StringsBuffer* buffer) {
void StringsBuffer_Get(StringsBuffer* buffer, Int32 index, STRING_TRANSIENT String* text) { void StringsBuffer_Get(StringsBuffer* buffer, Int32 index, STRING_TRANSIENT String* text) {
String raw = StringsBuffer_UNSAFE_Get(buffer, index); String raw = StringsBuffer_UNSAFE_Get(buffer, index);
String_Set(text, &raw); String_Copy(text, &raw);
} }
String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, Int32 index) { String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, Int32 index) {

View File

@ -42,7 +42,7 @@ String String_FromReadonly(STRING_REF const char* buffer);
#define String_FromRawArray(buffer) String_FromRaw(buffer, (UInt16)sizeof(buffer)) #define String_FromRawArray(buffer) String_FromRaw(buffer, (UInt16)sizeof(buffer))
void String_StripCols(STRING_TRANSIENT String* str); void String_StripCols(STRING_TRANSIENT String* str);
void String_Set(STRING_TRANSIENT String* str, STRING_PURE String* value); void String_Copy(STRING_TRANSIENT String* dst, STRING_PURE String* src);
/* Returns a string that points directly to a substring of the given string. /* Returns a string that points directly to a substring of the given string.
NOTE: THIS IS UNSAFE - IT MAINTAINS A REFERENCE TO THE ORIGINAL BUFFER, AND THE SUBSTRING IS NOT NULL TERMINATED */ NOTE: THIS IS UNSAFE - IT MAINTAINS A REFERENCE TO THE ORIGINAL BUFFER, AND THE SUBSTRING IS NOT NULL TERMINATED */
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length); String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length);

View File

@ -478,7 +478,7 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
if (String_Equals(url, &World_TextureUrl)) { if (String_Equals(url, &World_TextureUrl)) {
} else { } else {
bool zip = String_ContainsString(url, &zipExt); bool zip = String_ContainsString(url, &zipExt);
String_Set(&World_TextureUrl, url); String_Copy(&World_TextureUrl, url);
const char* operation = zip ? "extracting" : "decoding"; const char* operation = zip ? "extracting" : "decoding";
res = zip ? TexturePack_ExtractZip(&stream) : res = zip ? TexturePack_ExtractZip(&stream) :
@ -493,7 +493,7 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
void TexturePack_Extract_Req(struct AsyncRequest* item) { void TexturePack_Extract_Req(struct AsyncRequest* item) {
String url = String_FromRawArray(item->URL); String url = String_FromRawArray(item->URL);
String_Set(&World_TextureUrl, &url); String_Copy(&World_TextureUrl, &url);
void* data = item->ResultData; void* data = item->ResultData;
UInt32 len = item->ResultSize; UInt32 len = item->ResultSize;

View File

@ -1693,7 +1693,7 @@ static void ChatInputWidget_UpKey(struct GuiElem* elem) {
} }
if (widget->TypingLogPos == Chat_InputLog.Count) { if (widget->TypingLogPos == Chat_InputLog.Count) {
String_Set(&widget->OrigStr, &input->Text); String_Copy(&widget->OrigStr, &input->Text);
} }
if (!Chat_InputLog.Count) return; if (!Chat_InputLog.Count) return;
@ -2213,7 +2213,7 @@ String TextGroupWidget_UNSAFE_Get(struct TextGroupWidget* widget, Int32 i) {
void TextGroupWidget_GetText(struct TextGroupWidget* widget, Int32 index, STRING_TRANSIENT String* text) { void TextGroupWidget_GetText(struct TextGroupWidget* widget, Int32 index, STRING_TRANSIENT String* text) {
String line = TextGroupWidget_UNSAFE_Get(widget, index); String line = TextGroupWidget_UNSAFE_Get(widget, index);
String_Set(text, &line); String_Copy(text, &line);
} }
void TextGroupWidget_PushUpAndReplaceLast(struct TextGroupWidget* widget, STRING_PURE String* text) { void TextGroupWidget_PushUpAndReplaceLast(struct TextGroupWidget* widget, STRING_PURE String* text) {