/** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2023 tildearrow and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "sfWrapper.h" #include "../fileutils.h" #include "sndfile.h" sf_count_t _vioGetSize(void* user) { return ((SFWrapper*)user)->ioGetSize(); } sf_count_t _vioSeek(sf_count_t offset, int whence, void* user) { return ((SFWrapper*)user)->ioSeek(offset,whence); } sf_count_t _vioRead(void* ptr, sf_count_t count, void* user) { return ((SFWrapper*)user)->ioRead(ptr,count); } sf_count_t _vioWrite(const void* ptr, sf_count_t count, void* user) { return ((SFWrapper*)user)->ioWrite(ptr,count); } sf_count_t _vioTell(void* user) { return ((SFWrapper*)user)->ioTell(); } sf_count_t SFWrapper::ioGetSize() { sf_count_t ret=(sf_count_t)len; if (fileMode==SFM_WRITE || fileMode==SFM_RDWR) { ssize_t lastTell=ftell(f); fseek(f,0,SEEK_END); ret=(sf_count_t)ftell(f); fseek(f,lastTell,SEEK_SET); } return ret; } sf_count_t SFWrapper::ioSeek(sf_count_t offset, int whence) { return fseek(f,offset,whence); } sf_count_t SFWrapper::ioRead(void* ptr, sf_count_t count) { return fread(ptr,1,count,f); } sf_count_t SFWrapper::ioWrite(const void* ptr, sf_count_t count) { return fwrite(ptr,1,count,f); } sf_count_t SFWrapper::ioTell() { return ftell(f); } int SFWrapper::doClose() { int ret=sf_close(sf); fclose(f); return ret; } SNDFILE* SFWrapper::doOpen(const char* path, int mode, SF_INFO* sfinfo) { vio.get_filelen=_vioGetSize; vio.read=_vioRead; vio.seek=_vioSeek; vio.tell=_vioTell; vio.write=_vioWrite; const char* modeC="rb"; if (mode==SFM_WRITE) { modeC="wb"; } if (mode==SFM_RDWR) { modeC="rb+"; } f=ps_fopen(path,modeC); if (f==NULL) { return NULL; } if (fseek(f,0,SEEK_END)==-1) { fclose(f); f=NULL; return NULL; } len=ftell(f); if (len==(SIZE_MAX>>1)) { len=0; fclose(f); f=NULL; return NULL; } if (fseek(f,0,SEEK_SET)==-1) { len=0; fclose(f); f=NULL; return NULL; } sf=sf_open_virtual(&vio,mode,sfinfo,this); if (sf!=NULL) fileMode=mode; return sf; }