1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
29 // authors: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
32 //-----------------------------------------------------------------------------
34 #include "chuck_instr.h"
35 #include "chuck_bbq.h"
36 #include "chuck_errmsg.h"
41 #if defined(__WINDOWS_DS__) && !defined(__WINDOWS_PTHREAD__)
50 //-----------------------------------------------------------------------------
51 // name: class Chuck_VM_Frame
53 //-----------------------------------------------------------------------------
60 Chuck_VM_Frame() { size
= 0; }
67 //-----------------------------------------------------------------------------
68 // name: class Chuck_VM_Func
70 //-----------------------------------------------------------------------------
75 Chuck_VM_Frame
* frame
;
79 Chuck_VM_Func() { code
= NULL
; frame
= NULL
; index
= 0; }
86 //-----------------------------------------------------------------------------
87 // name: class Chuck_VM_FTable
88 // desc: function table
89 //-----------------------------------------------------------------------------
97 Chuck_VM_Func
* get_func( t_CKUINT index
);
98 t_CKUINT
append( Chuck_VM_Func
* f
);
99 t_CKBOOL
remove( t_CKUINT index
);
102 vector
<Chuck_VM_Func
*> func_table
;
108 //-----------------------------------------------------------------------------
111 //-----------------------------------------------------------------------------
129 //-----------------------------------------------------------------------------
132 //-----------------------------------------------------------------------------
133 Chuck_VM::~Chuck_VM()
135 if( m_init
) shutdown();
140 UGEN_TICK
__dac_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
141 { *out
= in
; return TRUE
; }
142 UGEN_TICK
__bunghole_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
143 { *out
= 0.0f
; return TRUE
; }
147 #ifdef __MACOSX_CORE__
148 t_CKINT
Chuck_VM::our_priority
= 95;
150 t_CKINT
Chuck_VM::our_priority
= 0x7fffffff;
154 #ifndef __WINDOWS_DS__
155 //-----------------------------------------------------------------------------
156 // name: set_priority()
158 //-----------------------------------------------------------------------------
159 t_CKBOOL
Chuck_VM::set_priority( t_CKINT priority
, Chuck_VM
* vm
)
161 struct sched_param param
;
162 pthread_t tid
= pthread_self();
165 if( pthread_getschedparam( tid
, &policy
, ¶m
) )
168 vm
->m_last_error
= "could not get current scheduling parameters";
173 param
.sched_priority
= priority
;
177 if( pthread_setschedparam( tid
, policy
, ¶m
) )
180 vm
->m_last_error
= "could not set new scheduling parameters";
187 //-----------------------------------------------------------------------------
188 // name: set_priority()
190 //-----------------------------------------------------------------------------
191 t_CKBOOL
Chuck_VM::set_priority( t_CKINT priority
, Chuck_VM
* vm
)
193 // if priority is 0, then do nothing
197 // set the priority class of the process
198 // if( !SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
201 // set the priority the thread
202 if( !SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
) )
205 vm
->m_last_error
= "could not set new scheduling parameters";
216 //-----------------------------------------------------------------------------
217 // name: initialize()
219 //-----------------------------------------------------------------------------
220 t_CKBOOL
Chuck_VM::initialize( t_CKBOOL enable_audio
, t_CKBOOL halt
, t_CKUINT srate
,
221 t_CKUINT buffer_size
, t_CKUINT num_buffers
,
222 t_CKUINT dac
, t_CKUINT adc
, t_CKINT priority
)
226 m_last_error
= "VM already initialized!";
230 //#ifndef __WINDOWS_DS__
231 // boost thread priority
232 if( priority
!= 0x7fffffff && !set_priority( priority
, this ) )
239 m_audio
= enable_audio
;
241 // allocate shreduler
242 m_shreduler
= new Chuck_VM_Shreduler
;
243 m_shreduler
->bbq
= m_audio
? m_bbq
: NULL
;
245 // allocate msg buffer
246 m_msg_buffer
= new CBuffer
;
247 m_msg_buffer
->initialize( 1024, sizeof(Chuck_Msg
*) );
248 m_reply_buffer
= new CBuffer
;
249 m_reply_buffer
->initialize( 1024, sizeof(Chuck_Msg
*) );
251 // allocate dac and adc
252 m_num_dac_channels
= 2;
253 m_dac
= new Chuck_UGen
[2];
254 m_dac
[0].tick
= __dac_tick
;
255 m_dac
[1].tick
= __dac_tick
;
256 m_num_adc_channels
= 2;
257 m_adc
= new Chuck_UGen
[2];
258 m_bunghole
= new Chuck_UGen
;
259 m_dac
[0].add_ref(); m_dac
[1].add_ref();
260 m_adc
[0].add_ref(); m_adc
[1].add_ref();
261 m_bunghole
->add_ref();
262 m_shreduler
->m_dac
= m_dac
;
263 m_shreduler
->m_adc
= m_adc
;
264 m_shreduler
->m_bunghole
= m_bunghole
;
265 m_shreduler
->m_num_dac_channels
= m_num_dac_channels
;
266 m_shreduler
->m_num_adc_channels
= m_num_adc_channels
;
271 if( !m_bbq
->initialize( 2, srate
, 16, buffer_size
, num_buffers
, dac
, adc
) )
273 m_last_error
= "cannot initialize audio device (try using --silent/-s)";
279 // at least set the sample rate and buffer size
280 m_bbq
->set_srate( srate
);
281 m_bbq
->set_bufsize( buffer_size
);
284 // m_bbq->midi_out()->open( 0 );
285 // m_bbq->midi_in()->open( 0 );
287 return m_init
= TRUE
;
293 //-----------------------------------------------------------------------------
296 //-----------------------------------------------------------------------------
297 t_CKBOOL
Chuck_VM::shutdown()
299 // make sure we are in the initialized state
300 if( !m_init
) return FALSE
;
309 // free the shreduler
310 SAFE_DELETE( m_shreduler
);
313 Chuck_VM_Shred
* curr
= m_shreds
, * prev
= NULL
;
326 m_bbq
->digi_out()->cleanup();
327 m_bbq
->digi_in()->cleanup();
329 SAFE_DELETE( m_bbq
);
341 //-----------------------------------------------------------------------------
344 //-----------------------------------------------------------------------------
345 t_CKBOOL
Chuck_VM::run( )
348 Chuck_VM_Shred
* shred
= NULL
;
349 Chuck_Msg
* msg
= NULL
;
354 if( !m_bbq
->digi_out()->initialize( ) )
356 m_last_error
= "cannot open audio output (option: use --silent/-s)";
360 m_bbq
->digi_in()->initialize( );
361 m_bbq
->digi_out()->start();
362 m_bbq
->digi_in()->start();
367 // get the shreds queued for 'now'
368 while( shred
= m_shreduler
->get() )
370 // set the current time of the shred
371 shred
->now
= shred
->wake_time
;
374 if( !shred
->run( this ) )
376 this->free( shred
, TRUE
);
378 if( !m_num_shreds
&& m_halt
) goto vm_stop
;
382 // advance the shreduler
383 m_shreduler
->advance();
386 while( m_msg_buffer
->get( &msg
, 1 ) )
400 //-----------------------------------------------------------------------------
403 //-----------------------------------------------------------------------------
404 t_CKBOOL
Chuck_VM::pause( )
414 //-----------------------------------------------------------------------------
417 //-----------------------------------------------------------------------------
418 t_CKBOOL
Chuck_VM::stop( )
421 Digitalio::m_end
= TRUE
;
429 //-----------------------------------------------------------------------------
432 //-----------------------------------------------------------------------------
433 void Chuck_VM::gc( t_CKUINT amount
)
440 //-----------------------------------------------------------------------------
443 //-----------------------------------------------------------------------------
451 //-----------------------------------------------------------------------------
454 //-----------------------------------------------------------------------------
455 t_CKBOOL
Chuck_VM::queue_msg( Chuck_Msg
* msg
, int count
)
457 m_msg_buffer
->put( &msg
, count
);
464 //-----------------------------------------------------------------------------
467 //-----------------------------------------------------------------------------
468 Chuck_Msg
* Chuck_VM::get_reply( )
470 Chuck_Msg
* msg
= NULL
;
471 m_reply_buffer
->get( &msg
, 1 );
478 //-----------------------------------------------------------------------------
479 // name: process_msg()
481 //-----------------------------------------------------------------------------
482 t_CKUINT
Chuck_VM::process_msg( Chuck_Msg
* msg
)
484 t_CKUINT retval
= 0xfffffff0;
486 if( msg
->type
== MSG_REPLACE
)
488 Chuck_VM_Shred
* out
= m_shreduler
->lookup( msg
->param
);
491 EM_error3( "[chuck](VM): error replacing shred: no shred with id %i...",
497 Chuck_VM_Shred
* shred
= msg
->shred
;
500 shred
= new Chuck_VM_Shred
;
501 shred
->initialize( msg
->code
);
502 shred
->name
= msg
->code
->name
;
504 // set the current time
505 shred
->start
= m_shreduler
->now_system
;
507 shred
->id
= msg
->param
;
510 if( m_shreduler
->replace( out
, shred
) )
512 EM_error3( "[chuck](VM): replacing shred %i (%s) with %i (%s)...",
513 out
->id
, mini(out
->name
.c_str()), shred
->id
, mini(shred
->name
.c_str()) );
514 this->free( out
, TRUE
, FALSE
);
520 EM_error3( "[chuck](VM): shreduler ERROR replacing shred %i...",
527 else if( msg
->type
== MSG_REMOVE
)
529 if( msg
->param
== 0xffffffff )
531 if( !this->m_num_shreds
)
533 EM_error3( "[chuck](VM): no shreds to remove..." );
538 t_CKUINT id
= m_shred_id
;
539 Chuck_VM_Shred
* shred
= NULL
;
540 while( id
>= 0 && m_shreduler
->remove( shred
= m_shreduler
->lookup( id
) ) == 0 )
544 EM_error3( "[chuck](VM): removing recent shred: %i (%s)...",
545 id
, mini(shred
->name
.c_str()) );
546 this->free( shred
, TRUE
);
551 EM_error3( "[chuck](VM): no shreds removed..." );
558 Chuck_VM_Shred
* shred
= m_shreduler
->lookup( msg
->param
);
561 EM_error3( "[chuck](VM): cannot remove: no shred with id %i...",
566 if( !m_shreduler
->remove( m_shreduler
->lookup( msg
->param
) ) )
568 EM_error3( "[chuck](VM): shreduler: cannot remove shred %i...",
573 EM_error3( "[chuck](VM): removing shred: %i (%s)...",
574 msg
->param
, mini(shred
->name
.c_str()) );
575 this->free( shred
, TRUE
);
579 else if( msg
->type
== MSG_REMOVEALL
)
581 t_CKUINT id
= m_shred_id
;
582 EM_error3( "[chuck](VM): removing all (%i) shreds...", m_num_shreds
);
583 Chuck_VM_Shred
* shred
= NULL
;
585 while( m_num_shreds
&& id
>= 0 )
587 if( m_shreduler
->remove( shred
= m_shreduler
->lookup( id
) ) )
595 else if( msg
->type
== MSG_ADD
)
598 if( msg
->shred
) id
= this->spork( msg
->shred
)->id
;
599 else id
= this->spork( msg
->code
, NULL
)->id
;
601 const char * s
= ( msg
->shred
? msg
->shred
->name
.c_str() : msg
->code
->name
.c_str() );
602 EM_error3( "[chuck](VM): sporking incoming shred: %i (%s)...", id
, mini(s
) );
606 else if( msg
->type
== MSG_KILL
)
608 EM_error3( "[chuck](VM): KILL received...." );
611 else if( msg
->type
== MSG_STATUS
)
613 m_shreduler
->status();
615 else if( msg
->type
== MSG_TIME
)
617 float srate
= (float)Digitalio::sampling_rate();
618 fprintf( stderr
, "[chuck](VM): the values of now:\n" );
619 fprintf( stderr
, " now = %i (samp)\n", m_shreduler
->now_system
);
620 fprintf( stderr
, " = %.6f (second)\n", m_shreduler
->now_system
/ srate
);
621 fprintf( stderr
, " = %.6f (minute)\n", m_shreduler
->now_system
/ srate
/ 60.0f
);
622 fprintf( stderr
, " = %.6f (hour)\n", m_shreduler
->now_system
/ srate
/ 60.0f
/ 60.0f
);
623 fprintf( stderr
, " = %.6f (day)\n", m_shreduler
->now_system
/ srate
/ 60.0f
/ 60.0f
/ 24.0f
);
624 fprintf( stderr
, " = %.6f (week)\n", m_shreduler
->now_system
/ srate
/ 60.0f
/ 60.0f
/ 24.0f
/ 7.0f
);
631 msg
->replyA
= retval
;
632 m_reply_buffer
->put( &msg
, 1 );
643 //-----------------------------------------------------------------------------
646 //-----------------------------------------------------------------------------
647 t_CKUINT
Chuck_VM::next_id( )
655 //-----------------------------------------------------------------------------
658 //-----------------------------------------------------------------------------
659 Chuck_VM_Shreduler
* Chuck_VM::shreduler( ) const
667 //-----------------------------------------------------------------------------
670 //-----------------------------------------------------------------------------
671 BBQ
* Chuck_VM::bbq( ) const
679 //-----------------------------------------------------------------------------
682 //-----------------------------------------------------------------------------
683 t_CKUINT
Chuck_VM::srate() const
685 return (t_CKUINT
)Digitalio::sampling_rate();
691 //-----------------------------------------------------------------------------
694 //-----------------------------------------------------------------------------
695 Chuck_VM_Shred
* Chuck_VM::fork( Chuck_VM_Code
* code
)
703 //-----------------------------------------------------------------------------
706 //-----------------------------------------------------------------------------
707 Chuck_VM_Shred
* Chuck_VM::spork( Chuck_VM_Code
* code
, Chuck_VM_Shred
* parent
)
709 // allocate a new shred
710 Chuck_VM_Shred
* shred
= new Chuck_VM_Shred
;
711 // initialize the shred (default stack size)
712 shred
->initialize( code
);
714 shred
->name
= code
->name
;
716 shred
->parent
= parent
;
718 this->spork( shred
);
726 //-----------------------------------------------------------------------------
729 //-----------------------------------------------------------------------------
730 Chuck_VM_Shred
* Chuck_VM::spork( Chuck_VM_Shred
* shred
)
732 // set the current time
733 shred
->start
= m_shreduler
->now_system
;
735 shred
->now
= shred
->wake_time
= m_shreduler
->now_system
;
737 shred
->id
= next_id();
738 // add it to the parent
740 shred
->parent
->children
[shred
->id
] = shred
;
742 m_shreduler
->shredule( shred
);
752 //-----------------------------------------------------------------------------
755 //-----------------------------------------------------------------------------
756 t_CKBOOL
Chuck_VM::free( Chuck_VM_Shred
* shred
, t_CKBOOL cascade
, t_CKBOOL dec
)
761 shred
->is_done
= TRUE
;
764 t_CKINT size
= shred
->children
.size();
767 vector
<Chuck_VM_Shred
*> list
; list
.resize( size
);
768 map
<t_CKUINT
, Chuck_VM_Shred
*>::iterator iter
; t_CKINT i
= 0;
769 for( iter
= shred
->children
.begin(); iter
!= shred
->children
.end(); iter
++ )
770 list
[i
++] = (*iter
).second
;
771 for( i
= 0; i
< size
; i
++ )
772 this->free( list
[i
], cascade
);
775 // make sure it's done
776 assert( shred
->children
.size() == 0 );
780 shred
->parent
->children
.erase( shred
->id
);
783 m_shreduler
->remove( shred
);
784 SAFE_DELETE( shred
);
785 if( dec
) m_num_shreds
--;
786 if( !m_num_shreds
) m_shred_id
= 0;
794 //-----------------------------------------------------------------------------
797 //-----------------------------------------------------------------------------
798 Chuck_DLL
* Chuck_VM::dll_load( const char * path
, const char * id
)
800 Chuck_DLL
* dll
= m_dlls
[path
];
803 dll
= new Chuck_DLL(id
);
804 if( !dll
) return NULL
;
807 if( !dll
->load( path
) )
809 m_last_error
= dll
->last_error();
823 //-----------------------------------------------------------------------------
824 // name: dll_unload()
826 //-----------------------------------------------------------------------------
827 t_CKBOOL
Chuck_VM::dll_unload( Chuck_DLL
*& dll
)
829 if( !dll
) return TRUE
;
842 //-----------------------------------------------------------------------------
845 //-----------------------------------------------------------------------------
846 void Chuck_VM::dll_clear()
848 map
<string
, Chuck_DLL
*>::iterator iter
;
849 for( iter
= m_dlls
.begin(); iter
!= m_dlls
.end(); iter
++ )
851 (*iter
).second
->unload();
852 delete (*iter
).second
;
861 //-----------------------------------------------------------------------------
862 // name: Chuck_VM_Stack()
864 //-----------------------------------------------------------------------------
865 Chuck_VM_Stack::Chuck_VM_Stack()
867 stack
= sp
= sp_max
= NULL
;
875 //-----------------------------------------------------------------------------
876 // name: ~Chuck_VM_Stack()
878 //-----------------------------------------------------------------------------
879 Chuck_VM_Stack::~Chuck_VM_Stack()
887 //-----------------------------------------------------------------------------
888 // name: Chuck_VM_Code()
890 //-----------------------------------------------------------------------------
891 Chuck_VM_Code::Chuck_VM_Code()
900 //-----------------------------------------------------------------------------
901 // name: ~Chuck_VM_Code()
903 //-----------------------------------------------------------------------------
904 Chuck_VM_Code::~Chuck_VM_Code()
915 //-----------------------------------------------------------------------------
916 // name: initialize()
918 //-----------------------------------------------------------------------------
919 t_CKBOOL
Chuck_VM_Stack::initialize( t_CKUINT size
)
925 stack
= new t_CKBYTE
[size
];
930 memset( stack
, 0, size
);
936 // set flag and return
937 return m_is_init
= TRUE
;
943 //-----------------------------------------------------------------------------
946 //-----------------------------------------------------------------------------
947 t_CKBOOL
Chuck_VM_Stack::shutdown()
953 SAFE_DELETE_ARRAY( stack
);
956 // set the flag to false
965 //-----------------------------------------------------------------------------
966 // name: Chuck_VM_Shred()
968 //-----------------------------------------------------------------------------
969 Chuck_VM_Shred::Chuck_VM_Shred()
971 mem
= new Chuck_VM_Stack
;
972 reg
= new Chuck_VM_Stack
;
982 //-----------------------------------------------------------------------------
983 // name: ~Chuck_VM_Shred()
985 //-----------------------------------------------------------------------------
986 Chuck_VM_Shred::~Chuck_VM_Shred()
994 //-----------------------------------------------------------------------------
995 // name: initialize()
997 //-----------------------------------------------------------------------------
998 t_CKBOOL
Chuck_VM_Shred::initialize( Chuck_VM_Code
* c
,
999 t_CKUINT mem_stack_size
,
1000 t_CKUINT reg_stack_size
)
1002 // allocate mem and reg
1003 if( !mem
->initialize( mem_stack_size
) ) return FALSE
;
1004 if( !reg
->initialize( reg_stack_size
) ) return FALSE
;
1026 //-----------------------------------------------------------------------------
1029 //-----------------------------------------------------------------------------
1030 t_CKBOOL
Chuck_VM_Shred::shutdown()
1032 // get iterator to our map
1033 map
<Chuck_UGen
*, Chuck_UGen
*>::iterator iter
= m_ugen_map
.begin();
1034 while( iter
!= m_ugen_map
.end() )
1036 (*iter
).first
->disconnect( TRUE
);
1044 // TODO: is this right?
1046 // what to do with next and prev?
1054 //-----------------------------------------------------------------------------
1057 //-----------------------------------------------------------------------------
1058 t_CKBOOL
Chuck_VM_Shred::add( Chuck_UGen
* ugen
)
1060 if( m_ugen_map
[ugen
] )
1063 m_ugen_map
[ugen
] = ugen
;
1070 //-----------------------------------------------------------------------------
1073 //-----------------------------------------------------------------------------
1074 t_CKBOOL
Chuck_VM_Shred::remove( Chuck_UGen
* ugen
)
1076 if( !m_ugen_map
[ugen
] )
1080 m_ugen_map
.erase( ugen
);
1087 //-----------------------------------------------------------------------------
1090 //-----------------------------------------------------------------------------
1091 t_CKBOOL
Chuck_VM_Shred::run( Chuck_VM
* vm
)
1094 instr
= code
->instr
;
1100 // execute the instruction
1101 instr
[pc
]->execute( vm
, this );
1108 // is the shred finished
1115 //-----------------------------------------------------------------------------
1116 // name: Chuck_VM_Shreduler()
1118 //-----------------------------------------------------------------------------
1119 Chuck_VM_Shreduler::Chuck_VM_Shreduler()
1128 //-----------------------------------------------------------------------------
1129 // name: ~Chuck_VM_Shreduler()
1131 //-----------------------------------------------------------------------------
1132 Chuck_VM_Shreduler::~Chuck_VM_Shreduler()
1140 //-----------------------------------------------------------------------------
1141 // name: initialize()
1143 //-----------------------------------------------------------------------------
1144 t_CKBOOL
Chuck_VM_Shreduler::initialize()
1152 //-----------------------------------------------------------------------------
1155 //-----------------------------------------------------------------------------
1156 t_CKBOOL
Chuck_VM_Shreduler::shutdown()
1164 //-----------------------------------------------------------------------------
1167 //-----------------------------------------------------------------------------
1168 t_CKBOOL
Chuck_VM_Shreduler::shredule( Chuck_VM_Shred
* shred
)
1170 return this->shredule( shred
, now_system
);
1176 //-----------------------------------------------------------------------------
1179 //-----------------------------------------------------------------------------
1180 t_CKBOOL
Chuck_VM_Shreduler::shredule( Chuck_VM_Shred
* shred
,
1181 t_CKTIME wake_time
)
1184 if( shred
->prev
|| shred
->next
)
1186 // something is really wrong here - no shred can be
1187 // shreduled more than once
1192 if( wake_time
< this->now_system
)
1194 // trying to enqueue on a time that is less than now
1198 shred
->wake_time
= wake_time
;
1205 // pointers to the shred queue
1206 Chuck_VM_Shred
* curr
= shred_list
;
1207 Chuck_VM_Shred
* prev
= NULL
;
1211 // found the place to insert
1212 if( curr
->wake_time
> wake_time
)
1221 shred
->next
= shred_list
;
1222 if( shred_list
) shred_list
->prev
= shred
;
1227 // insert the shred in sorted order
1228 shred
->next
= prev
->next
;
1230 if( prev
->next
) prev
->next
->prev
= shred
;
1240 //-----------------------------------------------------------------------------
1243 //-----------------------------------------------------------------------------
1244 void Chuck_VM_Shreduler::advance( )
1246 // advance system 'now'
1247 this->now_system
+= 1;
1251 BBQ
* audio
= this->bbq
;
1256 audio
->digi_in()->tick_in( &l
, &r
);
1257 m_adc
[0].m_current
= .5f
* ( l
+ r
) * m_adc
[0].m_gain
;
1258 // m_adc[1].m_current = r * m_adc[1].m_gain;
1262 m_dac
[0].system_tick( this->now_system
);
1263 //m_dac[1].system_tick( this->now_system );
1264 l
= m_dac
[0].m_current
;
1265 //r = m_dac[1].m_current;
1269 m_bunghole
->system_tick( this->now_system
);
1273 audio
->digi_out()->tick_out( l
, l
);
1279 //-----------------------------------------------------------------------------
1282 //-----------------------------------------------------------------------------
1283 Chuck_VM_Shred
* Chuck_VM_Shreduler::get( )
1285 Chuck_VM_Shred
* shred
= shred_list
;
1291 // TODO: should this be <=?
1292 if( shred
->wake_time
<= ( this->now_system
+ .5 ) )
1294 // if( shred->wake_time < this->now_system )
1297 shred_list
= shred
->next
;
1302 shred_list
->prev
= NULL
;
1312 //-----------------------------------------------------------------------------
1315 //-----------------------------------------------------------------------------
1316 t_CKBOOL
Chuck_VM_Shreduler::replace( Chuck_VM_Shred
* out
, Chuck_VM_Shred
* in
)
1325 out
->prev
->next
= in
;
1328 out
->next
->prev
= in
;
1330 in
->next
= out
->next
;
1331 in
->prev
= out
->prev
;
1333 out
->next
= out
->prev
= NULL
;
1335 in
->wake_time
= out
->wake_time
;
1336 in
->start
= in
->wake_time
;
1344 //-----------------------------------------------------------------------------
1347 //-----------------------------------------------------------------------------
1348 t_CKBOOL
Chuck_VM_Shreduler::remove( Chuck_VM_Shred
* out
)
1351 if( !out
|| ( !out
->prev
&& !out
->prev
&& out
!= shred_list
) )
1355 shred_list
= out
->next
;
1357 out
->prev
->next
= out
->next
;
1360 out
->next
->prev
= out
->prev
;
1362 out
->next
= out
->prev
= NULL
;
1370 //-----------------------------------------------------------------------------
1373 //-----------------------------------------------------------------------------
1374 Chuck_VM_Shred
* Chuck_VM_Shreduler::lookup( t_CKUINT id
)
1376 Chuck_VM_Shred
* shred
= shred_list
;
1384 if( shred
->id
== id
)
1387 shred
= shred
->next
;
1396 //-----------------------------------------------------------------------------
1399 //-----------------------------------------------------------------------------
1400 void Chuck_VM_Shreduler::status( )
1402 Chuck_VM_Shred
* shred
= shred_list
;
1404 t_CKUINT srate
= Digitalio::sampling_rate();
1405 t_CKUINT s
= (t_CKUINT
)now_system
;
1406 t_CKUINT h
= s
/(srate
*3600);
1407 s
= s
- (h
*(srate
*3600));
1408 t_CKUINT m
= s
/ (srate
*60);
1409 s
= s
- (m
*(srate
*60));
1410 t_CKUINT sec
= s
/ srate
;
1411 s
= s
- (sec
*(srate
));
1412 float millisecond
= s
/ (float)(srate
) * 1000.0f
;
1413 fprintf( stdout
, "[chuck](VM): status (now == %ih%im%is, %.1f samps) ...\n",
1414 h
, m
, sec
, now_system
);
1419 char * s
= buffer
, * ss
= buffer
;
1420 strcpy( buffer
, shred
->name
.c_str() );
1421 while( *s
++ ) if( *s
== '/' ) { ss
= s
+1; }
1424 " [shred id]: %i [source]: %s [spork time]: %.2fs ago\n",
1425 shred
->id
, mini( shred
->name
.c_str() ),
1426 (now_system
-shred
->start
)/(float)Digitalio::sampling_rate() );
1427 shred
= shred
->next
;