2009-05-22 21:58:48 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 Wincent Balin
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "plugin.h"
|
|
|
|
#include "pdbox.h"
|
|
|
|
|
2010-02-25 23:35:16 +00:00
|
|
|
#include "PDa/src/m_pd.h"
|
|
|
|
#include "PDa/src/s_stuff.h"
|
2009-07-03 22:16:11 +00:00
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
/* Welcome to the PDBox plugin */
|
|
|
|
PLUGIN_HEADER
|
|
|
|
PLUGIN_IRAM_DECLARE
|
|
|
|
|
2009-07-03 22:16:11 +00:00
|
|
|
/* Name of the file to open. */
|
|
|
|
char* filename;
|
|
|
|
|
|
|
|
/* Running time. */
|
|
|
|
uint64_t runningtime = 0;
|
|
|
|
|
|
|
|
/* Variables for Pure Data. */
|
|
|
|
int sys_verbose;
|
|
|
|
int sys_noloadbang;
|
|
|
|
t_symbol *sys_libdir;
|
|
|
|
t_namelist *sys_openlist;
|
|
|
|
int sys_soundindevlist[MAXAUDIOINDEV];
|
|
|
|
int sys_chinlist[MAXAUDIOINDEV];
|
|
|
|
int sys_soundoutdevlist[MAXAUDIOOUTDEV];
|
|
|
|
int sys_choutlist[MAXAUDIOOUTDEV];
|
2009-08-04 02:01:55 +00:00
|
|
|
t_binbuf* inbinbuf;
|
2009-07-03 22:16:11 +00:00
|
|
|
|
|
|
|
/* References for scheduler variables and functions. */
|
|
|
|
extern t_time sys_time;
|
|
|
|
extern t_time sys_time_per_dsp_tick;
|
|
|
|
extern void sched_tick(t_time next_sys_time);
|
|
|
|
|
2009-07-12 18:44:26 +00:00
|
|
|
/* LATER consider making this variable. It's now the LCM of all sample
|
|
|
|
rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
|
|
|
|
#define TIMEUNITPERSEC (32.*441000.)
|
|
|
|
|
2009-07-03 22:16:11 +00:00
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
/* Quit flag. */
|
|
|
|
bool quit = false;
|
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Stack sizes for threads. */
|
2009-08-04 02:01:55 +00:00
|
|
|
#define CORESTACKSIZE (1 * 1024 * 1024)
|
2009-07-23 21:37:35 +00:00
|
|
|
#define GUISTACKSIZE (512 * 1024)
|
|
|
|
|
|
|
|
/* Thread stacks. */
|
|
|
|
void* core_stack;
|
|
|
|
void* gui_stack;
|
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
/* Thread IDs. */
|
2009-07-23 21:37:35 +00:00
|
|
|
unsigned int core_thread_id;
|
2009-05-22 21:58:48 +00:00
|
|
|
unsigned int gui_thread_id;
|
|
|
|
|
|
|
|
|
|
|
|
/* GUI thread */
|
|
|
|
void gui_thread(void)
|
|
|
|
{
|
2009-08-04 02:01:55 +00:00
|
|
|
struct pd_widget widget[128];
|
|
|
|
unsigned int widgets = 0;
|
|
|
|
struct datagram dg;
|
|
|
|
bool update;
|
|
|
|
|
|
|
|
/* Initialize GUI. */
|
|
|
|
pd_gui_init();
|
|
|
|
|
|
|
|
/* Load PD patch. */
|
|
|
|
widgets = pd_gui_load_patch(widget,
|
|
|
|
sizeof(widget) / sizeof(struct pd_widget));
|
|
|
|
|
|
|
|
/* Draw initial state of UI. */
|
|
|
|
pd_gui_draw(widget, widgets);
|
2009-05-22 21:58:48 +00:00
|
|
|
|
|
|
|
/* GUI loop */
|
|
|
|
while(!quit)
|
|
|
|
{
|
2009-08-04 02:01:55 +00:00
|
|
|
/* Reset update flag. */
|
|
|
|
update = false;
|
|
|
|
|
|
|
|
/* Apply timer to widgets. */
|
|
|
|
update |=
|
|
|
|
pd_gui_apply_timeouts(widget, widgets);
|
2009-05-22 21:58:48 +00:00
|
|
|
|
2009-08-04 02:01:55 +00:00
|
|
|
/* Process buttons. */
|
|
|
|
update |=
|
|
|
|
pd_gui_parse_buttons(widgets);
|
2009-05-22 21:58:48 +00:00
|
|
|
|
2009-08-04 02:01:55 +00:00
|
|
|
/* Receive and parse datagrams. */
|
|
|
|
while(RECEIVE_FROM_CORE(&dg))
|
2009-05-22 21:58:48 +00:00
|
|
|
{
|
2009-08-04 02:01:55 +00:00
|
|
|
update = true;
|
|
|
|
pd_gui_parse_message(&dg, widget, widgets);
|
2009-05-22 21:58:48 +00:00
|
|
|
}
|
2009-08-04 02:01:55 +00:00
|
|
|
|
|
|
|
/* If there is something to update in GUI, do so. */
|
|
|
|
if(update)
|
|
|
|
pd_gui_draw(widget, widgets);
|
2009-07-03 22:16:11 +00:00
|
|
|
|
|
|
|
rb->sleep(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb->thread_exit();
|
|
|
|
}
|
2009-05-22 21:58:48 +00:00
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Core thread */
|
|
|
|
void core_thread(void)
|
2009-07-03 22:16:11 +00:00
|
|
|
{
|
2010-05-24 23:38:04 +00:00
|
|
|
/* Add the directory the called .pd file resides in to lib directories. */
|
2009-07-23 21:37:35 +00:00
|
|
|
sys_findlibdir(filename);
|
|
|
|
|
|
|
|
/* Open the PD design file. */
|
|
|
|
sys_openlist = namelist_append(sys_openlist, filename);
|
|
|
|
|
|
|
|
/* Fake a GUI start. */
|
|
|
|
sys_startgui(NULL);
|
|
|
|
|
|
|
|
/* Core scheduler loop */
|
2009-07-03 22:16:11 +00:00
|
|
|
while(!quit)
|
|
|
|
{
|
2009-08-04 02:01:55 +00:00
|
|
|
/* Receive datagrams. */
|
|
|
|
struct datagram dg;
|
|
|
|
|
|
|
|
while(RECEIVE_TO_CORE(&dg))
|
|
|
|
rockbox_receive_callback(&dg);
|
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Use sys_send_dacs() function as timer. */
|
|
|
|
while(sys_send_dacs() != SENDDACS_NO)
|
|
|
|
sched_tick(sys_time + sys_time_per_dsp_tick);
|
|
|
|
|
2010-05-24 23:38:04 +00:00
|
|
|
rb->sleep(1);
|
2009-05-22 21:58:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rb->thread_exit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
/* Plug-in entry point */
|
|
|
|
enum plugin_status plugin_start(const void* parameter)
|
|
|
|
{
|
|
|
|
PLUGIN_IRAM_INIT(rb)
|
|
|
|
|
2009-07-03 22:16:11 +00:00
|
|
|
/* Memory pool variables. */
|
2009-05-22 21:58:48 +00:00
|
|
|
size_t mem_size;
|
|
|
|
void* mem_pool;
|
|
|
|
|
2009-07-12 18:44:26 +00:00
|
|
|
/* Get the file name; check whether parameter contains no file name. */
|
2009-07-03 22:16:11 +00:00
|
|
|
filename = (char*) parameter;
|
2009-07-12 18:44:26 +00:00
|
|
|
if(strlen(filename) == 0)
|
|
|
|
{
|
|
|
|
rb->splash(HZ, "Play a .pd file!");
|
|
|
|
return PLUGIN_ERROR;
|
|
|
|
}
|
2009-05-22 21:58:48 +00:00
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Initialize memory pool. */
|
2009-05-22 21:58:48 +00:00
|
|
|
mem_pool = rb->plugin_get_audio_buffer(&mem_size);
|
|
|
|
if(mem_size < MIN_MEM_SIZE)
|
|
|
|
{
|
|
|
|
rb->splash(HZ, "Not enough memory!");
|
|
|
|
return PLUGIN_ERROR;
|
|
|
|
}
|
2010-05-24 23:38:04 +00:00
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
init_memory_pool(mem_size, mem_pool);
|
2009-05-22 21:58:48 +00:00
|
|
|
|
2009-05-26 21:07:40 +00:00
|
|
|
/* Initialize net. */
|
2009-05-22 21:58:48 +00:00
|
|
|
net_init();
|
|
|
|
|
2009-07-03 22:16:11 +00:00
|
|
|
/* Initialize Pure Data, as does sys_main in s_main.c */
|
|
|
|
pd_init();
|
|
|
|
|
2009-07-12 18:44:26 +00:00
|
|
|
/* Set audio API. */
|
|
|
|
sys_set_audio_api(API_ROCKBOX);
|
|
|
|
|
|
|
|
/* Initialize audio subsystem. */
|
|
|
|
sys_open_audio(0, /* No sound input yet */
|
|
|
|
sys_soundindevlist,
|
|
|
|
0, /* No sound input yet */
|
|
|
|
sys_chinlist,
|
|
|
|
1, /* One sound output device */
|
|
|
|
sys_soundoutdevlist,
|
|
|
|
-1, /* Use the default amount (2) of channels */
|
|
|
|
sys_choutlist,
|
|
|
|
PD_SAMPLERATE, /* Sample rate */
|
|
|
|
DEFAULTADVANCE, /* Scheduler advance */
|
|
|
|
1 /* Enable */);
|
|
|
|
|
2010-05-24 23:38:04 +00:00
|
|
|
/* Initialize scheduler time variables. */
|
|
|
|
sys_time = 0;
|
|
|
|
sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
|
|
|
|
((double) sys_schedblocksize) / sys_dacsr;
|
|
|
|
|
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Create stacks for threads. */
|
|
|
|
core_stack = getbytes(CORESTACKSIZE);
|
|
|
|
gui_stack = getbytes(GUISTACKSIZE);
|
|
|
|
if(core_stack == NULL || gui_stack == NULL)
|
|
|
|
{
|
|
|
|
rb->splash(HZ, "Not enough memory!");
|
|
|
|
return PLUGIN_ERROR;
|
|
|
|
}
|
2009-07-03 22:16:11 +00:00
|
|
|
|
2009-08-04 02:01:55 +00:00
|
|
|
/* Boost CPU. */
|
|
|
|
cpu_boost(true);
|
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
/* Start threads. */
|
2009-07-23 21:37:35 +00:00
|
|
|
core_thread_id =
|
|
|
|
rb->create_thread(&core_thread,
|
|
|
|
core_stack,
|
|
|
|
CORESTACKSIZE,
|
2009-07-03 22:16:11 +00:00
|
|
|
0, /* FIXME Which flags? */
|
2009-07-23 21:37:35 +00:00
|
|
|
"PD core"
|
2009-07-03 22:16:11 +00:00
|
|
|
IF_PRIO(, PRIORITY_REALTIME)
|
|
|
|
IF_COP(, COP));
|
2009-07-12 18:44:26 +00:00
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
gui_thread_id =
|
|
|
|
rb->create_thread(&gui_thread,
|
|
|
|
gui_stack,
|
2009-07-23 21:37:35 +00:00
|
|
|
GUISTACKSIZE,
|
2009-05-22 21:58:48 +00:00
|
|
|
0, /* FIXME Which flags? */
|
|
|
|
"PD GUI"
|
|
|
|
IF_PRIO(, PRIORITY_USER_INTERFACE)
|
|
|
|
IF_COP(, CPU));
|
|
|
|
|
|
|
|
/* If having an error creating threads, bail out. */
|
2009-07-23 21:37:35 +00:00
|
|
|
if(core_thread_id == 0 || gui_thread_id == 0)
|
2009-05-22 21:58:48 +00:00
|
|
|
return PLUGIN_ERROR;
|
|
|
|
|
2009-07-12 18:44:26 +00:00
|
|
|
/* Main loop. */
|
2009-05-22 21:58:48 +00:00
|
|
|
while(!quit)
|
2009-07-12 18:44:26 +00:00
|
|
|
{
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Add time slice in milliseconds. */
|
|
|
|
runningtime += (1000 / HZ);
|
2009-07-12 18:44:26 +00:00
|
|
|
|
|
|
|
/* Sleep to the next time slice. */
|
|
|
|
rb->sleep(1);
|
|
|
|
}
|
2009-05-22 21:58:48 +00:00
|
|
|
|
|
|
|
/* Wait for threads to complete. */
|
|
|
|
rb->thread_wait(gui_thread_id);
|
2009-07-23 21:37:35 +00:00
|
|
|
rb->thread_wait(core_thread_id);
|
2009-05-22 21:58:48 +00:00
|
|
|
|
2009-08-04 02:01:55 +00:00
|
|
|
/* Unboost CPU. */
|
|
|
|
cpu_boost(false);
|
|
|
|
|
2009-07-12 18:44:26 +00:00
|
|
|
/* Close audio subsystem. */
|
|
|
|
sys_close_audio();
|
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
/* Destroy net. */
|
|
|
|
net_destroy();
|
|
|
|
|
2009-07-23 21:37:35 +00:00
|
|
|
/* Clear memory pool. */
|
|
|
|
destroy_memory_pool(mem_pool);
|
|
|
|
|
2009-05-22 21:58:48 +00:00
|
|
|
return PLUGIN_OK;
|
|
|
|
}
|
2010-05-24 23:38:04 +00:00
|
|
|
|