2 * Copyright (C) 2009-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpc.wikia.com/
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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <mpd/client.h>
24 #include <mpd/async.h>
28 #include "do_command.h"
30 typedef struct event_entry
{
35 unsigned int num_entries
= 0;
36 event_entry
**entries
= NULL
;
37 struct mpd_connection
*conn
= NULL
;
39 /* Code borrowed from mpdscribble */
40 static void signal_handler(int signum
)
42 mpd_connection_free(conn
);
47 x_sigaction(int signum
, const struct sigaction
*act
)
49 if (sigaction(signum
, act
, NULL
) < 0) {
50 perror("sigaction()");
60 sigemptyset(&sa
.sa_mask
);
62 sa
.sa_handler
= signal_handler
;
63 x_sigaction(SIGINT
, &sa
);
64 x_sigaction(SIGTERM
, &sa
);
65 x_sigaction(SIGHUP
, &sa
);
67 sa
.sa_handler
= SIG_IGN
;
68 x_sigaction(SIGPIPE
, &sa
);
70 /* Parse the config file, return all the events to watch */
71 static enum mpd_idle
parse_cronfile(FILE *fp
)
73 enum mpd_idle values_events
= 0;
76 while(fgets(buffer
,1024*4, fp
) != NULL
)
79 for(i
=0; buffer
[i
] != '\0' && buffer
[i
] != ' '; i
++);
82 enum mpd_idle event
=0;
85 item
= strtok_r(&buffer
[0], "|", &saveptr
);
87 if(strncmp(item
, "PLAYER",strlen("PLAYER")) == 0) event
+= MPD_IDLE_PLAYER
;
88 else if(strncmp(item
, "DATABASE",strlen("DATABASE")) == 0) event
+= MPD_IDLE_DATABASE
;
89 else if(strncmp(item
, "STORED_PLAYLIST",strlen("STORED_PLAYLIST")) == 0) event
+= MPD_IDLE_STORED_PLAYLIST
;
90 else if(strncmp(item
, "QUEUE",strlen("QUEUE")) == 0) event
+= MPD_IDLE_QUEUE
;
91 else if(strncmp(item
, "MIXER",strlen("MIXER")) == 0) event
+= MPD_IDLE_MIXER
;
92 else if(strncmp(item
, "OUTPUT",strlen("OUTPUT")) == 0) event
+= MPD_IDLE_OUTPUT
;
93 else if(strncmp(item
, "OPTIONS",strlen("OPTIONS")) == 0) event
+= MPD_IDLE_OPTIONS
;
94 else if(strncmp(item
, "UPDATE",strlen("UPDATE")) == 0) event
+= MPD_IDLE_UPDATE
;
95 item
= strtok_r(NULL
, "|",&saveptr
);
98 entries
= realloc(entries
, (size_t)(num_entries
+1)*sizeof(*entries
));
99 entries
[num_entries
-1] = malloc(sizeof(struct event_entry
));
100 entries
[num_entries
-1]->event
= event
;
101 entries
[num_entries
-1]->command
= strdup(&buffer
[i
+1]);
102 entries
[num_entries
] = NULL
;
104 values_events
|= event
;
107 return values_events
;
110 int main (int argc
, char **argv
)
112 bool daemonize
= true;
113 bool file_specified
= false;
114 const char *hostname
= NULL
;
118 enum mpd_idle idle_event
, listen_to_events
=0;
121 * Parse the commandline options
125 for(i
=1;i
<(unsigned int)argc
;i
++)
127 if(argv
[i
][0] == '-'){
128 if(strcmp(argv
[i
], "-f") ==0) daemonize
= false;
129 else if (strncmp(argv
[i
], "--hostname=", 11) == 0){
130 hostname
= &(argv
[i
][11]);
131 } else if (strncmp(argv
[i
], "--port=", 7) == 0){
132 port
= atoi(&(argv
[i
][7]));
133 } else if (strcmp(argv
[i
], "-h") == 0 || strcmp(argv
[i
], "--help") == 0) {
134 printf("MPDCRON <OPTIONS> <CONFIG FILE> ...\n\n");
135 printf("-f Do not daemonize\n");
136 printf("--hostname=<name> Set hostname\n");
137 printf("--port=port Set port\n");
138 printf("--help -h Help message\n");
141 fprintf(stderr
, "Unknown parameter: %s\n", argv
[i
]);
147 fp
= fopen(argv
[i
], "r");
149 fprintf(stderr
, "Failed to open file: %s: %s\n", argv
[i
], strerror(errno
));
153 listen_to_events
|= parse_cronfile(fp
);
155 file_specified
= true;
160 * If no file specified try ~/.mpdcron
166 const char *homedir
= getenv("HOME");
167 if(homedir
== NULL
) {
168 fprintf(stderr
, "Homedir not found\n");
171 /* Create path to config file */
172 snprintf(buffer
,1024, "%s/.mpdcron", homedir
);
174 fp
= fopen(buffer
, "r");
176 /* not found is fatal here */
177 fprintf(stderr
, "No mpdcron file found\n");
181 listen_to_events
|= parse_cronfile(fp
);
185 conn
= mpd_connection_new(hostname
, port
, 5000);
188 fprintf(stderr
, "Failed to allocate memory\n");
192 if (mpd_connection_get_error(conn
) != MPD_ERROR_SUCCESS
) {
193 fprintf(stderr
,"%s\n", mpd_connection_get_error_message(conn
));
194 mpd_connection_free(conn
);
213 idle_event
=mpd_run_idle_mask(conn
,listen_to_events
);
214 if(idle_event
== 0) break;
215 for(i
=0; i
< num_entries
; i
++){
216 if((idle_event
&(entries
[i
]->event
)) != 0) {
217 do_command(entries
[i
]->command
);
221 /* Close/cleanup connection */
223 mpd_connection_free(conn
);
224 /* Free the entries */
225 for(i
=0;i
<num_entries
;i
++) {
226 free(entries
[i
]->command
);