📄 apollo-client.c
字号:
ArgCommand argcom[]={ { "dir", set_dir, " dir <name> : clear the play list and load the (hopefully) directory\n" " <name> as the play list. This should work with devices\n" " like /dev/cdrom to handle music CDs." }, { "time", set_time, " time [+|-|/]seconds :\n" "\t seconds : set the playback time to seconds\n" "\t+seconds : advance the playback by seconds\n" "\t-seconds : rewind the playback by seconds\n" "\t/seconds : set the playback time to seconds from the end\n" "\t of the song\n" " examples : xmmsctrl time 30, xmmsctrl time +10" }, { "track", set_track, " track <n> : set the n'th track in the play list as the current track" }, { "vol", set_vol, " vol [+|-]percent, with the following effects\n" "\t percent : set the volume to percent\n" "\t+percent : increase the volume with percent\n" "\t-percent : decrease the volume with percent\n" " examples : xmmsctrl vol 40, xmmsctrl vol +5, xmmsctrl vol -5" }};/* type for commands wanting many arguments */typedef struct { const char *name; void (*command)(gint, gint, gint, char **); const char *help;} ArgsCommand;/* many-arguments-command list */ArgsCommand argscom[]={ { "add", add_to_playlist, " add <names> : adds mp3s, directories, playlists to the playlist" }, { "add-to-playfirst", add_to_playfirst, " add-to-playfirst <names> : adds mp3s, directories, playlists to the playfirst list" }, { "add-to-playlist-and-playfirst", add_to_playlist_and_playfirst, " add-to-playlist-and-playfirst <names> : adds mp3s, directories, playlists to \n" " the playlist and playfirst" }};/* sizes of the lists */#define NCOM (sizeof(com)/sizeof(Command))#define NTST (sizeof(test)/sizeof(Test))#define NTOG (sizeof(toggle)/sizeof(ToggleCommand))#define NARG (sizeof(argcom)/sizeof(ArgCommand))#define NARGS (sizeof(argscom)/sizeof(ArgsCommand))/*! wrap function to print the current played mp3 file */static void print_current(gint session){ printf("%s\n", remote_get_playlist_file(session, remote_get_playlist_pos(session)));}/*! wrap function to print the current master volume */static void print_volume(gint session){ printf("%d\n", remote_get_main_volume(session));}/*! wrap function to print the current playback time in seconds */static void print_time(gint session){ printf("%d\n", remote_get_output_time(session) / 1000);}/*! wrap function to print the current played mp3 title */static void print_current_title(gint session){ printf("%s\n", remote_get_playlist_title(session, remote_get_playlist_pos(session)));} /*! returns OK if xmms is playing a stream */static gboolean is_stream_playing(gint session){ return !strncmp("http://", remote_get_playlist_file(session, remote_get_playlist_pos(session)), 7);}/*! * go to previous song, wrap to the last song if the position * in the play list is the first. Note that in case of CD, * the first position is 1 otherwise it is 0. */static void play_prev (gint session){ const gchar DEV[] = "/dev/"; gint first = 0; if (!strncmp(DEV, remote_get_playlist_file(session, remote_get_playlist_pos(session)), 5)) first = 1; if (first != remote_get_playlist_pos (session)) remote_playlist_prev(session); else remote_set_playlist_pos(session, remote_get_playlist_length(session) - 1);}/*! list the song names of the mp3 songs in the playlist */static void print_playlist(gint session){ int n = remote_get_playlist_length(session); int i = 0; while (i < n) { char *name = remote_get_playlist_title(session, i); /* name == NULL should not happen. * The occurence would be a bug from xmms. * If it happens, it is not dangerous here since (null) * will be output and at least one will see the problem if ( name == NULL ) break; */ printf("%d\t%s\n", ++i, name); }}/*! list the song files of the mp3 songs in the playlist */static void print_playfiles(gint session){ int n = remote_get_playlist_length(session); int i = 0; while (i < n) { char *name = remote_get_playlist_file(session, i); /* name == NULL should not happen. * The occurence would be a bug from xmms. * If it happens, it is not dangerous here since (null) * will be output and at least one will see the problem if ( name == NULL ) break; */ printf("%d\t%s\n", ++i, name); }}/*! wrap function to print the current play list position */static void print_current_pos(gint session){ /* print position + 1 to match the play list output */ printf("%d\n", remote_get_playlist_pos(session)+1);}/*! wrap function to remove currently playing mp3 from playlist */static void remove_from_playlist(gint session){ remote_playlist_delete(session, remote_get_playlist_pos(session));}/*! track command: needs a track number */static void set_track(gint session, char *arg){ int pos = atoi(arg); if (pos > 0) remote_set_playlist_pos(session, pos-1); else fprintf(stderr, "Invalid play list position (%d), must be >= 1\n", pos);}/*! vol command: needs number | +number | -number (0-100)*/static void set_vol(gint session, char *arg){ gint vol = remote_get_main_volume( session ); switch (arg[0]) { case '+': /* argument is positive */ case '-': /* argument is negative */ /* no test on the validity of the argument, * not critical: in the worst case 0 is returned */ vol += atoi(arg); break; default: vol = atoi(arg); } /* check bounds */ if (vol < 0) vol = 0; else if (vol > 100) vol = 100; remote_set_main_volume( session, vol );}/*! time command: needs number | +number | -number | /number */static void set_time(gint session, char *arg){ gint ptime = remote_get_output_time( session ); gint pos = remote_get_playlist_pos( session ); gint length = remote_get_playlist_time( session, pos ); switch (arg[0]) { case '+': /* argument is positive */ case '-': /* argument is negative */ /* no test on the validity of the argument, * not critical: in the worst case 0 is returned */ ptime += atoi(arg) * 1000; break; case '/': /* if arg[i] is a recognized string argument, by * definition it has at least one character, therefore * argv[i]+1 is at worst \0 and atoi returns in the * worst case 0 */ ptime = length - atoi(arg+1) * 1000; break; default: ptime = atoi(arg) * 1000; } /* check bounds */ if (ptime < 0) ptime = 0; else if (ptime > length) ptime = length; remote_jump_to_time( session, ptime );}/*! dir command: needs a string as argument */static void set_dir(gint session, char *arg){ remote_playlist_clear(session); remote_playlist_add_url_string(session, arg);}/*! add-to-playlist command: swallows the rest of argv */static void add_to_playlist(gint session, gint from_arg_no, int argc, char **argv){ remote_playlist(session, argv+from_arg_no, argc-from_arg_no, TRUE, FALSE);}/*! add-to-playfirst command: swallows the rest of argv */static void add_to_playfirst(gint session, gint from_arg_no, int argc, char **argv){ remote_playlist(session, argv+from_arg_no, argc-from_arg_no, TRUE, TRUE); }/*! add-to-playlist-and-playfirst command, swallows the rest of argv */static void add_to_playlist_and_playfirst(gint session, gint from_arg_no, int argc, char **argv){ remote_playlist(session, argv+from_arg_no, argc-from_arg_no, TRUE, FALSE); remote_playlist(session, argv+from_arg_no, argc-from_arg_no, TRUE, TRUE);}/*! * print xmmsctrl help * the dummy variable is used just for convenience */static void print_help(__attribute__ ((unused)) gint dummy) { unsigned int i; /* The string is cut to conform to ISO C89 */ puts("apollo-client, derived from xmmsctrl by Alexandre David <adavid@docs.uu.se>:\n" "apollo-client is a simple tool designed to be used at the shell level,\n" "typically in a small shell script associated to a keyboard shortcut. There\n" "are 4 different command types:\n" " - simple commands: apollo-client play\n" " perform a simple task\n" " - commands with a flag argument: apollo-client main 1\n" " set a particular state"); puts(" - condition testing: apollo-client playing\n" " can be used inif statements in shells. Something to notice: this was designed to be\n" " used simply, which is, directly in if statements: if <command>; then\n" " <command>; else <command>; fi. There you put directly \"apollo-client playing\"\n" " to test if xmms is playing. Notice how the if statement works: if the\n" " command succeeds, it returns a 0, which means OK, otherwise it returns\n" " an error code.\n" " - more specific commands with particular arguments"); /* simple commands, 2 special and the rest from the list */ puts("\n" "The simple commands are\n" " launch : launch a xmms instance if none is running\n" " not : negate the next condition test"); for (i=0; i<NCOM; i++) printf(" %-12s : %s\n", com[i].name, com[i].help); /* toggle commands from the list */ puts("\n" "The flag setting commands are used with 0 or 1"); for (i=0; i<NTOG; i++) printf(" %-12s : %s\n", toggle[i].name, toggle[i].help); /* test commands from the list */ puts("\n" "The condition testing commands are"); for (i=0; i<NTST; i++) printf(" %-12s : %s\n", test[i].name, test[i].help); /* argument commands, one special and the rest from the list */ puts("\n" "The other specific commands are\n" " session number : use the session number 'number', apollo-client looks\n" " automatically for the first working session.\n"); for (i=0; i<NARG; i++) printf(" %s\n\n", argcom[i].help); /* special format here */ /* multiple argument commands from the list */ for (i=0; i<NARGS; ++i) printf(" %s\n\n", argscom[i].help); /* special format here */ /* examples */ puts("\n" "Examples of shell scripts to define simple functions:\n" " Play/Stop :\n" " \tsh -c \"if apollo-client playing;\\\n" " \t then apollo-client stop;\\\n" " \t else apollo-client play; fi\"\n" " Play/Pause :\n" " \tsh -c \"if apollo-client playing;\\\n" " \t then apollo-client pause;\\\n" " \t else apollo-client play; fi\"\n");}/*! * launch a new apollo and return the session number * exit if error */static gint launch_apollo(void) { gint session; unsigned int tries; switch (fork()) { case -1: perror("fork"); exit(1); case 0: execlp("apollo", "apollo", "-vanilla", NULL); fprintf(stderr, "apollo not found!\n"); exit(0); default: for (tries = 0 ; tries < 10 ; tries++ ) { usleep( 500000 ); /* in usec */ for (session = 0 ; session < 16 ; session++ ) if ( remote_is_running( session ) ) return session; } exit(1); /* if no session found, abort */ }}int main( int argc, char *argv[] ) { int i = 1; unsigned int negate = 0; gint session; if (argc == 1) { print_help(0); return 1; } /* try to find automatically xmms session. */ for (session = 0 ; session < 16 ; session++) if (remote_is_running(session)) break; if (session == 16) { /* no session found */ if (strcmp( argv[1], "launch" )) return 1; /* error return = false */ else { i++; session = launch_apollo(); } } for (; i < argc ; i++) { /* special command tests first */ /* use a given session number */ if ( !strcmp( argv[i], "session" ) ) { /* if argument left */ if (++i < argc) session = atoi( argv[i] ); else /* no argument left */ fprintf(stderr, "Command usage: session number\n"); } /* negation handling */ else if (!strcmp(argv[i], "not")) negate ^= 1; /* handle generic commands if the command is not launch */ else if (strcmp( argv[i], "launch")) { unsigned int j; /* I don't need this, but this improves readability since * I avoid 3 nested if statements with it */ int matched = 0; /* test functions */ for (j=0; j<NTST; j++) if (!strcmp(argv[i], test[j].name)) return (!test[j].test(session))^negate; /* simple commands, we are here only if no test was found */ for (j=0; j<NCOM; j++) if (!strcmp(argv[i], com[j].name)) { com[j].command(session); matched = 1; break; /* command matched -> stop for loop */ } if (!matched) /* toggle commands */ for (j=0; j<NTOG; j++) { if (!strcmp(argv[i], toggle[j].name)) { if (++i < argc) /* if argument left */ toggle[j].command(session, atoi(argv[i])); else fprintf(stderr, "Command usage: %s 0|1\n", toggle[j].name); matched = 1; break; /* command matched -> stop for loop */ } } if (!matched) /* argument commands */ for (j=0; j<NARG; j++) { if (!strcmp(argv[i], argcom[j].name)) { if (++i < argc) /* if argument left */ argcom[j].command(session, argv[i]); /* i < argc here implies argv[i] != NULL */ else fprintf(stderr, "Command %s needs an argument. Usage:\n%s\n", argcom[j].name, argcom[j].help); matched = 1; break; } } if (!matched) /* swallow rest of args commands */ for (j=0; j<NARGS; j++) if (!strcmp(argv[i], argscom[j].name)) { argscom[j].command(session, i+1, argc, argv); /* could replace return with: match=1; i=argc; */ return 0; } if (!matched) fprintf(stderr, "Invalid command '%s' is ignored\n", argv[i]); } } return 0; /* OK result */}#ifdef __cplusplus};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -