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 struct ui_model
*create_ui_model(struct opts_options
*opts
);
32 void destroy_ui_model(struct ui_model
*model
);
33 static int new_turn(struct ogg_oggfile
*oggfiles
, struct ui_model
*model
, struct plr_context
*plr_ctx
, struct ui_context
*ui_ctx
, struct opts_options
*opts
);
36 main(int argc
, char **argv
)
38 char filename
[FILENAMELEN
];
41 struct ogg_oggfile
*oggfiles
;
42 struct opts_options opts
;
43 struct ogg_context
*ogg_ctx
;
44 struct plr_context
*plr_ctx
;
45 struct ui_context
*ui_ctx
;
46 struct ui_model
*ui_model
;
51 if (setlocale(LC_ALL
, "") == NULL
)
52 warnx("could not set locale");
54 opts_parse_options(&opts
, argc
, argv
);
56 * After this point the opts_options structure is considered read
60 if ((oggfiles
= malloc(opts
.choices
* sizeof(struct ogg_oggfile
))) == NULL
)
61 err(EX_SOFTWARE
, "could not malloc oggfiles");
62 if ((ogg_ctx
= ogg_context_open()) == NULL
)
63 errx(EX_SOFTWARE
, "could not open oggfile context");
64 if ((plr_ctx
= plr_context_open(opts
.ogg123
, opts
.ogg123_options
)) == NULL
)
65 errx(EX_SOFTWARE
, "could not open player context");
66 if ((ui_ctx
= ui_context_open()) == NULL
)
67 errx(EX_SOFTWARE
, "could not open ui context");
68 if ((ui_model
= create_ui_model(&opts
))== NULL
)
69 err(EX_SOFTWARE
, "could not create ui_model");
70 avoid_zombie_processes();
74 while (fgets(filename
, FILENAMELEN
, stdin
) != NULL
) {
75 if ((newline
= strchr(filename
, '\n')) != NULL
)
78 if (ogg_oggfile_create(ogg_ctx
, &oggfiles
[oggfileno
], filename
) == 0)
81 if (oggfileno
== opts
.choices
) {
83 if (new_turn(oggfiles
, ui_model
, plr_ctx
, ui_ctx
, &opts
))
89 destroy_ui_model(ui_model
);
90 ui_context_close(ui_ctx
);
91 plr_context_close(plr_ctx
);
92 if (ogg_context_close(ogg_ctx
) != 0)
93 warn("could not close oggfile context");
100 new_turn(struct ogg_oggfile
*oggfiles
, struct ui_model
*model
,
101 struct plr_context
*plr_ctx
, struct ui_context
*ui_ctx
,
102 struct opts_options
*opts
)
109 assert(oggfiles
!= NULL
);
110 assert(opts
!= NULL
);
113 model
->current_player
= ((model
->turn
- 1) % model
->players
);
114 for (i
= 0; i
< model
->choices
; i
++) {
115 model
->oggfiles
[i
].title
= oggfiles
[i
].title
;
116 model
->oggfiles
[i
].artist
= oggfiles
[i
].artist
;
117 model
->oggfiles
[i
].album
= oggfiles
[i
].album
;
119 correct
= rand() % model
->choices
;
120 model
->correct
= &model
->oggfiles
[correct
];
121 ui_display_quiz(ui_ctx
, model
);
122 plr_play(plr_ctx
, oggfiles
[correct
].filename
);
125 guess
= ui_get_key();
128 } while (guess
< '1' || guess
> '0' + opts
->choices
);
129 model
->guess
= &model
->oggfiles
[guess
- '1'];
130 if (model
->guess
== model
->correct
)
131 model
->score_delta
= MIN(opts
->time
, time(NULL
) - start
);
133 model
->score_delta
= opts
->time
;
134 model
->scores
[model
->current_player
] += model
->score_delta
;
135 ui_display_result(ui_ctx
, model
);
136 if (ui_get_key() == 'q')
143 create_ui_model(struct opts_options
*opts
)
145 struct ui_model
*model
;
148 assert(opts
!= NULL
);
150 if ((model
= malloc(sizeof(*model
))) == NULL
)
151 err(EX_SOFTWARE
, "could not malloc ui_model");
152 if ((model
->scores
= malloc(opts
->players
* sizeof(int))) == NULL
)
153 err(EX_SOFTWARE
, "could not malloc scores");
154 if ((model
->oggfiles
= malloc(opts
->choices
* sizeof(struct ui_oggfile
))) == NULL
)
155 err(EX_SOFTWARE
, "could not malloc oggfiles");
156 for (i
= 0; i
< opts
->players
; i
++) {
157 model
->scores
[i
] = 0;
160 model
->players
= opts
->players
;
161 model
->choices
= opts
->choices
;
167 destroy_ui_model(struct ui_model
*model
)
169 assert(model
!= NULL
);
172 free(model
->oggfiles
);
177 avoid_zombie_processes()
181 sa
.sa_handler
= SIG_IGN
;
183 sigemptyset(&(sa
.sa_mask
));
184 sigaddset(&(sa
.sa_mask
), SIGCHLD
);
186 sigaction(SIGCHLD
, &sa
, NULL
);