static M4Err AAC_ConnectService(NetClientPlugin *plug, LPNETSERVICE serv, const char *url) { char szURL[2048]; char *ext; M4Err reply; AACReader *read = plug->priv; read->service = serv; if (read->dnload) NM_CloseDownloader(read->dnload); read->dnload = NULL; strcpy(szURL, url); ext = strrchr(szURL, '#'); if (ext) ext[0] = 0; /*remote fetch*/ read->is_remote = !aac_is_local(szURL); if (read->is_remote) { aac_download_file(plug, (char *) szURL); return M4OK; } reply = M4OK; read->stream = fopen(szURL, "rb"); if (!read->stream) { reply = M4URLNotFound; } else if (!AAC_ConfigureFromFile(read)) { fclose(read->stream); read->stream = NULL; reply = M4UnsupportedURL; } NM_OnConnect(serv, NULL, reply); return M4OK; }
void AAC_OnData(void *cbk, char *data, u32 data_size) { M4Err e; char sMsg[1024]; Float perc, bytes_per_sec; const char *szCache; u32 total_size, bytes_done, net_status; AACReader *read = (AACReader *) cbk; e = NM_GetDownloaderStats(read->dnload, &total_size, &bytes_done, &bytes_per_sec, &net_status); if ((e == M4EOF) && read->stream) { read->is_remote = 0; return; } else if (e >= M4OK) { /*notify some connection / ...*/ if (total_size) { perc = (Float) (100 * bytes_done) / (Float) total_size; sprintf(sMsg, "Download %.2f %% (%.2f kBps)", perc, bytes_per_sec/1024); NM_OnMessage(read->service, M4OK, sMsg); } /*looks like a live stream*/ else { AAC_OnLiveData(read, data, data_size); return; } if (read->stream) return; /*open service*/ szCache = NM_GetCacheFileName(read->dnload); if (!szCache) e = M4InvalidPlugin; else { read->stream = fopen((char *) szCache, "rb"); if (!read->stream) e = M4ServiceError; else { e = M4OK; /*if full file at once (in cache) parse duration*/ if (bytes_done==total_size) read->is_remote = 0; /*not enough data*/ if (!AAC_ConfigureFromFile(read)) { /*bad data - there's likely some ID3 around...*/ if (bytes_done>10*1024) { e = M4CorruptedData; } else { fclose(read->stream); read->stream = NULL; return; } } } } } /*OK confirm*/ if (read->needs_connection) { read->needs_connection = 0; NM_OnConnect(read->service, NULL, e); } }
static GF_Err AAC_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { char szURL[2048]; char *ext; GF_Err reply; AACReader *read = plug->priv; read->service = serv; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; strcpy(szURL, url); ext = strrchr(szURL, '#'); if (ext) ext[0] = 0; /*remote fetch*/ read->is_remote = !aac_is_local(szURL); if (read->is_remote) { aac_download_file(plug, (char *) szURL); return GF_OK; } reply = GF_OK; read->stream = fopen(szURL, "rb"); if (!read->stream) { reply = GF_URL_ERROR; } else if (!AAC_ConfigureFromFile(read)) { fclose(read->stream); read->stream = NULL; reply = GF_NOT_SUPPORTED; } gf_term_on_connect(serv, NULL, reply); if (!reply && read->is_inline ) AAC_SetupObject(read); return GF_OK; }
static M4Err AAC_ServiceCommand(NetClientPlugin *plug, NetworkCommand *com) { AACReader *read = plug->priv; if (!com->base.on_channel) return M4NotSupported; switch (com->command_type) { case CHAN_SET_PULL: if ((read->es_ch == com->base.on_channel) && read->is_live) return M4NotSupported; return M4OK; case CHAN_INTERACTIVE: if ((read->es_ch == com->base.on_channel) && read->is_live) return M4NotSupported; return M4OK; case CHAN_BUFFER: if ((read->es_ch == com->base.on_channel) && read->is_live) { if (com->buffer.max<1000) com->buffer.max = 1000; com->buffer.min = com->buffer.max/2; } return M4OK; case CHAN_SET_PADDING: read->pad_bytes = com->pad.padding_bytes; return M4OK; case CHAN_DURATION: com->duration.duration = read->duration; com->duration.duration /= read->sample_rate; return M4OK; case CHAN_PLAY: read->start_range = com->play.start_range; read->end_range = com->play.end_range; read->current_time = 0; if (read->stream) fseek(read->stream, 0, SEEK_SET); if (read->es_ch == com->base.on_channel) { read->es_done = 0; /*PLAY after complete download, estimate duration*/ if (!read->is_remote && !read->duration) { AAC_ConfigureFromFile(read); if (read->duration) { NetworkCommand rcfg; rcfg.base.on_channel = read->es_ch; rcfg.base.command_type = CHAN_DURATION; rcfg.duration.duration = read->duration; rcfg.duration.duration /= read->sample_rate; NM_OnCommand(read->service, &rcfg, M4OK); } } } else if (read->od_ch == com->base.on_channel) { read->od_done = 0; } return M4OK; case CHAN_STOP: return M4OK; default: return M4OK; } }
static GF_Err AAC_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com) { AACReader *read = plug->priv; if (com->base.command_type==GF_NET_SERVICE_INFO) { com->info.name = read->icy_track_name ? read->icy_track_name : read->icy_name; com->info.comment = read->icy_genre; return GF_OK; } if (!com->base.on_channel) { /*if live session we may cache*/ if (read->is_live && (com->command_type==GF_NET_IS_CACHABLE)) return GF_OK; return GF_NOT_SUPPORTED; } switch (com->command_type) { case GF_NET_CHAN_SET_PULL: if ((read->ch == com->base.on_channel) && read->is_live) return GF_NOT_SUPPORTED; return GF_OK; case GF_NET_CHAN_INTERACTIVE: if ((read->ch == com->base.on_channel) && read->is_live) return GF_NOT_SUPPORTED; return GF_OK; case GF_NET_CHAN_BUFFER: if ((read->ch == com->base.on_channel) && read->is_live) { if (com->buffer.max<1000) com->buffer.max = 1000; com->buffer.min = com->buffer.max/2; } return GF_OK; case GF_NET_CHAN_SET_PADDING: read->pad_bytes = com->pad.padding_bytes; return GF_OK; case GF_NET_CHAN_DURATION: com->duration.duration = read->duration; com->duration.duration /= read->sample_rate; return GF_OK; case GF_NET_CHAN_PLAY: read->start_range = com->play.start_range; read->end_range = com->play.end_range; read->current_time = 0; if (read->stream) fseek(read->stream, 0, SEEK_SET); if (read->ch == com->base.on_channel) { read->done = 0; /*PLAY after complete download, estimate duration*/ if (!read->is_remote && !read->duration) { AAC_ConfigureFromFile(read); if (read->duration) { GF_NetworkCommand rcfg; rcfg.base.on_channel = read->ch; rcfg.base.command_type = GF_NET_CHAN_DURATION; rcfg.duration.duration = read->duration; rcfg.duration.duration /= read->sample_rate; gf_term_on_command(read->service, &rcfg, GF_OK); } } } return GF_OK; case GF_NET_CHAN_STOP: return GF_OK; default: return GF_OK; } }
void AAC_NetIO(void *cbk, GF_NETIO_Parameter *param) { GF_Err e; const char *szCache; u32 total_size, bytes_done; AACReader *read = (AACReader *) cbk; e = param->error; /*done*/ if (param->msg_type==GF_NETIO_DATA_TRANSFERED) { if (read->stream) { read->is_remote = 0; e = GF_EOS; } else { return; } } else if (param->msg_type==GF_NETIO_PARSE_HEADER) { if (!strcmp(param->name, "icy-name")) { if (read->icy_name) free(read->icy_name); read->icy_name = strdup(param->value); } if (!strcmp(param->name, "icy-genre")) { if (read->icy_genre) free(read->icy_genre); read->icy_genre = strdup(param->value); } if (!strcmp(param->name, "icy-meta")) { GF_NetworkCommand com; char *meta; if (read->icy_track_name) free(read->icy_track_name); read->icy_track_name = NULL; meta = param->value; while (meta && meta[0]) { char *sep = strchr(meta, ';'); if (sep) sep[0] = 0; if (!strnicmp(meta, "StreamTitle=", 12)) { read->icy_track_name = strdup(meta+12); } if (!sep) break; sep[0] = ';'; meta = sep+1; } com.base.command_type = GF_NET_SERVICE_INFO; gf_term_on_command(read->service, &com, GF_OK); } return; } else { /*handle service message*/ gf_term_download_update_stats(read->dnload); if (param->msg_type!=GF_NETIO_DATA_EXCHANGE) return; } /*data fetching or EOS*/ if (e >= GF_OK) { if (read->needs_connection) { gf_dm_sess_get_stats(read->dnload, NULL, NULL, &total_size, NULL, NULL, NULL); if (!total_size) read->is_live = 1; } if (read->is_live) { if (!e) AAC_OnLiveData(read, param->data, param->size); return; } if (read->stream) return; /*open service*/ szCache = gf_dm_sess_get_cache_name(read->dnload); if (!szCache) e = GF_IO_ERR; else { read->stream = fopen((char *) szCache, "rb"); if (!read->stream) e = GF_SERVICE_ERROR; else { /*if full file at once (in cache) parse duration*/ if (e==GF_EOS) read->is_remote = 0; e = GF_OK; /*not enough data*/ if (!AAC_ConfigureFromFile(read)) { /*get amount downloaded and check*/ gf_dm_sess_get_stats(read->dnload, NULL, NULL, NULL, &bytes_done, NULL, NULL); if (bytes_done>10*1024) { e = GF_CORRUPTED_DATA; } else { fclose(read->stream); read->stream = NULL; return; } } } } } /*OK confirm*/ if (read->needs_connection) { read->needs_connection = 0; gf_term_on_connect(read->service, NULL, e); if (!e) AAC_SetupObject(read); } }