1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 Wincent Balin
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
28 /* Welcome to the PDBox plugin */
32 /* Name of the file to open. */
36 uint64_t runningtime
= 0;
38 /* Variables for Pure Data. */
42 t_namelist
*sys_openlist
;
44 int sys_soundindevlist
[MAXAUDIOINDEV
];
46 int sys_chinlist
[MAXAUDIOINDEV
];
47 int sys_nsoundout
= 1;
48 int sys_soundoutdevlist
[MAXAUDIOOUTDEV
];
50 int sys_choutlist
[MAXAUDIOOUTDEV
];
51 static int sys_main_srate
= PD_SAMPLERATE
;
52 static int sys_main_advance
= PD_SAMPLES_PER_HZ
;
54 /* References for scheduler variables and functions. */
55 extern t_time sys_time
;
56 extern t_time sys_time_per_dsp_tick
;
57 extern void sched_tick(t_time next_sys_time
);
59 #define SAMPLES_SIZE 1000
60 t_sample samples
[SAMPLES_SIZE
];
66 unsigned int core_thread_id
;
67 unsigned int gui_thread_id
;
68 unsigned int time_thread_id
;
70 /* Stacks for threads. */
71 #define STACK_SIZE 16384
72 uint32_t core_stack
[STACK_SIZE
/ sizeof(uint32_t)];
73 uint32_t gui_stack
[STACK_SIZE
/ sizeof(uint32_t)];
74 uint32_t time_stack
[256 / sizeof(uint32_t)];
77 /* Core thread, scheduler. */
78 void core_thread(void)
80 /* struct datagram ping; */
82 /* LATER consider making this variable. It's now the LCM of all sample
83 rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
84 #define TIMEUNITPERSEC (32.*441000.)
87 sys_time_per_dsp_tick
= (TIMEUNITPERSEC
) *
88 ((double)sys_schedblocksize
) / sys_dacsr
;
95 /* Wait for request. */
96 while(!RECEIVE_TO_CORE(&ping
))
99 if(memcmp("Ping!", ping
.data
, ping
.size
) == 0)
101 SEND_FROM_CORE("Pong!");
106 /* Use sys_send_dacs() function as timer. */
107 if(sys_send_dacs() != SENDDACS_NO
)
108 sched_tick(sys_time
+ sys_time_per_dsp_tick
);
117 void gui_thread(void)
119 /* struct datagram pong; */
125 /* Send ping to the core. */
126 SEND_TO_CORE("Ping!");
127 rb
->splash(HZ
, "Sent ping.");
129 /* Wait for answer. */
130 while(!RECEIVE_FROM_CORE(&pong
))
133 /* If got a pong -- everything allright. */
134 if(memcmp("Pong!", pong
.data
, pong
.size
) == 0)
136 rb
->splash(HZ
, "Got pong!");
148 /* Running time thread. */
149 void time_thread(void)
153 /* Add time slice in milliseconds. */
154 runningtime
+= (1000 / HZ
);
162 /* Plug-in entry point */
163 enum plugin_status
plugin_start(const void* parameter
)
167 /* Memory pool variables. */
171 /* Get the file name. */
172 filename
= (char*) parameter
;
174 /* Allocate memory; check it's size; add to the pool. */
175 mem_pool
= rb
->plugin_get_audio_buffer(&mem_size
);
176 if(mem_size
< MIN_MEM_SIZE
)
178 rb
->splash(HZ
, "Not enough memory!");
181 add_pool(mem_pool
, mem_size
);
183 /* Initialize net. */
186 /* Initialize Pure Data, as does sys_main in s_main.c */
189 /* Add the directory the called .pd resides in to lib directories. */
190 sys_findlibdir(filename
);
192 /* Open the parameter file. */
193 sys_openlist
= namelist_append(sys_openlist
, filename
);
196 sys_set_audio_api(API_ROCKBOX
);
198 /* Fake a GUI start. */
201 /* Initialize audio subsystem. */
202 sys_open_audio(sys_nsoundin
, sys_soundindevlist
, sys_nchin
, sys_chinlist
,
203 sys_nsoundout
, sys_soundoutdevlist
, sys_nchout
, sys_choutlist
,
204 sys_main_srate
, sys_main_advance
, 1);
208 rb
->create_thread(&time_thread
,
211 0, /* FIXME Which flags? */
213 IF_PRIO(, PRIORITY_REALTIME
)
216 rb
->create_thread(&core_thread
,
219 0, /* FIXME Which flags? */
221 IF_PRIO(, MAX(PRIORITY_USER_INTERFACE
/ 2,
222 PRIORITY_REALTIME
+ 1))
225 rb
->create_thread(&gui_thread
,
228 0, /* FIXME Which flags? */
230 IF_PRIO(, PRIORITY_USER_INTERFACE
)
233 /* If having an error creating threads, bail out. */
234 if(core_thread_id
== 0 || gui_thread_id
== 0)
237 /* Wait for quit flag. */
241 /* Wait for threads to complete. */
242 rb
->thread_wait(gui_thread_id
);
243 rb
->thread_wait(core_thread_id
);
244 rb
->thread_wait(time_thread_id
);