2 * "THE BEER-WARE LICENSE" (Revision 42):
3 * <tobias.rehbein@web.de> wrote this file. As long as you retain this notice
4 * you can do whatever you want with this stuff. If we meet some day, and you
5 * think this stuff is worth it, you can buy me a beer in return.
24 #define MIN(a, b) ((a) < (b)) ? (a) : (b)
30 static void avoid_zombie_processes(void);
31 static int new_turn(struct ogg_oggfile
*oggfiles
, struct plr_context
*plr_ctx
, struct ui_context
*ui_ctx
, struct opts_options
*opts
);
34 main(int argc
, char **argv
)
36 char filename
[FILENAMELEN
];
39 struct ogg_oggfile
*oggfiles
;
40 struct opts_options opts
;
41 struct ogg_context
*ogg_ctx
;
42 struct plr_context
*plr_ctx
;
43 struct ui_context
*ui_ctx
;
48 if (setlocale(LC_ALL
, "") == NULL
)
49 warnx("could not set locale");
51 opts_parse_options(&opts
, argc
, argv
);
53 * After this point the opts_options structure is considered read
57 if ((ogg_ctx
= ogg_context_open()) == NULL
)
58 errx(EX_SOFTWARE
, "could not open oggfile context");
59 if ((plr_ctx
= plr_context_open(opts
.ogg123
, opts
.ogg123_options
)) == NULL
)
60 errx(EX_SOFTWARE
, "could not open player context");
61 if ((ui_ctx
= ui_context_open()) == NULL
)
62 errx(EX_SOFTWARE
, "could not open ui context");
63 if ((oggfiles
= malloc(opts
.choices
* sizeof(struct ogg_oggfile
))) == NULL
)
64 err(EX_SOFTWARE
, "could not malloc oggfiles");
65 avoid_zombie_processes();
68 while (fgets(filename
, FILENAMELEN
, stdin
) != NULL
) {
69 if ((newline
= strchr(filename
, '\n')) != NULL
)
72 if (ogg_oggfile_create(ogg_ctx
, &oggfiles
[oggfileno
], filename
) == 0)
75 if (oggfileno
== opts
.choices
) {
77 if (new_turn(oggfiles
, plr_ctx
, ui_ctx
, &opts
))
83 plr_context_close(plr_ctx
);
84 ui_context_close(ui_ctx
);
85 if (ogg_context_close(ogg_ctx
) != 0)
86 warn("could not close oggfile context");
92 new_turn(struct ogg_oggfile
*oggfiles
, struct plr_context
*plr_ctx
, struct ui_context
*ui_ctx
, struct opts_options
*opts
)
94 static int first_invocation
= 0;
95 static struct ui_model model
;
101 assert(oggfiles
!= NULL
);
102 assert(opts
!= NULL
);
104 if (!first_invocation
) {
105 first_invocation
= 1;
107 if ((model
.scores
= malloc(opts
->players
* sizeof(int))) == NULL
)
108 err(EX_SOFTWARE
, "could not malloc scores");
109 if ((model
.oggfiles
= malloc(opts
->choices
* sizeof(struct ui_oggfile
))) == NULL
)
110 err(EX_SOFTWARE
, "could not malloc oggfiles");
111 for (i
= 0; i
< opts
->players
; i
++) {
115 model
.players
= opts
->players
;
116 model
.choices
= opts
->choices
;
119 model
.current_player
= ((model
.turn
- 1) % model
.players
);
120 for (i
= 0; i
< model
.choices
; i
++) {
121 model
.oggfiles
[i
].title
= oggfiles
[i
].title
;
122 model
.oggfiles
[i
].artist
= oggfiles
[i
].artist
;
123 model
.oggfiles
[i
].album
= oggfiles
[i
].album
;
125 correct
= rand() % model
.choices
;
126 model
.correct
= &model
.oggfiles
[correct
];
127 ui_display_quiz(ui_ctx
, &model
);
128 plr_play(plr_ctx
, oggfiles
[correct
].filename
);
131 guess
= ui_get_key();
134 } while (guess
< '1' || guess
> '0' + opts
->choices
);
135 model
.guess
= &model
.oggfiles
[guess
- '1'];
136 if (model
.guess
== model
.correct
)
137 model
.score_delta
= MIN(opts
->time
, time(NULL
) - start
);
139 model
.score_delta
= opts
->time
;
140 model
.scores
[model
.current_player
] += model
.score_delta
;
141 ui_display_result(ui_ctx
, &model
);
142 if (ui_get_key() == 'q')
149 avoid_zombie_processes()
153 sa
.sa_handler
= SIG_IGN
;
155 sigemptyset(&(sa
.sa_mask
));
156 sigaddset(&(sa
.sa_mask
), SIGCHLD
);
158 sigaction(SIGCHLD
, &sa
, NULL
);