3 * Copyright (c) 2006 acmesystems.it - john@acmesystems.it
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 * Feedback, Bugs... info@acmesystems.it
31 STATE states[MAX_STATE_COUNT];
32 static EVENT events[MAX_EVENT_COUNT];
33 static TRANSITION transitions[MAX_TRANSITION_COUNT];
34 static int transition_count = 0;
35 int state_current = MP3_STATE_STARTUP;
36 static int state_previous = MP3_STATE_NONE;
37 static int shutdown = 0;
39 void state_setup(void){
40 EVENT_ADD(MP3_EVENT_TIMEOUT, "Timeout");
41 EVENT_ADD(MP3_EVENT_FILE, "File");
42 EVENT_ADD(MP3_EVENT_STREAM, "Stream");
43 EVENT_ADD(MP3_EVENT_STOP, "Stop");
44 EVENT_ADD(MP3_EVENT_ERROR, "Error");
45 EVENT_ADD(MP3_EVENT_SHUTDOWN, "Shutdown");
46 EVENT_ADD(MP3_EVENT_END, "End");
48 STATE_ADD(MP3_STATE_STARTUP, "Startup", state_startup_enter, NULL);
49 STATE_ADD(MP3_STATE_IDLE, "Idle", state_idle_enter, NULL);
50 STATE_ADD(MP3_STATE_FILE_START, "File startup", state_file_startup_enter, state_file_startup_leave);
51 STATE_ADD(MP3_STATE_FILE_HANDLE, "File handle", state_file_handle_enter, state_file_handle_leave);
52 STATE_ADD(MP3_STATE_STREAM_START, "Stream start", state_stream_startup_enter, state_stream_startup_leave);
53 STATE_ADD(MP3_STATE_STREAM_HANDLE, "Stream handle", state_stream_handle_enter, state_stream_handle_leave);
54 STATE_ADD(MP3_STATE_ERROR, "Error", state_error_enter, NULL);
55 STATE_ADD(MP3_STATE_SHUTDOWN, "Shutdown", state_shutdown_enter, NULL);
57 TRANSITION_ADD(MP3_STATE_STARTUP, MP3_EVENT_TIMEOUT, MP3_STATE_IDLE);
59 TRANSITION_ADD(MP3_STATE_IDLE, MP3_EVENT_TIMEOUT, MP3_STATE_IDLE);
60 TRANSITION_ADD(MP3_STATE_IDLE, MP3_EVENT_FILE, MP3_STATE_FILE_START);
61 TRANSITION_ADD(MP3_STATE_IDLE, MP3_EVENT_STREAM, MP3_STATE_STREAM_START);
63 TRANSITION_ADD(MP3_STATE_FILE_START, MP3_EVENT_TIMEOUT, MP3_STATE_FILE_HANDLE);
64 TRANSITION_ADD(MP3_STATE_FILE_START, MP3_EVENT_ERROR, MP3_STATE_ERROR);
66 TRANSITION_ADD(MP3_STATE_FILE_HANDLE, MP3_EVENT_TIMEOUT, MP3_STATE_FILE_HANDLE);
67 TRANSITION_ADD(MP3_STATE_FILE_HANDLE, MP3_EVENT_END, MP3_STATE_IDLE);
68 TRANSITION_ADD(MP3_STATE_FILE_HANDLE, MP3_EVENT_ERROR, MP3_STATE_ERROR);
69 TRANSITION_ADD(MP3_STATE_FILE_HANDLE, MP3_EVENT_FILE, MP3_STATE_FILE_START);
70 TRANSITION_ADD(MP3_STATE_FILE_HANDLE, MP3_EVENT_STOP, MP3_STATE_IDLE);
71 TRANSITION_ADD(MP3_STATE_FILE_HANDLE, MP3_EVENT_STREAM, MP3_STATE_STREAM_START);
73 TRANSITION_ADD(MP3_STATE_STREAM_START, MP3_EVENT_TIMEOUT, MP3_STATE_STREAM_HANDLE);
74 TRANSITION_ADD(MP3_STATE_STREAM_START, MP3_EVENT_ERROR, MP3_STATE_ERROR);
76 TRANSITION_ADD(MP3_STATE_STREAM_HANDLE, MP3_EVENT_TIMEOUT, MP3_STATE_STREAM_HANDLE);
77 TRANSITION_ADD(MP3_STATE_STREAM_HANDLE, MP3_EVENT_STOP, MP3_STATE_IDLE);
78 TRANSITION_ADD(MP3_STATE_STREAM_HANDLE, MP3_EVENT_ERROR, MP3_STATE_ERROR);
79 TRANSITION_ADD(MP3_STATE_STREAM_HANDLE, MP3_EVENT_FILE, MP3_STATE_FILE_START);
80 TRANSITION_ADD(MP3_STATE_STREAM_HANDLE, MP3_EVENT_STREAM, MP3_STATE_STREAM_START);
82 TRANSITION_ADD(MP3_STATE_ERROR, MP3_EVENT_TIMEOUT, MP3_STATE_IDLE);
84 TRANSITION_ADD(MP3_STATE_DEFAULT, MP3_EVENT_ERROR, MP3_STATE_ERROR);
85 TRANSITION_ADD(MP3_STATE_DEFAULT, MP3_EVENT_SHUTDOWN, MP3_STATE_SHUTDOWN);
86 state_startup_enter(0, 0, NULL);
89 void state_transition(int transition, int event, EVENT_PARAM *param){
90 state_previous = state_current;
91 state_current = transitions[transition].new_state;
92 if(state_previous != state_current){
93 printf("\n -- Transition %s -> %s\n",
94 states[state_previous].name,
95 states[state_current].name);
97 if(states[state_previous].leave != NULL)
98 states[state_previous].leave(state_current, event);
99 if(states[state_current].enter != NULL)
100 states[state_current].enter(state_previous, event, param);
109 void state_event(int event, EVENT_PARAM *param){
111 if(event != MP3_EVENT_TIMEOUT){
112 printf("\n -- Got event %s (%d) in state %s (%d)\n",
115 states[state_current].name,
118 for(i = 0; i < transition_count; i++){
119 if((transitions[i].old_state == state_current)
120 && (transitions[i].event == event)){
121 state_transition(i, event, param);
125 for(i = 0; i < transition_count; i++){
126 if((transitions[i].old_state == MP3_STATE_DEFAULT)
127 && (transitions[i].event == event)){
128 state_transition(i, event, param);
138 printf("Event %s not handled in state %s\n", events[event].name, states[state_current].name);
141 void state_mainloop(void){
144 state_event(MP3_EVENT_SHUTDOWN, NULL);
146 mp3_nix_socket_handle();
147 mp3_tcp_socket_handle();
148 if(state_current == MP3_STATE_IDLE){
153 state_event(MP3_EVENT_TIMEOUT, NULL);
157 EVENT_PARAM* state_new_event(unsigned char *text, int numeric){
158 EVENT_PARAM *p = (EVENT_PARAM*)malloc(sizeof(EVENT_PARAM));
160 p->text = strdup(text);
164 p->numeric = numeric;
168 void sig_handler(int sig){
172 int main(int argc, char **argv) {
173 unsigned char daemonize = 1;
176 printf("ALPMP3 - MP3 Statemachine v1.0\n");
179 if(!strcmp(argv[1], "--no-daemon")){
182 printf("I am now going to daemonize. If you want me to stay in ");
183 printf("the foreground, add the parameter --no-daemon.\n");
189 printf("----------------------------------------\n\n");
190 printf("Made by openwrt.org (blogic@openwrt.org)\n");
194 signal(SIGINT, sig_handler);