Posted to tcl by stu at Fri Jan 26 16:00:19 GMT 2018view raw

  1. /*
  2. * Copyright (c) 2014 Stuart Cassoff <stwo@users.sourceforge.net>
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16.  
  17.  
  18. /*
  19. * tjsndio.c
  20. *
  21. * Tcl / Jim interface to sndio(3).
  22. *
  23. */
  24.  
  25. /*
  26. * Notes:
  27. *
  28. * sio_open() sets FD_CLOEXEC
  29. *
  30. */
  31.  
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35.  
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <sndio.h>
  39.  
  40. #define COMBIEN(Z) ((int) (sizeof(Z) / sizeof(Z[0])))
  41.  
  42. #ifdef FOR_JIM
  43. #include <jim-subcmd.h>
  44. # define EZT_OK JIM_OK
  45. # define EZT_ERROR JIM_ERR
  46. # define Ezt_IncrRefCount(O) Jim_IncrRefCount((O))
  47. # define Ezt_DecrRefCount(O) Jim_DecrRefCount(interp,(O))
  48. # define Ezt_SetResult(O) Jim_SetResult(interp,(O))
  49. # define Ezt_Obj Jim_Obj
  50. # define Ezt_Interp Jim_Interp
  51. # define Ezt_NewInt(I) Ezt_NewIntObj(interp,(I))
  52. # define Ezt_GetInt(I,P) Ezt_GetIntFromJimObj(interp,(I),(P))
  53. # define Ezt_NewWide(I) Jim_NewWideObj(interp,(I))
  54. # define Ezt_GetWide Jim_GetWide
  55. # define Ezt_NewString(S,L) Jim_NewStringObj(interp,(S),(L))
  56. # define Ezt_GetString Jim_GetString
  57. # define Ezt_GetBytes Jim_GetString
  58. # define Ezt_NewList() Jim_NewListObj(interp, NULL, 0)
  59. # define Ezt_ListAppend(L,O) Jim_ListAppendElement(interp,(L),(O))
  60. # define Ezt_NewDict() Jim_NewDictObj(interp, NULL, 0)
  61. # define Ezt_DictPut(D,KO,VO) Jim_DictAddElement(interp,(D),(KO),(VO))
  62. # define ezt_wide jim_wide
  63. # define EZT_SUBCMD(S) int (S) (Ezt_Interp *interp, int objc, Ezt_Obj *const *objv)
  64. # define EZT_CMD(S) int (S) (Ezt_Interp *interp, int objc, Ezt_Obj *const *objv)
  65. # define ezt_subcmd_type jim_subcmd_type
  66. #else
  67. # include <tcl.h>
  68. # define EZT_OK TCL_OK
  69. # define EZT_ERROR TCL_ERROR
  70. # define Ezt_IncrRefCount(O) Tcl_IncrRefCount((O))
  71. # define Ezt_DecrRefCount(O) Tcl_DecrRefCount((O))
  72. # define Ezt_SetResult(O) Tcl_SetObjResult(interp,(O))
  73. # define Ezt_Obj Tcl_Obj
  74. # define Ezt_Interp Tcl_Interp
  75. # define Ezt_NewInt Tcl_NewIntObj
  76. # define Ezt_GetInt(I,P) Tcl_GetIntFromObj(interp,(I),(P))
  77. # define Ezt_NewWide Tcl_NewWideIntObj
  78. # define Ezt_GetWide Tcl_GetWideIntFromObj
  79. # define Ezt_NewString Tcl_NewStringObj
  80. # define Ezt_GetString Tcl_GetStringFromObj
  81. # define Ezt_GetBytes Tcl_GetByteArrayFromObj
  82. # define Ezt_NewList() Tcl_NewListObj(0,NULL)
  83. # define Ezt_ListAppend(L,O) Tcl_ListObjAppendElement(interp,(L),(O))
  84. # define Ezt_NewDict() Tcl_NewDictObj()
  85. # define Ezt_DictPut(D,KO,VO) Tcl_DictObjPut(interp,(D),(KO),(VO))
  86. # define ezt_wide TclWideInt
  87. # define EZT_SUBCMD(S) int (S) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
  88. # define EZT_CMD EZT_SUBCMD
  89. typedef struct {
  90. const char *name;
  91. const char *args;
  92. Tcl_ObjCmdProc *proc;
  93. short minargs;
  94. short maxargs;
  95. unsigned short flags;
  96. } ezt_subcmd_type;
  97. #endif
  98.  
  99. #ifdef FOR_JIM
  100. static Jim_Obj *
  101. Ezt_NewIntObj (Jim_Interp *interp, int i) {
  102. return Jim_NewWideObj(interp, (ezt_wide) i);
  103. }
  104. static int
  105. Ezt_GetIntFromJimObj (Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr) {
  106. jim_wide w;
  107. if (Jim_GetWide(interp, objPtr, &w) != JIM_OK) { return JIM_ERR; }
  108. *intPtr = (int) w;
  109. return JIM_OK;
  110. }
  111. #endif
  112.  
  113. typedef struct TJsio {
  114. struct sio_hdl *hd;
  115. Ezt_Obj *name;
  116. } TJsio;
  117.  
  118. static TJsio TJ;
  119. static TJsio *tj = &TJ;
  120.  
  121.  
  122. static EZT_SUBCMD(TJsio_Sndio_Open);
  123. static EZT_SUBCMD(TJsio_Sndio_Close);
  124. static EZT_SUBCMD(TJsio_Sndio_Cap);
  125. static EZT_SUBCMD(TJsio_Sndio_Start);
  126. static EZT_SUBCMD(TJsio_Sndio_Stop);
  127. static EZT_SUBCMD(TJsio_Sndio_Write);
  128. static EZT_SUBCMD(TJsio_Sndio_Configure);
  129. static EZT_SUBCMD(TJsio_GOpts_Cmd);
  130. static EZT_SUBCMD(TJsio_SOpts_Cmd);
  131.  
  132. static const ezt_subcmd_type TJsio_Cmds[] = {
  133. { "open" , NULL , TJsio_Sndio_Open , 0, 0, 0 },
  134. { "close" , NULL , TJsio_Sndio_Close , 0, 0, 0 },
  135. { "cap" , NULL , TJsio_Sndio_Cap , 0, 0, 0 },
  136. { "start" , NULL , TJsio_Sndio_Start , 0, 0, 0 },
  137. { "stop" , NULL , TJsio_Sndio_Stop , 0, 0, 0 },
  138. { "write" , "buf" , TJsio_Sndio_Write , 1, 1, 0 },
  139. { "configure" , NULL , TJsio_Sndio_Configure , 0, -1, 0 },
  140. { "gopts" , NULL , TJsio_GOpts_Cmd , 0, 0, 0 },
  141. { "sopts" , NULL , TJsio_SOpts_Cmd , 0, 0, 0 },
  142. { NULL , NULL , NULL , 0, 0, 0 }
  143. };
  144.  
  145. /***/
  146.  
  147. enum tjsioOptions {
  148. TJSIO_OPT_BITS = (1 << 0),
  149. TJSIO_OPT_BPS = (1 << 1),
  150. TJSIO_OPT_SIG = (1 << 2),
  151. TJSIO_OPT_LE = (1 << 3),
  152. TJSIO_OPT_MSB = (1 << 4),
  153. TJSIO_OPT_PCHAN = (1 << 5),
  154. TJSIO_OPT_RCHAN = (1 << 6),
  155. TJSIO_OPT_RATE = (1 << 7),
  156. TJSIO_OPT_APPBUFSZ = (1 << 8),
  157. TJSIO_OPT_BUFSZ = (1 << 9),
  158. TJSIO_OPT_ROUND = (1 << 10),
  159. TJSIO_OPT_XRUN = (1 << 11),
  160. TJZIO_ALL = (
  161. 0
  162. | TJSIO_OPT_BITS
  163. | TJSIO_OPT_BPS
  164. | TJSIO_OPT_SIG
  165. | TJSIO_OPT_LE
  166. | TJSIO_OPT_MSB
  167. | TJSIO_OPT_PCHAN
  168. | TJSIO_OPT_RCHAN
  169. | TJSIO_OPT_RATE
  170. | TJSIO_OPT_APPBUFSZ
  171. | TJSIO_OPT_BUFSZ
  172. | TJSIO_OPT_ROUND
  173. | TJSIO_OPT_XRUN
  174. ),
  175. TJSIO_OPT_INVALID = -1
  176. };
  177.  
  178. typedef struct TJsio_OptVals {
  179. int rate;
  180. } TJsio_OptVals;
  181.  
  182. enum tjsioOptionFlags {
  183. TJSIO_OPTFLAG_RD = (1 << 0),
  184. TJSIO_OPTFLAG_WR = (1 << 1),
  185. TJSIO_OPTFLAG_CR = (1 << 2),
  186. TJSIO_OPTFLAG_RW = (TJSIO_OPTFLAG_WR | TJSIO_OPTFLAG_RD),
  187. TJSIO_OPTFLAG_IV = 0
  188. };
  189.  
  190. typedef struct TJsio_Option {
  191. const char* name;
  192. enum tjsioOptions id;
  193. enum tjsioOptionFlags flags;
  194. } TJsio_Option;
  195.  
  196. static TJsio_Option TJsio_Options[] = {
  197. { "-bits" , TJSIO_OPT_BITS , TJSIO_OPTFLAG_RW },
  198. { "-bps" , TJSIO_OPT_BPS , TJSIO_OPTFLAG_RW },
  199. { "-sig" , TJSIO_OPT_SIG , TJSIO_OPTFLAG_RW },
  200. { "-le" , TJSIO_OPT_LE , TJSIO_OPTFLAG_RW },
  201. { "-msb" , TJSIO_OPT_MSB , TJSIO_OPTFLAG_RW },
  202. { "-pchan" , TJSIO_OPT_PCHAN , TJSIO_OPTFLAG_RW },
  203. { "-rchan" , TJSIO_OPT_RCHAN , TJSIO_OPTFLAG_RW },
  204. { "-rate" , TJSIO_OPT_RATE , TJSIO_OPTFLAG_RW },
  205. { "-appbufsz" , TJSIO_OPT_APPBUFSZ , TJSIO_OPTFLAG_RW },
  206. { "-bufsz" , TJSIO_OPT_BUFSZ , TJSIO_OPTFLAG_RW },
  207. { "-round" , TJSIO_OPT_ROUND , TJSIO_OPTFLAG_RW },
  208. { "-xrun" , TJSIO_OPT_XRUN , TJSIO_OPTFLAG_RW },
  209. { NULL , TJSIO_OPT_INVALID , TJSIO_OPTFLAG_IV }
  210. };
  211.  
  212.  
  213. #define TJSIO_XRUN_BAD (SIO_ERROR + SIO_IGNORE + SIO_SYNC)
  214.  
  215. typedef struct TJsio_Xrun {
  216. const char *name;
  217. unsigned int val;
  218. } TJsio_Xrun;
  219.  
  220. static TJsio_Xrun TJsio_Xruns[] = {
  221. { "error" , SIO_ERROR },
  222. { "ignore" , SIO_IGNORE },
  223. { "sync" , SIO_SYNC },
  224. { NULL , 0 }
  225. };
  226.  
  227. const char *
  228. TJsio_XrunToStr (unsigned int val) {
  229. TJsio_Xrun *x;
  230. for (x = &TJsio_Xruns[0]; x->name != NULL; x++) {
  231. if (x->val == val) {
  232. return x->name;
  233. }
  234. }
  235. return NULL;
  236. }
  237.  
  238. unsigned int
  239. TJsio_StrToXrun (const char *name) {
  240. TJsio_Xrun *x;
  241. for (x = &TJsio_Xruns[0]; x->name != NULL; x++) {
  242. if (strcmp(name, x->name) == 0) {
  243. return x->val;
  244. }
  245. }
  246. return TJSIO_XRUN_BAD;
  247. }
  248. /***/
  249.  
  250.  
  251. static
  252. EZT_SUBCMD(TJsio_Sndio_Open) {
  253. const char *name = SIO_DEVANY;
  254. int mode = SIO_PLAY;
  255.  
  256. if (tj->hd != NULL) {
  257. Ezt_SetResult(tj->name);
  258. return EZT_OK;
  259. }
  260.  
  261. tj->hd = sio_open(name, mode, 0);
  262. if (tj->hd == NULL) {
  263. /*Jim_SetResultFormatted(interp, "couldn't open \"%s\"", name);*/
  264. return EZT_ERROR;
  265. }
  266.  
  267. tj->name = Ezt_NewString(name, -1);
  268. Ezt_IncrRefCount(tj->name);
  269.  
  270. Ezt_SetResult(tj->name);
  271.  
  272. return EZT_OK;
  273. }
  274.  
  275.  
  276. static
  277. EZT_SUBCMD(TJsio_Sndio_Close) {
  278. sio_close(tj->hd);
  279. tj->hd = NULL;
  280. Ezt_DecrRefCount(tj->name);
  281. return EZT_OK;
  282. }
  283.  
  284.  
  285. static
  286. EZT_SUBCMD(TJsio_Sndio_Cap) {
  287. struct sio_cap cap;
  288. int i, j;
  289. Ezt_Obj *l, *d;
  290. Ezt_Obj *rates, *rchans, *pchans, *encs, *denc;
  291. unsigned int rate, rchan, pchan, enc;
  292.  
  293. if (tj->hd == NULL) {
  294. return EZT_ERROR;
  295. }
  296.  
  297. if (!sio_getcap(tj->hd, &cap)) {
  298. /*Jim_SetResultFormatted(interp, "couldn't cat cap from \"%s\"", "cow");*/
  299. return EZT_ERROR;
  300. }
  301.  
  302. l = Ezt_NewList();
  303. Ezt_IncrRefCount(l);
  304.  
  305. for (i = 0; i < cap.nconf; i++) {
  306. d = Ezt_NewDict(); Ezt_IncrRefCount(d);
  307. rates = Ezt_NewList(); Ezt_IncrRefCount(rates);
  308. rchans = Ezt_NewList(); Ezt_IncrRefCount(rchans);
  309. pchans = Ezt_NewList(); Ezt_IncrRefCount(pchans);
  310. encs = Ezt_NewList(); Ezt_IncrRefCount(encs);
  311. for (
  312. rate = cap.confs[i].rate,
  313. rchan = cap.confs[i].rchan,
  314. pchan = cap.confs[i].pchan,
  315. enc = cap.confs[i].enc,
  316. j = 0
  317. ;
  318. rate || rchan || pchan || enc
  319. ;
  320. rate >>= 1, rchan >>= 1, pchan >>= 1, enc >>= 1,
  321. j++
  322. ) {
  323. if (rate & 1) {
  324. Ezt_ListAppend(rates, Ezt_NewInt(cap.rate[j]));
  325. }
  326. if (rchan & 1) {
  327. Ezt_ListAppend(rchans, Ezt_NewInt(cap.rchan[j]));
  328. }
  329. if (pchan & 1) {
  330. Ezt_ListAppend(pchans, Ezt_NewInt(cap.pchan[j]));
  331. }
  332. if (enc & 1) {
  333. denc = Ezt_NewDict();
  334. Ezt_IncrRefCount(denc);
  335. Ezt_DictPut(denc, Ezt_NewString("-bits", -1), Ezt_NewInt(cap.enc[j].bits));
  336. Ezt_DictPut(denc, Ezt_NewString("-bps", -1), Ezt_NewInt(cap.enc[j].bps));
  337. Ezt_DictPut(denc, Ezt_NewString("-sig", -1), Ezt_NewInt(cap.enc[j].sig));
  338. Ezt_DictPut(denc, Ezt_NewString("-le", -1), Ezt_NewInt(cap.enc[j].le));
  339. Ezt_DictPut(denc, Ezt_NewString("-msb", -1), Ezt_NewInt(cap.enc[j].msb));
  340. Ezt_ListAppend(encs, denc);
  341. Ezt_DecrRefCount(denc);
  342. }
  343. }
  344. Ezt_DictPut(d, Ezt_NewString("rates" , -1), rates ); Ezt_DecrRefCount(rates);
  345. Ezt_DictPut(d, Ezt_NewString("rchans", -1), rchans); Ezt_DecrRefCount(rchans);
  346. Ezt_DictPut(d, Ezt_NewString("pchans", -1), pchans); Ezt_DecrRefCount(pchans);
  347. Ezt_DictPut(d, Ezt_NewString("encs" , -1), encs ); Ezt_DecrRefCount(encs);
  348. Ezt_ListAppend(l, d);
  349. Ezt_DecrRefCount(d);
  350. }
  351.  
  352. Ezt_SetResult(l);
  353. Ezt_DecrRefCount(l);
  354.  
  355. return EZT_OK;
  356. }
  357.  
  358.  
  359.  
  360. static
  361. EZT_SUBCMD(TJsio_Sndio_Start) {
  362. if (tj->hd == NULL) {
  363. return EZT_ERROR;
  364. }
  365. if (!sio_start(tj->hd)) {
  366. return EZT_ERROR;
  367. }
  368. return EZT_OK;
  369. }
  370.  
  371.  
  372. static
  373. EZT_SUBCMD(TJsio_Sndio_Stop) {
  374. if (tj->hd == NULL) {
  375. return EZT_ERROR;
  376. }
  377. if (!sio_stop(tj->hd)) {
  378. return EZT_ERROR;
  379. }
  380. return EZT_OK;
  381. }
  382.  
  383.  
  384. static
  385. EZT_SUBCMD(TJsio_Sndio_Write) {
  386. const char *buf;
  387. int len;
  388. #if FOR_TCL
  389. objc--; objv++;
  390. #endif
  391. if (tj->hd == NULL) {
  392. return EZT_ERROR;
  393. }
  394. buf = Ezt_GetBytes(objv[0], &len);
  395. sio_write(tj->hd, buf, len);
  396. return EZT_OK;
  397. }
  398.  
  399.  
  400. /* Returned obj will have refcount 1 */
  401. static Ezt_Obj *
  402. TJsio_ListOptions (
  403. Ezt_Interp *interp,
  404. enum tjsioOptionFlags mask
  405. ) {
  406. int i;
  407. Ezt_Obj *o;
  408. o = Ezt_NewList();
  409. Ezt_IncrRefCount(o);
  410. for (i = 0; i < COMBIEN(TJsio_Options) - 1; i++) {
  411. if ((TJsio_Options[i].flags & mask) != mask) { continue; }
  412. Ezt_ListAppend(o, Ezt_NewString(TJsio_Options[i].name,-1));
  413. }
  414. return o;
  415. }
  416.  
  417. static int
  418. TJsio_DoListOptions (
  419. Ezt_Interp *interp,
  420. enum tjsioOptionFlags mask
  421. ) {
  422. Ezt_Obj *o;
  423. o = TJsio_ListOptions(interp, mask);
  424. Ezt_SetResult(o);
  425. Ezt_DecrRefCount(o);
  426. return EZT_OK;
  427. }
  428.  
  429. static
  430. EZT_SUBCMD(TJsio_GOpts_Cmd) {
  431. return TJsio_DoListOptions(interp, TJSIO_OPTFLAG_RD);
  432. }
  433.  
  434. static
  435. EZT_SUBCMD(TJsio_SOpts_Cmd) {
  436. return TJsio_DoListOptions(interp, TJSIO_OPTFLAG_WR);
  437. }
  438.  
  439. static Ezt_Obj *
  440. TJsio_SndioParToObj (
  441. Ezt_Interp *interp,
  442. struct sio_par *p,
  443. enum tjsioOptions opt
  444. ) {
  445. unsigned int val;
  446.  
  447. switch (opt) {
  448. case TJSIO_OPT_BITS : val = p->bits ; break;
  449. case TJSIO_OPT_BPS : val = p->bps ; break;
  450. case TJSIO_OPT_SIG : val = p->sig ; break;
  451. case TJSIO_OPT_LE : val = p->le ; break;
  452. case TJSIO_OPT_MSB : val = p->msb ; break;
  453. case TJSIO_OPT_PCHAN : val = p->pchan ; break;
  454. case TJSIO_OPT_RCHAN : val = p->rchan ; break;
  455. case TJSIO_OPT_RATE : val = p->rate ; break;
  456. case TJSIO_OPT_APPBUFSZ : val = p->appbufsz ; break;
  457. case TJSIO_OPT_BUFSZ : val = p->bufsz ; break;
  458. case TJSIO_OPT_ROUND : val = p->round ; break;
  459. case TJSIO_OPT_XRUN:
  460. return Ezt_NewString(TJsio_XrunToStr(p->xrun), -1);
  461. default:
  462. return NULL;
  463. }
  464.  
  465. return Ezt_NewInt(val);
  466. }
  467.  
  468. static int
  469. TJsio_ObjToSndioPar (
  470. Ezt_Interp *interp,
  471. struct sio_par *p,
  472. enum tjsioOptions opt,
  473. Ezt_Obj *optVal
  474. ) {
  475. unsigned int val;
  476.  
  477. if (opt == TJSIO_OPT_XRUN) {
  478. if ((val = TJsio_StrToXrun(Ezt_GetString(optVal, NULL))) == TJSIO_XRUN_BAD) { return EZT_ERROR; }
  479. } else {
  480. if (Ezt_GetInt(optVal, &val) != EZT_OK) { return EZT_ERROR; }
  481. }
  482.  
  483. switch (opt) {
  484. case TJSIO_OPT_BITS: p->bits = val; break;
  485. case TJSIO_OPT_BPS: p->bps = val; break;
  486. case TJSIO_OPT_SIG: p->sig = val; break;
  487. case TJSIO_OPT_LE: p->le = val; break;
  488. case TJSIO_OPT_MSB: p->msb = val; break;
  489. case TJSIO_OPT_PCHAN: p->pchan = val; break;
  490. case TJSIO_OPT_RCHAN: p->rchan = val; break;
  491. case TJSIO_OPT_RATE: p->rate = val; break;
  492. case TJSIO_OPT_APPBUFSZ: p->appbufsz = val; break;
  493. case TJSIO_OPT_BUFSZ: p->bufsz = val; break;
  494. case TJSIO_OPT_ROUND: p->round = val; break;
  495. case TJSIO_OPT_XRUN: p->xrun = val; break;
  496. default:
  497. return EZT_ERROR;
  498. }
  499.  
  500. return EZT_OK;
  501. }
  502.  
  503. static int
  504. Ezt_FindOption (
  505. Ezt_Interp *interp,
  506. Ezt_Obj *option,
  507. enum tjsioOptionFlags mask,
  508. int *where
  509. ) {
  510. const char *optionStr = Ezt_GetString(option, NULL);
  511. int i;
  512. for (i = 0; i < COMBIEN(TJsio_Options) - 1; i++) {
  513. if ((TJsio_Options[i].flags & mask) != mask) { continue; }
  514. if (strcmp(optionStr, TJsio_Options[i].name) != 0) { continue; }
  515. *where = i;
  516. return EZT_OK;
  517. }
  518. /* return Duft_BadOption(interp, optionStr, mask, "option");*/
  519. return EZT_ERROR;
  520. }
  521.  
  522. static
  523. EZT_SUBCMD(TJsio_Sndio_Configure) {
  524. struct sio_par par;
  525. int i;
  526.  
  527. #if FOR_TCL
  528. objc--; objv++;
  529. #endif
  530.  
  531. if (tj->hd == NULL) {
  532. return EZT_ERROR;
  533. }
  534.  
  535. if ((objc > 1) && ((objc % 2) == 1)) {
  536. /*Ezt_WrongNumArgs(interp, 1, objv, "id ?-option value ...?");*/
  537. return EZT_ERROR;
  538. }
  539.  
  540. sio_initpar(&par);
  541.  
  542. if (objc > 1) {
  543. int j,k;
  544. for (j=0,k=1; k < objc; j+=2,k+=2) {
  545. if (Ezt_FindOption(interp, objv[j], TJSIO_OPTFLAG_RD, &i) != EZT_OK) {
  546. return EZT_ERROR;
  547. }
  548. if (TJsio_ObjToSndioPar(interp, &par, TJsio_Options[i].id, objv[k]) != EZT_OK) {
  549. return EZT_ERROR;
  550. }
  551. }
  552. if (!sio_setpar(tj->hd, &par)) {
  553. return EZT_ERROR;
  554. }
  555. return EZT_OK;
  556. }
  557.  
  558. if (!sio_getpar(tj->hd, &par)) {
  559. return EZT_ERROR;
  560. }
  561.  
  562. if (objc == 0) {
  563. Ezt_Obj *d;
  564. d = Ezt_NewDict();
  565. Ezt_IncrRefCount(d);
  566. for (i = 0; i < COMBIEN(TJsio_Options) - 1; i++) {
  567. Ezt_DictPut(d, Ezt_NewString(TJsio_Options[i].name, -1), TJsio_SndioParToObj(interp, &par, TJsio_Options[i].id));
  568. }
  569. Ezt_SetResult(d);
  570. Ezt_DecrRefCount(d);
  571. return EZT_OK;
  572. }
  573.  
  574. if (Ezt_FindOption(interp, objv[0], TJSIO_OPTFLAG_RD, &i) != EZT_OK) {
  575. return EZT_ERROR;
  576. }
  577. Ezt_SetResult(TJsio_SndioParToObj(interp, &par, TJsio_Options[i].id));
  578.  
  579. return EZT_OK;
  580. }
  581.  
  582. /***/
  583.  
  584. #ifdef FOR_JIM
  585. int
  586. Jim_sndioInit (Ezt_Interp *interp) {
  587. if (Jim_CreateCommand(interp, "sndio", Jim_SubCmdProc, (void *) TJsio_Cmds, NULL) != EZT_OK) { return EZT_ERROR; }
  588. if (Jim_PackageProvide(interp, PACKAGE_NAME, PACKAGE_VERSION, JIM_ERRMSG) != EZT_OK) { return EZT_ERROR; }
  589. return EZT_OK;
  590. }
  591. #else
  592.  
  593.  
  594. #define MIN_TCL_VERSION "8.5"
  595. #define TJSIO_NS "::sndio"
  596. #define TJSIO_EN "sndio"
  597. #define TJSIO_VER "0.1"
  598.  
  599. static int
  600. TJsio_CommonInit (
  601. Tcl_Interp *interp
  602. ) {
  603. if (Tcl_InitStubs (interp, MIN_TCL_VERSION, 0) == NULL) { return TCL_ERROR; }
  604. if (Tcl_PkgRequire (interp, "Tcl", MIN_TCL_VERSION, 0) == NULL) { return TCL_ERROR; }
  605. if (Tcl_CreateNamespace (interp, TJSIO_NS, NULL, NULL) == NULL) { return TCL_ERROR; }
  606. if (Tcl_PkgProvide (interp, "sndio", TJSIO_VER) != TCL_OK) { return TCL_ERROR; }
  607. return TCL_OK;
  608. }
  609.  
  610.  
  611. EXTERN int
  612. Sndio_Init (
  613. Tcl_Interp *interp
  614. ) {
  615. Tcl_Namespace *ns;
  616. const ezt_subcmd_type *c;
  617. Tcl_Obj *o;
  618. Tcl_Obj *map;
  619.  
  620. if (TJsio_CommonInit(interp) != TCL_OK) { return TCL_ERROR; }
  621.  
  622. if ((ns = Tcl_FindNamespace(interp, TJSIO_NS, NULL, TCL_LEAVE_ERR_MSG)) == NULL) { return TCL_ERROR; }
  623. map = Tcl_NewDictObj();
  624. for (c = &TJsio_Cmds[0]; c->name != NULL; c++) {
  625. o = Tcl_ObjPrintf("%s%s", TJSIO_NS, c->name);
  626. Tcl_IncrRefCount(o);
  627. if (Tcl_CreateObjCommand(interp, Tcl_GetString(o), c->proc, NULL, NULL) == NULL) { Tcl_DecrRefCount(o); return TCL_ERROR; }
  628. Tcl_DictObjPut(interp, map, Tcl_NewStringObj(c->name, -1), o);
  629. Tcl_DecrRefCount(o);
  630. if (Tcl_Export(interp, ns, c->name, 0) != TCL_OK) { return TCL_ERROR; }
  631. }
  632. if (Tcl_SetEnsembleMappingDict(interp, Tcl_CreateEnsemble(interp, TJSIO_EN, ns, TCL_ENSEMBLE_PREFIX), map) != TCL_OK) { return TCL_ERROR; };
  633. if (Tcl_Export(interp, ns, TJSIO_EN, 0) != TCL_OK) { return TCL_ERROR; }
  634. return TCL_OK;
  635. }
  636.  
  637. EXTERN int
  638. Sndio_SafeInit (
  639. Tcl_Interp *interp
  640. ) {
  641. return TJsio_CommonInit(interp);
  642. }
  643. #endif
  644.  
  645.  
  646. #ifdef __cplusplus
  647. }
  648. #endif
  649.  
  650.  
  651. /* EOF */
  652.