libopenmpt_c.cpp 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881
  1. /*
  2. * libopenmpt_c.cpp
  3. * ----------------
  4. * Purpose: libopenmpt C interface implementation
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #include "openmpt/all/BuildSettings.hpp"
  10. #include "libopenmpt_internal.h"
  11. #include "libopenmpt.h"
  12. #include "libopenmpt_ext.h"
  13. #include "libopenmpt_impl.hpp"
  14. #include "libopenmpt_ext_impl.hpp"
  15. #include <limits>
  16. #include <new>
  17. #include <stdexcept>
  18. #include <cmath>
  19. #include <cstdio>
  20. #include <cstdlib>
  21. #include <cstring>
  22. #if defined(_MSC_VER)
  23. #pragma warning(disable:4702) /* unreachable code */
  24. #endif
  25. namespace openmpt {
  26. static const char * strdup( const char * src ) {
  27. char * dst = (char*)std::calloc( std::strlen( src ) + 1, sizeof( char ) );
  28. if ( !dst ) {
  29. return NULL;
  30. }
  31. std::strcpy( dst, src );
  32. return dst;
  33. }
  34. class logfunc_logger : public log_interface {
  35. private:
  36. openmpt_log_func m_logfunc;
  37. void * m_user;
  38. public:
  39. logfunc_logger( openmpt_log_func func, void * user ) : m_logfunc(func), m_user(user) {
  40. return;
  41. }
  42. void log( const std::string & message ) const override {
  43. if ( m_logfunc ) {
  44. m_logfunc( message.c_str(), m_user );
  45. } else {
  46. openmpt_log_func_default( message.c_str(), m_user );
  47. }
  48. }
  49. }; // class logfunc_logger
  50. namespace interface {
  51. class invalid_module_pointer : public openmpt::exception {
  52. public:
  53. invalid_module_pointer()
  54. : openmpt::exception("module * not valid")
  55. {
  56. return;
  57. }
  58. invalid_module_pointer(const invalid_module_pointer&) = default;
  59. virtual ~invalid_module_pointer() noexcept = default;
  60. };
  61. class argument_null_pointer : public openmpt::exception {
  62. public:
  63. argument_null_pointer()
  64. : openmpt::exception("argument null pointer")
  65. {
  66. return;
  67. }
  68. argument_null_pointer(const argument_null_pointer&) = default;
  69. virtual ~argument_null_pointer() noexcept = default;
  70. };
  71. } // namespace interface
  72. static std::string format_exception( const char * const function ) {
  73. std::string err;
  74. try {
  75. // cppcheck false-positive
  76. // cppcheck-suppress rethrowNoCurrentException
  77. throw;
  78. } catch ( const openmpt::exception & e ) {
  79. err += function;
  80. err += ": ";
  81. err += "ERROR: ";
  82. const char * what = e.what();
  83. err += what ? what : "";
  84. } catch ( const std::bad_alloc & e ) {
  85. err += function;
  86. err += ": ";
  87. err += "OUT OF MEMORY: ";
  88. const char * what = e.what();
  89. err += what ? what : "";
  90. } catch ( const std::exception & e ) {
  91. err += function;
  92. err += ": ";
  93. err += "INTERNAL ERROR: ";
  94. const char * what = e.what();
  95. err += what ? what : "";
  96. } catch ( ... ) {
  97. err += function;
  98. err += ": ";
  99. err += "UNKNOWN INTERNAL ERROR";
  100. }
  101. return err;
  102. }
  103. static void error_message_from_exception( const char * * error_message, const std::exception & e ) {
  104. if ( error_message ) {
  105. const char * what = e.what();
  106. *error_message = ( what ? openmpt::strdup( what ) : openmpt::strdup( "" ) );
  107. }
  108. }
  109. static int error_from_exception( const char * * error_message ) {
  110. int error = 0;
  111. if ( error_message ) {
  112. if ( *error_message ) {
  113. openmpt_free_string( *error_message );
  114. *error_message = NULL;
  115. }
  116. }
  117. try {
  118. // cppcheck false-positive
  119. // cppcheck-suppress rethrowNoCurrentException
  120. throw;
  121. } catch ( const std::bad_alloc & e ) {
  122. error = OPENMPT_ERROR_OUT_OF_MEMORY;
  123. error_message_from_exception( error_message, e );
  124. } catch ( const openmpt::interface::invalid_module_pointer & e ) {
  125. error = OPENMPT_ERROR_INVALID_MODULE_POINTER;
  126. error_message_from_exception( error_message, e );
  127. } catch ( const openmpt::interface::argument_null_pointer & e ) {
  128. error = OPENMPT_ERROR_ARGUMENT_NULL_POINTER;
  129. error_message_from_exception( error_message, e );
  130. } catch ( const openmpt::exception & e ) {
  131. error = OPENMPT_ERROR_GENERAL;
  132. error_message_from_exception( error_message, e );
  133. } catch ( const std::invalid_argument & e ) {
  134. error = OPENMPT_ERROR_INVALID_ARGUMENT;
  135. error_message_from_exception( error_message, e );
  136. } catch ( const std::out_of_range & e ) {
  137. error = OPENMPT_ERROR_OUT_OF_RANGE;
  138. error_message_from_exception( error_message, e );
  139. } catch ( const std::length_error & e ) {
  140. error = OPENMPT_ERROR_LENGTH;
  141. error_message_from_exception( error_message, e );
  142. } catch ( const std::domain_error & e ) {
  143. error = OPENMPT_ERROR_DOMAIN;
  144. error_message_from_exception( error_message, e );
  145. } catch ( const std::logic_error & e ) {
  146. error = OPENMPT_ERROR_LOGIC;
  147. error_message_from_exception( error_message, e );
  148. } catch ( const std::underflow_error & e ) {
  149. error = OPENMPT_ERROR_UNDERFLOW;
  150. error_message_from_exception( error_message, e );
  151. } catch ( const std::overflow_error & e ) {
  152. error = OPENMPT_ERROR_OVERFLOW;
  153. error_message_from_exception( error_message, e );
  154. } catch ( const std::range_error & e ) {
  155. error = OPENMPT_ERROR_RANGE;
  156. error_message_from_exception( error_message, e );
  157. } catch ( const std::runtime_error & e ) {
  158. error = OPENMPT_ERROR_RUNTIME;
  159. error_message_from_exception( error_message, e );
  160. } catch ( const std::exception & e ) {
  161. error = OPENMPT_ERROR_EXCEPTION;
  162. error_message_from_exception( error_message, e );
  163. } catch ( ... ) {
  164. error = OPENMPT_ERROR_UNKNOWN;
  165. }
  166. return error;
  167. }
  168. } // namespace openmpt
  169. extern "C" {
  170. struct openmpt_module {
  171. openmpt_log_func logfunc;
  172. void * loguser;
  173. openmpt_error_func errfunc;
  174. void * erruser;
  175. int error;
  176. const char * error_message;
  177. openmpt::module_impl * impl;
  178. };
  179. struct openmpt_module_ext {
  180. openmpt_module mod;
  181. openmpt::module_ext_impl * impl;
  182. };
  183. } // extern "C"
  184. namespace openmpt {
  185. static void do_report_exception( const char * const function, openmpt_log_func const logfunc = 0, void * const loguser = 0, openmpt_error_func errfunc = 0, void * const erruser = 0, openmpt::module_impl * const impl = 0, openmpt_module * const mod = 0, int * const err = 0, const char * * err_msg = 0 ) {
  186. int error = OPENMPT_ERROR_OK;
  187. const char * error_message = NULL;
  188. int error_func_result = OPENMPT_ERROR_FUNC_RESULT_DEFAULT;
  189. if ( errfunc || mod || err || err_msg ) {
  190. error = error_from_exception( mod ? &error_message : NULL );
  191. }
  192. if ( errfunc ) {
  193. error_func_result = errfunc( error, erruser );
  194. }
  195. if ( mod && ( error_func_result & OPENMPT_ERROR_FUNC_RESULT_STORE ) ) {
  196. mod->error = error;
  197. mod->error_message = ( error_message ? openmpt::strdup( error_message ) : openmpt::strdup( "" ) );
  198. }
  199. if ( err ) {
  200. *err = error;
  201. }
  202. if ( err_msg ) {
  203. *err_msg = ( error_message ? openmpt::strdup( error_message ) : openmpt::strdup( "" ) );
  204. }
  205. if ( error_message ) {
  206. openmpt_free_string( error_message );
  207. error_message = NULL;
  208. }
  209. if ( error_func_result & OPENMPT_ERROR_FUNC_RESULT_LOG ) {
  210. try {
  211. const std::string message = format_exception( function );
  212. if ( impl ) {
  213. impl->PushToCSoundFileLog( message );
  214. } else if ( logfunc ) {
  215. logfunc( message.c_str(), loguser );
  216. } else {
  217. openmpt_log_func_default( message.c_str(), NULL );
  218. }
  219. } catch ( ... ) {
  220. fprintf( stderr, "openmpt: %s:%i: UNKNOWN INTERNAL ERROR in error handling: function='%s', logfunc=%p, loguser=%p, errfunc=%p, erruser=%p, impl=%p\n", __FILE__, static_cast<int>( __LINE__ ), function ? function : "", reinterpret_cast<void*>( logfunc ), loguser, reinterpret_cast<void*>( errfunc ), erruser, static_cast<void*>( impl ) );
  221. fflush( stderr );
  222. }
  223. }
  224. }
  225. static void report_exception( const char * const function, openmpt_module * mod = 0, int * error = 0, const char * * error_message = 0 ) {
  226. do_report_exception( function, mod ? mod->logfunc : NULL, mod ? mod->loguser : NULL, mod ? mod->errfunc : NULL, mod ? mod->erruser : NULL, mod ? mod->impl : 0, mod ? mod : NULL, error ? error : NULL, error_message ? error_message : NULL );
  227. }
  228. static void report_exception( const char * const function, openmpt_log_func const logfunc, void * const loguser, openmpt_error_func errfunc, void * const erruser, int * error, const char * * error_message ) {
  229. do_report_exception( function, logfunc, loguser, errfunc, erruser, 0, 0, error, error_message );
  230. }
  231. namespace interface {
  232. template < typename T >
  233. void check_soundfile( T * mod ) {
  234. if ( !mod ) {
  235. throw openmpt::interface::invalid_module_pointer();
  236. }
  237. }
  238. template < typename T >
  239. void check_pointer( T * p ) {
  240. if ( !p ) {
  241. throw openmpt::interface::argument_null_pointer();
  242. }
  243. }
  244. } // namespace interface
  245. } // namespace openmpt
  246. extern "C" {
  247. uint32_t openmpt_get_library_version(void) {
  248. try {
  249. return openmpt::get_library_version();
  250. } catch ( ... ) {
  251. openmpt::report_exception( __func__ );
  252. }
  253. return 0;
  254. }
  255. uint32_t openmpt_get_core_version(void) {
  256. try {
  257. return openmpt::get_core_version();
  258. } catch ( ... ) {
  259. openmpt::report_exception( __func__ );
  260. }
  261. return 0;
  262. }
  263. void openmpt_free_string( const char * str ) {
  264. try {
  265. std::free( const_cast< char * >( str ) );
  266. } catch ( ... ) {
  267. openmpt::report_exception( __func__ );
  268. }
  269. return;
  270. }
  271. const char * openmpt_get_string( const char * key ) {
  272. try {
  273. if ( !key ) {
  274. return openmpt::strdup( "" );
  275. }
  276. return openmpt::strdup( openmpt::string::get( key ).c_str() );
  277. } catch ( ... ) {
  278. openmpt::report_exception( __func__ );
  279. }
  280. return NULL;
  281. }
  282. const char * openmpt_get_supported_extensions(void) {
  283. try {
  284. std::string retval;
  285. bool first = true;
  286. std::vector<std::string> supported_extensions = openmpt::module_impl::get_supported_extensions();
  287. for ( std::vector<std::string>::iterator i = supported_extensions.begin(); i != supported_extensions.end(); ++i ) {
  288. if ( first ) {
  289. first = false;
  290. } else {
  291. retval += ";";
  292. }
  293. retval += *i;
  294. }
  295. return openmpt::strdup( retval.c_str() );
  296. } catch ( ... ) {
  297. openmpt::report_exception( __func__ );
  298. }
  299. return NULL;
  300. }
  301. /// <summary>
  302. /// From version 0.7.0
  303. /// Hakan DANISIK
  304. /// </summary>
  305. /// <param name="extension"></param>
  306. /// <returns></returns>
  307. const char * openmpt_get_tracker_name( const char * extension ) {
  308. try {
  309. std::string retval;
  310. if ( !extension ) {
  311. return NULL;
  312. }
  313. retval = openmpt::module_impl::get_tracker_name( extension );
  314. return openmpt::strdup( retval.c_str() );
  315. } catch ( ... ) {
  316. openmpt::report_exception( __func__ );
  317. }
  318. return NULL;
  319. }
  320. int openmpt_is_extension_supported( const char * extension ) {
  321. try {
  322. if ( !extension ) {
  323. return 0;
  324. }
  325. return openmpt::module_impl::is_extension_supported( extension ) ? 1 : 0;
  326. } catch ( ... ) {
  327. openmpt::report_exception( __func__ );
  328. }
  329. return 0;
  330. }
  331. void openmpt_log_func_default( const char * message, void * /*user*/ ) {
  332. fprintf( stderr, "openmpt: %s\n", message );
  333. fflush( stderr );
  334. }
  335. void openmpt_log_func_silent( const char * /*message*/ , void * /*user*/ ) {
  336. return;
  337. }
  338. int openmpt_error_is_transient( int error ) {
  339. int result = 0;
  340. switch ( error ) {
  341. case OPENMPT_ERROR_OUT_OF_MEMORY:
  342. result = 1;
  343. break;
  344. default:
  345. result = 0;
  346. break;
  347. }
  348. return result;
  349. }
  350. const char * openmpt_error_string( int error ) {
  351. const char * text = "unknown error";
  352. switch ( error ) {
  353. case OPENMPT_ERROR_OK:
  354. text = "";
  355. break;
  356. case OPENMPT_ERROR_UNKNOWN:
  357. text = "unknown internal error";
  358. break;
  359. case OPENMPT_ERROR_EXCEPTION:
  360. text = "unknown exception ";
  361. break;
  362. case OPENMPT_ERROR_OUT_OF_MEMORY:
  363. text = "out of memory";
  364. break;
  365. case OPENMPT_ERROR_RUNTIME:
  366. text = "runtime error";
  367. break;
  368. case OPENMPT_ERROR_RANGE:
  369. text = "range error";
  370. break;
  371. case OPENMPT_ERROR_OVERFLOW:
  372. text = "arithmetic overflow";
  373. break;
  374. case OPENMPT_ERROR_UNDERFLOW:
  375. text = "arithmetic underflow";
  376. break;
  377. case OPENMPT_ERROR_LOGIC:
  378. text = "logic error";
  379. break;
  380. case OPENMPT_ERROR_DOMAIN:
  381. text = "value domain error";
  382. break;
  383. case OPENMPT_ERROR_LENGTH:
  384. text = "maximum supported size exceeded";
  385. break;
  386. case OPENMPT_ERROR_OUT_OF_RANGE:
  387. text = "argument out of range";
  388. break;
  389. case OPENMPT_ERROR_INVALID_ARGUMENT:
  390. text = "invalid argument";
  391. break;
  392. case OPENMPT_ERROR_GENERAL:
  393. text = "libopenmpt error";
  394. break;
  395. }
  396. return openmpt::strdup( text );
  397. }
  398. int openmpt_error_func_default( int error, void * /* user */ ) {
  399. (void)error;
  400. return OPENMPT_ERROR_FUNC_RESULT_DEFAULT;
  401. }
  402. int openmpt_error_func_log( int error, void * /* user */ ) {
  403. (void)error;
  404. return OPENMPT_ERROR_FUNC_RESULT_LOG;
  405. }
  406. int openmpt_error_func_store( int error, void * /* user */ ) {
  407. (void)error;
  408. return OPENMPT_ERROR_FUNC_RESULT_STORE;
  409. }
  410. int openmpt_error_func_ignore( int error, void * /* user */ ) {
  411. (void)error;
  412. return OPENMPT_ERROR_FUNC_RESULT_NONE;
  413. }
  414. int openmpt_error_func_errno( int error, void * user ) {
  415. int * e = (int *)user;
  416. if ( !e ) {
  417. return OPENMPT_ERROR_FUNC_RESULT_DEFAULT;
  418. }
  419. *e = error;
  420. return OPENMPT_ERROR_FUNC_RESULT_NONE;
  421. }
  422. void * openmpt_error_func_errno_userdata( int * error ) {
  423. return (void *)error;
  424. }
  425. double openmpt_could_open_probability( openmpt_stream_callbacks stream_callbacks, void * stream, double effort, openmpt_log_func logfunc, void * loguser ) {
  426. return openmpt_could_open_probability2( stream_callbacks, stream, effort, logfunc, loguser, NULL, NULL, NULL, NULL );
  427. }
  428. double openmpt_could_open_propability( openmpt_stream_callbacks stream_callbacks, void * stream, double effort, openmpt_log_func logfunc, void * loguser ) {
  429. return openmpt_could_open_probability2( stream_callbacks, stream, effort, logfunc, loguser, NULL, NULL, NULL, NULL );
  430. }
  431. double openmpt_could_open_probability2( openmpt_stream_callbacks stream_callbacks, void * stream, double effort, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ) {
  432. try {
  433. openmpt::callback_stream_wrapper istream = { stream, stream_callbacks.read, stream_callbacks.seek, stream_callbacks.tell };
  434. return openmpt::module_impl::could_open_probability( istream, effort, openmpt::helper::make_unique<openmpt::logfunc_logger>( logfunc ? logfunc : openmpt_log_func_default, loguser ) );
  435. } catch ( ... ) {
  436. openmpt::report_exception( __func__, logfunc, loguser, errfunc, erruser, error, error_message );
  437. }
  438. return 0.0;
  439. }
  440. size_t openmpt_probe_file_header_get_recommended_size(void) {
  441. try {
  442. return openmpt::module_impl::probe_file_header_get_recommended_size();
  443. } catch ( ... ) {
  444. openmpt::report_exception( __func__ );
  445. }
  446. return 0;
  447. }
  448. int openmpt_probe_file_header( uint64_t flags, const void * data, size_t size, uint64_t filesize, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ) {
  449. try {
  450. return openmpt::module_impl::probe_file_header( flags, data, size, filesize );
  451. } catch ( ... ) {
  452. openmpt::report_exception( __func__, logfunc, loguser, errfunc, erruser, error, error_message );
  453. }
  454. return OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR;
  455. }
  456. int openmpt_probe_file_header_without_filesize( uint64_t flags, const void * data, size_t size, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ) {
  457. try {
  458. return openmpt::module_impl::probe_file_header( flags, data, size );
  459. } catch ( ... ) {
  460. openmpt::report_exception( __func__, logfunc, loguser, errfunc, erruser, error, error_message );
  461. }
  462. return OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR;
  463. }
  464. int openmpt_probe_file_header_from_stream( uint64_t flags, openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ) {
  465. try {
  466. openmpt::callback_stream_wrapper istream = { stream, stream_callbacks.read, stream_callbacks.seek, stream_callbacks.tell };
  467. return openmpt::module_impl::probe_file_header( flags, istream );
  468. } catch ( ... ) {
  469. openmpt::report_exception( __func__, logfunc, loguser, errfunc, erruser, error, error_message );
  470. }
  471. return OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR;
  472. }
  473. openmpt_module * openmpt_module_create( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * user, const openmpt_module_initial_ctl * ctls ) {
  474. return openmpt_module_create2( stream_callbacks, stream, logfunc, user, NULL, NULL, NULL, NULL, ctls );
  475. }
  476. openmpt_module * openmpt_module_create2( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ) {
  477. try {
  478. openmpt_module * mod = (openmpt_module*)std::calloc( 1, sizeof( openmpt_module ) );
  479. if ( !mod ) {
  480. throw std::bad_alloc();
  481. }
  482. std::memset( mod, 0, sizeof( openmpt_module ) );
  483. mod->logfunc = logfunc ? logfunc : openmpt_log_func_default;
  484. mod->loguser = loguser;
  485. mod->errfunc = errfunc ? errfunc : NULL;
  486. mod->erruser = erruser;
  487. mod->error = OPENMPT_ERROR_OK;
  488. mod->error_message = NULL;
  489. mod->impl = 0;
  490. try {
  491. std::map< std::string, std::string > ctls_map;
  492. if ( ctls ) {
  493. for ( const openmpt_module_initial_ctl * it = ctls; it->ctl; ++it ) {
  494. if ( it->value ) {
  495. ctls_map[ it->ctl ] = it->value;
  496. } else {
  497. ctls_map.erase( it->ctl );
  498. }
  499. }
  500. }
  501. openmpt::callback_stream_wrapper istream = { stream, stream_callbacks.read, stream_callbacks.seek, stream_callbacks.tell };
  502. mod->impl = new openmpt::module_impl( istream, openmpt::helper::make_unique<openmpt::logfunc_logger>( mod->logfunc, mod->loguser ), ctls_map );
  503. return mod;
  504. } catch ( ... ) {
  505. #if defined(_MSC_VER)
  506. #pragma warning(push)
  507. #pragma warning(disable:6001) // false-positive: Using uninitialized memory 'mod'.
  508. #endif // _MSC_VER
  509. openmpt::report_exception( __func__, mod, error, error_message );
  510. #if defined(_MSC_VER)
  511. #pragma warning(pop)
  512. #endif // _MSC_VER
  513. }
  514. delete mod->impl;
  515. mod->impl = 0;
  516. if ( mod->error_message ) {
  517. openmpt_free_string( mod->error_message );
  518. mod->error_message = NULL;
  519. }
  520. std::free( (void*)mod );
  521. mod = NULL;
  522. } catch ( ... ) {
  523. openmpt::report_exception( __func__, 0, error, error_message );
  524. }
  525. return NULL;
  526. }
  527. openmpt_module * openmpt_module_create_from_memory( const void * filedata, size_t filesize, openmpt_log_func logfunc, void * user, const openmpt_module_initial_ctl * ctls ) {
  528. return openmpt_module_create_from_memory2( filedata, filesize, logfunc, user, NULL, NULL, NULL, NULL, ctls );
  529. }
  530. openmpt_module * openmpt_module_create_from_memory2( const void * filedata, size_t filesize, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ) {
  531. try {
  532. openmpt_module * mod = (openmpt_module*)std::calloc( 1, sizeof( openmpt_module ) );
  533. if ( !mod ) {
  534. throw std::bad_alloc();
  535. }
  536. std::memset( mod, 0, sizeof( openmpt_module ) );
  537. mod->logfunc = logfunc ? logfunc : openmpt_log_func_default;
  538. mod->loguser = loguser;
  539. mod->errfunc = errfunc ? errfunc : NULL;
  540. mod->erruser = erruser;
  541. mod->error = OPENMPT_ERROR_OK;
  542. mod->error_message = NULL;
  543. mod->impl = 0;
  544. try {
  545. std::map< std::string, std::string > ctls_map;
  546. if ( ctls ) {
  547. for ( const openmpt_module_initial_ctl * it = ctls; it->ctl; ++it ) {
  548. if ( it->value ) {
  549. ctls_map[ it->ctl ] = it->value;
  550. } else {
  551. ctls_map.erase( it->ctl );
  552. }
  553. }
  554. }
  555. mod->impl = new openmpt::module_impl( filedata, filesize, openmpt::helper::make_unique<openmpt::logfunc_logger>( mod->logfunc, mod->loguser ), ctls_map );
  556. return mod;
  557. } catch ( ... ) {
  558. #if defined(_MSC_VER)
  559. #pragma warning(push)
  560. #pragma warning(disable:6001) // false-positive: Using uninitialized memory 'mod'.
  561. #endif // _MSC_VER
  562. openmpt::report_exception( __func__, mod, error, error_message );
  563. #if defined(_MSC_VER)
  564. #pragma warning(pop)
  565. #endif // _MSC_VER
  566. }
  567. delete mod->impl;
  568. mod->impl = 0;
  569. if ( mod->error_message ) {
  570. openmpt_free_string( mod->error_message );
  571. mod->error_message = NULL;
  572. }
  573. std::free( (void*)mod );
  574. mod = NULL;
  575. } catch ( ... ) {
  576. openmpt::report_exception( __func__, 0, error, error_message );
  577. }
  578. return NULL;
  579. }
  580. void openmpt_module_destroy( openmpt_module * mod ) {
  581. try {
  582. openmpt::interface::check_soundfile( mod );
  583. delete mod->impl;
  584. mod->impl = 0;
  585. if ( mod->error_message ) {
  586. openmpt_free_string( mod->error_message );
  587. mod->error_message = NULL;
  588. }
  589. std::free( (void*)mod );
  590. mod = NULL;
  591. return;
  592. } catch ( ... ) {
  593. openmpt::report_exception( __func__, mod );
  594. }
  595. return;
  596. }
  597. void openmpt_module_set_log_func( openmpt_module * mod, openmpt_log_func logfunc, void * loguser ) {
  598. try {
  599. openmpt::interface::check_soundfile( mod );
  600. mod->logfunc = logfunc ? logfunc : openmpt_log_func_default;
  601. mod->loguser = loguser;
  602. return;
  603. } catch ( ... ) {
  604. openmpt::report_exception( __func__, mod );
  605. }
  606. return;
  607. }
  608. void openmpt_module_set_error_func( openmpt_module * mod, openmpt_error_func errfunc, void * erruser ) {
  609. try {
  610. openmpt::interface::check_soundfile( mod );
  611. mod->errfunc = errfunc ? errfunc : NULL;
  612. mod->erruser = erruser;
  613. mod->error = OPENMPT_ERROR_OK;
  614. return;
  615. } catch ( ... ) {
  616. openmpt::report_exception( __func__, mod );
  617. }
  618. return;
  619. }
  620. int openmpt_module_error_get_last( openmpt_module * mod ) {
  621. try {
  622. openmpt::interface::check_soundfile( mod );
  623. return mod->error;
  624. } catch ( ... ) {
  625. openmpt::report_exception( __func__, mod );
  626. }
  627. return -1;
  628. }
  629. const char * openmpt_module_error_get_last_message( openmpt_module * mod ) {
  630. try {
  631. openmpt::interface::check_soundfile( mod );
  632. return mod->error_message ? openmpt::strdup( mod->error_message ) : openmpt::strdup( "" );
  633. } catch ( ... ) {
  634. openmpt::report_exception( __func__, mod );
  635. }
  636. return NULL;
  637. }
  638. void openmpt_module_error_set_last( openmpt_module * mod, int error ) {
  639. try {
  640. openmpt::interface::check_soundfile( mod );
  641. mod->error = error;
  642. if ( mod->error_message ) {
  643. openmpt_free_string( mod->error_message );
  644. mod->error_message = NULL;
  645. }
  646. return;
  647. } catch ( ... ) {
  648. openmpt::report_exception( __func__, mod );
  649. }
  650. return;
  651. }
  652. void openmpt_module_error_clear( openmpt_module * mod ) {
  653. try {
  654. openmpt::interface::check_soundfile( mod );
  655. mod->error = OPENMPT_ERROR_OK;
  656. if ( mod->error_message ) {
  657. openmpt_free_string( mod->error_message );
  658. mod->error_message = NULL;
  659. }
  660. return;
  661. } catch ( ... ) {
  662. openmpt::report_exception( __func__, mod );
  663. }
  664. return;
  665. }
  666. int openmpt_module_select_subsong( openmpt_module * mod, int32_t subsong ) {
  667. try {
  668. openmpt::interface::check_soundfile( mod );
  669. mod->impl->select_subsong( subsong );
  670. return 1;
  671. } catch ( ... ) {
  672. openmpt::report_exception( __func__, mod );
  673. }
  674. return 0;
  675. }
  676. int32_t openmpt_module_get_selected_subsong( openmpt_module * mod ) {
  677. try {
  678. openmpt::interface::check_soundfile( mod );
  679. return mod->impl->get_selected_subsong();
  680. } catch ( ... ) {
  681. openmpt::report_exception( __func__, mod );
  682. }
  683. return -1;
  684. }
  685. int openmpt_module_set_repeat_count( openmpt_module * mod, int32_t repeat_count ) {
  686. try {
  687. openmpt::interface::check_soundfile( mod );
  688. mod->impl->set_repeat_count( repeat_count );
  689. return 1;
  690. } catch ( ... ) {
  691. openmpt::report_exception( __func__, mod );
  692. }
  693. return 0;
  694. }
  695. int32_t openmpt_module_get_repeat_count( openmpt_module * mod ) {
  696. try {
  697. openmpt::interface::check_soundfile( mod );
  698. return mod->impl->get_repeat_count();
  699. } catch ( ... ) {
  700. openmpt::report_exception( __func__, mod );
  701. }
  702. return 0;
  703. }
  704. double openmpt_module_get_duration_seconds( openmpt_module * mod ) {
  705. try {
  706. openmpt::interface::check_soundfile( mod );
  707. return mod->impl->get_duration_seconds();
  708. } catch ( ... ) {
  709. openmpt::report_exception( __func__, mod );
  710. }
  711. return 0.0;
  712. }
  713. double openmpt_module_set_position_seconds( openmpt_module * mod, double seconds ) {
  714. try {
  715. openmpt::interface::check_soundfile( mod );
  716. return mod->impl->set_position_seconds( seconds );
  717. } catch ( ... ) {
  718. openmpt::report_exception( __func__, mod );
  719. }
  720. return 0.0;
  721. }
  722. double openmpt_module_get_position_seconds( openmpt_module * mod ) {
  723. try {
  724. openmpt::interface::check_soundfile( mod );
  725. return mod->impl->get_position_seconds();
  726. } catch ( ... ) {
  727. openmpt::report_exception( __func__, mod );
  728. }
  729. return 0.0;
  730. }
  731. double openmpt_module_set_position_order_row( openmpt_module * mod, int32_t order, int32_t row ) {
  732. try {
  733. openmpt::interface::check_soundfile( mod );
  734. return mod->impl->set_position_order_row( order, row );
  735. } catch ( ... ) {
  736. openmpt::report_exception( __func__, mod );
  737. }
  738. return 0.0;
  739. }
  740. int openmpt_module_get_render_param( openmpt_module * mod, int param, int32_t * value ) {
  741. try {
  742. openmpt::interface::check_soundfile( mod );
  743. openmpt::interface::check_pointer( value );
  744. *value = mod->impl->get_render_param( (openmpt::module::render_param)param );
  745. return 1;
  746. } catch ( ... ) {
  747. openmpt::report_exception( __func__, mod );
  748. }
  749. return 0;
  750. }
  751. int openmpt_module_set_render_param( openmpt_module * mod, int param, int32_t value ) {
  752. try {
  753. openmpt::interface::check_soundfile( mod );
  754. mod->impl->set_render_param( (openmpt::module::render_param)param, value );
  755. return 1;
  756. } catch ( ... ) {
  757. openmpt::report_exception( __func__, mod );
  758. }
  759. return 0;
  760. }
  761. size_t openmpt_module_read_mono( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * mono ) {
  762. try {
  763. openmpt::interface::check_soundfile( mod );
  764. return mod->impl->read( samplerate, count, mono );
  765. } catch ( ... ) {
  766. openmpt::report_exception( __func__, mod );
  767. }
  768. return 0;
  769. }
  770. size_t openmpt_module_read_stereo( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * left, int16_t * right ) {
  771. try {
  772. openmpt::interface::check_soundfile( mod );
  773. return mod->impl->read( samplerate, count, left, right );
  774. } catch ( ... ) {
  775. openmpt::report_exception( __func__, mod );
  776. }
  777. return 0;
  778. }
  779. size_t openmpt_module_read_quad( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * left, int16_t * right, int16_t * rear_left, int16_t * rear_right ) {
  780. try {
  781. openmpt::interface::check_soundfile( mod );
  782. return mod->impl->read( samplerate, count, left, right, rear_left, rear_right );
  783. } catch ( ... ) {
  784. openmpt::report_exception( __func__, mod );
  785. }
  786. return 0;
  787. }
  788. size_t openmpt_module_read_float_mono( openmpt_module * mod, int32_t samplerate, size_t count, float * mono ) {
  789. try {
  790. openmpt::interface::check_soundfile( mod );
  791. return mod->impl->read( samplerate, count, mono );
  792. } catch ( ... ) {
  793. openmpt::report_exception( __func__, mod );
  794. }
  795. return 0;
  796. }
  797. size_t openmpt_module_read_float_stereo( openmpt_module * mod, int32_t samplerate, size_t count, float * left, float * right ) {
  798. try {
  799. openmpt::interface::check_soundfile( mod );
  800. return mod->impl->read( samplerate, count, left, right );
  801. } catch ( ... ) {
  802. openmpt::report_exception( __func__, mod );
  803. }
  804. return 0;
  805. }
  806. size_t openmpt_module_read_float_quad( openmpt_module * mod, int32_t samplerate, size_t count, float * left, float * right, float * rear_left, float * rear_right ) {
  807. try {
  808. openmpt::interface::check_soundfile( mod );
  809. return mod->impl->read( samplerate, count, left, right, rear_left, rear_right );
  810. } catch ( ... ) {
  811. openmpt::report_exception( __func__, mod );
  812. }
  813. return 0;
  814. }
  815. size_t openmpt_module_read_interleaved_stereo( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * interleaved_stereo ) {
  816. try {
  817. openmpt::interface::check_soundfile( mod );
  818. return mod->impl->read_interleaved_stereo( samplerate, count, interleaved_stereo );
  819. } catch ( ... ) {
  820. openmpt::report_exception( __func__, mod );
  821. }
  822. return 0;
  823. }
  824. size_t openmpt_module_read_interleaved_quad( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * interleaved_quad ) {
  825. try {
  826. openmpt::interface::check_soundfile( mod );
  827. return mod->impl->read_interleaved_quad( samplerate, count, interleaved_quad );
  828. } catch ( ... ) {
  829. openmpt::report_exception( __func__, mod );
  830. }
  831. return 0;
  832. }
  833. size_t openmpt_module_read_interleaved_float_stereo( openmpt_module * mod, int32_t samplerate, size_t count, float * interleaved_stereo ) {
  834. try {
  835. openmpt::interface::check_soundfile( mod );
  836. return mod->impl->read_interleaved_stereo( samplerate, count, interleaved_stereo );
  837. } catch ( ... ) {
  838. openmpt::report_exception( __func__, mod );
  839. }
  840. return 0;
  841. }
  842. size_t openmpt_module_read_interleaved_float_quad( openmpt_module * mod, int32_t samplerate, size_t count, float * interleaved_quad ) {
  843. try {
  844. openmpt::interface::check_soundfile( mod );
  845. return mod->impl->read_interleaved_quad( samplerate, count, interleaved_quad );
  846. } catch ( ... ) {
  847. openmpt::report_exception( __func__, mod );
  848. }
  849. return 0;
  850. }
  851. const char * openmpt_module_get_metadata_keys( openmpt_module * mod ) {
  852. try {
  853. openmpt::interface::check_soundfile( mod );
  854. std::string retval;
  855. bool first = true;
  856. std::vector<std::string> metadata_keys = mod->impl->get_metadata_keys();
  857. for ( std::vector<std::string>::iterator i = metadata_keys.begin(); i != metadata_keys.end(); ++i ) {
  858. if ( first ) {
  859. first = false;
  860. } else {
  861. retval += ";";
  862. }
  863. retval += *i;
  864. }
  865. return openmpt::strdup( retval.c_str() );
  866. } catch ( ... ) {
  867. openmpt::report_exception( __func__, mod );
  868. }
  869. return NULL;
  870. }
  871. const char * openmpt_module_get_metadata( openmpt_module * mod, const char * key ) {
  872. try {
  873. openmpt::interface::check_soundfile( mod );
  874. openmpt::interface::check_pointer( key );
  875. return openmpt::strdup( mod->impl->get_metadata( key ).c_str() );
  876. } catch ( ... ) {
  877. openmpt::report_exception( __func__, mod );
  878. }
  879. return NULL;
  880. }
  881. double openmpt_module_get_current_estimated_bpm( openmpt_module * mod ) {
  882. try {
  883. openmpt::interface::check_soundfile( mod );
  884. return mod->impl->get_current_estimated_bpm();
  885. } catch ( ... ) {
  886. openmpt::report_exception( __func__, mod );
  887. }
  888. return 0.0;
  889. }
  890. int32_t openmpt_module_get_current_speed( openmpt_module * mod ) {
  891. try {
  892. openmpt::interface::check_soundfile( mod );
  893. return mod->impl->get_current_speed();
  894. } catch ( ... ) {
  895. openmpt::report_exception( __func__, mod );
  896. }
  897. return 0;
  898. }
  899. int32_t openmpt_module_get_current_tempo( openmpt_module * mod ) {
  900. try {
  901. openmpt::interface::check_soundfile( mod );
  902. return mod->impl->get_current_tempo();
  903. } catch ( ... ) {
  904. openmpt::report_exception( __func__, mod );
  905. }
  906. return 0;
  907. }
  908. int32_t openmpt_module_get_current_order( openmpt_module * mod ) {
  909. try {
  910. openmpt::interface::check_soundfile( mod );
  911. return mod->impl->get_current_order();
  912. } catch ( ... ) {
  913. openmpt::report_exception( __func__, mod );
  914. }
  915. return 0;
  916. }
  917. int32_t openmpt_module_get_current_pattern( openmpt_module * mod ) {
  918. try {
  919. openmpt::interface::check_soundfile( mod );
  920. return mod->impl->get_current_pattern();
  921. } catch ( ... ) {
  922. openmpt::report_exception( __func__, mod );
  923. }
  924. return 0;
  925. }
  926. int32_t openmpt_module_get_current_row( openmpt_module * mod ) {
  927. try {
  928. openmpt::interface::check_soundfile( mod );
  929. return mod->impl->get_current_row();
  930. } catch ( ... ) {
  931. openmpt::report_exception( __func__, mod );
  932. }
  933. return 0;
  934. }
  935. int32_t openmpt_module_get_current_playing_channels( openmpt_module * mod ) {
  936. try {
  937. openmpt::interface::check_soundfile( mod );
  938. return mod->impl->get_current_playing_channels();
  939. } catch ( ... ) {
  940. openmpt::report_exception( __func__, mod );
  941. }
  942. return 0;
  943. }
  944. float openmpt_module_get_current_channel_vu_mono( openmpt_module * mod, int32_t channel ) {
  945. try {
  946. openmpt::interface::check_soundfile( mod );
  947. return mod->impl->get_current_channel_vu_mono( channel );
  948. } catch ( ... ) {
  949. openmpt::report_exception( __func__, mod );
  950. }
  951. return 0.0;
  952. }
  953. float openmpt_module_get_current_channel_vu_left( openmpt_module * mod, int32_t channel ) {
  954. try {
  955. openmpt::interface::check_soundfile( mod );
  956. return mod->impl->get_current_channel_vu_left( channel );
  957. } catch ( ... ) {
  958. openmpt::report_exception( __func__, mod );
  959. }
  960. return 0.0;
  961. }
  962. float openmpt_module_get_current_channel_vu_right( openmpt_module * mod, int32_t channel ) {
  963. try {
  964. openmpt::interface::check_soundfile( mod );
  965. return mod->impl->get_current_channel_vu_right( channel );
  966. } catch ( ... ) {
  967. openmpt::report_exception( __func__, mod );
  968. }
  969. return 0.0;
  970. }
  971. float openmpt_module_get_current_channel_vu_rear_left( openmpt_module * mod, int32_t channel ) {
  972. try {
  973. openmpt::interface::check_soundfile( mod );
  974. return mod->impl->get_current_channel_vu_rear_left( channel );
  975. } catch ( ... ) {
  976. openmpt::report_exception( __func__, mod );
  977. }
  978. return 0.0;
  979. }
  980. float openmpt_module_get_current_channel_vu_rear_right( openmpt_module * mod, int32_t channel ) {
  981. try {
  982. openmpt::interface::check_soundfile( mod );
  983. return mod->impl->get_current_channel_vu_rear_right( channel );
  984. } catch ( ... ) {
  985. openmpt::report_exception( __func__, mod );
  986. }
  987. return 0.0;
  988. }
  989. int32_t openmpt_module_get_num_subsongs( openmpt_module * mod ) {
  990. try {
  991. openmpt::interface::check_soundfile( mod );
  992. return mod->impl->get_num_subsongs();
  993. } catch ( ... ) {
  994. openmpt::report_exception( __func__, mod );
  995. }
  996. return 0;
  997. }
  998. int32_t openmpt_module_get_num_channels( openmpt_module * mod ) {
  999. try {
  1000. openmpt::interface::check_soundfile( mod );
  1001. return mod->impl->get_num_channels();
  1002. } catch ( ... ) {
  1003. openmpt::report_exception( __func__, mod );
  1004. }
  1005. return 0;
  1006. }
  1007. int32_t openmpt_module_get_num_orders( openmpt_module * mod ) {
  1008. try {
  1009. openmpt::interface::check_soundfile( mod );
  1010. return mod->impl->get_num_orders();
  1011. } catch ( ... ) {
  1012. openmpt::report_exception( __func__, mod );
  1013. }
  1014. return 0;
  1015. }
  1016. int32_t openmpt_module_get_num_patterns( openmpt_module * mod ) {
  1017. try {
  1018. openmpt::interface::check_soundfile( mod );
  1019. return mod->impl->get_num_patterns();
  1020. } catch ( ... ) {
  1021. openmpt::report_exception( __func__, mod );
  1022. }
  1023. return 0;
  1024. }
  1025. int32_t openmpt_module_get_num_instruments( openmpt_module * mod ) {
  1026. try {
  1027. openmpt::interface::check_soundfile( mod );
  1028. return mod->impl->get_num_instruments();
  1029. } catch ( ... ) {
  1030. openmpt::report_exception( __func__, mod );
  1031. }
  1032. return 0;
  1033. }
  1034. int32_t openmpt_module_get_num_samples( openmpt_module * mod ) {
  1035. try {
  1036. openmpt::interface::check_soundfile( mod );
  1037. return mod->impl->get_num_samples();
  1038. } catch ( ... ) {
  1039. openmpt::report_exception( __func__, mod );
  1040. }
  1041. return 0;
  1042. }
  1043. const char * openmpt_module_get_subsong_name( openmpt_module * mod, int32_t index ) {
  1044. try {
  1045. openmpt::interface::check_soundfile( mod );
  1046. std::vector<std::string> names = mod->impl->get_subsong_names();
  1047. if ( names.size() >= (std::size_t)std::numeric_limits<int32_t>::max() ) {
  1048. throw std::runtime_error("too many names");
  1049. }
  1050. if ( index < 0 || index >= (int32_t)names.size() ) {
  1051. return openmpt::strdup( "" );
  1052. }
  1053. return openmpt::strdup( names[index].c_str() );
  1054. } catch ( ... ) {
  1055. openmpt::report_exception( __func__, mod );
  1056. }
  1057. return NULL;
  1058. }
  1059. const char * openmpt_module_get_channel_name( openmpt_module * mod, int32_t index ) {
  1060. try {
  1061. openmpt::interface::check_soundfile( mod );
  1062. std::vector<std::string> names = mod->impl->get_channel_names();
  1063. if ( names.size() >= (std::size_t)std::numeric_limits<int32_t>::max() ) {
  1064. throw std::runtime_error("too many names");
  1065. }
  1066. if ( index < 0 || index >= (int32_t)names.size() ) {
  1067. return openmpt::strdup( "" );
  1068. }
  1069. return openmpt::strdup( names[index].c_str() );
  1070. } catch ( ... ) {
  1071. openmpt::report_exception( __func__, mod );
  1072. }
  1073. return NULL;
  1074. }
  1075. const char * openmpt_module_get_order_name( openmpt_module * mod, int32_t index ) {
  1076. try {
  1077. openmpt::interface::check_soundfile( mod );
  1078. std::vector<std::string> names = mod->impl->get_order_names();
  1079. if ( names.size() >= (std::size_t)std::numeric_limits<int32_t>::max() ) {
  1080. throw std::runtime_error("too many names");
  1081. }
  1082. if ( index < 0 || index >= (int32_t)names.size() ) {
  1083. return openmpt::strdup( "" );
  1084. }
  1085. return openmpt::strdup( names[index].c_str() );
  1086. } catch ( ... ) {
  1087. openmpt::report_exception( __func__, mod );
  1088. }
  1089. return NULL;
  1090. }
  1091. const char * openmpt_module_get_pattern_name( openmpt_module * mod, int32_t index ) {
  1092. try {
  1093. openmpt::interface::check_soundfile( mod );
  1094. std::vector<std::string> names = mod->impl->get_pattern_names();
  1095. if ( names.size() >= (std::size_t)std::numeric_limits<int32_t>::max() ) {
  1096. throw std::runtime_error("too many names");
  1097. }
  1098. if ( index < 0 || index >= (int32_t)names.size() ) {
  1099. return openmpt::strdup( "" );
  1100. }
  1101. return openmpt::strdup( names[index].c_str() );
  1102. } catch ( ... ) {
  1103. openmpt::report_exception( __func__, mod );
  1104. }
  1105. return NULL;
  1106. }
  1107. const char * openmpt_module_get_instrument_name( openmpt_module * mod, int32_t index ) {
  1108. try {
  1109. openmpt::interface::check_soundfile( mod );
  1110. std::vector<std::string> names = mod->impl->get_instrument_names();
  1111. if ( names.size() >= (std::size_t)std::numeric_limits<int32_t>::max() ) {
  1112. throw std::runtime_error("too many names");
  1113. }
  1114. if ( index < 0 || index >= (int32_t)names.size() ) {
  1115. return openmpt::strdup( "" );
  1116. }
  1117. return openmpt::strdup( names[index].c_str() );
  1118. } catch ( ... ) {
  1119. openmpt::report_exception( __func__, mod );
  1120. }
  1121. return NULL;
  1122. }
  1123. const char * openmpt_module_get_sample_name( openmpt_module * mod, int32_t index ) {
  1124. try {
  1125. openmpt::interface::check_soundfile( mod );
  1126. std::vector<std::string> names = mod->impl->get_sample_names();
  1127. if ( names.size() >= (std::size_t)std::numeric_limits<int32_t>::max() ) {
  1128. throw std::runtime_error("too many names");
  1129. }
  1130. if ( index < 0 || index >= (int32_t)names.size() ) {
  1131. return openmpt::strdup( "" );
  1132. }
  1133. return openmpt::strdup( names[index].c_str() );
  1134. } catch ( ... ) {
  1135. openmpt::report_exception( __func__, mod );
  1136. }
  1137. return NULL;
  1138. }
  1139. int32_t openmpt_module_get_order_pattern( openmpt_module * mod, int32_t order ) {
  1140. try {
  1141. openmpt::interface::check_soundfile( mod );
  1142. return mod->impl->get_order_pattern( order );
  1143. } catch ( ... ) {
  1144. openmpt::report_exception( __func__, mod );
  1145. }
  1146. return 0;
  1147. }
  1148. int32_t openmpt_module_get_pattern_num_rows( openmpt_module * mod, int32_t pattern ) {
  1149. try {
  1150. openmpt::interface::check_soundfile( mod );
  1151. return mod->impl->get_pattern_num_rows( pattern );
  1152. } catch ( ... ) {
  1153. openmpt::report_exception( __func__, mod );
  1154. }
  1155. return 0;
  1156. }
  1157. uint8_t openmpt_module_get_pattern_row_channel_command( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, int command ) {
  1158. try {
  1159. openmpt::interface::check_soundfile( mod );
  1160. return mod->impl->get_pattern_row_channel_command( pattern, row, channel, command );
  1161. } catch ( ... ) {
  1162. openmpt::report_exception( __func__, mod );
  1163. }
  1164. return 0;
  1165. }
  1166. const char * openmpt_module_format_pattern_row_channel_command( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, int command ) {
  1167. try {
  1168. openmpt::interface::check_soundfile( mod );
  1169. return openmpt::strdup( mod->impl->format_pattern_row_channel_command( pattern, row, channel, command ).c_str() );
  1170. } catch ( ... ) {
  1171. openmpt::report_exception( __func__, mod );
  1172. }
  1173. return 0;
  1174. }
  1175. const char * openmpt_module_highlight_pattern_row_channel_command( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, int command ) {
  1176. try {
  1177. openmpt::interface::check_soundfile( mod );
  1178. return openmpt::strdup( mod->impl->highlight_pattern_row_channel_command( pattern, row, channel, command ).c_str() );
  1179. } catch ( ... ) {
  1180. openmpt::report_exception( __func__, mod );
  1181. }
  1182. return 0;
  1183. }
  1184. const char * openmpt_module_format_pattern_row_channel( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, size_t width, int pad ) {
  1185. try {
  1186. openmpt::interface::check_soundfile( mod );
  1187. return openmpt::strdup( mod->impl->format_pattern_row_channel( pattern, row, channel, width, pad ? true : false ).c_str() );
  1188. } catch ( ... ) {
  1189. openmpt::report_exception( __func__, mod );
  1190. }
  1191. return 0;
  1192. }
  1193. const char * openmpt_module_highlight_pattern_row_channel( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, size_t width, int pad ) {
  1194. try {
  1195. openmpt::interface::check_soundfile( mod );
  1196. return openmpt::strdup( mod->impl->highlight_pattern_row_channel( pattern, row, channel, width, pad ? true : false ).c_str() );
  1197. } catch ( ... ) {
  1198. openmpt::report_exception( __func__, mod );
  1199. }
  1200. return 0;
  1201. }
  1202. const char * openmpt_module_get_ctls( openmpt_module * mod ) {
  1203. try {
  1204. openmpt::interface::check_soundfile( mod );
  1205. std::string retval;
  1206. bool first = true;
  1207. std::vector<std::string> ctls = mod->impl->get_ctls();
  1208. for ( std::vector<std::string>::iterator i = ctls.begin(); i != ctls.end(); ++i ) {
  1209. if ( first ) {
  1210. first = false;
  1211. } else {
  1212. retval += ";";
  1213. }
  1214. retval += *i;
  1215. }
  1216. return openmpt::strdup( retval.c_str() );
  1217. } catch ( ... ) {
  1218. openmpt::report_exception( __func__, mod );
  1219. }
  1220. return NULL;
  1221. }
  1222. const char * openmpt_module_ctl_get( openmpt_module * mod, const char * ctl ) {
  1223. try {
  1224. openmpt::interface::check_soundfile( mod );
  1225. openmpt::interface::check_pointer( ctl );
  1226. return openmpt::strdup( mod->impl->ctl_get( ctl ).c_str() );
  1227. } catch ( ... ) {
  1228. openmpt::report_exception( __func__, mod );
  1229. }
  1230. return NULL;
  1231. }
  1232. int openmpt_module_ctl_get_boolean( openmpt_module * mod, const char * ctl ) {
  1233. try {
  1234. openmpt::interface::check_soundfile( mod );
  1235. openmpt::interface::check_pointer( ctl );
  1236. return mod->impl->ctl_get_boolean( ctl );
  1237. } catch ( ... ) {
  1238. openmpt::report_exception( __func__, mod );
  1239. }
  1240. return 0;
  1241. }
  1242. int64_t openmpt_module_ctl_get_integer( openmpt_module * mod, const char * ctl ) {
  1243. try {
  1244. openmpt::interface::check_soundfile( mod );
  1245. openmpt::interface::check_pointer( ctl );
  1246. return mod->impl->ctl_get_integer( ctl );
  1247. } catch ( ... ) {
  1248. openmpt::report_exception( __func__, mod );
  1249. }
  1250. return 0;
  1251. }
  1252. double openmpt_module_ctl_get_floatingpoint( openmpt_module * mod, const char * ctl ) {
  1253. try {
  1254. openmpt::interface::check_soundfile( mod );
  1255. openmpt::interface::check_pointer( ctl );
  1256. return mod->impl->ctl_get_floatingpoint( ctl );
  1257. } catch ( ... ) {
  1258. openmpt::report_exception( __func__, mod );
  1259. }
  1260. return 0.0;
  1261. }
  1262. const char * openmpt_module_ctl_get_text( openmpt_module * mod, const char * ctl ) {
  1263. try {
  1264. openmpt::interface::check_soundfile( mod );
  1265. openmpt::interface::check_pointer( ctl );
  1266. return openmpt::strdup( mod->impl->ctl_get_text( ctl ).c_str() );
  1267. } catch ( ... ) {
  1268. openmpt::report_exception( __func__, mod );
  1269. }
  1270. return NULL;
  1271. }
  1272. int openmpt_module_ctl_set( openmpt_module * mod, const char * ctl, const char * value ) {
  1273. try {
  1274. openmpt::interface::check_soundfile( mod );
  1275. openmpt::interface::check_pointer( ctl );
  1276. openmpt::interface::check_pointer( value );
  1277. mod->impl->ctl_set( ctl, value );
  1278. return 1;
  1279. } catch ( ... ) {
  1280. openmpt::report_exception( __func__, mod );
  1281. }
  1282. return 0;
  1283. }
  1284. int openmpt_module_ctl_set_boolean( openmpt_module * mod, const char * ctl, int value ) {
  1285. try {
  1286. openmpt::interface::check_soundfile( mod );
  1287. openmpt::interface::check_pointer( ctl );
  1288. mod->impl->ctl_set_boolean( ctl, value ? true : false );
  1289. return 1;
  1290. } catch ( ... ) {
  1291. openmpt::report_exception( __func__, mod );
  1292. }
  1293. return 0;
  1294. }
  1295. int openmpt_module_ctl_set_integer( openmpt_module * mod, const char * ctl, int64_t value ) {
  1296. try {
  1297. openmpt::interface::check_soundfile( mod );
  1298. openmpt::interface::check_pointer( ctl );
  1299. mod->impl->ctl_set_integer( ctl, value );
  1300. return 1;
  1301. } catch ( ... ) {
  1302. openmpt::report_exception( __func__, mod );
  1303. }
  1304. return 0;
  1305. }
  1306. int openmpt_module_ctl_set_floatingpoint( openmpt_module * mod, const char * ctl, double value ) {
  1307. try {
  1308. openmpt::interface::check_soundfile( mod );
  1309. openmpt::interface::check_pointer( ctl );
  1310. mod->impl->ctl_set_floatingpoint( ctl, value );
  1311. return 1;
  1312. } catch ( ... ) {
  1313. openmpt::report_exception( __func__, mod );
  1314. }
  1315. return 0;
  1316. }
  1317. int openmpt_module_ctl_set_text( openmpt_module * mod, const char * ctl, const char * value ) {
  1318. try {
  1319. openmpt::interface::check_soundfile( mod );
  1320. openmpt::interface::check_pointer( ctl );
  1321. openmpt::interface::check_pointer( value );
  1322. mod->impl->ctl_set_text( ctl, value );
  1323. return 1;
  1324. } catch ( ... ) {
  1325. openmpt::report_exception( __func__, mod );
  1326. }
  1327. return 0;
  1328. }
  1329. openmpt_module_ext * openmpt_module_ext_create( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ) {
  1330. try {
  1331. openmpt_module_ext * mod_ext = (openmpt_module_ext*)std::calloc( 1, sizeof( openmpt_module_ext ) );
  1332. if ( !mod_ext ) {
  1333. throw std::bad_alloc();
  1334. }
  1335. std::memset( mod_ext, 0, sizeof( openmpt_module_ext ) );
  1336. openmpt_module * mod = &mod_ext->mod;
  1337. std::memset( mod, 0, sizeof( openmpt_module ) );
  1338. mod_ext->impl = 0;
  1339. mod->logfunc = logfunc ? logfunc : openmpt_log_func_default;
  1340. mod->loguser = loguser;
  1341. mod->errfunc = errfunc ? errfunc : NULL;
  1342. mod->erruser = erruser;
  1343. mod->error = OPENMPT_ERROR_OK;
  1344. mod->error_message = NULL;
  1345. mod->impl = 0;
  1346. try {
  1347. std::map< std::string, std::string > ctls_map;
  1348. if ( ctls ) {
  1349. for ( const openmpt_module_initial_ctl * it = ctls; it->ctl; ++it ) {
  1350. if ( it->value ) {
  1351. ctls_map[ it->ctl ] = it->value;
  1352. } else {
  1353. ctls_map.erase( it->ctl );
  1354. }
  1355. }
  1356. }
  1357. openmpt::callback_stream_wrapper istream = { stream, stream_callbacks.read, stream_callbacks.seek, stream_callbacks.tell };
  1358. mod_ext->impl = new openmpt::module_ext_impl( istream, openmpt::helper::make_unique<openmpt::logfunc_logger>( mod->logfunc, mod->loguser ), ctls_map );
  1359. mod->impl = mod_ext->impl;
  1360. return mod_ext;
  1361. } catch ( ... ) {
  1362. openmpt::report_exception( __func__, mod, error, error_message );
  1363. }
  1364. #if defined(_MSC_VER)
  1365. #pragma warning(push)
  1366. #pragma warning(disable:6001) // false-positive: Using uninitialized memory 'mod_ext'.
  1367. #endif // _MSC_VER
  1368. delete mod_ext->impl;
  1369. #if defined(_MSC_VER)
  1370. #pragma warning(pop)
  1371. #endif // _MSC_VER
  1372. mod_ext->impl = 0;
  1373. mod->impl = 0;
  1374. if ( mod->error_message ) {
  1375. openmpt_free_string( mod->error_message );
  1376. mod->error_message = NULL;
  1377. }
  1378. std::free( (void*)mod_ext );
  1379. mod_ext = NULL;
  1380. } catch ( ... ) {
  1381. openmpt::report_exception( __func__, 0, error, error_message );
  1382. }
  1383. return NULL;
  1384. }
  1385. openmpt_module_ext * openmpt_module_ext_create_from_memory( const void * filedata, size_t filesize, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ) {
  1386. try {
  1387. openmpt_module_ext * mod_ext = (openmpt_module_ext*)std::calloc( 1, sizeof( openmpt_module_ext ) );
  1388. if ( !mod_ext ) {
  1389. throw std::bad_alloc();
  1390. }
  1391. std::memset( mod_ext, 0, sizeof( openmpt_module_ext ) );
  1392. openmpt_module * mod = &mod_ext->mod;
  1393. std::memset( mod, 0, sizeof( openmpt_module ) );
  1394. mod_ext->impl = 0;
  1395. mod->logfunc = logfunc ? logfunc : openmpt_log_func_default;
  1396. mod->loguser = loguser;
  1397. mod->errfunc = errfunc ? errfunc : NULL;
  1398. mod->erruser = erruser;
  1399. mod->error = OPENMPT_ERROR_OK;
  1400. mod->error_message = NULL;
  1401. mod->impl = 0;
  1402. try {
  1403. std::map< std::string, std::string > ctls_map;
  1404. if ( ctls ) {
  1405. for ( const openmpt_module_initial_ctl * it = ctls; it->ctl; ++it ) {
  1406. if ( it->value ) {
  1407. ctls_map[ it->ctl ] = it->value;
  1408. } else {
  1409. ctls_map.erase( it->ctl );
  1410. }
  1411. }
  1412. }
  1413. mod_ext->impl = new openmpt::module_ext_impl( filedata, filesize, openmpt::helper::make_unique<openmpt::logfunc_logger>( mod->logfunc, mod->loguser ), ctls_map );
  1414. mod->impl = mod_ext->impl;
  1415. return mod_ext;
  1416. } catch ( ... ) {
  1417. openmpt::report_exception( __func__, mod, error, error_message );
  1418. }
  1419. #if defined(_MSC_VER)
  1420. #pragma warning(push)
  1421. #pragma warning(disable:6001) // false-positive: Using uninitialized memory 'mod_ext'.
  1422. #endif // _MSC_VER
  1423. delete mod_ext->impl;
  1424. #if defined(_MSC_VER)
  1425. #pragma warning(pop)
  1426. #endif // _MSC_VER
  1427. mod_ext->impl = 0;
  1428. mod->impl = 0;
  1429. if ( mod->error_message ) {
  1430. openmpt_free_string( mod->error_message );
  1431. mod->error_message = NULL;
  1432. }
  1433. std::free( (void*)mod_ext );
  1434. mod_ext = NULL;
  1435. } catch ( ... ) {
  1436. openmpt::report_exception( __func__, 0, error, error_message );
  1437. }
  1438. return NULL;
  1439. }
  1440. void openmpt_module_ext_destroy( openmpt_module_ext * mod_ext ) {
  1441. try {
  1442. openmpt::interface::check_soundfile( mod_ext );
  1443. openmpt_module * mod = &mod_ext->mod;
  1444. mod->impl = 0;
  1445. delete mod_ext->impl;
  1446. mod_ext->impl = 0;
  1447. if ( mod->error_message ) {
  1448. openmpt_free_string( mod->error_message );
  1449. mod->error_message = NULL;
  1450. }
  1451. std::free( (void*)mod_ext );
  1452. mod_ext = NULL;
  1453. return;
  1454. } catch ( ... ) {
  1455. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1456. }
  1457. return;
  1458. }
  1459. openmpt_module * openmpt_module_ext_get_module( openmpt_module_ext * mod_ext ) {
  1460. try {
  1461. openmpt::interface::check_soundfile( mod_ext );
  1462. openmpt_module * mod = &mod_ext->mod;
  1463. return mod;
  1464. } catch ( ... ) {
  1465. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1466. }
  1467. return NULL;
  1468. }
  1469. static int get_pattern_row_channel_volume_effect_type( openmpt_module_ext * mod_ext, int32_t pattern, int32_t row, int32_t channel ) {
  1470. try {
  1471. openmpt::interface::check_soundfile( mod_ext );
  1472. return mod_ext->impl->get_pattern_row_channel_volume_effect_type( pattern, row, channel );
  1473. } catch ( ... ) {
  1474. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1475. }
  1476. return -1;
  1477. }
  1478. static int get_pattern_row_channel_effect_type( openmpt_module_ext * mod_ext, int32_t pattern, int32_t row, int32_t channel ) {
  1479. try {
  1480. openmpt::interface::check_soundfile( mod_ext );
  1481. return mod_ext->impl->get_pattern_row_channel_effect_type( pattern, row, channel );
  1482. } catch ( ... ) {
  1483. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1484. }
  1485. return -1;
  1486. }
  1487. static int set_current_speed( openmpt_module_ext * mod_ext, int32_t speed ) {
  1488. try {
  1489. openmpt::interface::check_soundfile( mod_ext );
  1490. mod_ext->impl->set_current_speed( speed );
  1491. return 1;
  1492. } catch ( ... ) {
  1493. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1494. }
  1495. return 0;
  1496. }
  1497. static int set_current_tempo( openmpt_module_ext * mod_ext, int32_t tempo ) {
  1498. try {
  1499. openmpt::interface::check_soundfile( mod_ext );
  1500. mod_ext->impl->set_current_tempo( tempo );
  1501. return 1;
  1502. } catch ( ... ) {
  1503. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1504. }
  1505. return 0;
  1506. }
  1507. static int set_tempo_factor( openmpt_module_ext * mod_ext, double factor ) {
  1508. try {
  1509. openmpt::interface::check_soundfile( mod_ext );
  1510. mod_ext->impl->set_tempo_factor( factor );
  1511. return 1;
  1512. } catch ( ... ) {
  1513. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1514. }
  1515. return 0;
  1516. }
  1517. static double get_tempo_factor( openmpt_module_ext * mod_ext ) {
  1518. try {
  1519. openmpt::interface::check_soundfile( mod_ext );
  1520. return mod_ext->impl->get_tempo_factor();
  1521. } catch ( ... ) {
  1522. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1523. }
  1524. return 0.0;
  1525. }
  1526. static int set_pitch_factor( openmpt_module_ext * mod_ext, double factor ) {
  1527. try {
  1528. openmpt::interface::check_soundfile( mod_ext );
  1529. mod_ext->impl->set_pitch_factor( factor );
  1530. return 1;
  1531. } catch ( ... ) {
  1532. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1533. }
  1534. return 0;
  1535. }
  1536. static double get_pitch_factor( openmpt_module_ext * mod_ext ) {
  1537. try {
  1538. openmpt::interface::check_soundfile( mod_ext );
  1539. return mod_ext->impl->get_pitch_factor();
  1540. } catch ( ... ) {
  1541. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1542. }
  1543. return 0.0;
  1544. }
  1545. static int set_global_volume( openmpt_module_ext * mod_ext, double volume ) {
  1546. try {
  1547. openmpt::interface::check_soundfile( mod_ext );
  1548. mod_ext->impl->set_global_volume( volume );
  1549. return 1;
  1550. } catch ( ... ) {
  1551. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1552. }
  1553. return 0;
  1554. }
  1555. static double get_global_volume( openmpt_module_ext * mod_ext ) {
  1556. try {
  1557. openmpt::interface::check_soundfile( mod_ext );
  1558. return mod_ext->impl->get_global_volume();
  1559. } catch ( ... ) {
  1560. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1561. }
  1562. return 0.0;
  1563. }
  1564. static int set_channel_volume( openmpt_module_ext * mod_ext, int32_t channel, double volume ) {
  1565. try {
  1566. openmpt::interface::check_soundfile( mod_ext );
  1567. mod_ext->impl->set_channel_volume( channel, volume );
  1568. return 1;
  1569. } catch ( ... ) {
  1570. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1571. }
  1572. return 0;
  1573. }
  1574. static double get_channel_volume( openmpt_module_ext * mod_ext, int32_t channel ) {
  1575. try {
  1576. openmpt::interface::check_soundfile( mod_ext );
  1577. return mod_ext->impl->get_channel_volume( channel );
  1578. } catch ( ... ) {
  1579. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1580. }
  1581. return 0.0;
  1582. }
  1583. static int set_channel_mute_status( openmpt_module_ext * mod_ext, int32_t channel, int mute ) {
  1584. try {
  1585. openmpt::interface::check_soundfile( mod_ext );
  1586. mod_ext->impl->set_channel_mute_status( channel, mute ? true : false );
  1587. return 1;
  1588. } catch ( ... ) {
  1589. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1590. }
  1591. return 0;
  1592. }
  1593. static int get_channel_mute_status( openmpt_module_ext * mod_ext, int32_t channel ) {
  1594. try {
  1595. openmpt::interface::check_soundfile( mod_ext );
  1596. return mod_ext->impl->get_channel_mute_status( channel ) ? 1 : 0;
  1597. } catch ( ... ) {
  1598. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1599. }
  1600. return -1;
  1601. }
  1602. static int set_instrument_mute_status( openmpt_module_ext * mod_ext, int32_t instrument, int mute ) {
  1603. try {
  1604. openmpt::interface::check_soundfile( mod_ext );
  1605. mod_ext->impl->set_instrument_mute_status( instrument, mute ? true : false );
  1606. return 1;
  1607. } catch ( ... ) {
  1608. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1609. }
  1610. return 0;
  1611. }
  1612. static int get_instrument_mute_status( openmpt_module_ext * mod_ext, int32_t instrument ) {
  1613. try {
  1614. openmpt::interface::check_soundfile( mod_ext );
  1615. return mod_ext->impl->get_instrument_mute_status( instrument ) ? 1 : 0;
  1616. } catch ( ... ) {
  1617. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1618. }
  1619. return -1;
  1620. }
  1621. static int32_t play_note( openmpt_module_ext * mod_ext, int32_t instrument, int32_t note, double volume, double panning ) {
  1622. try {
  1623. openmpt::interface::check_soundfile( mod_ext );
  1624. return mod_ext->impl->play_note( instrument, note, volume, panning );
  1625. } catch ( ... ) {
  1626. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1627. }
  1628. return -1;
  1629. }
  1630. static int stop_note( openmpt_module_ext * mod_ext, int32_t channel ) {
  1631. try {
  1632. openmpt::interface::check_soundfile( mod_ext );
  1633. mod_ext->impl->stop_note( channel );
  1634. return 1;
  1635. } catch ( ... ) {
  1636. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1637. }
  1638. return 0;
  1639. }
  1640. static int note_off( openmpt_module_ext * mod_ext, int32_t channel ) {
  1641. try {
  1642. openmpt::interface::check_soundfile( mod_ext );
  1643. mod_ext->impl->note_off(channel );
  1644. return 1;
  1645. } catch ( ... ) {
  1646. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1647. }
  1648. return 0;
  1649. }
  1650. static int note_fade( openmpt_module_ext * mod_ext, int32_t channel ) {
  1651. try {
  1652. openmpt::interface::check_soundfile( mod_ext );
  1653. mod_ext->impl->note_fade(channel );
  1654. return 1;
  1655. } catch ( ... ) {
  1656. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1657. }
  1658. return 0;
  1659. }
  1660. static int set_channel_panning( openmpt_module_ext * mod_ext, int32_t channel, double panning ) {
  1661. try {
  1662. openmpt::interface::check_soundfile( mod_ext );
  1663. mod_ext->impl->set_channel_panning( channel, panning );
  1664. return 1;
  1665. } catch ( ... ) {
  1666. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1667. }
  1668. return 0;
  1669. }
  1670. static double get_channel_panning( openmpt_module_ext * mod_ext, int32_t channel ) {
  1671. try {
  1672. openmpt::interface::check_soundfile( mod_ext );
  1673. return mod_ext->impl->get_channel_panning( channel );
  1674. } catch ( ... ) {
  1675. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1676. }
  1677. return 0.0;
  1678. }
  1679. static int set_note_finetune( openmpt_module_ext * mod_ext, int32_t channel, double finetune ) {
  1680. try {
  1681. openmpt::interface::check_soundfile( mod_ext );
  1682. mod_ext->impl->set_note_finetune( channel, finetune );
  1683. return 1;
  1684. } catch ( ... ) {
  1685. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1686. }
  1687. return 0;
  1688. }
  1689. static double get_note_finetune( openmpt_module_ext * mod_ext, int32_t channel ) {
  1690. try {
  1691. openmpt::interface::check_soundfile( mod_ext );
  1692. return mod_ext->impl->get_note_finetune( channel );
  1693. } catch ( ... ) {
  1694. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1695. }
  1696. return 0.0;
  1697. }
  1698. /* add stuff here */
  1699. int openmpt_module_ext_get_interface( openmpt_module_ext * mod_ext, const char * interface_id, void * interface, size_t interface_size ) {
  1700. try {
  1701. openmpt::interface::check_soundfile( mod_ext );
  1702. openmpt::interface::check_pointer( interface_id );
  1703. openmpt::interface::check_pointer( interface );
  1704. std::memset( interface, 0, interface_size );
  1705. int result = 0;
  1706. if ( !std::strcmp( interface_id, "" ) ) {
  1707. result = 0;
  1708. } else if ( !std::strcmp( interface_id, LIBOPENMPT_EXT_C_INTERFACE_PATTERN_VIS ) && ( interface_size == sizeof( openmpt_module_ext_interface_pattern_vis ) ) ) {
  1709. openmpt_module_ext_interface_pattern_vis * i = static_cast< openmpt_module_ext_interface_pattern_vis * >( interface );
  1710. i->get_pattern_row_channel_volume_effect_type = &get_pattern_row_channel_volume_effect_type;
  1711. i->get_pattern_row_channel_effect_type = &get_pattern_row_channel_effect_type;
  1712. result = 1;
  1713. } else if ( !std::strcmp( interface_id, LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE ) && ( interface_size == sizeof( openmpt_module_ext_interface_interactive ) ) ) {
  1714. openmpt_module_ext_interface_interactive * i = static_cast< openmpt_module_ext_interface_interactive * >( interface );
  1715. i->set_current_speed = &set_current_speed;
  1716. i->set_current_tempo = &set_current_tempo;
  1717. i->set_tempo_factor = &set_tempo_factor;
  1718. i->get_tempo_factor = &get_tempo_factor;
  1719. i->set_pitch_factor = &set_pitch_factor;
  1720. i->get_pitch_factor = &get_pitch_factor;
  1721. i->set_global_volume = &set_global_volume;
  1722. i->get_global_volume = &get_global_volume;
  1723. i->set_channel_volume = &set_channel_volume;
  1724. i->get_channel_volume = &get_channel_volume;
  1725. i->set_channel_mute_status = &set_channel_mute_status;
  1726. i->get_channel_mute_status = &get_channel_mute_status;
  1727. i->set_instrument_mute_status = &set_instrument_mute_status;
  1728. i->get_instrument_mute_status = &get_instrument_mute_status;
  1729. i->play_note = &play_note;
  1730. i->stop_note = &stop_note;
  1731. result = 1;
  1732. } else if ( !std::strcmp( interface_id, LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE2 ) && ( interface_size == sizeof( openmpt_module_ext_interface_interactive2 ) ) ) {
  1733. openmpt_module_ext_interface_interactive2 * i = static_cast< openmpt_module_ext_interface_interactive2 * >( interface );
  1734. i->note_off = &note_off;
  1735. i->note_fade = &note_fade;
  1736. i->set_channel_panning = &set_channel_panning;
  1737. i->get_channel_panning = &get_channel_panning;
  1738. i->set_note_finetune = &set_note_finetune;
  1739. i->get_note_finetune = &get_note_finetune;
  1740. result = 1;
  1741. /* add stuff here */
  1742. } else {
  1743. result = 0;
  1744. }
  1745. return result;
  1746. } catch ( ... ) {
  1747. openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
  1748. }
  1749. return 0;
  1750. }
  1751. } // extern "C"