ExtendedRead.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. ** Copyright (C) 2007-2011 Nullsoft, Inc.
  3. **
  4. ** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
  5. ** liable for any damages arising from the use of this software.
  6. **
  7. ** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
  8. ** alter it and redistribute it freely, subject to the following restrictions:
  9. **
  10. ** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
  11. ** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  12. **
  13. ** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  14. **
  15. ** 3. This notice may not be removed or altered from any source distribution.
  16. **
  17. ** Author: Ben Allison [email protected]
  18. ** Created: March 1, 2007
  19. **
  20. */
  21. #include "main.h"
  22. #include <FLAC/all.h>
  23. #include "StreamFileWin32.h"
  24. #include "QuickBuf.h"
  25. #include <bfc/platform/types.h>
  26. #include <assert.h>
  27. #include "FLACFileCallbacks.h"
  28. #include "nswasabi/ReferenceCounted.h"
  29. struct ExtendedRead
  30. {
  31. int bps, channels, samplerate, truebps;
  32. uint64_t samples;
  33. QuickBuf output;
  34. FLAC__StreamDecoder *decoder;
  35. size_t used;
  36. FLACClientData client_data;
  37. };
  38. static void OnError(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
  39. {
  40. //client_data=client_data; // dummy line so i can set a breakpoint
  41. }
  42. static void OnMetadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
  43. {
  44. ExtendedRead *ext = FLAC_GetObject<ExtendedRead>(client_data);
  45. switch(metadata->type)
  46. {
  47. case FLAC__METADATA_TYPE_STREAMINFO:
  48. {
  49. ext->truebps=metadata->data.stream_info.bits_per_sample;
  50. ext->bps = (ext->truebps +7) & (~7);
  51. ext->channels=metadata->data.stream_info.channels;
  52. ext->samplerate=metadata->data.stream_info.sample_rate;
  53. ext->samples=metadata->data.stream_info.total_samples;
  54. }
  55. break;
  56. }
  57. }
  58. static FLAC__StreamDecoderWriteStatus OnAudio(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
  59. {
  60. ExtendedRead *ext = FLAC_GetObject<ExtendedRead>(client_data);
  61. int byteLength = (ext->bps/8) * ext->channels * frame->header.blocksize;
  62. ext->output.Reserve(byteLength);
  63. InterleaveAndTruncate(buffer, ext->output, ext->bps, ext->channels, frame->header.blocksize);
  64. ext->used = byteLength;
  65. return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  66. }
  67. extern "C"
  68. {
  69. __declspec( dllexport ) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
  70. {
  71. nx_file_t file;
  72. ReferenceCountedNXString filename_nx;
  73. ReferenceCountedNXURI filename_uri;
  74. NXStringCreateWithUTF16(&filename_nx, fn);
  75. NXURICreateWithNXString(&filename_uri, filename_nx);
  76. int ret = NXFileOpenFile(&file, filename_uri, nx_file_FILE_read_binary);
  77. if (ret != NErr_Success)
  78. return 0;
  79. ExtendedRead * e = (ExtendedRead *)calloc(sizeof(ExtendedRead), 1);
  80. e->decoder = FLAC__stream_decoder_new();
  81. if (e->decoder == 0)
  82. {
  83. NXFileRelease(file);
  84. free(e);
  85. return 0;
  86. }
  87. e->client_data.SetFile(file);
  88. e->client_data.SetObject(e);
  89. FLAC__stream_decoder_set_md5_checking(e->decoder, true);
  90. if(FLAC__stream_decoder_init_stream(
  91. e->decoder,
  92. FLAC_NXFile_Read,
  93. FLAC_NXFile_Seek,
  94. FLAC_NXFile_Tell,
  95. FLAC_NXFile_Length,
  96. FLAC_NXFile_EOF,
  97. OnAudio,
  98. OnMetadata,
  99. OnError,
  100. &e->client_data
  101. ) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
  102. {
  103. FLAC__stream_decoder_delete(e->decoder);
  104. NXFileRelease(file);
  105. free(e);
  106. return 0;
  107. }
  108. FLAC__stream_decoder_process_until_end_of_metadata(e->decoder);
  109. *bps = e->truebps;
  110. *nch = e->channels;
  111. *srate = e->samplerate;
  112. *size = (int)(e->samples * (e->bps/8) * e->channels);
  113. return (intptr_t) e;
  114. }
  115. __declspec( dllexport ) intptr_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch)
  116. {
  117. ExtendedRead *ext = (ExtendedRead *)handle;
  118. while(!ext->used) // loop until we get some data
  119. {
  120. if (FLAC__stream_decoder_process_single(ext->decoder) == 0)
  121. break; // break out if there's an error
  122. FLAC__StreamDecoderState FLACstate = FLAC__stream_decoder_get_state(ext->decoder);
  123. if (FLACstate == FLAC__STREAM_DECODER_END_OF_STREAM) // break out if we hit EOF
  124. break;
  125. }
  126. if (ext->used)
  127. {
  128. size_t toCopy = min(len, ext->used);
  129. memcpy(dest, ext->output, toCopy);
  130. if (toCopy < ext->used)
  131. ext->output.Move(toCopy);
  132. ext->used-=toCopy;
  133. return toCopy;
  134. }
  135. return 0;
  136. }
  137. __declspec( dllexport ) void winampGetExtendedRead_close(intptr_t handle)
  138. {
  139. ExtendedRead *ext = (ExtendedRead *)handle;
  140. ext->output.Free();
  141. FLAC__stream_decoder_finish(ext->decoder);
  142. FLAC__stream_decoder_delete(ext->decoder);
  143. NXFileRelease(ext->client_data.GetFile());
  144. free(ext);
  145. }
  146. }