PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/libmikmod-3.2.0/playercode/mloader.c

#
C | 620 lines | 467 code | 96 blank | 57 comment | 110 complexity | dc4d36370ad6738a4345f81b4c8e7c18 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0
  1. /* MikMod sound library
  2. (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
  3. AUTHORS for complete list.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of
  7. the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.
  16. */
  17. /*==============================================================================
  18. $Id$
  19. These routines are used to access the available module loaders
  20. ==============================================================================*/
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #ifdef HAVE_MEMORY_H
  28. #include <memory.h>
  29. #endif
  30. #include <string.h>
  31. #include "mikmod_internals.h"
  32. #ifdef SUNOS
  33. extern int fprintf(FILE *, const char *, ...);
  34. #endif
  35. MREADER *modreader;
  36. MODULE of;
  37. static MLOADER *firstloader=NULL;
  38. UWORD finetune[16]={
  39. 8363,8413,8463,8529,8581,8651,8723,8757,
  40. 7895,7941,7985,8046,8107,8169,8232,8280
  41. };
  42. MIKMODAPI CHAR* MikMod_InfoLoader(void)
  43. {
  44. int len=0;
  45. MLOADER *l;
  46. CHAR *list=NULL;
  47. MUTEX_LOCK(lists);
  48. /* compute size of buffer */
  49. for(l=firstloader;l;l=l->next) len+=1+(l->next?1:0)+strlen(l->version);
  50. if(len)
  51. if((list=MikMod_malloc(len*sizeof(CHAR)))) {
  52. CHAR * list_end = list;
  53. list[0]=0;
  54. /* list all registered module loders */
  55. for(l=firstloader;l;l=l->next)
  56. {
  57. list_end += sprintf(list_end,
  58. "%s%s",l->version, ((l->next) ? "\n" : "")
  59. );
  60. }
  61. }
  62. MUTEX_UNLOCK(lists);
  63. return list;
  64. }
  65. void _mm_registerloader(MLOADER* ldr)
  66. {
  67. MLOADER *cruise=firstloader;
  68. if(cruise) {
  69. while(cruise->next) cruise = cruise->next;
  70. cruise->next=ldr;
  71. } else
  72. firstloader=ldr;
  73. }
  74. MIKMODAPI void MikMod_RegisterLoader(struct MLOADER* ldr)
  75. {
  76. /* if we try to register an invalid loader, or an already registered loader,
  77. ignore this attempt */
  78. if ((!ldr)||(ldr->next))
  79. return;
  80. MUTEX_LOCK(lists);
  81. _mm_registerloader(ldr);
  82. MUTEX_UNLOCK(lists);
  83. }
  84. BOOL ReadComment(UWORD len)
  85. {
  86. if(len) {
  87. int i;
  88. if(!(of.comment=(CHAR*)MikMod_malloc(len+1))) return 0;
  89. _mm_read_UBYTES(of.comment,len,modreader);
  90. /* translate IT linefeeds */
  91. for(i=0;i<len;i++)
  92. if(of.comment[i]=='\r') of.comment[i]='\n';
  93. of.comment[len]=0; /* just in case */
  94. }
  95. if(!of.comment[0]) {
  96. MikMod_free(of.comment);
  97. of.comment=NULL;
  98. }
  99. return 1;
  100. }
  101. BOOL ReadLinedComment(UWORD len,UWORD linelen)
  102. {
  103. CHAR *tempcomment,*line,*storage;
  104. UWORD total=0,t,lines;
  105. int i;
  106. lines = (len + linelen - 1) / linelen;
  107. if (len) {
  108. if(!(tempcomment=(CHAR*)MikMod_malloc(len+1))) return 0;
  109. if(!(storage=(CHAR*)MikMod_malloc(linelen+1))) {
  110. MikMod_free(tempcomment);
  111. return 0;
  112. }
  113. memset(tempcomment, ' ', len);
  114. _mm_read_UBYTES(tempcomment,len,modreader);
  115. /* compute message length */
  116. for(line=tempcomment,total=t=0;t<lines;t++,line+=linelen) {
  117. for(i=linelen;(i>=0)&&(line[i]==' ');i--) line[i]=0;
  118. for(i=0;i<linelen;i++) if (!line[i]) break;
  119. total+=1+i;
  120. }
  121. if(total>lines) {
  122. if(!(of.comment=(CHAR*)MikMod_malloc(total+1))) {
  123. MikMod_free(storage);
  124. MikMod_free(tempcomment);
  125. return 0;
  126. }
  127. /* convert message */
  128. for(line=tempcomment,t=0;t<lines;t++,line+=linelen) {
  129. for(i=0;i<linelen;i++) if(!(storage[i]=line[i])) break;
  130. storage[i]=0; /* if (i==linelen) */
  131. strcat(of.comment,storage);strcat(of.comment,"\r");
  132. }
  133. MikMod_free(storage);
  134. MikMod_free(tempcomment);
  135. }
  136. }
  137. return 1;
  138. }
  139. BOOL AllocPositions(int total)
  140. {
  141. if(!total) {
  142. _mm_errno=MMERR_NOT_A_MODULE;
  143. return 0;
  144. }
  145. if(!(of.positions=MikMod_calloc(total,sizeof(UWORD)))) return 0;
  146. return 1;
  147. }
  148. BOOL AllocPatterns(void)
  149. {
  150. int s,t,tracks = 0;
  151. if((!of.numpat)||(!of.numchn)) {
  152. _mm_errno=MMERR_NOT_A_MODULE;
  153. return 0;
  154. }
  155. /* Allocate track sequencing array */
  156. if(!(of.patterns=(UWORD*)MikMod_calloc((ULONG)(of.numpat+1)*of.numchn,sizeof(UWORD)))) return 0;
  157. if(!(of.pattrows=(UWORD*)MikMod_calloc(of.numpat+1,sizeof(UWORD)))) return 0;
  158. for(t=0;t<=of.numpat;t++) {
  159. of.pattrows[t]=64;
  160. for(s=0;s<of.numchn;s++)
  161. of.patterns[(t*of.numchn)+s]=tracks++;
  162. }
  163. return 1;
  164. }
  165. BOOL AllocTracks(void)
  166. {
  167. if(!of.numtrk) {
  168. _mm_errno=MMERR_NOT_A_MODULE;
  169. return 0;
  170. }
  171. if(!(of.tracks=(UBYTE **)MikMod_calloc(of.numtrk,sizeof(UBYTE *)))) return 0;
  172. return 1;
  173. }
  174. BOOL AllocInstruments(void)
  175. {
  176. int t,n;
  177. if(!of.numins) {
  178. _mm_errno=MMERR_NOT_A_MODULE;
  179. return 0;
  180. }
  181. if(!(of.instruments=(INSTRUMENT*)MikMod_calloc(of.numins,sizeof(INSTRUMENT))))
  182. return 0;
  183. for(t=0;t<of.numins;t++) {
  184. for(n=0;n<INSTNOTES;n++) {
  185. /* Init note / sample lookup table */
  186. of.instruments[t].samplenote[n] = n;
  187. of.instruments[t].samplenumber[n] = t;
  188. }
  189. of.instruments[t].globvol = 64;
  190. }
  191. return 1;
  192. }
  193. BOOL AllocSamples(void)
  194. {
  195. UWORD u;
  196. if(!of.numsmp) {
  197. _mm_errno=MMERR_NOT_A_MODULE;
  198. return 0;
  199. }
  200. if(!(of.samples=(SAMPLE*)MikMod_calloc(of.numsmp,sizeof(SAMPLE)))) return 0;
  201. for(u=0;u<of.numsmp;u++) {
  202. of.samples[u].panning = 128; /* center */
  203. of.samples[u].handle = -1;
  204. of.samples[u].globvol = 64;
  205. of.samples[u].volume = 64;
  206. }
  207. return 1;
  208. }
  209. static BOOL ML_LoadSamples(void)
  210. {
  211. SAMPLE *s;
  212. int u;
  213. for(u=of.numsmp,s=of.samples;u;u--,s++)
  214. if(s->length) SL_RegisterSample(s,MD_MUSIC,modreader);
  215. return 1;
  216. }
  217. /* Creates a CSTR out of a character buffer of 'len' bytes, but strips any
  218. terminating non-printing characters like 0, spaces etc. */
  219. CHAR *DupStr(CHAR* s,UWORD len,BOOL strict)
  220. {
  221. UWORD t;
  222. CHAR *d=NULL;
  223. /* Scan for last printing char in buffer [includes high ascii up to 254] */
  224. while(len) {
  225. if(s[len-1]>0x20) break;
  226. len--;
  227. }
  228. /* Scan forward for possible NULL character */
  229. if(strict) {
  230. for(t=0;t<len;t++) if (!s[t]) break;
  231. if (t<len) len=t;
  232. }
  233. /* When the buffer wasn't completely empty, allocate a cstring and copy the
  234. buffer into that string, except for any control-chars */
  235. if((d=(CHAR*)MikMod_malloc(sizeof(CHAR)*(len+1)))) {
  236. for(t=0;t<len;t++) d[t]=(s[t]<32)?'.':s[t];
  237. d[len]=0;
  238. }
  239. return d;
  240. }
  241. CHAR *StrDup(CHAR *s)
  242. {
  243. size_t l = strlen(s) + 1;
  244. CHAR *d = MikMod_malloc(l);
  245. strcpy(d, s);
  246. return d;
  247. }
  248. static void ML_XFreeSample(SAMPLE *s)
  249. {
  250. if(s->handle>=0)
  251. MD_SampleUnload(s->handle);
  252. if(s->samplename) MikMod_free(s->samplename);
  253. }
  254. static void ML_XFreeInstrument(INSTRUMENT *i)
  255. {
  256. if(i->insname) MikMod_free(i->insname);
  257. }
  258. static void ML_FreeEx(MODULE *mf)
  259. {
  260. UWORD t;
  261. if(mf->songname) MikMod_free(mf->songname);
  262. if(mf->comment) MikMod_free(mf->comment);
  263. if(mf->modtype) MikMod_free(mf->modtype);
  264. if(mf->positions) MikMod_free(mf->positions);
  265. if(mf->patterns) MikMod_free(mf->patterns);
  266. if(mf->pattrows) MikMod_free(mf->pattrows);
  267. if(mf->tracks) {
  268. for(t=0;t<mf->numtrk;t++)
  269. if(mf->tracks[t]) MikMod_free(mf->tracks[t]);
  270. MikMod_free(mf->tracks);
  271. }
  272. if(mf->instruments) {
  273. for(t=0;t<mf->numins;t++)
  274. ML_XFreeInstrument(&mf->instruments[t]);
  275. MikMod_free(mf->instruments);
  276. }
  277. if(mf->samples) {
  278. for(t=0;t<mf->numsmp;t++)
  279. if(mf->samples[t].length) ML_XFreeSample(&mf->samples[t]);
  280. MikMod_free(mf->samples);
  281. }
  282. memset(mf,0,sizeof(MODULE));
  283. if(mf!=&of) MikMod_free(mf);
  284. }
  285. static MODULE *ML_AllocUniMod(void)
  286. {
  287. MODULE *mf;
  288. return (mf=MikMod_malloc(sizeof(MODULE)));
  289. }
  290. void Player_Free_internal(MODULE *mf)
  291. {
  292. if(mf) {
  293. Player_Exit_internal(mf);
  294. ML_FreeEx(mf);
  295. }
  296. }
  297. MIKMODAPI void Player_Free(MODULE *mf)
  298. {
  299. MUTEX_LOCK(vars);
  300. Player_Free_internal(mf);
  301. MUTEX_UNLOCK(vars);
  302. }
  303. static CHAR* Player_LoadTitle_internal(MREADER *reader)
  304. {
  305. MLOADER *l;
  306. modreader=reader;
  307. _mm_errno = 0;
  308. _mm_critical = 0;
  309. _mm_iobase_setcur(modreader);
  310. /* Try to find a loader that recognizes the module */
  311. for(l=firstloader;l;l=l->next) {
  312. _mm_rewind(modreader);
  313. if(l->Test()) break;
  314. }
  315. if(!l) {
  316. _mm_errno = MMERR_NOT_A_MODULE;
  317. if(_mm_errorhandler) _mm_errorhandler();
  318. return NULL;
  319. }
  320. return l->LoadTitle();
  321. }
  322. MIKMODAPI CHAR* Player_LoadTitleFP(FILE *fp)
  323. {
  324. CHAR* result=NULL;
  325. MREADER* reader;
  326. if(fp && (reader=_mm_new_file_reader(fp))) {
  327. MUTEX_LOCK(lists);
  328. result=Player_LoadTitle_internal(reader);
  329. MUTEX_UNLOCK(lists);
  330. _mm_delete_file_reader(reader);
  331. }
  332. return result;
  333. }
  334. MIKMODAPI CHAR* Player_LoadTitleMem(const char *buffer,int len)
  335. {
  336. CHAR *result=NULL;
  337. MREADER* reader;
  338. if ((reader=_mm_new_mem_reader(buffer,len)))
  339. {
  340. MUTEX_LOCK(lists);
  341. result=Player_LoadTitle_internal(reader);
  342. MUTEX_UNLOCK(lists);
  343. _mm_delete_mem_reader(reader);
  344. }
  345. return result;
  346. }
  347. MIKMODAPI CHAR* Player_LoadTitleGeneric(MREADER *reader)
  348. {
  349. CHAR *result=NULL;
  350. if (reader) {
  351. MUTEX_LOCK(lists);
  352. result=Player_LoadTitle_internal(reader);
  353. MUTEX_UNLOCK(lists);
  354. }
  355. return result;
  356. }
  357. MIKMODAPI CHAR* Player_LoadTitle(CHAR* filename)
  358. {
  359. CHAR* result=NULL;
  360. FILE* fp;
  361. MREADER* reader;
  362. if((fp=_mm_fopen(filename,"rb"))) {
  363. if((reader=_mm_new_file_reader(fp))) {
  364. MUTEX_LOCK(lists);
  365. result=Player_LoadTitle_internal(reader);
  366. MUTEX_UNLOCK(lists);
  367. _mm_delete_file_reader(reader);
  368. }
  369. _mm_fclose(fp);
  370. }
  371. return result;
  372. }
  373. /* Loads a module given an reader */
  374. MODULE* Player_LoadGeneric_internal(MREADER *reader,int maxchan,BOOL curious)
  375. {
  376. int t;
  377. MLOADER *l;
  378. BOOL ok;
  379. MODULE *mf;
  380. modreader = reader;
  381. _mm_errno = 0;
  382. _mm_critical = 0;
  383. _mm_iobase_setcur(modreader);
  384. /* Try to find a loader that recognizes the module */
  385. for(l=firstloader;l;l=l->next) {
  386. _mm_rewind(modreader);
  387. if(l->Test()) break;
  388. }
  389. if(!l) {
  390. _mm_errno = MMERR_NOT_A_MODULE;
  391. if(_mm_errorhandler) _mm_errorhandler();
  392. _mm_rewind(modreader);_mm_iobase_revert(modreader);
  393. return NULL;
  394. }
  395. /* init unitrk routines */
  396. if(!UniInit()) {
  397. if(_mm_errorhandler) _mm_errorhandler();
  398. _mm_rewind(modreader);_mm_iobase_revert(modreader);
  399. return NULL;
  400. }
  401. /* init the module structure with vanilla settings */
  402. memset(&of,0,sizeof(MODULE));
  403. of.bpmlimit = 33;
  404. of.initvolume = 128;
  405. for (t = 0; t < UF_MAXCHAN; t++) of.chanvol[t] = 64;
  406. for (t = 0; t < UF_MAXCHAN; t++)
  407. of.panning[t] = ((t + 1) & 2) ? PAN_RIGHT : PAN_LEFT;
  408. /* init module loader and load the header / patterns */
  409. if (!l->Init || l->Init()) {
  410. _mm_rewind(modreader);
  411. ok = l->Load(curious);
  412. if (ok) {
  413. /* propagate inflags=flags for in-module samples */
  414. for (t = 0; t < of.numsmp; t++)
  415. if (of.samples[t].inflags == 0)
  416. of.samples[t].inflags = of.samples[t].flags;
  417. }
  418. } else
  419. ok = 0;
  420. /* free loader and unitrk allocations */
  421. if (l->Cleanup) l->Cleanup();
  422. UniCleanup();
  423. if(!ok) {
  424. ML_FreeEx(&of);
  425. if(_mm_errorhandler) _mm_errorhandler();
  426. _mm_rewind(modreader);_mm_iobase_revert(modreader);
  427. return NULL;
  428. }
  429. if(!ML_LoadSamples()) {
  430. ML_FreeEx(&of);
  431. if(_mm_errorhandler) _mm_errorhandler();
  432. _mm_rewind(modreader);_mm_iobase_revert(modreader);
  433. return NULL;
  434. }
  435. if(!(mf=ML_AllocUniMod())) {
  436. ML_FreeEx(&of);
  437. _mm_rewind(modreader);_mm_iobase_revert(modreader);
  438. if(_mm_errorhandler) _mm_errorhandler();
  439. return NULL;
  440. }
  441. /* If the module doesn't have any specific panning, create a
  442. MOD-like panning, with the channels half-separated. */
  443. if (!(of.flags & UF_PANNING))
  444. for (t = 0; t < of.numchn; t++)
  445. of.panning[t] = ((t + 1) & 2) ? PAN_HALFRIGHT : PAN_HALFLEFT;
  446. /* Copy the static MODULE contents into the dynamic MODULE struct. */
  447. memcpy(mf,&of,sizeof(MODULE));
  448. if(maxchan>0) {
  449. if(!(mf->flags&UF_NNA)&&(mf->numchn<maxchan))
  450. maxchan = mf->numchn;
  451. else
  452. if((mf->numvoices)&&(mf->numvoices<maxchan))
  453. maxchan = mf->numvoices;
  454. if(maxchan<mf->numchn) mf->flags |= UF_NNA;
  455. if(MikMod_SetNumVoices_internal(maxchan,-1)) {
  456. _mm_iobase_revert(modreader);
  457. Player_Free(mf);
  458. return NULL;
  459. }
  460. }
  461. if(SL_LoadSamples()) {
  462. _mm_iobase_revert(modreader);
  463. Player_Free_internal(mf);
  464. return NULL;
  465. }
  466. if(Player_Init(mf)) {
  467. _mm_iobase_revert(modreader);
  468. Player_Free_internal(mf);
  469. mf=NULL;
  470. }
  471. _mm_iobase_revert(modreader);
  472. return mf;
  473. }
  474. MIKMODAPI MODULE* Player_LoadGeneric(MREADER *reader,int maxchan,BOOL curious)
  475. {
  476. MODULE* result;
  477. MUTEX_LOCK(vars);
  478. MUTEX_LOCK(lists);
  479. result=Player_LoadGeneric_internal(reader,maxchan,curious);
  480. MUTEX_UNLOCK(lists);
  481. MUTEX_UNLOCK(vars);
  482. return result;
  483. }
  484. MIKMODAPI MODULE* Player_LoadMem(const char *buffer,int len,int maxchan,BOOL curious)
  485. {
  486. MODULE* result=NULL;
  487. MREADER* reader;
  488. if ((reader=_mm_new_mem_reader(buffer, len))) {
  489. result=Player_LoadGeneric(reader,maxchan,curious);
  490. _mm_delete_mem_reader(reader);
  491. }
  492. return result;
  493. }
  494. /* Loads a module given a file pointer.
  495. File is loaded from the current file seek position. */
  496. MIKMODAPI MODULE* Player_LoadFP(FILE* fp,int maxchan,BOOL curious)
  497. {
  498. MODULE* result=NULL;
  499. struct MREADER* reader=_mm_new_file_reader (fp);
  500. if (reader) {
  501. result=Player_LoadGeneric(reader,maxchan,curious);
  502. _mm_delete_file_reader(reader);
  503. }
  504. return result;
  505. }
  506. /* Open a module via its filename. The loader will initialize the specified
  507. song-player 'player'. */
  508. MIKMODAPI MODULE* Player_Load(CHAR* filename,int maxchan,BOOL curious)
  509. {
  510. FILE *fp;
  511. MODULE *mf=NULL;
  512. if((fp=_mm_fopen(filename,"rb"))) {
  513. mf=Player_LoadFP(fp,maxchan,curious);
  514. _mm_fclose(fp);
  515. }
  516. return mf;
  517. }
  518. /* ex:set ts=4: */