annotate stitch/source.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
rev   line source
tomwalters@0 1 /*
tomwalters@0 2 source.c
tomwalters@0 3 ========
tomwalters@0 4
tomwalters@0 5 New super minimal source system.
tomwalters@0 6
tomwalters@0 7 John Holdsworth, 2nd January 1989.
tomwalters@0 8
tomwalters@0 9 edited: MAA 3-8-1993
tomwalters@0 10 new options "review_aid" and "frameno_aid"
tomwalters@0 11
tomwalters@0 12 */
tomwalters@0 13
tomwalters@0 14 #if 0
tomwalters@0 15
tomwalters@0 16 What is a Source?
tomwalters@0 17 =================
tomwalters@0 18
tomwalters@0 19 Sources are a suggested style for coding computational processes on
tomwalters@0 20 continuous data streams. Making the extra effort to code according to
tomwalters@0 21 this style allows such processes to be easilly cascaded while still
tomwalters@0 22 able to operate on data streams of indefinite length. This is done by
tomwalters@0 23 performing the processing of the data stream in segments and passing
tomwalters@0 24 intermediate results systematically between processing stages using a
tomwalters@0 25 simple convention.
tomwalters@0 26
tomwalters@0 27 A source is like a file, in that it specifies the source of stream of
tomwalters@0 28 data. The data can be read in segments of user-defined size, like
tomwalters@0 29 reading from a file. For example, the routines sread() and sseek()
tomwalters@0 30 operate on Sources the same way that fread() and fseek() operate on
tomwalters@0 31 file streams. (sseek() operations on sources can only move forward in
tomwalters@0 32 a data stream).
tomwalters@0 33
tomwalters@0 34 Sources are different from files in that they do not necessarilly
tomwalters@0 35 just read data from disk. A Source may generally be a transformation
tomwalters@0 36 of data, or some simple processing operation on data. In addition, the
tomwalters@0 37 data may originate in any way the user may specify. The data may come
tomwalters@0 38 from a previous (cascaded) "Source".
tomwalters@0 39
tomwalters@0 40 The structured type "Source" contains enough information to generate
tomwalters@0 41 a stream of data. One way of processing a stream of data is to perform
tomwalters@0 42 a simple data-processing operation on another stream of data.
tomwalters@0 43 The input stream can be specified using a source.
tomwalters@0 44 Composite data-processing functions can be built up by cascading a
tomwalters@0 45 number of elementary functions.
tomwalters@0 46
tomwalters@0 47 If data is processed in large enough segments, the overhead of
tomwalters@0 48 performing the processing task in stages is not significant.
tomwalters@0 49
tomwalters@0 50
tomwalters@0 51 How to use sources
tomwalters@0 52 ==================
tomwalters@0 53
tomwalters@0 54 There are two distinct phases in working with sources, analogous to
tomwalters@0 55 opening a file (eg fopen()), and reading the file (eg fread()).
tomwalters@0 56
tomwalters@0 57 The first phase uses "setup" functions, analogous to fopen().
tomwalters@0 58 (See io.c for sources which read from disk. See model.c for sources
tomwalters@0 59 which perform specialised auditory-modelling processes).
tomwalters@0 60 Setup functions always return a Source. They may take one or more
tomwalters@0 61 sources as arguments, as a specification of the input to the process
tomwalters@0 62 the source performs. The user may define his own setup routine for
tomwalters@0 63 any new process. This routine intialises the source structure with
tomwalters@0 64 a pointer to a callback function, which performs the data processing
tomwalters@0 65 when the source is used.
tomwalters@0 66
tomwalters@0 67 The second phase uses pull/fill/roll functions, analogous to fread().
tomwalters@0 68 Unlike the fread function, Sources do not require you to supply a
tomwalters@0 69 buffer for the data to be "read" into.
tomwalters@0 70 There are three types of operation that can be performed on sources
tomwalters@0 71 depending on whether the users wishes to supply the data buffer.
tomwalters@0 72 (These three operations are referred to as "methods", in the style of
tomwalters@0 73 object-oriented programming. Sources are thought of as "objects").
tomwalters@0 74
tomwalters@0 75 The Pull() method returns a pointer to a buffer which has been
tomwalters@0 76 allocated by the source itself.
tomwalters@0 77 In the following example, the buffer will contain the next 100 bytes
tomwalters@0 78 of processed data.
tomwalters@0 79
tomwalters@0 80 /* declarations */
tomwalters@0 81 char *buffer ;
tomwalters@0 82 Source source = OpenSource( somehow ) ;
tomwalters@0 83 ByteCount bytes = 100 ;
tomwalters@0 84
tomwalters@0 85 /* call to "pull" 100 bytes of data out of Source "source" */
tomwalters@0 86 buffer = Pull( source, bytes ) ;
tomwalters@0 87
tomwalters@0 88
tomwalters@0 89 If the user has a buffer available for data and would prefer the data
tomwalters@0 90 be directly tranfered into it, the Fill() method can be used instead of
tomwalters@0 91 the Pull() method. The Fill method returns the address of the buffer
tomwalters@0 92 the user provides in case it is of use for the programmer.
tomwalters@0 93
tomwalters@0 94 /* declarations */
tomwalters@0 95 char buffer[100] ;
tomwalters@0 96 Source source = OpenSource( somehow ) ;
tomwalters@0 97 ByteCount bytes = 100 ;
tomwalters@0 98
tomwalters@0 99 /* call to "fill" the user's buffer with 100 bytes of data */
tomwalters@0 100 (void) Fill( source, bytes, buffer ) ;
tomwalters@0 101
tomwalters@0 102
tomwalters@0 103 In addition there is one further method of calling data from a source
tomwalters@0 104 that works like Pull(), but keeps a given number of bytes from the
tomwalters@0 105 previous call in the buffer.
tomwalters@0 106 The pointer returned by roll points to the start of the new data, as
tomwalters@0 107 in pull, but the space immediately before the pointer is still valid
tomwalters@0 108 and contains a specified number of bytes of data kept from the previous
tomwalters@0 109 call.
tomwalters@0 110 Bytes at the end of the buffer can be kept for the following roll call.
tomwalters@0 111
tomwalters@0 112 /* declarations */
tomwalters@0 113 char *buffer ;
tomwalters@0 114 Source source = OpenSource( somehow ) ;
tomwalters@0 115 ByteCount bytes = 100 ;
tomwalters@0 116
tomwalters@0 117 /* call to "pull" 100 bytes of data out of Source "source" */
tomwalters@0 118 buffer = Roll( source, bytes, 50 ) ;
tomwalters@0 119
tomwalters@0 120 /* "pull" another 100 bytes out of the source. */
tomwalters@0 121 /* The last 50 bytes of the previous call will be kept in the */
tomwalters@0 122 /* buffer, and will immediately precede the new 100 bytes. */
tomwalters@0 123 buffer = Roll( source, &bytes, 50 ) ;
tomwalters@0 124
tomwalters@0 125
tomwalters@0 126 In order for Roll to work properly though it MUST be the only call
tomwalters@0 127 made on a given source. This is as it retains more information
tomwalters@0 128 between calls than the Pull() and Fill() methods.
tomwalters@0 129
tomwalters@0 130
tomwalters@0 131 More recent versions are defined as: PullSome, FillSome, RollSome.
tomwalters@0 132 In these methods, a pointer to the number of bytes (eg. &bytes) is
tomwalters@0 133 used, so that the source can indicate that less data was available
tomwalters@0 134 than was requested.
tomwalters@0 135
tomwalters@0 136 Remember also that requesting a negative number of bytes is interpreted
tomwalters@0 137 as requesting a skip without processing of the negative of that number
tomwalters@0 138 of bytes. This works as most processing sources will simply ignore
tomwalters@0 139 a request to process a negative number of bytes but will pass on the
tomwalters@0 140 request to their input sources which may which to actually act on the
tomwalters@0 141 skip operation.
tomwalters@0 142
tomwalters@0 143 More importantly A request for zero bytes it taken to mean that the
tomwalters@0 144 source is not required anymore and should close itself and free any
tomwalters@0 145 resources it is using. If the request is passed on to any input sources
tomwalters@0 146 a close operation cascades the close request to it's' input sources. This
tomwalters@0 147 means in order to close a cascade of process only the final source need be closed.
tomwalters@0 148 N.B. The close operation is only performed if the number of bytes requested is
tomwalters@0 149 zero not if the number of bytes returned is zero.
tomwalters@0 150
tomwalters@0 151
tomwalters@0 152
tomwalters@0 153 ...ctd jwh
tomwalters@0 154
tomwalters@0 155 Writing new sources
tomwalters@0 156 ===================
tomwalters@0 157
tomwalters@0 158 At the lowest level a source is a pointer to a struct which contains
tomwalters@0 159 pointers to three functions or methods to deal with the three types
tomwalters@0 160 of request that can be issued to a source. Pull(), Fill(),and Roll()
tomwalters@0 161 are #defines macros that convert the not quite C language calls into
tomwalters@0 162 full C calls passing the source pointer as the first argument then
tomwalters@0 163 the arguments the user specifies.
tomwalters@0 164
tomwalters@0 165 For example:
tomwalters@0 166
tomwalters@0 167 buffer = PullSome( source, bytes ) ;
tomwalters@0 168
tomwalters@0 169 Becomes:
tomwalters@0 170
tomwalters@0 171 buffer = source->methods->pull( source, bytes ) ;
tomwalters@0 172
tomwalters@0 173 The #define macros is used simply as a convienience.
tomwalters@0 174
tomwalters@0 175 The basic Source typedefs are as follows :
tomwalters@0 176
tomwalters@0 177 typedef struct _methods {
tomwalters@0 178 Pointer (*pull)(), (*fill)(), (*roll)() ;
tomwalters@0 179 } Methods ;
tomwalters@0 180 typedef struct _source {
tomwalters@0 181 Methods methods ; Pointer buffer ; ByteCount bsize, valid ;
tomwalters@0 182 } Source ;
tomwalters@0 183
tomwalters@0 184 All sources must point to a structure containing at least this information
tomwalters@0 185 for Pull(), Fill() and Roll() operations to work on all sources.
tomwalters@0 186
tomwalters@0 187 To create a source the user initialises a static variable of type struct _methods with
tomwalters@0 188 the three routines written to support the three basic source operations.
tomwalters@0 189 A pointer to this structure is then used to initialise the methods field of
tomwalters@0 190 the struct _source section of the source's' state. A pointer to this structure
tomwalters@0 191 becomes the new source.
tomwalters@0 192
tomwalters@0 193 The function setSource() is provided to perform this minimal setup of
tomwalters@0 194 a new source and to initialise the other fields in the source
tomwalters@0 195 structure. The pointer to the new Source structure is allocated outside
tomwalters@0 196 setSource and passed to it in order to alow the possibility of it containing
tomwalters@0 197 more than the basic source information.
tomwalters@0 198
tomwalters@0 199 #endif
tomwalters@0 200
tomwalters@0 201 #include <stdio.h> /* added: MAA 3-8-1993*/
tomwalters@0 202 #include "stitch.h"
tomwalters@0 203 #include "source.h"
tomwalters@0 204 #include "options.h" /* added: MAA 3-8-1993*/
tomwalters@0 205
tomwalters@0 206 #ifndef DEBUG
tomwalters@0 207 #define DEBUG 0
tomwalters@0 208 #endif
tomwalters@0 209
tomwalters@0 210
tomwalters@0 211 /*
tomwalters@0 212 initialise new Source structure
tomwalters@0 213
tomwalters@0 214 */
tomwalters@0 215
tomwalters@0 216 Source setSource( source, puller, filler, roller, name )
tomwalters@0 217 struct _source *source ;
tomwalters@0 218 Pointer (*puller)(), (*filler)(), (*roller)() ;
tomwalters@0 219 char *name ;
tomwalters@0 220 {
tomwalters@0 221 Source returned ;
tomwalters@0 222 Source (*opener)() = 0 ;
tomwalters@0 223
tomwalters@0 224 source->pull = puller ;
tomwalters@0 225 source->fill = filler ;
tomwalters@0 226 source->roll = roller ;
tomwalters@0 227 source->open = opener ;
tomwalters@0 228
tomwalters@0 229 source->type = "void" ;
tomwalters@0 230 source->name = name ;
tomwalters@0 231
tomwalters@0 232 source->opened = 0 ;
tomwalters@0 233 source->returned = (Pointer) 0 ;
tomwalters@0 234 #if DEBUG
tomwalters@0 235 printf( "Creating %s\n", SourceName( source ) ) ;
tomwalters@0 236 #endif
tomwalters@0 237 _SPTR( returned ) = source ;
tomwalters@0 238
tomwalters@0 239 return ( returned ) ;
tomwalters@0 240 }
tomwalters@0 241
tomwalters@0 242 Source typeSource( source, type )
tomwalters@0 243 Source source ;
tomwalters@0 244 char *type ;
tomwalters@0 245 {
tomwalters@0 246 _SPTR( source )->type = type ;
tomwalters@0 247
tomwalters@0 248 return ( source ) ;
tomwalters@0 249 }
tomwalters@0 250
tomwalters@0 251 char *sourceType( source )
tomwalters@0 252 Source source ;
tomwalters@0 253 {
tomwalters@0 254 return ( _SPTR( source )->type ) ;
tomwalters@0 255 }
tomwalters@0 256
tomwalters@0 257 char *sourceName( source )
tomwalters@0 258 Source source ;
tomwalters@0 259 {
tomwalters@0 260 return ( _SPTR( source )->name ) ;
tomwalters@0 261 }
tomwalters@0 262
tomwalters@0 263 Pointer deleteSource( source )
tomwalters@0 264 Source source ;
tomwalters@0 265 {
tomwalters@0 266 #if DEBUG
tomwalters@0 267 printf( "Deleteing %s\n", SourceName( source ) ) ;
tomwalters@0 268 #endif
tomwalters@0 269 Delete( source ) ;
tomwalters@0 270
tomwalters@0 271 return ( (Pointer) 0 ) ;
tomwalters@0 272 }
tomwalters@0 273
tomwalters@0 274
tomwalters@0 275 #if 00
tomwalters@0 276 struct _source_operators NameOfClass = {
tomwalters@0 277 setSource, deleteSource,
tomwalters@0 278 typeSource, sourceType,
tomwalters@0 279 sourceName
tomwalters@0 280 } ;
tomwalters@0 281 #endif
tomwalters@0 282
tomwalters@0 283
tomwalters@0 284 /* MAA: 3-8-1993 */
tomwalters@0 285
tomwalters@0 286 void sinkSource( source, framebytes, frames )
tomwalters@0 287 Source source ;
tomwalters@0 288 int framebytes ;
tomwalters@0 289 long frames ;
tomwalters@0 290 {
tomwalters@0 291 long frame ;
tomwalters@0 292
tomwalters@0 293
tomwalters@0 294 extern *reviewstr;
tomwalters@0 295 extern *framenumberstr;
tomwalters@0 296
tomwalters@0 297 for( frame=0 ; frame<frames ; frame++ ) {
tomwalters@0 298
tomwalters@0 299 if ( isON (framenumberstr) || isON (reviewstr) ){
tomwalters@0 300 fprintf(stderr, " %i ", frame+1);
tomwalters@0 301 fflush(stderr);}
tomwalters@0 302
tomwalters@0 303 (void) Pull( source, framebytes ) ;
tomwalters@0 304
tomwalters@0 305 if ( isON (reviewstr)) {
tomwalters@0 306 fflush(stdin);getchar();}
tomwalters@0 307 }
tomwalters@0 308 return ;
tomwalters@0 309 }
tomwalters@0 310
tomwalters@0 311
tomwalters@0 312
tomwalters@0 313 void CloseSource( source )
tomwalters@0 314 Source source ;
tomwalters@0 315 {
tomwalters@0 316 (void) Pull( source, 0 ) ;
tomwalters@0 317
tomwalters@0 318 return ;
tomwalters@0 319 }
tomwalters@0 320
tomwalters@0 321 void sinkAndCloseSource( source, framebytes, frames )
tomwalters@0 322 Source source ;
tomwalters@0 323 int framebytes ;
tomwalters@0 324 long frames ;
tomwalters@0 325 {
tomwalters@0 326 SinkSource( source, framebytes, frames ) ;
tomwalters@0 327
tomwalters@0 328 CloseSource( source ) ;
tomwalters@0 329
tomwalters@0 330 return ;
tomwalters@0 331 }
tomwalters@0 332
tomwalters@0 333 /* tapping derived source */
tomwalters@0 334
tomwalters@0 335 typedef struct {
tomwalters@0 336 struct _source parent ;
tomwalters@0 337 Pointer state ;
tomwalters@0 338 void (*callback)(), (*close)() ;
tomwalters@0 339 Source input ;
tomwalters@0 340 } *TappingSource ;
tomwalters@0 341
tomwalters@0 342 static Pointer tapping_callback( source, bytes, buffer, last )
tomwalters@0 343 TappingSource source ;
tomwalters@0 344 ByteCount *bytes ;
tomwalters@0 345 Pointer buffer ;
tomwalters@0 346 int last ;
tomwalters@0 347 {
tomwalters@0 348 source->callback( source->state, bytes, buffer, buffer+*bytes ) ;
tomwalters@0 349
tomwalters@0 350 if( !last )
tomwalters@0 351 return ( buffer ) ;
tomwalters@0 352 else {
tomwalters@0 353 if( source->close != (void ( * )()) 0 )
tomwalters@0 354 source->close( source->state ) ;
tomwalters@0 355
tomwalters@0 356 return ( DeleteSource( source ) ) ;
tomwalters@0 357 }
tomwalters@0 358 }
tomwalters@0 359
tomwalters@0 360 static Pointer tappingPuller( source, bytes )
tomwalters@0 361 TappingSource source ;
tomwalters@0 362 ByteCount *bytes ;
tomwalters@0 363 {
tomwalters@0 364 register int last = *bytes == 0 ;
tomwalters@0 365 Pointer buffer = PullSome( source->input, bytes ) ;
tomwalters@0 366
tomwalters@0 367 #if DEBUG
tomwalters@0 368 printf( "\"%s\" pull tapping %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
tomwalters@0 369 #endif
tomwalters@0 370
tomwalters@0 371 return ( tapping_callback( source, bytes, buffer, last ) ) ;
tomwalters@0 372 }
tomwalters@0 373
tomwalters@0 374 static Pointer tappingFiller( source, bytes, buffer )
tomwalters@0 375 TappingSource source ;
tomwalters@0 376 ByteCount *bytes ;
tomwalters@0 377 Pointer buffer ;
tomwalters@0 378 {
tomwalters@0 379 register int last = *bytes == 0 ;
tomwalters@0 380
tomwalters@0 381 FillSome( source->input, bytes, buffer ) ;
tomwalters@0 382
tomwalters@0 383 #if DEBUG
tomwalters@0 384 printf( "\"%s\" fill tapping %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
tomwalters@0 385 #endif
tomwalters@0 386
tomwalters@0 387 return ( tapping_callback( source, bytes, buffer, last ) ) ;
tomwalters@0 388 }
tomwalters@0 389
tomwalters@0 390 static Pointer tappingRoller( source, bytes, keep )
tomwalters@0 391 TappingSource source ;
tomwalters@0 392 ByteCount *bytes, keep ;
tomwalters@0 393 {
tomwalters@0 394 register int last = *bytes == 0 ;
tomwalters@0 395 Pointer buffer = RollSome( source->input, bytes, keep ) ;
tomwalters@0 396
tomwalters@0 397 #if DEBUG
tomwalters@0 398 printf( "\"%s\" roll tapping %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
tomwalters@0 399 #endif
tomwalters@0 400
tomwalters@0 401 return ( tapping_callback( source, bytes, buffer, last ) ) ;
tomwalters@0 402 }
tomwalters@0 403
tomwalters@0 404 Source newTappingSource( state, callback, close, input, name )
tomwalters@0 405 Pointer state ;
tomwalters@0 406 void (*callback)(), (*close)() ;
tomwalters@0 407 Source input ;
tomwalters@0 408 char *name ;
tomwalters@0 409 {
tomwalters@0 410 DeclareNew( TappingSource, source ) ;
tomwalters@0 411
tomwalters@0 412 source->state = state ;
tomwalters@0 413 source->callback = callback ;
tomwalters@0 414 source->close = close ;
tomwalters@0 415 source->input = input ;
tomwalters@0 416
tomwalters@0 417 return ( SetSource( source, tappingPuller, tappingFiller, tappingRoller, name ) ) ;
tomwalters@0 418 }
tomwalters@0 419
tomwalters@0 420 /* rollable derived source */
tomwalters@0 421
tomwalters@0 422 typedef struct {
tomwalters@0 423 struct _source parent ;
tomwalters@0 424 Pointer buffer ;
tomwalters@0 425 ByteCount bsize, valid ;
tomwalters@0 426 Source input ;
tomwalters@0 427 } *RollableSource ;
tomwalters@0 428
tomwalters@0 429 Pointer DeleteRollableSource( source )
tomwalters@0 430 RollableSource source ;
tomwalters@0 431 {
tomwalters@0 432 if( source->bsize != 0 )
tomwalters@0 433 Delete( source->buffer ) ;
tomwalters@0 434
tomwalters@0 435 return ( DeleteSource( source ) ) ;
tomwalters@0 436 }
tomwalters@0 437
tomwalters@0 438 static Pointer rollablePuller( source, bytes )
tomwalters@0 439 RollableSource source ;
tomwalters@0 440 ByteCount *bytes ;
tomwalters@0 441 {
tomwalters@0 442 #if DEBUG
tomwalters@0 443 printf( "rollable \"%s\" pulling %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
tomwalters@0 444 #endif
tomwalters@0 445
tomwalters@0 446 return ( RollSome( source->input, bytes, 0 ) ) ;
tomwalters@0 447 }
tomwalters@0 448
tomwalters@0 449 static Pointer rollableFiller( source, bytes, buffer )
tomwalters@0 450 RollableSource source ;
tomwalters@0 451 ByteCount *bytes ;
tomwalters@0 452 Pointer buffer ;
tomwalters@0 453 {
tomwalters@0 454 register int last = *bytes == 0 ;
tomwalters@0 455
tomwalters@0 456 FillSome( source->input, bytes, buffer ) ;
tomwalters@0 457
tomwalters@0 458 source->valid = *bytes ;
tomwalters@0 459
tomwalters@0 460 #if DEBUG
tomwalters@0 461 printf( "rollable \"%s\" filling %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
tomwalters@0 462 #endif
tomwalters@0 463
tomwalters@0 464 if( !last )
tomwalters@0 465 return ( buffer ) ;
tomwalters@0 466 else
tomwalters@0 467 return ( DeleteRollableSource( source ) ) ;
tomwalters@0 468 }
tomwalters@0 469
tomwalters@0 470 static Pointer rollableRoller( source, bytes, keep )
tomwalters@0 471 RollableSource source ;
tomwalters@0 472 ByteCount *bytes, keep ;
tomwalters@0 473 {
tomwalters@0 474 register int last = *bytes == 0 ;
tomwalters@0 475 Pointer oldBuffer = source->buffer ;
tomwalters@0 476 ByteCount toStore = *bytes + keep ;
tomwalters@0 477
tomwalters@0 478 if( source->bsize < toStore ) {
tomwalters@0 479
tomwalters@0 480 source->buffer = Allocate( toStore, "source.c for retaining buffer" ) ;
tomwalters@0 481
tomwalters@0 482 source->bsize = toStore ;
tomwalters@0 483 }
tomwalters@0 484
tomwalters@0 485 if( oldBuffer == (Pointer) 0 )
tomwalters@0 486 ZeroArray( (char *) source->buffer, keep ) ;
tomwalters@0 487 else {
tomwalters@0 488 CopyArray( (char *) oldBuffer+source->valid-keep, (char *) source->buffer, keep ) ;
tomwalters@0 489
tomwalters@0 490 if( oldBuffer != source->buffer )
tomwalters@0 491 Delete( oldBuffer ) ;
tomwalters@0 492 }
tomwalters@0 493
tomwalters@0 494 FillSome( source->input, bytes, source->buffer + keep ) ;
tomwalters@0 495
tomwalters@0 496 source->valid = keep + *bytes ;
tomwalters@0 497
tomwalters@0 498 if( !last )
tomwalters@0 499 return ( source->buffer + keep ) ;
tomwalters@0 500 else
tomwalters@0 501 return ( DeleteRollableSource( source ) ) ;
tomwalters@0 502 }
tomwalters@0 503
tomwalters@0 504 Source newRollableSource( input )
tomwalters@0 505 Source input ;
tomwalters@0 506 {
tomwalters@0 507 DeclareNew( RollableSource, source ) ;
tomwalters@0 508
tomwalters@0 509 source->buffer = (Pointer) 0 ;
tomwalters@0 510
tomwalters@0 511 source->bsize = 0 ;
tomwalters@0 512 source->valid = 0 ;
tomwalters@0 513
tomwalters@0 514 source->input = input ;
tomwalters@0 515
tomwalters@0 516 return ( SetSource( source, rollablePuller, rollableFiller, rollableRoller, "rollable" ) ) ;
tomwalters@0 517 }
tomwalters@0 518
tomwalters@0 519 /* all other sources don't support rolling */
tomwalters@0 520
tomwalters@0 521 Pointer nonRoller( source, bytes, keep )
tomwalters@0 522 Source source ;
tomwalters@0 523 ByteCount *bytes, keep ;
tomwalters@0 524 {
tomwalters@0 525 stitch_error( "Sorry rolling not availiable on source \"%s\"\n", SourceName( source ) ) ;
tomwalters@0 526
tomwalters@0 527 return ( Pull( source, bytes ) ) ;
tomwalters@0 528 }
tomwalters@0 529
tomwalters@0 530
tomwalters@0 531
tomwalters@0 532 /* for compatability */
tomwalters@0 533
tomwalters@0 534 typedef struct _auto_source {
tomwalters@0 535 struct _fillable_source parent ; Pointer state ; void (*callback)() ;
tomwalters@0 536 } *AutoSource ;
tomwalters@0 537
tomwalters@0 538 static Pointer autoFiller( source, bytes, buffer )
tomwalters@0 539 AutoSource source ;
tomwalters@0 540 ByteCount *bytes ;
tomwalters@0 541 Pointer buffer ;
tomwalters@0 542 {
tomwalters@0 543 register int last = *bytes == 0 ;
tomwalters@0 544
tomwalters@0 545 source->callback( source->state, *bytes, buffer ) ;
tomwalters@0 546
tomwalters@0 547 if( !last )
tomwalters@0 548 return ( buffer ) ;
tomwalters@0 549 else
tomwalters@0 550 return ( DeleteFillableSource( source ) ) ;
tomwalters@0 551 }
tomwalters@0 552
tomwalters@0 553 Source stdAutoSource( state, callback )
tomwalters@0 554 Pointer state ;
tomwalters@0 555 void (*callback)() ;
tomwalters@0 556 {
tomwalters@0 557 DeclareNew( AutoSource, source ) ;
tomwalters@0 558
tomwalters@0 559 source->state = state ;
tomwalters@0 560 source->callback = callback ;
tomwalters@0 561
tomwalters@0 562 return ( SetFillableSource( source, autoFiller, "stdAuto" ) ) ;
tomwalters@0 563 }
tomwalters@0 564
tomwalters@0 565 typedef struct _self_source {
tomwalters@0 566 struct _pullable_source parent ; Pointer state, (*callback)() ;
tomwalters@0 567 } *SelfSource ;
tomwalters@0 568
tomwalters@0 569 static Pointer selfGenerator( source, bytes )
tomwalters@0 570 SelfSource source ;
tomwalters@0 571 ByteCount *bytes ;
tomwalters@0 572 {
tomwalters@0 573 register int last = *bytes == 0 ;
tomwalters@0 574 Pointer ptr = source->callback( source->state, *bytes ) ;
tomwalters@0 575
tomwalters@0 576 if( !last )
tomwalters@0 577 return ( ptr ) ;
tomwalters@0 578 else
tomwalters@0 579 return ( DeleteSource( source ) ) ;
tomwalters@0 580 }
tomwalters@0 581
tomwalters@0 582 Source stdSelfSource( state, callback )
tomwalters@0 583 Pointer state ;
tomwalters@0 584 Pointer (*callback)() ;
tomwalters@0 585 {
tomwalters@0 586 DeclareNew( SelfSource, source ) ;
tomwalters@0 587
tomwalters@0 588 source->state = state ;
tomwalters@0 589 source->callback = callback ;
tomwalters@0 590
tomwalters@0 591 return ( SetPullableSource( source, selfGenerator, "stdSelf" ) ) ;
tomwalters@0 592 }
tomwalters@0 593
tomwalters@0 594 Source stdStaticSource( ptr )
tomwalters@0 595 Pointer ptr ;
tomwalters@0 596 {
tomwalters@0 597 return ( NewStaticSource( ptr ) ) ;
tomwalters@0 598 }
tomwalters@0 599
tomwalters@0 600 Source stdSlaveSource( source )
tomwalters@0 601 Source source ;
tomwalters@0 602 {
tomwalters@0 603 return ( NewSlaveSource( source ) ) ;
tomwalters@0 604 }
tomwalters@0 605
tomwalters@0 606 Pointer oldPull( source, bytes )
tomwalters@0 607 struct _source *source ;
tomwalters@0 608 ByteCount bytes ;
tomwalters@0 609 {
tomwalters@0 610 ByteCount tmp = bytes ;
tomwalters@0 611
tomwalters@0 612 return ( source->pull( source, &tmp ) ) ;
tomwalters@0 613 }
tomwalters@0 614
tomwalters@0 615 Pointer oldFill( source, bytes, buffer )
tomwalters@0 616 struct _source *source ;
tomwalters@0 617 ByteCount bytes ;
tomwalters@0 618 Pointer buffer ;
tomwalters@0 619 {
tomwalters@0 620 ByteCount tmp = bytes ;
tomwalters@0 621 Pointer bptr = buffer ;
tomwalters@0 622
tomwalters@0 623 do {
tomwalters@0 624 tmp = buffer + bytes - bptr ;
tomwalters@0 625
tomwalters@0 626 source->fill( source, &tmp, bptr ) ;
tomwalters@0 627 bptr += tmp ;
tomwalters@0 628
tomwalters@0 629 } while( bptr < buffer + bytes && tmp != 0 ) ;
tomwalters@0 630
tomwalters@0 631 return ( buffer ) ;
tomwalters@0 632 }
tomwalters@0 633
tomwalters@0 634 Pointer oldRoll( source, bytes, keep )
tomwalters@0 635 struct _source *source ;
tomwalters@0 636 ByteCount bytes, keep ;
tomwalters@0 637 {
tomwalters@0 638 ByteCount tmp = bytes ;
tomwalters@0 639
tomwalters@0 640 return ( source->roll( source, &tmp, keep ) ) ;
tomwalters@0 641 }
tomwalters@0 642
tomwalters@0 643 #if 00
tomwalters@0 644 static struct _source convertors = { oldPull, oldFill, oldRoll } ;
tomwalters@0 645 struct _source *call_conversions = &convertors ;
tomwalters@0 646 #endif
tomwalters@0 647
tomwalters@0 648 /* for binding multiple sources */
tomwalters@0 649
tomwalters@0 650 #if !defined(PC) && !defined(DSP32)
tomwalters@0 651 #include <varargs.h>
tomwalters@0 652
tomwalters@0 653 Source *BindSources( va_alist )
tomwalters@0 654 va_dcl
tomwalters@0 655 {
tomwalters@0 656 Source *inputs ;
tomwalters@0 657 va_list argp ;
tomwalters@0 658 int count, c ;
tomwalters@0 659
tomwalters@0 660 va_start( argp ) ;
tomwalters@0 661
tomwalters@0 662 for( count=0 ; _SPTR( va_arg( argp, Source ) ) != (struct _source *) 0 ; count++ )
tomwalters@0 663 ;
tomwalters@0 664
tomwalters@0 665 inputs = NewArray( Source, count+1, "for binding inputs in source.c" ) ;
tomwalters@0 666
tomwalters@0 667 va_end( argp ) ;
tomwalters@0 668 va_start( argp ) ;
tomwalters@0 669
tomwalters@0 670 for( c=0 ; c<=count ; c++ )
tomwalters@0 671 inputs[c] = va_arg( argp, Source ) ;
tomwalters@0 672
tomwalters@0 673 va_end( argp ) ;
tomwalters@0 674
tomwalters@0 675 return ( inputs ) ;
tomwalters@0 676 }
tomwalters@0 677 #endif
tomwalters@0 678
tomwalters@0 679 struct _source notRealySource ;
tomwalters@0 680
tomwalters@0 681 Source EmptySource ;