/* Filename with extension: "NAME.EXT;1" Filename without extension: "NAME." Directory name: "NAME" */ static uint iso_ent_name_write(char *dst, const ffstr *filename, uint attr) { ffstr name, ext; ffpath_splitname(filename->ptr, filename->len, &name, &ext); name.len = ffmin(name.len, 8); ext.len = ffmin(ext.len, 3); uint fnlen = name.len + ext.len; if (!(attr & FFUNIX_FILE_DIR) || ext.len != 0) fnlen += FFSLEN("."); if (!(attr & FFUNIX_FILE_DIR)) fnlen += FFSLEN(";1"); if (dst == NULL) return fnlen; char *p = dst; const char *end = dst + fnlen; p += iso_copyname(p, end, name.ptr, name.len); if (!(attr & FFUNIX_FILE_DIR) || ext.len != 0) *p++ = '.'; p += iso_copyname(p, end, ext.ptr, ext.len); if (!(attr & FFUNIX_FILE_DIR)) ffs_copyz(p, end, ";1"); return fnlen; }
static size_t iso_copyname(char *dst, const char *end, const char *src, size_t len) { size_t i; len = ffmin(len, end - dst); for (i = 0; i != len; i++) { uint ch = (byte)src[i]; if (ffchar_isletter(ch)) dst[i] = ffchar_upper(ch); else if (ffchar_isdigit(ch)) dst[i] = ch; else dst[i] = '_'; } return i; }
/* [(1X*)...] 0X* */ static uint64 xz_varint(const byte **_p, size_t len) { uint i = 0; uint64 n = 0; const byte *p = *_p; len = ffmin(len, 9); for (;;) { if (i == len) { *_p = p + len; return 0; } n |= (uint64)(p[i] & ~0x80) << (i * 7); if (!(p[i++] & 0x80)) break; } *_p = p + i; return n; }
int ffvorbis_decode(ffvorbis *v, const char *pkt, size_t len) { enum { R_HDR, R_TAGS, R_TAG, R_BOOK, R_DATA }; int r; if (len == 0) return FFVORBIS_RMORE; ogg_packet opkt; ffmem_tzero(&opkt); opkt.packet = (void*)pkt, opkt.bytes = len; opkt.packetno = v->pktno++; opkt.granulepos = -1; opkt.e_o_s = v->fin; switch (v->state) { case R_HDR: if (0 != vorb_info(pkt, len, &v->info.channels, &v->info.rate, &v->info.bitrate_nominal)) return ERR(v, FFVORBIS_EPKT); if (0 != (r = vorbis_decode_init(&v->vctx, &opkt))) return ERR(v, r); v->state = R_TAGS; return FFVORBIS_RHDR; case R_TAGS: if (NULL == (v->vtag.data = vorb_comm(pkt, len, &v->vtag.datalen))) return ERR(v, FFVORBIS_ETAG); v->state = R_TAG; // break case R_TAG: r = ffvorbtag_parse(&v->vtag); if (r == FFVORBTAG_ERR) return ERR(v, FFVORBIS_ETAG); else if (r == FFVORBTAG_DONE) { if (!(v->vtag.datalen != 0 && v->vtag.data[0] == 1)) return ERR(v, FFVORBIS_ETAG); v->state = R_BOOK; return FFVORBIS_RHDRFIN; } return FFVORBIS_RTAG; case R_BOOK: if (0 != (r = vorbis_decode_init(&v->vctx, &opkt))) return ERR(v, r); v->state = R_DATA; return FFVORBIS_RMORE; } r = vorbis_decode(v->vctx, &opkt, &v->pcm); if (r < 0) return v->err = r, FFVORBIS_RWARN; else if (r == 0) return FFVORBIS_RMORE; if (v->seek_sample != (uint64)-1) { if (v->seek_sample < v->cursample) { //couldn't find the target packet within the page v->seek_sample = v->cursample; } uint skip = ffmin(v->seek_sample - v->cursample, r); v->cursample += skip; if (v->cursample != v->seek_sample || (uint)r == skip) return FFVORBIS_RMORE; //not yet reached the target packet v->seek_sample = (uint64)-1; for (uint i = 0; i != v->info.channels; i++) { v->pcm_arr[i] = v->pcm[i] + skip; } v->pcm = v->pcm_arr; r -= skip; } if (v->total_samples != (uint64)-1) r = ffmin(r, v->total_samples - v->cursample); v->pkt_samples = r; v->pcmlen = r * sizeof(float) * v->info.channels; v->cursample += r; return FFVORBIS_RDATA; }
static int logz_conf_end(ffparser_schem *ps, loggzip *lz) { lz->gzlev = (uint)ffmin(lz->gzlev, 9); return 0; }
const char* ffpcm_channelstr(uint channels) { return _ffpcm_channelstr[ffmin(channels - 1, FFCNT(_ffpcm_channelstr) - 1)]; }
void handleEvents() { sf::Event Event; const sf::Input& Input = App->GetInput(); bool shiftDown = Input.IsKeyDown(sf::Key::LShift) || Input.IsKeyDown(sf::Key::RShift); while (App->GetEvent(Event)) { // Close window : exit if (Event.Type == sf::Event::Closed) App->Close(); // // Escape key : exit if (Event.Type == sf::Event::KeyPressed) { if(Event.Key.Code == sf::Key::Escape) App->Close(); else if(Event.Key.Code == sf::Key::Delete) deleteShape(); else if(Event.Key.Code == sf::Key::Up && selected != 0) { Shape* s = findShape(selected); switch(colorM) { case COLOR_R: s->color[0] = ffmin(1.0, s->color[0]+0.05); break; case COLOR_G: s->color[1] = ffmin(1.0, s->color[1]+0.05); break; case COLOR_B: s->color[2] = ffmin(1.0, s->color[2]+0.05); break; } } else if(Event.Key.Code == sf::Key::Down && selected != 0) { Shape* s = findShape(selected); switch(colorM) { case COLOR_R: s->color[0] = ffmax(0.0, s->color[0]-0.05); break; case COLOR_G: s->color[1] = ffmax(0.0, s->color[1]-0.05); break; case COLOR_B: s->color[2] = ffmax(0.0, s->color[2]-0.05); break; } } } // Resize event : adjust viewport if (Event.Type == sf::Event::Resized) { glViewport(0, 0, Event.Size.Width, Event.Size.Height); currentRes[0] = Event.Size.Width; currentRes[1] = Event.Size.Height; update_perspective(); } if (Event.Type == sf::Event::MouseButtonPressed) { lastPos[0] = Event.MouseButton.X; lastPos[1] = Event.MouseButton.Y; float x = Event.MouseButton.X; float y = currentRes[1]-Event.MouseButton.Y; if(Event.MouseButton.Button == sf::Mouse::Left) { if(!handleButtons(x,y)) { handleSelection(Event.MouseButton.X, Event.MouseButton.Y); } } if(Event.MouseButton.Button == sf::Mouse::Left && !shiftDown) { buttonDown[0] = 1; } if(Event.MouseButton.Button == sf::Mouse::Right) buttonDown[1] = 1; if(Event.MouseButton.Button == sf::Mouse::Middle) buttonDown[2] = 1; if(Event.MouseButton.Button == sf::Mouse::Left && shiftDown) buttonDown[2] = 1; } if (Event.Type == sf::Event::MouseButtonReleased) { if(Event.MouseButton.Button == sf::Mouse::Left && !shiftDown) buttonDown[0] = 0; if(Event.MouseButton.Button == sf::Mouse::Right) buttonDown[1] = 0; if(Event.MouseButton.Button == sf::Mouse::Middle) buttonDown[2] = 0; if(Event.MouseButton.Button == sf::Mouse::Left && shiftDown) buttonDown[2] = 0; } if (Event.Type == sf::Event::MouseMoved && (buttonDown[0] || buttonDown[1] || buttonDown[2]) ) { int x = Event.MouseMove.X; int y = Event.MouseMove.Y; if(selected == 0) { if(buttonDown[0]) camera.trackball_rotate(lastPos[0], lastPos[1], x, y, currentRes[0], currentRes[1]); if(buttonDown[1]) camera.trackball_translate(lastPos[0], lastPos[1], x, y); if(buttonDown[2]) camera.trackball_translate_z(lastPos[0], lastPos[1], x, y); } else { Shape* s = findShape(selected); float diff = (x-lastPos[0])-(y-lastPos[1]); vec3 v; switch(axisM) { case X_AXIS: v = vec3(diff,0.0,0.0); break; case Y_AXIS: v = vec3(0.0,diff,0.0); break; case Z_AXIS: v = vec3(0.0,0.0,diff); break; } switch(transM) { case TRANS_TRANSLATION: s->trans.trans += v*0.01; break; case TRANS_ROTATION: s->rot.trans += v*0.1; break; case TRANS_SCALE: s->scale.trans += v*0.01; break; } } lastPos[0] = x; lastPos[1] = y; } } }
/* Encode audio data into FLAC frames. An input sample must be within 32-bit container. To encode a frame libFLAC needs NBLOCK+1 input samples. flac_encode() returns a frame with NBLOCK encoded samples, so 1 sample always stays cached in libFLAC until we explicitly flush output data. */ int ffflac_encode(ffflac_enc *f) { uint samples, sampsize, blksize; int r; switch (f->state) { case ENC_HDR: if (NULL == ffarr_realloc(&f->outbuf, (f->info.minblock + 1) * sizeof(int) * f->info.channels)) return ERR(f, FLAC_ESYS); for (uint i = 0; i != f->info.channels; i++) { f->pcm32[i] = (void*)(f->outbuf.ptr + (f->info.minblock + 1) * sizeof(int) * i); } f->cap_pcm32 = f->info.minblock + 1; f->state = ENC_FRAMES; // break case ENC_FRAMES: break; case ENC_DONE: { flac_conf info = {0}; flac_encode_info(f->enc, &info); f->info.minblock = info.min_blocksize; f->info.maxblock = info.max_blocksize; f->info.minframe = info.min_framesize; f->info.maxframe = info.max_framesize; ffmemcpy(f->info.md5, info.md5, sizeof(f->info.md5)); return FFFLAC_RDONE; } } sampsize = f->info.bits/8 * f->info.channels; samples = ffmin(f->pcmlen / sampsize - f->off_pcm, f->cap_pcm32 - f->off_pcm32); if (samples == 0 && !f->fin) { f->off_pcm = 0; return FFFLAC_RMORE; } const void* src[FLAC__MAX_CHANNELS]; int* dst[FLAC__MAX_CHANNELS]; for (uint i = 0; i != f->info.channels; i++) { src[i] = (char*)f->pcm[i] + f->off_pcm * f->info.bits/8; dst[i] = f->pcm32[i] + f->off_pcm32; } if (0 != (r = pcm_to32(dst, src, f->info.bits, f->info.channels, samples))) return ERR(f, FLAC_EFMT); f->off_pcm += samples; f->off_pcm32 += samples; if (!(f->off_pcm32 == f->cap_pcm32 || f->fin)) { f->off_pcm = 0; return FFFLAC_RMORE; } samples = f->off_pcm32; f->off_pcm32 = 0; r = flac_encode(f->enc, (const int**)f->pcm32, &samples, (char**)&f->data); if (r < 0) return f->errtype = FLAC_ELIB, f->err = r, FFFLAC_RERR; blksize = f->info.minblock; if (r == 0 && f->fin) { samples = 0; r = flac_encode(f->enc, (const int**)f->pcm32, &samples, (char**)&f->data); if (r < 0) return f->errtype = FLAC_ELIB, f->err = r, FFFLAC_RERR; blksize = samples; f->state = ENC_DONE; } FF_ASSERT(r != 0); FF_ASSERT(samples == f->cap_pcm32 || f->fin); if (f->cap_pcm32 == f->info.minblock + 1) f->cap_pcm32 = f->info.minblock; f->frsamps = blksize; f->datalen = r; return FFFLAC_RDATA; }
int ffwav_decode(ffwav *w) { int r; struct ffwav_chunk *chunk, *parent; for (;;) { switch (w->state) { case R_SKIP: chunk = &w->chunks[w->ictx]; r = ffmin(chunk->size, w->datalen); FFARR_SHIFT(w->data, w->datalen, r); chunk->size -= r; w->off += r; if (chunk->size != 0) return FFWAV_RMORE; w->state = R_NEXTCHUNK; continue; case R_PADDING: if (w->datalen == 0) return FFWAV_RMORE; if (w->data[0] == '\0') { // skip padding byte FFARR_SHIFT(w->data, w->datalen, 1); w->off += 1; parent = &w->chunks[w->ictx - 1]; if (parent->size != 0) parent->size -= 1; } w->state = R_NEXTCHUNK; // break case R_NEXTCHUNK: chunk = &w->chunks[w->ictx]; if (chunk->size == 0) { if (chunk->flags & F_PADD) { chunk->flags &= ~F_PADD; w->state = R_PADDING; continue; } uint id = chunk->id; ffmem_tzero(chunk); w->ictx--; switch (id) { case T_RIFF: return FFWAV_RDONE; } continue; } FF_ASSERT(chunk->ctx != NULL); // break case R_FIRSTCHUNK: w->gather_size = sizeof(struct wav_chunk); w->state = R_GATHER, w->nxstate = R_CHUNKHDR; // break case R_GATHER: r = ffarr_append_until(&w->buf, w->data, w->datalen, w->gather_size); if (r == 0) return FFWAV_RMORE; else if (r == -1) return ERR(w, WAV_ESYS); FFARR_SHIFT(w->data, w->datalen, r); w->off += w->gather_size; ffstr_set2(&w->gather_buf, &w->buf); w->buf.len = 0; w->state = w->nxstate; continue; case R_CHUNKHDR: { parent = &w->chunks[w->ictx]; chunk = &w->chunks[++w->ictx]; wav_findchunk(w->gather_buf.ptr, parent->ctx, chunk, w->off - w->gather_buf.len); if (!(chunk->id == T_DATA && chunk->size == (uint)-1)) { if (chunk->size > parent->size) return ERR(w, WAV_ELARGE); parent->size -= sizeof(struct wav_chunk) + chunk->size; } if (chunk->id == 0) { //unknown chunk w->state = R_SKIP; continue; } if (chunk->id == T_DATA && chunk->size == (uint)-1) w->inf_data = 1; uint minsize = GET_MINSIZE(chunk->flags); if (minsize != 0 && chunk->size < minsize) return ERR(w, WAV_ESMALL); if ((chunk->flags & F_WHOLE) || minsize != 0) { w->gather_size = (minsize != 0) ? minsize : chunk->size; chunk->size -= w->gather_size; w->state = R_GATHER, w->nxstate = R_CHUNK; continue; } w->state = R_CHUNK; continue; } case R_CHUNK: chunk = &w->chunks[w->ictx]; if (chunk->id & T_TAG) { w->tag = chunk->id & ~T_TAG; ffstr_setz(&w->tagval, w->gather_buf.ptr); w->state = R_NEXTCHUNK; return FFWAV_RTAG; } switch (chunk->id) { case T_RIFF: if (!!ffs_cmp(w->gather_buf.ptr, "WAVE", 4)) return ERR(w, WAV_ERIFF); w->chunks[w->ictx].ctx = wav_ctx_riff; break; case T_FMT: if (w->has_fmt) return ERR(w, WAV_EDUPFMT); w->has_fmt = 1; if (0 > (r = wav_fmt(w->gather_buf.ptr, w->gather_buf.len, &w->fmt, &w->bitrate))) return ERR(w, -r); w->sampsize = ffpcm_size1(&w->fmt); if (NULL == ffarr_realloc(&w->buf, w->sampsize)) return ERR(w, WAV_ESYS); break; case T_LIST: if (!!ffs_cmp(w->gather_buf.ptr, "INFO", 4)) { w->state = R_SKIP; continue; } w->chunks[w->ictx].ctx = wav_ctx_list; break; case T_DATA: if (!w->has_fmt) return ERR(w, WAV_ENOFMT); w->dataoff = w->off; w->datasize = ff_align_floor(chunk->size, w->sampsize); if (!w->inf_data) w->total_samples = chunk->size / w->sampsize; w->state = R_DATA; return FFWAV_RHDR; } w->state = R_NEXTCHUNK; continue; case R_SEEK: w->off = w->dataoff + w->cursample * w->sampsize; w->state = R_DATA; return FFWAV_RSEEK; case R_DATAOK: w->cursample += w->pcmlen / w->sampsize; w->state = R_DATA; // break case R_DATA: { uint chunk_size = w->dataoff + w->datasize - w->off; if (chunk_size == 0) { chunk = &w->chunks[w->ictx]; chunk->size -= w->datasize; w->state = R_SKIP; continue; } uint n = (uint)ffmin(chunk_size, w->datalen); n = ff_align_floor(n, w->sampsize); if (n == 0) { w->gather_size = w->sampsize; w->state = R_GATHER, w->nxstate = R_BUFDATA; continue; //not even 1 complete PCM sample } w->pcm = (void*)w->data, w->pcmlen = n; FFARR_SHIFT(w->data, w->datalen, n); w->off += n; w->state = R_DATAOK; return FFWAV_RDATA; } case R_BUFDATA: w->pcm = w->gather_buf.ptr, w->pcmlen = w->gather_buf.len; w->state = R_DATAOK; return FFWAV_RDATA; } } //unreachable }
static void corecmd_run(uint cmd, void *udata) { dbglog("%s cmd:%u udata:%p", __func__, cmd, udata); switch ((enum ACTION)cmd) { case A_SHOWPCM: file_showpcm(); break; case A_DELFILE: file_del(); break; case A_PLAY: if (gg->curtrk != NULL) gg->track->cmd(gg->curtrk->trk, FMED_TRACK_STOP); gg->qu->cmd(FMED_QUE_PLAY, (void*)gg->qu->fmed_queue_item(-1, gg->focused)); break; case A_PLAYPAUSE: if (gg->curtrk == NULL) { gg->qu->cmd(FMED_QUE_PLAY, NULL); break; } if (gg->curtrk->paused) { gg->curtrk->paused = 0; wmain_status(""); gg->curtrk->d->snd_output_pause = 0; gg->track->cmd(gg->curtrk->trk, FMED_TRACK_UNPAUSE); break; } gg->curtrk->d->snd_output_pause = 1; wmain_status("Paused"); gg->curtrk->paused = 1; break; case A_STOP: gg->track->cmd(NULL, FMED_TRACK_STOPALL); break; case A_STOP_AFTER: gg->qu->cmd(FMED_QUE_STOP_AFTER, NULL); break; case A_NEXT: case A_PREV: { if (gg->curtrk != NULL) gg->track->cmd(gg->curtrk->trk, FMED_TRACK_STOP); uint id = (cmd == A_NEXT) ? FMED_QUE_NEXT2 : FMED_QUE_PREV2; gg->qu->cmd(id, (gg->curtrk != NULL) ? gg->curtrk->qent : NULL); break; } case A_SEEK: case A_FFWD: case A_RWND: case A_LEAP_FWD: case A_LEAP_BACK: gtrk_seek(cmd, (size_t)udata); break; case A_SETGOPOS: if (gg->curtrk != NULL) { gg->go_pos = gg->curtrk->time_cur; wmain_status("Marker: %u:%02u" , gg->go_pos / 60, gg->go_pos % 60); } break; case A_GOPOS: if (gg->curtrk != NULL && gg->go_pos != (uint)-1) gg->curtrk->time_seek = gg->go_pos; break; case A_VOL: gg->vol = (size_t)udata; gtrk_vol(gg->vol); break; case A_VOLUP: gg->vol = ffmin(gg->vol + 5, MAXVOL); gtrk_vol(gg->vol); break; case A_VOLDOWN: gg->vol = ffmax((int)gg->vol - 5, 0); gtrk_vol(gg->vol); break; case A_VOLRESET: gg->vol = 100; gtrk_vol(gg->vol); break; case A_LIST_SAVE: { char *list_fn = udata; gg->qu->fmed_queue_save(-1, list_fn); ffmem_free(list_fn); break; } case A_LIST_REMOVE: list_rmitems(); break; case A_LIST_RMDEAD: gg->qu->cmd(FMED_QUE_RMDEAD, NULL); break; case A_LIST_CLEAR: gg->qu->cmd(FMED_QUE_CLEAR | FMED_QUE_NO_ONCHANGE, NULL); ffui_post_view_clear(&gg->wmain.vlist); break; case A_LIST_RANDOM: core->props->list_random = !core->props->list_random; break; case A_ONDROPFILE: { ffstr *d = udata; ffstr s = *d, ln; while (s.len != 0) { ffstr_nextval3(&s, &ln, '\n'); if (!ffs_matchz(ln.ptr, ln.len, "file://")) continue; ffstr_shift(&ln, FFSLEN("file://")); wmain_ent_add(&ln); } ffstr_free(d); ffmem_free(d); break; } case A_URL_ADD: { ffstr *s = udata; wmain_ent_add(s); ffstr_free(s); ffmem_free(s); break; } case A_ONCLOSE: if (gg->conf.autosave_playlists) lists_save(); core->sig(FMED_STOP); break; case LOADLISTS: lists_load(); break; default: FF_ASSERT(0); } }