|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00033 #define FILE_MPLAYER_BLACKLIST "mplayer.blacklist" 00034 00037 #define BLACKLIST_ALL_DELAY 1500 00038 00040 static uint8 shuffle = 0; 00042 static uint8 *shuffle_blacklist = NULL; 00044 static button_struct button_play, button_shuffle, button_blacklist, button_close, button_help; 00045 00049 static void list_handle_enter(list_struct *list) 00050 { 00051 sound_start_bg_music(list->text[list->row_selected - 1][0], setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC), -1); 00052 sound_map_background(1); 00053 shuffle = 0; 00054 } 00055 00058 static const char *list_text_color_hook(list_struct *list, const char *default_color, uint32 row, uint32 col) 00059 { 00060 (void) list; 00061 (void) col; 00062 00063 if (shuffle_blacklist[row]) 00064 { 00065 return COLOR_RED; 00066 } 00067 00068 return default_color; 00069 } 00070 00075 static void mplayer_do_shuffle(list_struct *list) 00076 { 00077 size_t i; 00078 uint8 found_num = 0; 00079 uint32 *row_ids, row_num, selected; 00080 00081 /* Calculate whether there are enough non-blacklisted songs to 00082 * shuffle through. */ 00083 for (i = 0; i < list->rows - 1 && found_num < 2; i++) 00084 { 00085 if (!shuffle_blacklist[i]) 00086 { 00087 found_num++; 00088 } 00089 } 00090 00091 if (found_num < 2) 00092 { 00093 return; 00094 } 00095 00096 /* Build a list containing non-blacklisted row IDs. */ 00097 row_num = 0; 00098 row_ids = malloc(sizeof(*row_ids) * (list->rows - 1)); 00099 00100 for (i = 0; i < list->rows - 1; i++) 00101 { 00102 if (!shuffle_blacklist[i]) 00103 { 00104 row_ids[row_num++] = i; 00105 } 00106 } 00107 00108 /* Select a row ID at random. */ 00109 selected = row_ids[rndm(1, row_num) - 1]; 00110 free(row_ids); 00111 00112 list->row_selected = selected + 1; 00113 list->row_offset = MIN(list->rows - list->max_rows, selected); 00114 sound_start_bg_music(list->text[list->row_selected - 1][0], setting_get_int(OPT_CAT_SOUND, OPT_VOLUME_MUSIC), 0); 00115 cur_widget[MPLAYER_ID]->redraw = 1; 00116 } 00117 00120 static void mplayer_check_shuffle() 00121 { 00122 if (!sound_playing_music()) 00123 { 00124 mplayer_do_shuffle(list_exists(LIST_MPLAYER)); 00125 } 00126 } 00127 00133 static int mplayer_blacklisted(list_struct *list) 00134 { 00135 if (list && shuffle_blacklist && shuffle_blacklist[list->row_selected - 1]) 00136 { 00137 return 1; 00138 } 00139 00140 return 0; 00141 } 00142 00146 static void mplayer_blacklist_toggle(list_struct *list) 00147 { 00148 if (list && shuffle_blacklist) 00149 { 00150 /* Clear blacklist status. */ 00151 if (shuffle_blacklist[list->row_selected - 1]) 00152 { 00153 shuffle_blacklist[list->row_selected - 1] = 0; 00154 } 00155 /* Enable blacklist status. */ 00156 else 00157 { 00158 shuffle_blacklist[list->row_selected - 1] = 1; 00159 00160 /* Shuffle mode and we're playing the music we just 00161 * blacklisted, so stop playing it. */ 00162 if (shuffle && !strcmp(sound_get_bg_music_basename(), list->text[list->row_selected - 1][0])) 00163 { 00164 sound_start_bg_music("no_music", 0, 0); 00165 } 00166 } 00167 00168 cur_widget[MPLAYER_ID]->redraw = 1; 00169 } 00170 } 00171 00176 static void mplayer_blacklist_mass_toggle(list_struct *list, uint8 state) 00177 { 00178 if (list && shuffle_blacklist) 00179 { 00180 size_t row; 00181 00182 for (row = 0; row < list->rows - 1; row++) 00183 { 00184 shuffle_blacklist[row] = state; 00185 } 00186 00187 /* Shuffle mode and we're disabling all, turn off music. */ 00188 if (shuffle && state == 1) 00189 { 00190 sound_start_bg_music("no_music", 0, 0); 00191 } 00192 00193 cur_widget[MPLAYER_ID]->redraw = 1; 00194 } 00195 } 00196 00200 static void mplayer_blacklist_save(list_struct *list) 00201 { 00202 FILE *fp; 00203 size_t row; 00204 00205 fp = fopen_wrapper(FILE_MPLAYER_BLACKLIST, "w"); 00206 00207 for (row = 0; row < list->rows; row++) 00208 { 00209 if (shuffle_blacklist[row]) 00210 { 00211 fprintf(fp, "%s\n", list->text[row][0]); 00212 } 00213 } 00214 00215 fclose(fp); 00216 } 00217 00224 static void mplayer_list_init(list_struct *list, const char *path, uint8 duplicates) 00225 { 00226 DIR *dir; 00227 struct dirent *currentfile; 00228 00229 /* Read the media directory and add the file names to the list. */ 00230 dir = opendir(path); 00231 00232 if (!dir) 00233 { 00234 return; 00235 } 00236 00237 while ((currentfile = readdir(dir))) 00238 { 00239 /* Ignore hidden files and files without extension. */ 00240 if (currentfile->d_name[0] == '.' || !strchr(currentfile->d_name, '.')) 00241 { 00242 continue; 00243 } 00244 00245 /* Check for duplicates. */ 00246 if (duplicates) 00247 { 00248 uint8 found = 0; 00249 uint32 row; 00250 00251 for (row = 0; row < list->rows; row++) 00252 { 00253 if (!strcmp(list->text[row][0], currentfile->d_name)) 00254 { 00255 found = 1; 00256 break; 00257 } 00258 } 00259 00260 if (found) 00261 { 00262 continue; 00263 } 00264 } 00265 00266 list_add(list, list->rows, 0, currentfile->d_name); 00267 } 00268 00269 closedir(dir); 00270 } 00271 00275 void widget_show_mplayer(widgetdata *widget) 00276 { 00277 SDL_Rect box, box2; 00278 list_struct *list; 00279 const char *bg_music; 00280 char buf[HUGE_BUF]; 00281 00282 if (!widget->widgetSF) 00283 { 00284 widget->widgetSF = SDL_ConvertSurface(Bitmaps[BITMAP_CONTENT]->bitmap, Bitmaps[BITMAP_CONTENT]->bitmap->format, Bitmaps[BITMAP_CONTENT]->bitmap->flags); 00285 } 00286 00287 list = list_exists(LIST_MPLAYER); 00288 00289 /* The list doesn't exist yet, create it. */ 00290 if (!list) 00291 { 00292 char version[MAX_BUF]; 00293 00294 /* Create the list and set up settings. */ 00295 list = list_create(LIST_MPLAYER, 12, 1, 8); 00296 list->handle_enter_func = list_handle_enter; 00297 list->text_color_hook = list_text_color_hook; 00298 list->surface = widget->widgetSF; 00299 list_scrollbar_enable(list); 00300 list_set_column(list, 0, 130, 7, NULL, -1); 00301 list_set_font(list, FONT_ARIAL10); 00302 00303 /* Add default media directory songs. */ 00304 get_data_dir_file(buf, sizeof(buf), DIRECTORY_MEDIA); 00305 mplayer_list_init(list, buf, 0); 00306 00307 /* Now add custom ones, but ignore duplicates. */ 00308 snprintf(buf, sizeof(buf), "%s/.atrinik/%s/"DIRECTORY_MEDIA, package_get_version_partial(version, sizeof(version)), get_config_dir()); 00309 mplayer_list_init(list, buf, 1); 00310 00311 /* If we added any, sort the list alphabetically and add an entry 00312 * to disable background music. */ 00313 if (list->rows) 00314 { 00315 FILE *fp; 00316 00317 /* Allocate the blacklist. + 1 is for the last entry added 00318 * further down. It is not actually used by the blacklist as 00319 * it's not possible to toggle it on/off using the button, but 00320 * it simplifies other logic checks. */ 00321 shuffle_blacklist = calloc(1, sizeof(*shuffle_blacklist) * (list->rows + 1)); 00322 00323 /* Sort the list. */ 00324 list_sort(list, LIST_SORT_ALPHA); 00325 00326 /* Read the blacklist file contents. */ 00327 fp = fopen_wrapper(FILE_MPLAYER_BLACKLIST, "r"); 00328 00329 if (fp) 00330 { 00331 size_t row; 00332 00333 while (fgets(buf, sizeof(buf) - 1, fp)) 00334 { 00335 for (row = 0; row < list->rows; row++) 00336 { 00337 if (!strncmp(buf, list->text[row][0], strlen(buf) - 1)) 00338 { 00339 shuffle_blacklist[row] = 1; 00340 break; 00341 } 00342 } 00343 } 00344 00345 fclose(fp); 00346 } 00347 00348 list_add(list, list->rows, 0, "Disable music"); 00349 } 00350 00351 list_set_focus(list); 00352 00353 button_create(&button_play); 00354 button_create(&button_shuffle); 00355 button_create(&button_blacklist); 00356 button_create(&button_help); 00357 button_create(&button_close); 00358 button_blacklist.bitmap = button_help.bitmap = button_close.bitmap = BITMAP_BUTTON_ROUND; 00359 button_blacklist.bitmap_pressed = button_help.bitmap_pressed = button_close.bitmap_pressed = BITMAP_BUTTON_ROUND_DOWN; 00360 } 00361 00362 if (widget->redraw) 00363 { 00364 _BLTFX bltfx; 00365 00366 bltfx.surface = widget->widgetSF; 00367 bltfx.flags = 0; 00368 bltfx.alpha = 0; 00369 sprite_blt(Bitmaps[BITMAP_CONTENT], 0, 0, NULL, &bltfx); 00370 00371 widget->redraw = 0; 00372 00373 box.h = 0; 00374 box.w = widget->wd; 00375 string_blt(widget->widgetSF, FONT_SERIF12, "Music Player", 0, 3, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00376 list->focus = 1; 00377 list_set_parent(list, widget->x1, widget->y1); 00378 list_show(list, 10, 2); 00379 box.w /= 2; 00380 string_blt(widget->widgetSF, FONT_SANS10, "Currently playing:", widget->wd / 2, 22, COLOR_WHITE, TEXT_ALIGN_CENTER, &box); 00381 box.h = 120; 00382 box.w -= 6; 00383 string_blt(widget->widgetSF, FONT_ARIAL10, "You can use the music player to play your favorite tunes from the game, or play them all one-by-one in random order (shuffle).\n\nNote that if you use the music player, in-game areas won't change your music until you click <b>Stop</b>.", widget->wd / 2, 60, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); 00384 } 00385 00386 box2.x = widget->x1; 00387 box2.y = widget->y1; 00388 SDL_BlitSurface(widget->widgetSF, NULL, ScreenSurface, &box2); 00389 00390 bg_music = sound_get_bg_music_basename(); 00391 box.h = 0; 00392 box.w = widget->wd / 2; 00393 00394 /* Store the background music file name in temporary buffer and 00395 * make sure it won't overflow by truncating it if necessary. */ 00396 if (bg_music) 00397 { 00398 strncpy(buf, bg_music, sizeof(buf) - 1); 00399 buf[sizeof(buf) - 1] = '\0'; 00400 string_truncate_overflow(FONT_SANS11, buf, 150); 00401 } 00402 00403 /* Show the music that is being played. */ 00404 string_blt(ScreenSurface, FONT_SANS11, bg_music ? buf : "No music", widget->x1 + widget->wd / 2 - 5, widget->y1 + 34, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); 00405 00406 button_play.x = widget->x1 + 10; 00407 button_play.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON]->bitmap->h - 4; 00408 button_render(&button_play, sound_map_background(-1) ? "Stop" : "Play"); 00409 00410 button_shuffle.x = widget->x1 + 10 + Bitmaps[BITMAP_BUTTON]->bitmap->w + 5; 00411 button_shuffle.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON]->bitmap->h - 4; 00412 00413 if (shuffle) 00414 { 00415 button_shuffle.pressed = 1; 00416 } 00417 00418 button_render(&button_shuffle, "Shuffle"); 00419 00420 button_blacklist.x = widget->x1 + 10 + Bitmaps[BITMAP_BUTTON]->bitmap->w * 2 + 5 * 2; 00421 button_blacklist.y = widget->y1 + widget->ht - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->h - 5; 00422 button_blacklist.disabled = list->row_selected == list->rows; 00423 00424 /* Do mass blacklist status change if the button has been held for 00425 * some time. */ 00426 if (button_blacklist.pressed && SDL_GetTicks() - button_blacklist.pressed_ticks > BLACKLIST_ALL_DELAY) 00427 { 00428 mplayer_blacklist_mass_toggle(list, mplayer_blacklisted(list)); 00429 mplayer_blacklist_save(list); 00430 button_blacklist.pressed_ticks = SDL_GetTicks(); 00431 } 00432 00433 button_render(&button_blacklist, mplayer_blacklisted(list) ? "+" : "-"); 00434 00435 /* Show close button. */ 00436 button_close.x = widget->x1 + widget->wd - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->w - 4; 00437 button_close.y = widget->y1 + 4; 00438 button_render(&button_close, "X"); 00439 00440 /* Show help button. */ 00441 button_help.x = widget->x1 + widget->wd - Bitmaps[BITMAP_BUTTON_ROUND]->bitmap->w * 2 - 4; 00442 button_help.y = widget->y1 + 4; 00443 button_render(&button_help, "?"); 00444 } 00445 00449 void widget_mplayer_background(widgetdata *widget) 00450 { 00451 (void) widget; 00452 00453 /* If shuffle is enabled, check whether we need to start playing 00454 * another song. */ 00455 if (shuffle) 00456 { 00457 mplayer_check_shuffle(); 00458 } 00459 } 00460 00464 void widget_mplayer_deinit(widgetdata *widget) 00465 { 00466 (void) widget; 00467 00468 free(shuffle_blacklist); 00469 shuffle_blacklist = NULL; 00470 } 00471 00476 void widget_mplayer_mevent(widgetdata *widget, SDL_Event *event) 00477 { 00478 list_struct *list = list_exists(LIST_MPLAYER); 00479 00480 /* If the list has handled the mouse event, we need to redraw the 00481 * widget. */ 00482 if (list && list_handle_mouse(list, event->motion.x - widget->x1, event->motion.y - widget->y1, event)) 00483 { 00484 widget->redraw = 1; 00485 } 00486 00487 if (button_event(&button_play, event)) 00488 { 00489 if (sound_map_background(-1)) 00490 { 00491 sound_start_bg_music("no_music", 0, 0); 00492 sound_map_background(0); 00493 shuffle = 0; 00494 } 00495 else 00496 { 00497 list_handle_enter(list); 00498 } 00499 } 00500 else if (button_event(&button_shuffle, event)) 00501 { 00502 shuffle = !shuffle; 00503 00504 if (shuffle) 00505 { 00506 mplayer_do_shuffle(list); 00507 sound_map_background(1); 00508 } 00509 else 00510 { 00511 sound_start_bg_music("no_music", 0, 0); 00512 sound_map_background(0); 00513 } 00514 } 00515 else if (button_event(&button_blacklist, event)) 00516 { 00517 /* Toggle the blacklist state of the selected row. */ 00518 mplayer_blacklist_toggle(list); 00519 mplayer_blacklist_save(list); 00520 } 00521 else if (button_event(&button_close, event)) 00522 { 00523 widget->show = 0; 00524 button_close.pressed = 0; 00525 } 00526 else if (button_event(&button_help, event)) 00527 { 00528 show_help("music player"); 00529 } 00530 } 00531 00534 void mplayer_now_playing() 00535 { 00536 char buf[HUGE_BUF]; 00537 00538 if (sound_map_background(-1) && sound_playing_music()) 00539 { 00540 snprintf(buf, sizeof(buf), "/me is currently listening to: %s", sound_get_bg_music_basename()); 00541 send_command(buf); 00542 } 00543 else 00544 { 00545 draw_info(COLOR_RED, "You are not playing any custom music."); 00546 } 00547 }
1.7.4