Changeset 4580:435fb7a75ea4 in roaraudio


Ignore:
Timestamp:
11/03/10 05:36:42 (13 years ago)
Author:
phi
Branch:
default
Phase:
public
Message:

added file mode to VS API (Closes: #3), still needs some tuning of the main loop

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • ChangeLog

    r4579 r4580  
    11v. 0.4beta2 - ? 
    22        * Announce standards via OpenSLP (Closes: #5) 
    3         * Updated VS API (Closes: #54) 
     3        * Updated VS API (Closes: #54, #3) 
    44 
    55v. 0.4beta1 - Mon Nov 01 2010 16:14 CET 
  • include/libroar/vs.h

    r4213 r4580  
    6868 */ 
    6969#define roar_vs_new_playback(s,n,r,c,e,b,error) roar_vs_new_simple((s), (n), (r), (c), (e), (b), ROAR_DIR_PLAY, (error)) 
     70 
     71 
     72/* Attach a open file. 
     73 */ 
     74 
     75int roar_vs_file(roar_vs_t * vss, struct roar_vio_calls * vio, int closefile, int * error); 
     76 
     77/* Open a file and attach it. 
     78 */ 
     79int roar_vs_file_simple(roar_vs_t * vss, char * filename, int * error); 
     80 
     81/* Connects to a server to just play a file. 
     82 */ 
     83roar_vs_t * roar_vs_new_from_file(const char * server, const char * name, char * filename, int * error); 
    7084 
    7185/* Boolean TRUE for VS functions */ 
     
    201215int     roar_vs_role          (roar_vs_t * vss, int role, int * error); 
    202216 
     217/* Run a single interation. 
     218 * This will try to read data from source, write it to the stream 
     219 * and flush the buffer in buffered mode. 
     220 * Returns -1 on error, 0 on EOF and positive true value on no error. 
     221 */ 
     222int     roar_vs_iterate       (roar_vs_t * vss, int wait, int * error); 
     223 
     224/* Iterate untill EOF or error. 
     225 * Very simple main loop. 
     226 * Returns 0 on no error and -1 on error. 
     227 */ 
     228int     roar_vs_run           (roar_vs_t * vss, int * error); 
     229 
    203230/* Get used connection object 
    204231 * This may be usefull if you want to use functions from the main API. 
  • libroar/vs.c

    r4579 r4580  
    3636#include "libroar.h" 
    3737 
    38 #define FLAG_NONE     0x0000 
    39 #define FLAG_STREAM   0x0001 
    40 #define FLAG_NONBLOCK 0x0002 
    41 #define FLAG_BUFFERED 0x0004 
     38#define FLAG_NONE      0x0000 
     39#define FLAG_STREAM    0x0001 
     40#define FLAG_NONBLOCK  0x0002 
     41#define FLAG_BUFFERED  0x0004 
     42#define FLAG_CLOSEFILE 0x0008 
     43#define FLAG_DIR_IN    0x1000 
     44#define FLAG_DIR_OUT   0x2000 
    4245 
    4346#define _initerr()  do { errno = 0; roar_err_clear(); } while(0) 
     
    5760 int                      mixerid; 
    5861 int                      first_primid; 
     62 struct roar_buffer     * readbuffer, * writebuffer; 
     63 struct roar_vio_calls    file_store; 
     64 struct roar_vio_calls  * file; 
    5965}; 
    6066 
     
    173179 vss->flags |= FLAG_STREAM; 
    174180 
     181 switch (dir) { 
     182  case ROAR_DIR_PLAY: vss->flags |= FLAG_DIR_OUT; break; 
     183 } 
     184 
    175185 return 0; 
    176186} 
     
    200210} 
    201211 
     212int roar_vs_file(roar_vs_t * vss, struct roar_vio_calls * vio, int closefile, int * error) { 
     213 _ckvss(-1); 
     214 
     215 if ( vio == NULL || (closefile != ROAR_VS_TRUE && closefile != ROAR_VS_FALSE)) { 
     216  _seterr(ROAR_ERROR_INVAL); 
     217  return -1; 
     218 } 
     219 
     220 if ( vss->file != NULL ) { 
     221  _seterr(ROAR_ERROR_INVAL); 
     222  return -1; 
     223 } 
     224 
     225 vss->file = vio; 
     226 if ( closefile == ROAR_VS_TRUE ) 
     227  vss->flags |= FLAG_CLOSEFILE; 
     228 
     229 return 0; 
     230} 
     231 
     232int roar_vs_file_simple(roar_vs_t * vss, char * filename, int * error) { 
     233 struct roar_vio_defaults def; 
     234 struct roar_vio_calls * file; 
     235 char buf[64]; 
     236 ssize_t ret; 
     237 int dir = O_RDONLY; 
     238 int codec; 
     239 
     240 _ckvss(-1); 
     241 
     242 if ( vss->file != NULL ) { 
     243  _seterr(ROAR_ERROR_INVAL); 
     244  return -1; 
     245 } 
     246 
     247 if ( vss->flags & FLAG_STREAM ) { 
     248  switch (vss->flags & (FLAG_DIR_IN|FLAG_DIR_OUT)) { 
     249   case FLAG_DIR_IN:  dir = O_WRONLY; break; 
     250   case FLAG_DIR_OUT: dir = O_RDONLY; break; 
     251   case FLAG_DIR_IN|FLAG_DIR_OUT: dir = O_RDWR; break; 
     252   default: return -1; 
     253  } 
     254 } 
     255 
     256 file = &(vss->file_store); 
     257 
     258 // TODO: FIXME: correct error handling bellow. 
     259 
     260 if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, dir, 0644) == -1 ) 
     261  return -11; 
     262 
     263 if ( roar_vio_open_dstr(file, filename, &def, 1) == -1 ) { 
     264  return -1; 
     265 } 
     266 
     267 if ( !(vss->flags & FLAG_STREAM) ) { 
     268  ret = roar_vio_read(file, buf, sizeof(buf)); 
     269 
     270  codec = roar_file_codecdetect(buf, ret); 
     271 
     272  if ( vss->info.codec == -1 ) { 
     273   roar_vio_close(file); 
     274   return -1; 
     275  } 
     276 
     277  memset(&(vss->info), 0, sizeof(vss->info)); 
     278 
     279  vss->info.rate     = ROAR_RATE_DEFAULT; 
     280  vss->info.channels = ROAR_CHANNELS_DEFAULT; 
     281  vss->info.codec    = codec; 
     282  vss->info.bits     = ROAR_BITS_DEFAULT; 
     283 
     284  if ( roar_vio_lseek(file, 0, SEEK_SET) != 0 ) { 
     285   roar_vio_close(file); 
     286   return -1; 
     287  } 
     288 
     289  ret = roar_vs_stream(vss, &(vss->info), ROAR_DIR_PLAY, error); 
     290 
     291  if ( ret == -1 ) { 
     292   roar_vio_close(file); 
     293   return -1; 
     294  } 
     295 } 
     296 
     297 if ( roar_vs_file(vss, file, ROAR_VS_TRUE, error) == -1 ) { 
     298  roar_vio_close(file); 
     299  return -1; 
     300 } 
     301 
     302 return 0; 
     303} 
     304 
     305roar_vs_t * roar_vs_new_from_file(const char * server, const char * name, char * filename, int * error) { 
     306 roar_vs_t * vss = roar_vs_new(server, name, error); 
     307 
     308 if ( vss == NULL ) 
     309  return NULL; 
     310 
     311 if ( roar_vs_file_simple(vss, filename, error) != 0 ) { 
     312  roar_vs_close(vss, ROAR_VS_TRUE, NULL); 
     313  return NULL; 
     314 } 
     315 
     316 return vss; 
     317} 
     318 
    202319int roar_vs_close(roar_vs_t * vss, int killit, int * error) { 
    203320 if ( killit != ROAR_VS_TRUE && killit != ROAR_VS_FALSE ) { 
     
    207324 
    208325 _ckvss(-1); 
     326 
     327 if ( vss->readbuffer != NULL ) 
     328  roar_buffer_free(vss->readbuffer); 
     329 if ( vss->writebuffer != NULL ) 
     330  roar_buffer_free(vss->writebuffer); 
     331 
     332 if ( vss->file != NULL && vss->flags & FLAG_CLOSEFILE ) 
     333  roar_vio_close(vss->file); 
    209334 
    210335 if ( vss->flags & FLAG_STREAM ) { 
     
    746871} 
    747872 
     873 
     874int     roar_vs_iterate       (roar_vs_t * vss, int wait, int * error) { 
     875 struct roar_vio_select vios[3]; 
     876 struct roar_vio_selecttv rtv = {.sec = 0, .nsec = 1}; 
     877 size_t len = 0; 
     878 ssize_t i; 
     879 ssize_t ret; 
     880 int can_read = 0, can_write = 0; 
     881 int can_flush_stream = 0, can_flush_file = 0; 
     882 int is_eof = 0; 
     883 void * data; 
     884 
     885 _ckvss(-1); 
     886 
     887 if ( wait != ROAR_VS_WAIT && wait != ROAR_VS_NOWAIT ) { 
     888  _seterr(ROAR_ERROR_INVAL); 
     889  return -1; 
     890 } 
     891 
     892 ROAR_VIO_SELECT_SETVIO(&(vios[len]), &(vss->vio), ((vss->flags & FLAG_DIR_IN  ? ROAR_VIO_SELECT_READ  : 0) | 
     893                                                    (vss->flags & FLAG_DIR_OUT ? ROAR_VIO_SELECT_WRITE : 0))); 
     894 vios[len].ud.vp = &(vss->vio); 
     895 len++; 
     896 
     897 ROAR_VIO_SELECT_SETVIO(&(vios[len]), roar_get_connection_vio2(vss->con), ROAR_VIO_SELECT_READ); 
     898 vios[len].ud.vp = vss->con; 
     899 len++; 
     900 
     901 
     902// TODO: FIXME: need to do two select()s so we can sleep more efficently and test for both directions. 
     903// for the moment we disable file direction and hope it will not block anyway... 
     904/* 
     905 if ( vss->file != NULL ) { 
     906  ROAR_VIO_SELECT_SETVIO(&(vios[len]), vss->file, ((vss->flags & FLAG_DIR_IN  ? ROAR_VIO_SELECT_WRITE : 0) | 
     907                                                   (vss->flags & FLAG_DIR_OUT ? ROAR_VIO_SELECT_READ  : 0))); 
     908  vios[len].ud.vp = vss->file; 
     909  len++; 
     910 } 
     911*/ 
     912 
     913 ret = roar_vio_select(vios, len, (wait == ROAR_VS_NOWAIT ? &rtv : NULL), NULL); 
     914 
     915// part 2 of above hack: 
     916// emulate read handle. 
     917  vios[len].ud.vp   = vss->file; 
     918  vios[len].eventsa = ROAR_VIO_SELECT_WRITE|ROAR_VIO_SELECT_READ;; 
     919  len++; 
     920 
     921 // no error here nor EOF. 
     922 if ( ret == 0 ) 
     923  return 1; 
     924 
     925 for (i = 0; i < len; i++) { 
     926  if ( !vios[i].eventsa ) 
     927   continue; 
     928 
     929  if ( vios[i].ud.vp == &(vss->vio) ) { 
     930   if ( vios[i].eventsa & ROAR_VIO_SELECT_READ ) 
     931    can_read++; 
     932 
     933   if ( vios[i].eventsa & ROAR_VIO_SELECT_WRITE ) { 
     934    can_write++; 
     935    can_flush_stream = 1; 
     936   } 
     937  } else if ( vios[i].ud.vp == vss->con ) { 
     938   roar_sync(vss->con); 
     939  } else if ( vios[i].ud.vp == vss->file ) { 
     940   if ( vios[i].eventsa & ROAR_VIO_SELECT_READ ) 
     941    can_write++; 
     942 
     943   if ( vios[i].eventsa & ROAR_VIO_SELECT_WRITE ) { 
     944    can_read++; 
     945    can_flush_file = 1; 
     946   } 
     947  } 
     948 } 
     949 
     950 // TODO: FIXME: Need to correct error handling here! 
     951 
     952 if ( can_flush_stream && vss->writebuffer != NULL ) { 
     953  if ( roar_buffer_get_data(vss->writebuffer, &data) == -1 ) 
     954   return -1; 
     955 
     956  if ( roar_buffer_get_len(vss->writebuffer, &len) == -1 ) 
     957   return -1; 
     958 
     959  ret = roar_vs_write(vss, data, len, error); 
     960 
     961  if ( ret == -1 ) { 
     962   return -1; 
     963  } else if ( ret == len ) { 
     964   roar_buffer_free(vss->writebuffer); 
     965   vss->writebuffer = NULL; 
     966  } else { 
     967   if ( roar_buffer_set_offset(vss->writebuffer, ret) == -1 ) 
     968    return -1; 
     969  } 
     970 } 
     971 
     972 if ( can_flush_file && vss->readbuffer != NULL ) { 
     973  if ( roar_buffer_get_data(vss->readbuffer, &data) == -1 ) 
     974   return -1; 
     975 
     976  if ( roar_buffer_get_len(vss->readbuffer, &len) == -1 ) 
     977   return -1; 
     978 
     979  ret = roar_vio_write(vss->file, data, len); 
     980 
     981  if ( ret == -1 ) { 
     982   return -1; 
     983  } else if ( ret == len ) { 
     984   roar_buffer_free(vss->readbuffer); 
     985   vss->readbuffer = NULL; 
     986  } else { 
     987   if ( roar_buffer_set_offset(vss->readbuffer, ret) == -1 ) 
     988    return -1; 
     989  } 
     990 } 
     991 
     992#define _READ_SIZE 1024 
     993 
     994 if ( can_read == 2 && vss->readbuffer == NULL ) { 
     995  if ( roar_buffer_new_data(&(vss->readbuffer), (len = _READ_SIZE), &data) == -1 )  
     996   return -1; 
     997 
     998  ret = roar_vs_read(vss, data, len, error); 
     999 
     1000  if ( ret == -1 ) { 
     1001   roar_buffer_free(vss->readbuffer); 
     1002   vss->readbuffer = NULL; 
     1003   return -1; 
     1004  } else if ( ret == 0 ) { 
     1005   is_eof = 1; 
     1006   roar_buffer_free(vss->readbuffer); 
     1007   vss->readbuffer = NULL; 
     1008  } else { 
     1009   len = ret; 
     1010   if ( roar_buffer_set_len(vss->readbuffer, len) == -1 ) 
     1011    return -1; 
     1012 
     1013   ret = roar_vio_write(vss->file, data, len); 
     1014 
     1015   if ( ret == -1 ) { 
     1016    return -1; 
     1017   } else if ( ret == len ) { 
     1018    roar_buffer_free(vss->readbuffer); 
     1019    vss->readbuffer = NULL; 
     1020   } else { 
     1021    if ( roar_buffer_set_offset(vss->readbuffer, ret) == -1 ) 
     1022     return -1; 
     1023   } 
     1024  } 
     1025 } 
     1026 
     1027 if ( can_write == 2 && vss->writebuffer == NULL ) { 
     1028  if ( roar_buffer_new_data(&(vss->writebuffer), (len = _READ_SIZE), &data) == -1 ) 
     1029   return -1; 
     1030 
     1031  ret = roar_vio_read(vss->file, data, len); 
     1032 
     1033  if ( ret == -1 ) { 
     1034   roar_buffer_free(vss->writebuffer); 
     1035   vss->readbuffer = NULL; 
     1036   return -1; 
     1037  } else if ( ret == 0 ) { 
     1038   is_eof = 1; 
     1039   roar_buffer_free(vss->writebuffer); 
     1040   vss->readbuffer = NULL; 
     1041  } else { 
     1042   if ( len != ret ) { 
     1043    len = ret; 
     1044    if ( roar_buffer_set_len(vss->readbuffer, len) == -1 ) 
     1045     return -1; 
     1046   } 
     1047 
     1048   ret = roar_vs_write(vss, data, len, error); 
     1049 
     1050   if ( ret == -1 ) { 
     1051    return -1; 
     1052   } else if ( ret == len ) { 
     1053    roar_buffer_free(vss->writebuffer); 
     1054    vss->writebuffer = NULL; 
     1055   } else { 
     1056    if ( roar_buffer_set_offset(vss->writebuffer, ret) == -1 ) 
     1057     return -1; 
     1058   } 
     1059  } 
     1060 } 
     1061 
     1062 return is_eof ? 0 : 1; 
     1063} 
     1064 
     1065int     roar_vs_run           (roar_vs_t * vss, int * error) { 
     1066 int ret; 
     1067 
     1068 _ckvss(-1); 
     1069 
     1070 while ((ret = roar_vs_iterate(vss, ROAR_VS_WAIT, error)) > 0); 
     1071 
     1072 if ( ret == 0 ) { 
     1073  // flush buffers: 
     1074  roar_vs_iterate(vss, ROAR_VS_WAIT, error); 
     1075 } 
     1076 
     1077 return ret; 
     1078} 
     1079 
     1080 
    7481081struct roar_connection * roar_vs_connection_obj(roar_vs_t * vss, int * error) { 
    7491082 _ckvss(NULL); 
Note: See TracChangeset for help on using the changeset viewer.