comparison tools/ppl.c @ 2275:ba696835f66d

Add CLI-only mode to PPL (-C option).
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 18 Jun 2019 09:11:52 +0300
parents e3f0eaf23f4f
children 2c90e455f006
comparison
equal deleted inserted replaced
2274:a4c1fafd442a 2275:ba696835f66d
59 int optOutFormat = JSS_AUDIO_S16, 59 int optOutFormat = JSS_AUDIO_S16,
60 optOutChannels = 2, 60 optOutChannels = 2,
61 optOutFreq = 48000, 61 optOutFreq = 48000,
62 optMuteOChannels = -1, 62 optMuteOChannels = -1,
63 optStartOrder = 0; 63 optStartOrder = 0;
64 BOOL optUsePlayTime = FALSE; 64 BOOL optUsePlayTime = FALSE,
65 optUseGUI = TRUE;
65 size_t optPlayTime; 66 size_t optPlayTime;
66 67
67 68
68 static const DMOptArg optList[] = 69 static const DMOptArg optList[] =
69 { 70 {
70 { 0, '?', "help", "Show this help", OPT_NONE }, 71 { 0, '?', "help", "Show this help", OPT_NONE },
71 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, 72 { 1, 'v', "verbose", "Be more verbose", OPT_NONE },
72 { 2, 0, "fs", "Fullscreen", OPT_NONE }, 73 { 2, 0, "fs", "Fullscreen", OPT_NONE },
74 { 12, 'C', "cli", "Do not open GUI window", OPT_NONE },
73 { 3, 'w', "window", "Initial window size/resolution -w 640x480", OPT_ARGREQ }, 75 { 3, 'w', "window", "Initial window size/resolution -w 640x480", OPT_ARGREQ },
74 76
75 { 4, '1', "16bit", "16-bit output", OPT_NONE }, 77 { 4, '1', "16bit", "16-bit output", OPT_NONE },
76 { 5, '8', "8bit", "8-bit output", OPT_NONE }, 78 { 5, '8', "8bit", "8-bit output", OPT_NONE },
77 { 6, 'm', "mono", "Mono output", OPT_NONE }, 79 { 6, 'm', "mono", "Mono output", OPT_NONE },
161 case 11: 163 case 11:
162 optPlayTime = atoi(optArg); 164 optPlayTime = atoi(optArg);
163 optUsePlayTime = TRUE; 165 optUsePlayTime = TRUE;
164 break; 166 break;
165 167
168 case 12:
169 optUseGUI = FALSE;
170 break;
171
166 default: 172 default:
167 dmErrorMsg("Unimplemented option argument '%s'.\n", currArg); 173 dmErrorMsg("Unimplemented option argument '%s'.\n", currArg);
168 return FALSE; 174 return FALSE;
169 } 175 }
170 176
595 601
596 if (result != DMERR_OK) 602 if (result != DMERR_OK)
597 { 603 {
598 dmErrorMsg("Error loading module file, %d: %s\n", 604 dmErrorMsg("Error loading module file, %d: %s\n",
599 result, dmErrorStr(result)); 605 result, dmErrorStr(result));
600 goto error_exit; 606 goto exit;
601 } 607 }
602 608
603 // Try to convert it 609 // Try to convert it
604 if ((result = jssConvertModuleForPlaying(eng.mod)) != DMERR_OK) 610 if ((result = jssConvertModuleForPlaying(eng.mod)) != DMERR_OK)
605 { 611 {
606 dmErrorMsg("Could not convert module for playing, %d: %s\n", 612 dmErrorMsg("Could not convert module for playing, %d: %s\n",
607 result, dmErrorStr(result)); 613 result, dmErrorStr(result));
608 goto error_exit; 614 goto exit;
609 } 615 }
610 616
611 // Get font
612 result = dmf_open_memio(NULL, "pplfont.fnt", engineSetupFont, sizeof(engineSetupFont), &file);
613 if (result != DMERR_OK)
614 {
615 dmErrorMsg("Error opening font file 'pplfont.fnt', #%d: %s\n",
616 result, dmErrorStr(result));
617 goto error_exit;
618 }
619 result = dmLoadBitmapFont(file, &font);
620 dmf_close(file);
621 if (result != DMERR_OK)
622 {
623 dmErrorMsg("Could not load font from file, %d: %s\n",
624 result, dmErrorStr(result));
625 goto error_exit;
626 }
627
628 SDL_Color pal[DMFONT_NPALETTE];
629 for (int n = 0; n < DMFONT_NPALETTE; n++)
630 {
631 pal[n].r = pal[n].g = pal[n].b = 0;
632 pal[n].a = n > 0 ? 255 : 0;
633 }
634 dmSetBitmapFontPalette(font, pal, 0, DMFONT_NPALETTE);
635 617
636 // Initialize SDL components 618 // Initialize SDL components
637 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0) 619 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) != 0)
638 { 620 {
639 dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError()); 621 dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError());
640 goto error_exit; 622 goto exit;
641 } 623 }
642 initSDL = TRUE; 624 initSDL = TRUE;
643 625
644 626
645 // Initialize mixing device 627 // Initialize mixing device
648 630
649 eng.dev = jvmInit(optOutFormat, optOutChannels, optOutFreq, JMIX_AUTO); 631 eng.dev = jvmInit(optOutFormat, optOutChannels, optOutFreq, JMIX_AUTO);
650 if (eng.dev == NULL) 632 if (eng.dev == NULL)
651 { 633 {
652 dmErrorMsg("jvmInit() returned NULL\n"); 634 dmErrorMsg("jvmInit() returned NULL\n");
653 goto error_exit; 635 goto exit;
654 } 636 }
655 637
656 switch (optOutFormat) 638 switch (optOutFormat)
657 { 639 {
658 case JSS_AUDIO_S16: eng.afmt.format = AUDIO_S16SYS; break; 640 case JSS_AUDIO_S16: eng.afmt.format = AUDIO_S16SYS; break;
660 case JSS_AUDIO_S8: eng.afmt.format = AUDIO_S8; break; 642 case JSS_AUDIO_S8: eng.afmt.format = AUDIO_S8; break;
661 case JSS_AUDIO_U8: eng.afmt.format = AUDIO_U8; break; 643 case JSS_AUDIO_U8: eng.afmt.format = AUDIO_U8; break;
662 default: 644 default:
663 dmErrorMsg("Unsupported audio format %d (could not set matching SDL format)\n", 645 dmErrorMsg("Unsupported audio format %d (could not set matching SDL format)\n",
664 optOutFormat); 646 optOutFormat);
665 goto error_exit; 647 goto exit;
666 } 648 }
667 649
668 eng.afmt.freq = optOutFreq; 650 eng.afmt.freq = optOutFreq;
669 eng.afmt.channels = optOutChannels; 651 eng.afmt.channels = optOutChannels;
670 eng.afmt.samples = optOutFreq / 16; 652 eng.afmt.samples = optOutFreq / 16;
674 // Open the audio device 656 // Open the audio device
675 if (SDL_OpenAudio(&eng.afmt, NULL) < 0) 657 if (SDL_OpenAudio(&eng.afmt, NULL) < 0)
676 { 658 {
677 dmErrorMsg("Couldn't open SDL audio: %s\n", 659 dmErrorMsg("Couldn't open SDL audio: %s\n",
678 SDL_GetError()); 660 SDL_GetError());
679 goto error_exit; 661 goto exit;
680 } 662 }
681 audioInit = TRUE; 663 audioInit = TRUE;
682 664
683 // Initialize player 665 // Initialize player
684 if ((eng.plr = jmpInit(eng.dev)) == NULL) 666 if ((eng.plr = jmpInit(eng.dev)) == NULL)
685 { 667 {
686 dmErrorMsg("jmpInit() returned NULL\n"); 668 dmErrorMsg("jmpInit() returned NULL\n");
687 goto error_exit; 669 goto exit;
688 } 670 }
689 671
690 jvmSetCallback(eng.dev, jmpExec, eng.plr); 672 jvmSetCallback(eng.dev, jmpExec, eng.plr);
691 jmpSetModule(eng.plr, eng.mod); 673 jmpSetModule(eng.plr, eng.mod);
692 jmpPlayOrder(eng.plr, optStartOrder); 674 jmpPlayOrder(eng.plr, optStartOrder);
698 jvmMute(eng.dev, optMuteOChannels, FALSE); 680 jvmMute(eng.dev, optMuteOChannels, FALSE);
699 eng.actChannel = optMuteOChannels; 681 eng.actChannel = optMuteOChannels;
700 muteState = TRUE; 682 muteState = TRUE;
701 } 683 }
702 684
703 // Open window 685 if (optUseGUI)
704 if ((eng.window = SDL_CreateWindow(dmProgName, 686 {
705 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 687 // Get font
706 eng.optScrWidth, eng.optScrHeight, 688 result = dmf_open_memio(NULL, "pplfont.fnt", engineSetupFont, sizeof(engineSetupFont), &file);
707 eng.optVFlags | SDL_WINDOW_RESIZABLE 689 if (result != DMERR_OK)
708 //| SDL_WINDOW_HIDDEN 690 {
709 )) == NULL) 691 dmErrorMsg("Error opening font file 'pplfont.fnt', #%d: %s\n",
710 { 692 result, dmErrorStr(result));
711 dmErrorMsg("Can't create an SDL window: %s\n", SDL_GetError()); 693 goto exit;
712 goto error_exit; 694 }
713 } 695 result = dmLoadBitmapFont(file, &font);
714 696 dmf_close(file);
715 SDL_SetWindowTitle(eng.window, dmProgDesc); 697 if (result != DMERR_OK)
716 698 {
717 if ((eng.renderer = SDL_CreateRenderer(eng.window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL) 699 dmErrorMsg("Could not load font from file, %d: %s\n",
718 { 700 result, dmErrorStr(result));
719 dmErrorMsg("Can't create an SDL renderer: %s\n", SDL_GetError()); 701 goto exit;
720 goto error_exit; 702 }
721 } 703
722 704 SDL_Color pal[DMFONT_NPALETTE];
723 if (!dmInitializeVideo()) 705 for (int n = 0; n < DMFONT_NPALETTE; n++)
724 goto error_exit; 706 {
725 707 pal[n].r = pal[n].g = pal[n].b = 0;
726 // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); 708 pal[n].a = n > 0 ? 255 : 0;
727 // SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); 709 }
710 dmSetBitmapFontPalette(font, pal, 0, DMFONT_NPALETTE);
711
712 // Open window
713 if ((eng.window = SDL_CreateWindow(dmProgName,
714 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
715 eng.optScrWidth, eng.optScrHeight,
716 eng.optVFlags | SDL_WINDOW_RESIZABLE
717 //| SDL_WINDOW_HIDDEN
718 )) == NULL)
719 {
720 dmErrorMsg("Can't create an SDL window: %s\n", SDL_GetError());
721 goto exit;
722 }
723
724 SDL_SetWindowTitle(eng.window, dmProgDesc);
725
726 if ((eng.renderer = SDL_CreateRenderer(eng.window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL)
727 {
728 dmErrorMsg("Can't create an SDL renderer: %s\n", SDL_GetError());
729 goto exit;
730 }
731
732 if (!dmInitializeVideo())
733 goto exit;
734
735 //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
736 //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
737 }
728 738
729 // okay, main loop here ... "play" module and print out info 739 // okay, main loop here ... "play" module and print out info
730 SDL_LockAudio(); 740 SDL_LockAudio();
731 SDL_PauseAudio(0); 741 SDL_PauseAudio(0);
732 SDL_UnlockAudio(); 742 SDL_UnlockAudio();
807 break; 817 break;
808 818
809 case SDLK_f: 819 case SDLK_f:
810 eng.optVFlags ^= SDL_WINDOW_FULLSCREEN_DESKTOP; 820 eng.optVFlags ^= SDL_WINDOW_FULLSCREEN_DESKTOP;
811 if (SDL_SetWindowFullscreen(eng.window, eng.optVFlags) != 0) 821 if (SDL_SetWindowFullscreen(eng.window, eng.optVFlags) != 0)
812 goto error_exit; 822 goto exit;
813 needUpdate = TRUE; 823 needUpdate = TRUE;
814 break; 824 break;
815 825
816 default: 826 default:
817 break; 827 break;
828 838
829 case SDL_WINDOWEVENT_RESIZED: 839 case SDL_WINDOWEVENT_RESIZED:
830 eng.optScrWidth = eng.event.window.data1; 840 eng.optScrWidth = eng.event.window.data1;
831 eng.optScrHeight = eng.event.window.data2; 841 eng.optScrHeight = eng.event.window.data2;
832 if (!dmInitializeVideo()) 842 if (!dmInitializeVideo())
833 goto error_exit; 843 goto exit;
834 844
835 needUpdate = TRUE; 845 needUpdate = TRUE;
836 break; 846 break;
837 } 847 }
838 break; 848 break;
840 case SDL_QUIT: 850 case SDL_QUIT:
841 eng.exitFlag = TRUE; 851 eng.exitFlag = TRUE;
842 break; 852 break;
843 } 853 }
844 854
845 855 // Check for end of song
846 #if 1
847 JSS_LOCK(eng.plr); 856 JSS_LOCK(eng.plr);
848 JSSPattern *currPattern = eng.plr->pattern;
849 int currRow = eng.plr->row;
850 if (!eng.plr->isPlaying) 857 if (!eng.plr->isPlaying)
851 eng.exitFlag = TRUE; 858 eng.exitFlag = TRUE;
852 JSS_UNLOCK(eng.plr); 859 JSS_UNLOCK(eng.plr);
853 860
854 if (currRow != prevRow || needUpdate) 861 if (optUseGUI)
855 { 862 {
856 prevRow = currRow; 863 // Check if we need to update screen
857 needUpdate = TRUE;
858 }
859
860 // Draw frame
861 if (needUpdate)
862 {
863 dmClearSurface(eng.screen, col.boxBg);
864
865 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5,
866 "%s v%s by ccr/TNSP - (c) Copyright 2012-2018 TNSP",
867 dmProgDesc, dmProgVersion);
868
869 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2),
870 "Song: '%s'",
871 eng.mod->moduleName);
872
873 dmDisplayPattern(eng.screen, 5, 5 + (font->height + 2) * 3 + 4,
874 eng.screen->w - 6,
875 eng.screen->h * 0.8,
876 currPattern, currRow);
877
878 JSS_LOCK(eng.plr); 864 JSS_LOCK(eng.plr);
879 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2) * 2, 865 JSSPattern *currPattern = eng.plr->pattern;
880 "Tempo: %3d | Speed: %3d | Row: %3d/%-3d | Order: %3d/%-3d | Pattern: %3d/%-3d", 866 int currRow = eng.plr->row;
881 eng.plr->tempo, eng.plr->speed,
882 eng.plr->row, (eng.plr->pattern != NULL) ? eng.plr->pattern->nrows : 0,
883 eng.plr->order + 1, eng.mod->norders,
884 eng.plr->npattern, eng.mod->npatterns);
885 JSS_UNLOCK(eng.plr); 867 JSS_UNLOCK(eng.plr);
886 needRender = TRUE; 868
887 } 869 if (currRow != prevRow || needUpdate)
888 870 {
889 if (needUpdate || currTick - prevTick >= (eng.pauseFlag ? 100 : 20)) 871 prevRow = currRow;
890 { 872 needUpdate = TRUE;
891 JSS_LOCK(eng.dev); 873 }
892 dmDisplayChannels(eng.screen, 5, eng.screen->h * 0.8 + 5, 874
893 eng.screen->w - 5, eng.screen->h - 5, eng.dev); 875 // Draw frame
894 JSS_UNLOCK(eng.dev); 876 if (needUpdate)
895 needRender = TRUE; 877 {
896 } 878 dmClearSurface(eng.screen, col.boxBg);
897 879
898 if (needUpdate) 880 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5,
899 prevTick = currTick; 881 "%s v%s by ccr/TNSP - (c) Copyright 2012-2018 TNSP",
900 882 dmProgDesc, dmProgVersion);
901 #endif 883
902 // Flip screen 884 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2),
903 if (needRender) 885 "Song: '%s'",
904 { 886 eng.mod->moduleName);
905 SDL_Surface dst; 887
906 SDL_LockTexture(eng.texture, NULL, &dst.pixels, &dst.pitch); 888 dmDisplayPattern(eng.screen, 5, 5 + (font->height + 2) * 3 + 4,
907 889 eng.screen->w - 6,
908 if (dst.pitch != eng.screen->pitch) 890 eng.screen->h * 0.8,
909 eng.exitFlag = TRUE; 891 currPattern, currRow);
910 else 892
911 memcpy(dst.pixels, eng.screen->pixels, eng.screen->h * dst.pitch); 893 JSS_LOCK(eng.plr);
912 894 dmDrawBMTextQ(eng.screen, font, DMD_TRANSPARENT, 5, 5 + (font->height + 2) * 2,
913 SDL_UnlockTexture(eng.texture); 895 "Tempo: %3d | Speed: %3d | Row: %3d/%-3d | Order: %3d/%-3d | Pattern: %3d/%-3d",
914 896 eng.plr->tempo, eng.plr->speed,
915 //SDL_RenderClear(eng.renderer); 897 eng.plr->row, (eng.plr->pattern != NULL) ? eng.plr->pattern->nrows : 0,
916 SDL_RenderCopy(eng.renderer, eng.texture, NULL, NULL); 898 eng.plr->order + 1, eng.mod->norders,
917 SDL_RenderPresent(eng.renderer); 899 eng.plr->npattern, eng.mod->npatterns);
918 } 900 JSS_UNLOCK(eng.plr);
901 needRender = TRUE;
902 }
903
904 if (needUpdate || currTick - prevTick >= (eng.pauseFlag ? 100 : 20))
905 {
906 JSS_LOCK(eng.dev);
907 dmDisplayChannels(eng.screen, 5, eng.screen->h * 0.8 + 5,
908 eng.screen->w - 5, eng.screen->h - 5, eng.dev);
909 JSS_UNLOCK(eng.dev);
910 needRender = TRUE;
911 }
912
913 if (needUpdate)
914 prevTick = currTick;
915
916 // Flip screen
917 if (needRender)
918 {
919 SDL_Surface dst;
920 SDL_LockTexture(eng.texture, NULL, &dst.pixels, &dst.pitch);
921
922 if (dst.pitch != eng.screen->pitch)
923 eng.exitFlag = TRUE;
924 else
925 memcpy(dst.pixels, eng.screen->pixels, eng.screen->h * dst.pitch);
926
927 SDL_UnlockTexture(eng.texture);
928
929 //SDL_RenderClear(eng.renderer);
930 SDL_RenderCopy(eng.renderer, eng.texture, NULL, NULL);
931 SDL_RenderPresent(eng.renderer);
932 }
933 } // optUseGUI
919 934
920 SDL_Delay(eng.pauseFlag ? 100 : 30); 935 SDL_Delay(eng.pauseFlag ? 100 : 30);
921 } 936 }
922 937
923 error_exit: 938 exit:
924 if (eng.texture != NULL) 939 // Cleanup
925 SDL_DestroyTexture(eng.texture); 940 if (optUseGUI)
926 941 {
927 if (eng.renderer != NULL) 942 dmMsg(1, "GUI shutdown.\n");
928 SDL_DestroyRenderer(eng.renderer); 943 if (eng.texture != NULL)
929 944 SDL_DestroyTexture(eng.texture);
930 if (eng.window != NULL) 945
931 SDL_DestroyWindow(eng.window); 946 if (eng.renderer != NULL)
932 947 SDL_DestroyRenderer(eng.renderer);
933 if (eng.screen != NULL) 948
934 SDL_FreeSurface(eng.screen); 949 if (eng.window != NULL)
935 950 SDL_DestroyWindow(eng.window);
936 dmMsg(0, "Audio shutdown.\n"); 951
952 if (eng.screen != NULL)
953 SDL_FreeSurface(eng.screen);
954
955 dmFreeBitmapFont(font);
956 }
957
958 dmMsg(1, "Audio shutdown.\n");
937 if (audioInit) 959 if (audioInit)
938 { 960 {
939 SDL_LockAudio(); 961 SDL_LockAudio();
940 SDL_PauseAudio(1); 962 SDL_PauseAudio(1);
941 SDL_UnlockAudio(); 963 SDL_UnlockAudio();
944 966
945 jmpClose(eng.plr); 967 jmpClose(eng.plr);
946 jvmClose(eng.dev); 968 jvmClose(eng.dev);
947 jssFreeModule(eng.mod); 969 jssFreeModule(eng.mod);
948 970
949 dmFreeBitmapFont(font); 971 dmMsg(1, "Shut down SDL.\n");
950
951 if (initSDL) 972 if (initSDL)
952 SDL_Quit(); 973 SDL_Quit();
953 974
954 jssClose(); 975 jssClose();
955 976