int main(int argc, char **argv) { initchip(); initgui(); if(!strcmp("--audio", argv[1])) { loadfile(argv[2]); char *pcmname = (argc > 2) ? argv[3] : "audio" ; FILE *f = fopen(pcmname, "w"); startplaysong(0); while(playsong) { u8 res = interrupthandler(); fwrite(&res, 1, 1, f); } fclose(f); } else { if(argc != 2) { err(1, "usage: %s <filename>\n", argv[0]); } SDL_AudioSpec requested, obtained; SDL_Init(SDL_INIT_AUDIO); atexit(SDL_Quit); requested.freq = 16000; requested.format = AUDIO_U8; requested.samples = 256; requested.callback = audiocb; requested.channels = 1; if(SDL_OpenAudio(&requested, &obtained) == -1) { err(1, "SDL_OpenAudio"); } fprintf(stderr, "freq %d\n", obtained.freq); fprintf(stderr, "samples %d\n", obtained.samples); loadfile(argv[1]); SDL_PauseAudio(0); guiloop(); } return 0; }
/* vi insert mode */ void insertmode(void){ int c; currmode = PM_INSERT; drawgui(); for(;;){ if((c = getch()) != ERR) switch(c){ case KEY_ESCAPE: currmode = PM_NORMAL; return; case 'h': case KEY_LEFT: act_mvleft(); break; case 'j': case KEY_DOWN: act_mvdown(); break; case 'k': case KEY_UP: act_mvup(); break; case 'l': case KEY_RIGHT: act_mvright(); break; /* change octave */ case '<': if(octave) octave--; break; case '>': if(octave < 8) octave++; break; /* change instrument */ case CTRL('J'): if(currtab == 2){ act_viewinstrdec(); }else if(currtab == 1){ act_viewtrackdec(); } break; case CTRL('K'): if(currtab == 2){ act_viewinstrinc(); }else if(currtab == 1){ act_viewtrackinc(); } break; case '[': act_viewinstrdec(); break; case ']': act_viewinstrinc(); break; case CTRL('H'): currtab--; if(currtab < 0) currtab = 2; break; case CTRL('L'): currtab++; currtab %= 3; break; case 'Z': c = nextchar(); switch(c){ case 'Z': lft_savefile(filename); erase(); refresh(); endwin(); exit(0); break; case 'Q': erase(); refresh(); endwin(); exit(0); break; } break; case ' ': silence(); currmode = PM_NORMAL; return; case ENTER: if(currtab != 2){ if(currtab == 1){ silence(); startplaytrack(currtrack); }else if(currtab == 0){ silence(); startplaysong(songy); } } break; case '`': if(currtab == 0){ int t = tune->sng[songy].track[songx / 4]; if(t) currtrack = t; currtab = 1; }else if(currtab == 1){ currtab = 0; } break; default: _insertc(c); if(currtab == 1){ tracky+=step; tracky %= (tune->tracklen); }else if(currtab == 2){ //if(instry < instrument[currinstr].length-1) instry++; if(instrx < 2) instrx++; else instrx--; instry %= instrument[currinstr].length; } saved = 0; } drawgui(); usleep(10000); } }
int main(int argc, char **argv){ SDL_AudioSpec requested, obtained; int quit = 0; int xo, yo; int i, j, k; int meter[4]; static char chars[10] = { '+', '-', '*', '#', 'X', '@', '%', '$', 'M', 'W' }; caca_display_t *dp; caca_canvas_t *cv; caca_canvas_t *pineapple; if(SDL_Init( SDL_INIT_AUDIO ) < 0){ err(1, "Couldnt initialize SDL\n"); exit(1); } cv = caca_create_canvas(80, 24); pineapple = caca_create_canvas(0, 0); if((cv == NULL) || (pineapple == NULL)){ printf("failed to create canvas\n"); return 1; } dp = caca_create_display(cv); caca_set_display_time(dp, 20000); if(dp == NULL){ printf("Failed to create display\n"); return 1; } caca_import_file(pineapple, "./pineapple", ""); atexit(SDL_Quit); requested.freq = 16000; requested.format = AUDIO_U8; requested.samples = 256; requested.callback = audiocb; requested.channels = 1; if(SDL_OpenAudio(&requested, &obtained) == -1){ err(1, "SDL_OpenAudio"); } initchip(); loadfile(argv[1]); SDL_PauseAudio(0); silence(); startplaysong(0); while(!quit) { caca_event_t ev; caca_set_color_ansi(cv, CACA_DEFAULT, CACA_DEFAULT); caca_clear_canvas(cv); xo = caca_get_canvas_width(cv); yo = caca_get_canvas_height(cv); //caca_blit(cv, 0, 0, pineapple, NULL); caca_blit(cv, 55, 0, pineapple, NULL); caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16)); caca_put_str(cv, (xo - strlen("pineapple player")) / 2, (yo / 2) - 5, "pineapple player"); caca_set_color_ansi(cv, caca_rand(0, 16), caca_rand(0, 16)); caca_printf(cv, (xo - strlen("song pos -> ")) / 2, (yo / 2) - 3, "song pos -> %x", songpos); for(i = 0; i < 4; i ++) meter[i] = (osc[i].volume*20)/255; /* note visualizer */ i = 0; for(j = 0; j < 25; j=j+6){ for(k = 0; k < 4; k++){ caca_draw_line(cv, (((xo/2)+10)-j)-k, yo, (((xo/2)+10)-j)-k, yo - meter[i], chars[caca_rand(0, 9)]); } i++; } for(i = 0; i < 4; i ++) caca_printf(cv, 0, i, "%0x", osc[i].volume); while(caca_get_event(dp, CACA_EVENT_ANY, &ev, 0)) { if(caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS) { switch(caca_get_event_key_ch(&ev)) { case 'q': case 'Q': case CACA_KEY_ESCAPE: quit = 1; break; } } } caca_refresh_display(dp); } silence(); caca_free_display(dp); caca_free_canvas(cv); return 0; }
/* normal mode */ void normalmode(int c){ int i; // don't save the action for repeat if it's a movement or a repeat, or // something else that doesnt make sense to repeat if(c != 'h' && c != 'j' && c != 'k' && c != 'l' && c != CTRL('D') && c != CTRL('U') && c != CTRL('H') && c != CTRL('L') && c != 'H' && c != 'M' && c != 'L' && c != 'g' && c != 'G' && c != '.'){ lastaction = c; lastrepeatnum = cmdrepeatnum; } for(i=0; i<cmdrepeatnum; i++){ switch(c){ /* add line */ case 'a': act_addline(); break; case '.': // if the last command was a replace, just insert the last thing // inserted instead of calling insertmode() if(lastaction == 'r') _insertc(lastinsert); else normalmode(lastaction); cmdrepeatnum = lastrepeatnum; break; case KEY_ESCAPE: disptick = 0; jammermode(); break; case CTRL('Y'): switch(currtab){ case 0: if(songoffs>0){ if(songy==getmaxy(stdscr)-3+songoffs) songy--; songoffs--; } break; case 1: if(trackoffs>0){ if(tracky==getmaxy(stdscr)-3+trackoffs) tracky--; trackoffs--; } break; case 2: if(instroffs>0){ if(instry==getmaxy(stdscr)-3+instroffs) instry--; instroffs--; } break; } break; case CTRL('E'): switch(currtab){ case 0: if(songy<=tune->songlen-2){ if(songy==songoffs) songy++; songoffs++; } break; case 1: if(tracky<=(tune->tracklen)-2){ if(tracky==trackoffs) tracky++; trackoffs++; } break; case 2: if(instry<=instrument[currinstr].length-2){ if(instry==instroffs) instry++; instroffs++; } break; } break; case 'H': switch(currtab){ case 0: songy = songoffs; break; case 1: tracky = trackoffs; break; case 2: instry = instroffs; break; } break; // the second cases (to the right of the colon) for M and L // took some serious guesswork, so I'm not sure if they're // correct but they seem to work. case 'M': switch(currtab){ case 0: songy = (tune->songlen <= getmaxy(stdscr)-2)? tune->songlen/2 : ((getmaxy(stdscr)-6)/2) + songoffs; break; case 1: tracky = (tune->tracklen <= getmaxy(stdscr)-2)? tune->tracklen/2 : ((getmaxy(stdscr)-6)/2) + trackoffs; break; case 2: instry = (instrument[currinstr].length <= getmaxy(stdscr)-2)? instrument[currinstr].length/2 : ((getmaxy(stdscr)-6)/2) + instroffs; break; } break; case 'L': switch(currtab){ case 0: songy = (tune->songlen <= getmaxy(stdscr)-2)? tune->songlen-1 : getmaxy(stdscr)-3+songoffs; break; case 1: tracky = (tune->tracklen <= getmaxy(stdscr)-2)? tune->tracklen-1 : getmaxy(stdscr)-3+trackoffs; break; case 2: instry = (instrument[currinstr].length <= getmaxy(stdscr)-2)? instrument[currinstr].length-1 : getmaxy(stdscr)-3+instroffs; break; } break; case 'g': if(nextchar() == 'g'){ act_mvtop(); } break; case 'G': act_mvbottom(); break; // yank case 'y': c = nextchar(); switch(c){ case 'y': //tclip = malloc(1); if(currtab == 0){ tcliplen = 1; memcpy(&tclip, &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 1; memcpy(&tclip, &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 1; memcpy(&iclip, &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; case 'j': //tclip = malloc(2); if(currtab == 0){ tcliplen = 2; memcpy(&tclip[0], &tune->sng[songy], sizeof(struct songline)); act_mvdown(); memcpy(&tclip[1], &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 2; memcpy(&tclip[0], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); act_mvdown(); memcpy(&tclip[1], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 2; memcpy(&iclip[0], &instrument[currinstr].line[instry], sizeof(struct instrline)); act_mvdown(); memcpy(&iclip[1], &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; case 'k': //tclip = malloc(2); if(currtab == 0){ tcliplen = 2; memcpy(&tclip[1], &tune->sng[songy], sizeof(struct songline)); act_mvup(); memcpy(&tclip[0], &tune->sng[songy], sizeof(struct songline)); }else if(currtab == 1){ tcliplen = 2; memcpy(&tclip[1], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); act_mvup(); memcpy(&tclip[0], &tune->trk[currtrack].line[tracky], sizeof(struct trackline)); }else if(currtab == 2){ icliplen = 2; memcpy(&iclip[1], &instrument[currinstr].line[instry], sizeof(struct instrline)); act_mvup(); memcpy(&iclip[0], &instrument[currinstr].line[instry], sizeof(struct instrline)); } break; } break; //paste case 'p': if(currtab == 0){ if(tune->songlen < 256){ for(int i = 0; i < tcliplen; i++){ // insert new line memmove(&tune->sng[songy + 2], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); songy++; tune->songlen++; memset(&tune->sng[songy], 0, sizeof(struct songline)); // paste to new line memcpy(&tune->sng[songy], &tclip[i], sizeof(struct songline)); } } }else if(currtab == 1){ for(int i = 0; i < tcliplen; i++){ memcpy(&tune->trk[currtrack].line[tracky], &tclip[i], sizeof(struct trackline)); if(tracky < (tune->tracklen)-step) tracky += step; else tracky = (tune->tracklen)-1; } }else if(currtab == 2){ if(instrument[currinstr].length < 256){ // insert new line for(int i = 0; i < icliplen; i++){ struct instrument *in = &instrument[currinstr]; instry++; memmove(&in->line[instry + 1], &in->line[instry + 0], sizeof(struct instrline) * (in->length - instry)); in->length++; in->line[instry].cmd = '0'; in->line[instry].param = 0; // paste to new line memcpy(&instrument[currinstr].line[instry], &iclip[i], sizeof(struct instrline)); } } //if(instry < instrument[currinstr].length-1) instry++; } break; // copy everything in the current phrase or instrument into the next free one case '^': if(currtab == 1){ f = nextfreetrack(); memcpy(&tune->trk[f], &tune->trk[currtrack], sizeof(struct track)); currtrack = f; }else if(currtab == 2){ f = nextfreeinstr(); memcpy(&instrument[f], &instrument[currinstr], sizeof(struct instrument)); currinstr = f; } break; // TODO: Y and P can be removed after we make visual mode // copy whole phrase or instrument case 'Y': if(currtab == 1){ memcpy(&tclip, &tune->trk[currtrack], sizeof(struct track)); }else if(currtab == 2){ memcpy(&iclip, &instrument[currinstr], sizeof(struct instrument)); } break; // paste whole phrase or instrument case 'P': if(currtab == 1){ memcpy(&tune->trk[currtrack], &tclip, sizeof(struct track)); }else if(currtab == 2){ memcpy(&instrument[currinstr], &iclip, sizeof(struct instrument)); } break; /* delete line */ // TODO: clean this SHIT up // TODO: add an ACT_ function for delete case 'd': c = nextchar(); switch(c){ case 'd': act_delline(); break; case 'k': if(currtab == 2){ struct instrument *in = &instrument[currinstr]; instry--; int i; for(i=0; i<2; i++){ if(in->length > 1){ memmove(&in->line[instry + 0], &in->line[instry + 1], sizeof(struct instrline) * (in->length - instry - 1)); in->length--; if(instry >= in->length) instry = in->length - 1; } } }else if(currtab == 0){ songy--; int i; for(i=0; i<2; i++){ if(tune->songlen > 1){ memmove(&tune->sng[songy + 0], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); tune->songlen--; if(songy >= tune->songlen) songy = tune->songlen - 1; } } } break; case 'j': if(currtab == 2){ struct instrument *in = &instrument[currinstr]; int i; for(i=0; i<2; i++){ if(in->length > 1){ memmove(&in->line[instry + 0], &in->line[instry + 1], sizeof(struct instrline) * (in->length - instry - 1)); in->length--; if(instry >= in->length) instry = in->length - 1; } } }else if(currtab == 0){ int i; for(i=0; i<2; i++){ if(tune->songlen > 1){ memmove(&tune->sng[songy + 0], &tune->sng[songy + 1], sizeof(struct songline) * (tune->songlen - songy - 1)); tune->songlen--; if(songy >= tune->songlen) songy = tune->songlen - 1; } } } break; } break; /* undo */ case 'u': act_undo(); /* Clear */ case 'x': act_clronething(); break; case 'X': act_clritall(); break; case ENTER: if(currtab != 2){ if(currtab == 1){ silence(); startplaytrack(currtrack); }else if(currtab == 0){ silence(); startplaysong(songy); } } break; case 'Z': c = nextchar(); switch(c){ case 'Z': lft_savefile(filename); erase(); refresh(); endwin(); exit(0); break; case 'Q': erase(); refresh(); endwin(); exit(0); break; } break; /* Enter command mode */ case ':': cmdlinemode(); break; case ' ': silence(); tune->plonked = 0; break; // TODO: make an act_ function for '`' case '`': if(currtab == 0){ int t = tune->sng[songy].track[songx / 4]; if(t) currtrack = t; currtab = 1; if(playtrack){ startplaytrack(currtrack); } }else if((currtab == 1) && ((trackx == 2) || (trackx == 3))){ int i = tune->trk[currtrack].line[tracky].instr; if(i) currinstr = i; currtab = 2; } else if(currtab == 1){ currtab = 0; }else if(currtab == 2){ currtab = 1; } break; /* Enter insert mode */ case 'i': insertmode(); break; /* Enter visual mode */ case 'v': visualmode(); break; /* Enter visual line mode */ case 'V': visuallinemode(); break; /* enter jammer mode */ case CTRL('A'): jammermode(); break; /* Add new line and enter insert mode */ case 'o': act_addline(); insertmode(); break; case 'h': case KEY_LEFT: act_mvleft(); break; case 'j': case KEY_DOWN: act_mvdown(); break; case 'k': case KEY_UP: act_mvup(); break; case 'l': case KEY_RIGHT: act_mvright(); break; case '<': if(octave) octave--; break; case '>': if(octave < 8) octave++; break; case '{': if(currtrack > 1) currtrack--; break; case '}': if(currtrack < 255) currtrack++; break; case 'J': if(currtab == 0){ if( (songx%4) < 2){ act_trackdec(); }else{ act_transpdec(); } }else if(currtab == 1){ switch(trackx){ case 0: act_notedec(); break; case 1: act_octavedec(); break; case 2: act_instrdec(); break; case 3: act_instrdec(); break; case 4: act_fxdec(); break; case 5: case 6: act_paramdec(); break; case 7: act_fxdec(); break; case 8: case 9: act_paramdec(); break; default: setdisplay("in J"); break; } }else if(currtab == 2){ switch(instrx){ case 0: act_fxdec(); break; case 1: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_notedec(); }else{ act_paramdec(); } break; case 2: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_notedec(); }else{ act_paramdec(); } break; } } break; case 'K': if(currtab == 0){ if( (songx%4) < 2){ act_trackinc(); }else{ act_transpinc(); } }else if(currtab == 1){ switch(trackx){ case 0: act_noteinc(); break; case 1: act_octaveinc(); break; case 2: act_instrinc(); break; case 3: act_instrinc(); break; case 4: act_fxinc(); break; case 5: case 6: act_paraminc(); break; case 7: act_fxinc(); break; case 8: case 9: act_paraminc(); break; default: setdisplay("in K"); break; } }else if(currtab == 2){ switch(instrx){ case 0: act_fxinc(); break; case 1: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_noteinc(); }else{ act_paraminc(); } break; case 2: if(instrument[currinstr].line[instry].cmd == '+' || instrument[currinstr].line[instry].cmd == '='){ act_noteinc(); }else{ act_paraminc(); } break; } } break; case CTRL('J'): if(currtab == 2){ act_viewinstrdec(); }else if(currtab == 1){ act_viewtrackdec(); } break; case CTRL('K'): if(currtab == 2){ act_viewinstrinc(); }else if(currtab == 1){ act_viewtrackinc(); } break; case '[': act_viewinstrdec(); break; case ']': act_viewinstrinc(); break; case '(': callbacktime++; break; case ')': callbacktime--; break; case '-': if(step > 0) step--; break; case '=': if(step < 0x0f) step++; break; case CTRL('H'): currtab--; if(currtab < 0) currtab = 2; break; case CTRL('L'): currtab++; currtab %= 3; break; case KEY_TAB: currtab++; currtab %= 3; break; case CTRL('U'): act_bigmvup(); break; case CTRL('D'): act_bigmvdown(); break; /*case CTRL('P'): vimode = false; break;*/ // replace case 'r': _insertc(nextchar()); break; default: break; } // end switch } // end for cmdrepeatnum = 1; cmdrepeat = 0; }