static access_t *GetAccess(access_t *access) { access_sys_t *sys = access->p_sys; access_t *a = sys->access; if (a != NULL) { if (!vlc_access_Eof(a)) return a; vlc_access_Delete(a); sys->access = NULL; } if (sys->next == NULL) { error: access->info.b_eof = true; return NULL; } a = vlc_access_NewMRL(VLC_OBJECT(access), sys->next->mrl); if (a == NULL) goto error; sys->access = a; sys->next = sys->next->next; return a; }
static void AStreamDestroy(stream_t *s) { stream_sys_t *sys = s->p_sys; if (sys->block != NULL) block_Release(sys->block); vlc_access_Delete(sys->access); free(sys); }
static int Seek(access_t *access, uint64_t position) { access_sys_t *sys = access->p_sys; if (sys->access != NULL) { vlc_access_Delete(sys->access); sys->access = NULL; } sys->next = sys->first; access->info.i_pos = 0; for (;;) { access_t *a = GetAccess(access); if (a == NULL) break; bool can_seek; access_Control(a, ACCESS_CAN_SEEK, &can_seek); if (!can_seek) break; uint64_t size; if (access_GetSize(a, &size)) break; if (position - access->info.i_pos < size) { if (vlc_access_Seek(a, position - access->info.i_pos)) break; access->info.i_pos = position; return VLC_SUCCESS; } access->info.i_pos += size; vlc_access_Delete(a); sys->access = NULL; } return VLC_EGENERIC; }
static void Close(vlc_object_t *obj) { access_t *access = (access_t *)obj; access_sys_t *sys = access->p_sys; if (sys->access != NULL) vlc_access_Delete(sys->access); for (struct access_entry *e = sys->first, *next; e != NULL; e = next) { next = e->next; free(e); } free(sys); }
static int Open(vlc_object_t *obj) { access_t *access = (access_t *)obj; char *list = var_CreateGetNonEmptyString(access, "concat-list"); if (list == NULL) return VLC_EGENERIC; access_sys_t *sys = malloc(sizeof (*sys)); if (unlikely(sys == NULL)) { free(list); return VLC_ENOMEM; } var_SetString(access, "concat-list", ""); /* prevent recursion */ bool read_cb = true; sys->access = NULL; sys->can_seek = true; sys->can_seek_fast = true; sys->can_pause = true; sys->can_control_pace = true; sys->size = 0; sys->caching = 0; struct access_entry **pp = &sys->first; for (char *buf, *mrl = strtok_r(list, ",", &buf); mrl != NULL; mrl = strtok_r(NULL, ",", &buf)) { size_t mlen = strlen(mrl); struct access_entry *e = malloc(sizeof (*e) + mlen); if (unlikely(e == NULL)) break; access_t *a = vlc_access_NewMRL(obj, mrl); if (a == NULL) { msg_Err(access, "cannot concatenate location %s", mrl); free(e); continue; } if (a->pf_read == NULL) { if (a->pf_block == NULL) { msg_Err(access, "cannot concatenate directory %s", mrl); vlc_access_Delete(a); free(e); continue; } read_cb = false; } *pp = e; e->next = NULL; memcpy(e->mrl, mrl, mlen + 1); if (sys->can_seek) access_Control(a, ACCESS_CAN_SEEK, &sys->can_seek); if (sys->can_seek_fast) access_Control(a, ACCESS_CAN_FASTSEEK, &sys->can_seek_fast); if (sys->can_pause) access_Control(a, ACCESS_CAN_PAUSE, &sys->can_pause); if (sys->can_control_pace) access_Control(a, ACCESS_CAN_CONTROL_PACE, &sys->can_control_pace); if (sys->size != UINT64_MAX) { uint64_t size; if (access_GetSize(a, &size)) sys->size = UINT64_MAX; else sys->size += size; } int64_t caching; access_Control(a, ACCESS_GET_PTS_DELAY, &caching); if (caching > sys->caching) sys->caching = caching; vlc_access_Delete(a); pp = &e->next; } free(list); *pp = NULL; sys->next = sys->first; access_InitFields(access); access->pf_read = read_cb ? Read : NULL; access->pf_block = read_cb ? NULL : Block; access->pf_seek = Seek; access->pf_control = Control; access->p_sys = sys; return VLC_SUCCESS; }