Changeset 3971:370e1268ac0e in roaraudio for libroar/vio_buffer.c
- Timestamp:
- 06/26/10 13:52:29 (14 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libroar/vio_buffer.c
r3969 r3971 36 36 #include "libroar.h" 37 37 38 int roar_vio_open_buffer (struct roar_vio_calls * calls, struct roar_vio_calls * dst, ssize_t minsize, int use_re) { 39 struct roar_vio_buffer * self;; 40 41 if ( calls == NULL || dst == NULL ) 42 return -1; 43 44 if ( (self = roar_mm_malloc(sizeof(struct roar_vio_buffer))) == NULL ) 45 return -1; 46 47 memset(self, 0, sizeof(struct roar_vio_buffer)); 48 49 self->backend = dst; 50 self->min_bufsize = minsize; 51 self->use_re = use_re; 52 53 if ( use_re ) { 54 if ( roar_vio_open_re(&(self->re_vio), dst) == -1 ) { 55 roar_mm_free(self); 56 return -1; 57 } 58 } 59 60 memset(calls, 0, sizeof(struct roar_vio_calls)); 61 62 calls->inst = self; 63 calls->close = roar_vio_buffer_close; 64 calls->write = roar_vio_buffer_write; 65 calls->nonblock = roar_vio_buffer_nonblock; 66 calls->ctl = roar_vio_buffer_ctl; 67 calls->sync = roar_vio_buffer_sync; 68 calls->lseek = roar_vio_buffer_lseek; 69 70 return 0; 71 } 72 73 int roar_vio_buffer_close (struct roar_vio_calls * vio) { 74 struct roar_vio_buffer * self = vio->inst; 75 int ret; 76 77 if ( self->buf_old != NULL ) 78 roar_buffer_free(self->buf_old); 79 80 if ( self->buf_cur != NULL ) 81 roar_buffer_free(self->buf_cur); 82 83 if ( self->use_re ) { 84 ret = roar_vio_close(&(self->re_vio)); 85 } else { 86 ret = roar_vio_close(self->backend); 87 } 88 89 roar_mm_free(self); 90 91 return ret; 92 } 93 94 ssize_t roar_vio_buffer_read (struct roar_vio_calls * vio, void *buf, size_t count); 95 96 int roar_vio_buffer_sync (struct roar_vio_calls * vio) { 97 struct roar_vio_buffer * self = vio->inst; 98 struct roar_vio_calls * backend; 99 off_t dst = 0; 100 101 if ( self->use_re ) { 102 backend = &(self->re_vio); 103 } else { 104 backend = self->backend; 105 } 106 107 // bring backend in sync state, if this fails we do not need to continue... 108 if ( self->use_re ) { 109 if ( roar_vio_sync(backend) == -1 ) 110 return -1; 111 } else { 112 if ( roar_vio_sync(backend) == -1 ) 113 return -1; 114 } 115 116 if ( self->buf_old == NULL && self->buf_cur == NULL ) 117 return 0; // we are in sync in case no buffers are currently used. 118 119 if (self->buf_old != NULL && self->buf_cur == NULL ) { 120 // we just finished the segment 121 roar_buffer_free(self->buf_old); 122 return 0; 123 } 124 125 // calc seek pos: 126 if ( self->offset.is_old ) { 127 dst = (self->len_cur + self->len_old) - self->offset.offset; 128 } else { 129 dst = self->len_cur - self->offset.offset; 130 } 131 132 dst = -dst; 133 134 // do the seek: 135 if ( roar_vio_lseek(backend, dst, SEEK_CUR) == (off_t)-1 ) 136 return -1; 137 138 // free all internal buffers: 139 if ( self->buf_old != NULL ) 140 roar_buffer_free(self->buf_old); 141 142 if ( self->buf_cur != NULL ) 143 roar_buffer_free(self->buf_cur); 144 145 self->offset.is_old = 0; 146 self->offset.offset = 0; 147 148 // funally bring the backend in sync state again, to be sure all changes are done. 149 if ( self->use_re ) { 150 if ( roar_vio_sync(backend) == -1 ) 151 return -1; 152 } else { 153 if ( roar_vio_sync(backend) == -1 ) 154 return -1; 155 } 156 157 return 0; 158 } 159 160 off_t roar_vio_buffer_lseek (struct roar_vio_calls * vio, off_t offset, int whence) { 161 struct roar_vio_buffer * self = vio->inst; 162 size_t newoff; 163 off_t ret; 164 off_t invoff; 165 166 // in-memory seeking is only supported for SEEK_CUR: 167 if ( whence == SEEK_CUR ) { 168 if ( offset == 0 ) { 169 return 0; 170 } else if ( offset > 0 ) { 171 newoff = self->offset.offset + offset; 172 173 if ( self->offset.is_old ) { 174 if ( newoff == self->len_old ) { 175 self->offset.is_old = 0; 176 self->offset.offset = 0; 177 self->abspos += offset; 178 return self->abspos; 179 } else if ( newoff < self->len_old ) { 180 self->offset.offset = newoff; 181 self->abspos += offset; 182 return self->abspos; 183 } else if ( newoff > self->len_old ) { 184 if ( newoff < (self->len_old + self->len_cur ) ) { 185 self->offset.is_old = 0; 186 self->offset.offset = offset + self->offset.offset - self->len_old; 187 self->abspos += offset; 188 return self->abspos; 189 } 190 } 191 } else { 192 if ( newoff == self->len_cur ) { 193 roar_buffer_free(self->buf_old); 194 self->buf_old = self->buf_cur; 195 self->buf_cur = NULL; 196 self->offset.offset = 0; 197 self->abspos += offset; 198 return self->abspos; 199 } else if ( newoff < self->len_cur ) { 200 self->offset.offset = newoff; 201 self->abspos += offset; 202 return self->abspos; 203 } 204 } 205 } else { 206 invoff = -offset; 207 208 if ( invoff <= self->offset.offset ) { 209 self->offset.offset = 0; 210 self->abspos -= invoff; 211 return self->abspos; 212 } 213 214 if ( !self->offset.is_old ) { 215 if ( invoff > self->offset.offset ) { 216 if ( invoff <= (self->len_old + self->offset.offset) ) { 217 self->offset.is_old = 1; 218 self->offset.offset = (self->len_old + self->offset.offset) - invoff; 219 self->abspos -= invoff; 220 return self->abspos; 221 } 222 } 223 } 224 } 225 } 226 227 // we need to do a physical seek; 228 // get in sync with current possition, flush all buffers,... 229 if ( roar_vio_buffer_sync(vio) == -1 ) 230 return -1; 231 232 // do the seek: 233 if ( self->use_re ) { 234 ret = roar_vio_lseek(&(self->re_vio), offset, whence); 235 } else { 236 ret = roar_vio_lseek(self->backend, offset, whence); 237 } 238 239 if (ret != (off_t)-1) 240 self->abspos = ret; 241 242 return ret; 243 } 244 245 int roar_vio_buffer_ctl (struct roar_vio_calls * vio, int cmd, void * data) { 246 struct roar_vio_buffer * self; 247 248 if (vio == NULL || cmd == -1) 249 return -1; 250 251 ROAR_DBG("roar_vio_buffer_ctl(vio=%p, cmd=0x%.8x, data=%p) = ?", vio, cmd, data); 252 253 self = vio->inst; 254 255 switch (cmd) { 256 case ROAR_VIO_CTL_GET_NAME: 257 if ( data == NULL ) 258 return -1; 259 260 *(char**)data = "buffer"; 261 return 0; 262 break; 263 case ROAR_VIO_CTL_GET_NEXT: 264 if ( self->use_re ) { 265 *(struct roar_vio_calls **)data = &(self->re_vio); 266 } else { 267 *(struct roar_vio_calls **)data = self->backend; 268 } 269 return 0; 270 break; 271 case ROAR_VIO_CTL_SET_NEXT: 272 if ( self->use_re ) { 273 return roar_vio_ctl(&(self->re_vio), ROAR_VIO_CTL_SET_NEXT, data); 274 } else { 275 self->backend = *(struct roar_vio_calls **)data; 276 } 277 return 0; 278 break; 279 } 280 281 return roar_vio_ctl((struct roar_vio_calls *) vio->inst, cmd, data); 282 } 283 284 ssize_t roar_vio_buffer_write (struct roar_vio_calls * vio, void *buf, size_t count) { 285 struct roar_vio_buffer * self = vio->inst; 286 287 if ( self->use_re ) { 288 return roar_vio_write(&(self->re_vio), buf, count); 289 } else { 290 return roar_vio_write(self->backend, buf, count); 291 } 292 } 293 294 int roar_vio_buffer_nonblock(struct roar_vio_calls * vio, int state) { 295 struct roar_vio_buffer * self = vio->inst; 296 297 if ( self->use_re ) { 298 return roar_vio_nonblock(&(self->re_vio), state); 299 } else { 300 return roar_vio_nonblock(self->backend, state); 301 } 302 } 303 38 304 //ll
Note: See TracChangeset
for help on using the changeset viewer.