Update copyright notices.
[state-utils.git] / src / state-save.c
blob88b3a6f821057043ef40be8c7649ac4e22acdb3a
1 /*
2 * state-utils
3 * (c) 2005-2009 by Avuton Olrich <avuton@gmail.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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <errno.h>
21 #include <sys/stat.h>
22 #include <stdio.h>
23 #include <stdlib.h>
25 #include "libmpdclient.h"
26 #include "conn.h"
27 #include "state.h"
30 * void exit_on_help(char ** argv):
31 * Takes argv as an argument
33 * Expected action: Simply check for -h or --help as an argument
34 * and if it exists show usage.
36 * Returns: exits only
39 static void exit_on_help(char **argv)
41 if (!(argv[1] && argv[1][0] == '-'))
42 return;
44 if ((argv[1][1] == '-' && argv[1][2] == 'h') || (argv[1][1] == 'h')) {
45 printf("Usage: state-save [STATE NAME]"
46 "\nExample: state-save my_cool_statefile"
47 "\n\n"
48 "\n -h, --help\t\tThis usage"
49 "\n\nReport bugs to Avuton Olrich <avuton@gmail.com>"
50 "\nSee 'man 1 state-save' for more information\n");
51 exit(1);
57 * FILE * get_fp(int,char):
58 * Takes argc,argv as it's arguments.
60 * Expected action: This simply formats the filename, gets
61 * the current user's home directory name, if it doesn't yet
62 * exist it creats it, then turns the filename into a file
63 * pointer.
65 * Returns: A file pointer
67 static FILE *get_fp(int argc, char **argv)
69 char filename[FILENAME_MAX];
70 char dirname[FILENAME_MAX];
71 FILE *fp;
73 sprintf(dirname, "%s/.mpd_states", get_home_dir());
75 if (argc == 1) {
76 sprintf(filename, "%s/default", dirname);
77 } else {
78 sprintf(filename, "%s/%s", dirname, argv[1]);
82 * Create the directory/file if necessary and
83 * make sure things are coherant.
85 errno = 0;
86 while (!(fp = fopen(filename, "w"))) {
87 /* ENOENT: No such file or directory */
88 if (errno == ENOENT) {
89 errno = 0;
91 if (mkdir(dirname, (mode_t) 0700)) {
92 break;
95 check_perror(errno, "Couldn't create state-utils directory");
97 return fp;
101 * void print_playlist(FILE,conn):
102 * Takes a file pointer and the connection as arguments
104 * Expected action: Print the playlist from connection
105 * to the file pointer
107 * Returns: void, There's no need to do anything other
108 * than log the error and return.
110 * Example output:
111 * playlist_begin
112 * 0:Albums/Sublime/40 Oz. To Freedom/01.sublime_-_waiting_for_my_ruca.flac
113 * 1:Albums/Sublime/40 Oz. To Freedom/02.sublime_-_40_oz._to_freedom.flac
114 * playlist_end
117 static void print_playlist(FILE * fp, mpd_Connection * conn)
120 mpd_InfoEntity *entity = NULL;
121 mpd_sendPlaylistInfoCommand(conn, -1);
123 entity = mpd_getNextInfoEntity(conn);
126 * Don't freak if we can't get playlist
127 * user may simply not have permissions.
129 if (conn->error || !entity) {
130 fprintf(stderr, "Cannot get the playlist, continuing...\n");
131 mpd_clearError(conn);
132 return;
135 fprintf(fp, "playlist_begin\n");
136 do {
137 if (entity->type == MPD_INFO_ENTITY_TYPE_SONG) {
138 fprintf(fp, "%i:%s\n",
139 entity->info.song->pos,
140 entity->info.song->file);
142 mpd_freeInfoEntity(entity);
143 } while ((entity = mpd_getNextInfoEntity(conn)));
144 mpd_finishCommand(conn);
145 fprintf(fp, "playlist_end\n");
146 printErrorAndExit(conn);
150 * void print_outputs(FILE,conn)
151 * Takes a file pointer and the connection as arguments
153 * Expected action: Print the outputs from the connection to
154 * the file pointer.
156 * Returns: void, There's no need to do anything other than log the
157 * error and return.
159 * Example output:
160 * outputs_begin
161 * 0:1:ALSA output (emu10k1)
162 * 1:1:ALSA output (intel8x0)
163 * outputs_end
165 * Explanation of output:
166 * The first number is the device number, sequentially.
167 * The second number is 0 is disabled, 1 is enabled.
168 * The third is the name as defined in the MPD.
170 static void print_outputs(FILE * fp, mpd_Connection * conn)
172 mpd_OutputEntity *output = NULL;
173 mpd_sendOutputsCommand(conn);
175 output = mpd_getNextOutput(conn);
178 * Don't freak if we can't get outputs
179 * user may simply not have permissions.
181 if (conn->error || !output) {
182 if (conn->error) {
183 fprintf(stderr,
184 "Cannot get the outputs due to: %s, continuing...\n",
185 conn->errorStr);
186 } else { /* !output */
187 fprintf(stderr,
188 "Cannot get the outputs, this is not necessarily an error, continuing...\n");
190 mpd_clearError(conn);
191 return;
194 fprintf(fp, "outputs_begin\n");
195 do {
196 if (output->id >= 0) {
197 fprintf(fp, "%i:%i:%s\n",
198 output->id, output->enabled, output->name);
200 mpd_freeOutputElement(output);
201 } while ((output = mpd_getNextOutput(conn)));
202 mpd_finishCommand(conn);
203 fprintf(fp, "outputs_end\n");
204 printErrorAndExit(conn);
208 * void print_status(FILE,conn)
209 * Takes a file pointer and connection as arguments
211 * Expected action: Get all useful information from the MPD
212 * status conn and output to the file pointer.
214 * Returns: void, There's no need to do anything other than log
215 * or exit() if required.
217 * Example output:
218 * state: play
219 * current: 5
220 * time: 62
221 * random: 0
222 * repeat: 0
223 * crossfade: 0
224 * volume: 100
226 static void print_status(FILE * fp, mpd_Connection * conn)
228 mpd_Status *status;
230 mpd_sendStatusCommand(conn);
231 printErrorAndExit(conn);
233 status = mpd_getStatus(conn);
234 printErrorAndExit(conn);
236 if (!status) {
237 fprintf(stderr, "Out of memory");
238 exit(8);
241 mpd_nextListOkCommand(conn);
242 printErrorAndExit(conn);
244 /* state: play */
245 fprintf(fp, "state: ");
246 if (status->state == MPD_STATUS_STATE_PLAY) {
247 fprintf(fp, "play\n");
248 } else if (status->state == MPD_STATUS_STATE_PAUSE) {
249 fprintf(fp, "pause\n");
250 } else {
251 fprintf(fp, "stop\n");
254 /* current: 0 */
255 fprintf(fp, "current: %i\n", status->song);
257 /* time: 1029 */
258 fprintf(fp, "time: %i\n", status->elapsedTime);
260 /* random: 0 */
261 fprintf(fp, "random: %i\n", status->random ? 1 : 0);
263 /* repeat: 0 */
264 fprintf(fp, "repeat: %i\n", status->repeat ? 1 : 0);
266 if (status->single) {
267 /* single: 0 */
268 fprintf(fp, "single: %i\n", status->single ? 1 : 0);
271 if (status->consume) {
272 /* consume: 0 */
273 fprintf(fp, "consume: %i\n", status->consume ? 1 : 0);
276 /* crossfade: 0 */
277 fprintf(fp, "crossfade: %i\n", status->crossfade ? 1 : 0);
279 fprintf(fp, "volume: %i\n", status->volume);
281 mpd_finishCommand(conn);
283 mpd_freeStatus(status);
284 printErrorAndExit(conn);
288 * duh
290 int main(int argc, char **argv)
292 FILE *fp;
293 mpd_Connection *conn;
295 exit_on_help(argv);
296 fp = get_fp(argc, argv);
297 conn = setup_connection(NULL, NULL);
299 print_status(fp, conn);
300 print_playlist(fp, conn);
301 print_outputs(fp, conn);
303 fclose(fp);
304 mpd_closeConnection(conn);
306 return 0;