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
);